/* ── Reset & Base ── */
*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  /*
   * Exact Telegram "Night Blue" (tinted dark) palette
   * Source: Telegram-iOS DefaultDarkTintedPresentationTheme.swift
   * Accent: #2EA6FF
   */
  --tg-bg: #17212B;
  --tg-bg-secondary: #232E3C;
  --tg-bg-input: #101A24;
  --tg-separator: #344150;
  --tg-text: #F5F5F5;
  --tg-hint: #708499;
  --tg-link: #6AB3F3;
  --tg-accent: #2EA6FF;
  --tg-button: #5288C1;
  --tg-section-header: #6AB3F3;
  --tg-destructive: #EC3942;

  /* Premium gradient (from Telegram-Mac Appearance.swift) */
  --premium-blue: #6B93FF;
  --premium-purple: #976FFF;
  --premium-pink: #E46ACE;

  /* Star gold — luxury rich gold */
  --gold: #FFB800;
  --gold-bright: #FFCA28;
  --gold-deep: #E5A100;
  --gold-glow: rgba(255, 184, 0, 0.5);

  /* Base sans stack (mirrors the body font-family below). MUST stay defined:
     the V8 home block uses `font: <w> <sz> var(--font-sans, inherit)` in 9
     places, and if this var is missing the fallback resolves to
     `font: <w> <sz> inherit` — which is INVALID in the font shorthand, so the
     whole declaration is dropped and the text falls back to base sizes. That
     was the 2026-05-25 "V8 type scale doesn't match the preview" bug. */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: linear-gradient(160deg, #0a1420 0%, #0e1a2a 30%, #0c1725 60%, #0e1422 100%);
  color: var(--tg-theme-text-color, var(--tg-text));
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 90% 50% at 10% 0%, rgba(46, 166, 255, 0.10) 0%, transparent 55%),
    radial-gradient(ellipse 70% 50% at 90% 100%, rgba(151, 111, 255, 0.07) 0%, transparent 55%),
    radial-gradient(ellipse 60% 40% at 50% 50%, rgba(46, 166, 255, 0.04) 0%, transparent 60%);
  pointer-events: none;
}

@media (min-width: 600px) {
  body::before {
    background:
      radial-gradient(ellipse 80% 50% at 10% 0%, rgba(46, 166, 255, 0.22) 0%, transparent 55%),
      radial-gradient(ellipse 70% 50% at 90% 100%, rgba(151, 111, 255, 0.18) 0%, transparent 55%),
      radial-gradient(ellipse 60% 40% at 50% 50%, rgba(46, 166, 255, 0.10) 0%, transparent 60%);
  }
}

/* ── State visibility ── */
.state {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.hidden {
  display: none !important;
}

/* ── Animations ── */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

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

@keyframes countUp {
  from { opacity: 0; transform: scale(0.85); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

@keyframes starGlow {
  0%, 100% { filter: drop-shadow(0 0 4px rgba(255, 184, 0, 0.5)); }
  50% { filter: drop-shadow(0 0 14px rgba(255, 184, 0, 0.8)); }
}

@keyframes premiumGradient {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* ── Loading State ── */
.loading-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  animation: fadeIn 0.4s ease-out;
}

.loading-video {
  width: 200px;
  height: 200px;
  object-fit: contain;
  border-radius: 20px;
  pointer-events: none;
}

.loading-text {
  font-size: 17px;
  font-weight: 600;
  color: var(--tg-theme-text-color, var(--tg-text));
}

.loading-sub {
  font-size: 14px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  animation: pulse 2s ease-in-out infinite;
}

/* ── Refresh Toast — floating pill at top, no layout impact ── */
.refresh-banner {
  position: fixed;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  padding: 4px 12px;
  font-size: 11px;
  font-weight: 500;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  background: rgba(0, 0, 0, 0.45);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-radius: 999px;
  pointer-events: none;
  z-index: 2000;
  white-space: nowrap;
  animation: refreshSlideIn 0.25s ease-out;
}
/* The "Refreshing…" toast reflects a portfolio/home data refresh. It's a
   body-level position:fixed pill, so without scoping it floats over whatever
   page is active and covers the header (users saw it over Predictions). Keep
   it only on the two surfaces that this data actually feeds — Home + Portfolio
   — via the body[data-page] set on every nav switch. (#id only, so the
   .refresh-banner.search-toast on Home is unaffected.) */
body:not([data-page="home"]):not([data-page="portfolio"]) #refresh-banner { display: none !important; }

@keyframes refreshSlideIn {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

.refresh-banner--out {
  animation: refreshSlideOut 0.2s ease-in forwards;
}

@keyframes refreshSlideOut {
  from { opacity: 1; transform: translate(-50%, 0); }
  to { opacity: 0; transform: translate(-50%, -10px); }
}

/* ── Search Toast — same pill, brighter since user-initiated ── */
.search-toast {
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, var(--premium-blue), var(--premium-purple));
  box-shadow: 0 4px 14px rgba(99, 102, 241, 0.35);
}

/* Dim main content while searching for another user */
body.is-searching #page-home,
body.is-searching #page-leaderboard,
body.is-searching #page-settings {
  opacity: 0.45;
  pointer-events: none;
  transition: opacity 0.2s ease;
  filter: saturate(0.7);
}

/* ── Header ── */
.header {
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  animation: fadeInUp 0.4s ease-out;
}

.user-info {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Round 113 (2026-05-08) — was `flex-shrink: 0`, which let user-info
     expand to its content's natural width on long display names like
     «Neko-ryder Hirasawa 🐍 | 死». The expansion pushed the inline
     search-row past the header's right edge, overlapping the search
     input. Switching to `flex: 0 1 auto` lets user-info shrink when
     room runs out; combined with the ellipsis on .user-name-text below,
     long names truncate cleanly while the › chevron and search-row
     stay fully visible. Future-proof: any new long-name source (alias
     concat, emoji-heavy display_name, etc.) won't ever overlap. */
  flex: 0 1 auto;
  min-width: 0;
}

/* When profile-rating is visible (viewing another user), hide inline search for space */
.header:has(#profile-rating:not(.hidden)) .search-row--inline {
  display: none;
}

.user-avatar {
  /* Round 66 (2026-05-05) — premium gradient ring + soft purple glow,
   * matches the blue→purple→pink hero recipe used on Market title,
   * totals-num, search-btn. Avatar still sits on its theme background;
   * the ring is painted via box-shadow so it works regardless of
   * whether <img> is present or the fallback initial circle is drawn. */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--tg-theme-button-color, var(--tg-button));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 700;
  color: var(--tg-theme-button-text-color, #ffffff);
  flex-shrink: 0;
  position: relative;
  box-shadow:
    0 0 0 1.5px rgba(151, 111, 255, 0.55),
    0 4px 14px rgba(151, 111, 255, 0.22);
}
/* Gradient ring overlay — circular border that fades through the
 * blue→purple→pink palette around the avatar. Sits ON TOP of box-shadow
 * tint to give the ring genuine hue variation instead of flat purple. */
.user-avatar::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  padding: 2px;
  background: linear-gradient(135deg,
    var(--premium-blue) 0%,
    var(--premium-purple) 55%,
    var(--premium-pink) 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

.user-avatar-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

/* Home avatar = the Settings entry point (Settings has no bottom-nav tab).
 * A gear badge marks it as settings; shown only on your OWN profile — when
 * viewing another user, #profile-rating is visible and :has() strips the
 * affordance (this file already relies on :has()). The avatar keeps its
 * existing premium gradient ring. */
.user-avatar-wrap { position: relative; display: inline-flex; flex-shrink: 0; cursor: pointer; }
.user-avatar-wrap:active { transform: scale(0.95); }
.user-avatar-gear {
  position: absolute; right: -4px; top: -4px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--tg-bg); border: 2px solid var(--tg-accent);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.user-avatar-gear .gc-icon { width: 12px; height: 12px; }
.header:has(#profile-rating:not(.hidden)) .user-avatar-wrap { cursor: default; }
.header:has(#profile-rating:not(.hidden)) .user-avatar-gear { display: none; }

.user-name {
  /* Round 66 — clean white name with bumped weight (was 600 → 700)
   * for visual parity with the new gradient search-btn. NO gradient
   * text-clip here: the name often contains emojis (🐸 etc.) which
   * lose their colour glyphs when clipped, going purple-on-purple.
   * App-wide pattern: hero numerics get the blue→purple→pink wash
   * (.totals-num, .market-stat-value); name text stays white. Same
   * decision as top-3 leaderboard text-shadow recipe in Round 47. */
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.2px;
  color: var(--tg-theme-text-color, var(--tg-text));
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  /* Round 113 — must allow shrinking inside .user-info so the inner
     ellipsis-truncating .user-name-text actually has somewhere to
     shrink to. Without min-width:0 the flex item refuses to shrink
     below the content's intrinsic min-content width, defeating the
     ellipsis. */
  min-width: 0;
  max-width: 100%;
  /* Round 124 (2026-05-27) — own-profile names land here as raw text
     (ui.js sets nameEl.textContent = name). Round 113 only added the
     ellipsis to the foreign-profile .user-name-text wrapper, so a long
     OWN name («Андрей Васильев») wrapped to two lines instead of
     truncating, which then squeezed the inline search pill. Restate
     the single-line ellipsis here so direct text content truncates;
     harmless for the foreign path (its .user-name-link child carries
     max-width:100% and truncates internally, the alias block sits
     below unaffected). */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.user-name-link {
  color: var(--tg-theme-text-color, var(--tg-text));
  text-decoration: none;
  /* Round 113 — flex layout so .user-name-text can ellipsis-truncate
     while the › chevron stays pinned at the end (text-overflow on a
     single inline run would chop the chevron first). */
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  max-width: 100%;
  min-width: 0;
}

.user-name-text {
  /* Round 113 — the actual ellipsis target. Long display names
     (any TG handle / display_name string) truncate here without
     touching the › chevron sibling. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.user-name-link:active {
  opacity: 0.7;
}

.user-name-arrow {
  color: var(--tg-theme-hint-color, var(--tg-hint));
  font-size: 20px;
  margin-left: 2px;
}

/* Subscript shown when the search resolved an alternative @username for
   the same Telegram account. Sits directly under the canonical name so
   the user sees their typed query was honoured. */
.user-name-alias {
  font-size: 11px;
  font-weight: 400;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  margin-top: 1px;
  letter-spacing: 0;
  opacity: 0.85;
  /* Round 113 — same single-line ellipsis treatment as
     .user-name-text. The alias breadcrumb can carry any TG handle
     up to 32 chars («matched @SomeMaximumLengthHandle1234») which
     overflowed the user-info box on narrow viewports. Block
     children of .user-name don't get the parent's nowrap by
     default, so we restate it here. max-width:100% binds the
     truncation target to .user-name's flex width. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.user-username {
  font-size: 14px;
  font-weight: 400;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}

/* ── Profile Rating ── */
.profile-rating {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

.profile-rating.hidden {
  display: none;
}

.rate-btn {
  /* Round 66 — purple-tinted glass to match the search-row pill family
   * instead of the old generic white-on-grey. Voted state lights up
   * with a subtle blue→pink gradient (premium recipe) instead of the
   * cold-blue tint. */
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid rgba(151, 111, 255, 0.22);
  border-radius: 14px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0) 100%),
    rgba(151, 111, 255, 0.08);
  color: var(--tg-theme-text-color, var(--tg-text));
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}

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

/* Round 89 — POST in flight: the click handler painted the optimistic
 * next state and is now waiting for the server. Visually communicate
 * "your tap registered but we're still confirming" so the user
 * doesn't double-tap. pointer-events:none is the hard stop in case
 * the JS in-flight guard is bypassed (e.g. JS error mid-await). */
.rate-btn.is-pending {
  opacity: 0.55;
  pointer-events: none;
}

.rate-btn.voted {
  border-color: var(--premium-purple);
  background: linear-gradient(135deg,
    rgba(107, 147, 255, 0.20) 0%,
    rgba(151, 111, 255, 0.20) 55%,
    rgba(228, 106, 206, 0.20) 100%);
  box-shadow: 0 0 0 2px rgba(151, 111, 255, 0.18);
}

.profile-views {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}
.profile-views .gc-icon { width: 13px; height: 13px; opacity: 0.85; }

/* ── Search Row ── */
/* Trio (input + 📋 paste + 🔍 submit) renders as a SINGLE pill — no
 * visible gaps, shared rounded ends, internal borders removed where
 * segments touch. Polished look replacing the earlier "three separate
 * boxes" version (user feedback 2026-05-03: «выглядят как дешевый
 * фикс»). */
.search-row {
  display: flex;
  gap: 0;
  padding: 0 clamp(12px, 3vw, 20px) clamp(8px, 2vw, 16px);
  animation: fadeInUp 0.45s ease-out;
  position: relative;  /* anchor for .search-suggestions */
  align-items: stretch;
}

/* ── Typeahead suggestions dropdown ──────────────────────────────────────
 * Lives absolutely-positioned under each search input. Each row mirrors
 * a leaderboard mini-row (avatar + name/sub + total stars) so the dropdown
 * feels native to the rest of the app. Hidden by default via the [hidden]
 * attribute; JS toggles `el.hidden = false` when matches arrive. */
.search-suggestions {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 360px;
  overflow-y: auto;
  background: var(--tg-theme-bg-color, #1c1d22);
  border: 1px solid rgba(151, 111, 255, 0.25);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  padding: 4px;
}

.ss-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.12s ease;
}

.ss-item:hover,
.ss-item:active {
  background: rgba(151, 111, 255, 0.12);
}

.ss-avatar,
.ss-avatar-img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--premium-blue), var(--premium-purple));
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  object-fit: cover;
}

.ss-info {
  flex: 1;
  min-width: 0;
}

.ss-name {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}

.ss-sub {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

.ss-value {
  font-size: 13px;
  font-weight: 700;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  white-space: nowrap;
}

/* Inline variant: lives inside .header, compact, takes remaining right-side space */
.search-row--inline {
  flex: 1;
  padding: 0;
  margin-left: auto;
  /* Round 113 — was `min-width: 0`, allowing the search-row to be
     squeezed to zero by a long user-name. Now: hard floor at 140 px so
     the input stays usable regardless of how long the user-name gets.
     Combined with .user-info's `flex: 0 1 auto` + .user-name-text
     ellipsis, the layout is robust to any name length. */
  min-width: 140px;
  animation: none;
}

.search-row--inline .search-input {
  padding: 8px 12px;
  font-size: 13px;
  border-radius: 12px 0 0 12px;
}

.search-row--inline .search-btn {
  padding: 8px 12px;
  font-size: 14px;
  border-radius: 0 12px 12px 0;
  flex-shrink: 0;
}

.search-input {
  /* Round 66 — frosted-glass background (top sheen + purple tint),
   * 14 px corners (was 12), focus halo via box-shadow. Reads as glass,
   * not a flat purple slab. */
  flex: 1;
  padding: 10px 14px;
  font-size: 14px;
  border: 1px solid rgba(107, 147, 255, 0.28);
  border-right: none;                          /* connect to next segment */
  border-radius: 14px 0 0 14px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0) 100%),
    rgba(107, 147, 255, 0.10);
  color: var(--tg-theme-text-color, var(--tg-text));
  outline: none;
  transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
  min-width: 0;
}

.search-input:focus {
  /* Round 67-fix — focus glow shifted from purple to blue family so it
   * matches the (now solid blue) submit button and (light blue) paste
   * segment. Without this the focused pill would jump purple → blue
   * mid-segment. */
  border-color: var(--premium-blue);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0) 100%),
    rgba(107, 147, 255, 0.16);
  box-shadow: 0 0 0 3px rgba(107, 147, 255, 0.20);
}
/* When input has focus, the entire pill highlights together —
 * border-color applies to the paste segment too via :has() so the
 * three segments read as one focused control. */
.search-row:has(.search-input:focus) .search-paste-btn {
  border-color: var(--premium-blue);
}

.search-input::placeholder {
  color: var(--tg-theme-hint-color, var(--tg-hint));
}

/* Paste clipboard button — small 📋 icon between the input and the
 * 🔍 submit button. Appears only when input is empty (toggled by JS).
 * Exists as the ultimate fallback for environments where Ctrl+V doesn't
 * work (some Linux Telegram Desktop builds where neither the `paste` DOM
 * event nor navigator.clipboard work reliably).
 *
 * Layout 2026-05-03: switched from position:absolute overlay (which
 * covered the input's right side and clipped the placeholder text)
 * to a flex-sibling slot — input | 📋 paste | 🔍 submit. This way
 * the input gets its full visible width without padding-right hacks
 * and the paste icon never covers typed/placeholder text. */
.search-paste-btn {
  /* Round 67-fix (2026-05-06) — light-blue glass to differentiate from
   * the (now solid blue) submit button. User: «для кнопки paste тоже
   * светло-голубой фон, чтобы было отличие». Same border + sheen
   * recipe, just shifted from purple tint to blue tint. Borders on
   * top/bottom only — segment merges into the pill. */
  flex-shrink: 0;
  width: 36px;
  padding: 0;
  border: 1px solid rgba(107, 147, 255, 0.28);
  border-left: none;
  border-right: none;
  border-radius: 0;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0) 100%),
    rgba(107, 147, 255, 0.18);
  color: #fff;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  opacity: 1;
  transition: background 0.15s, transform 0.1s;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Touch tuning — kill 300ms double-tap delay + prevent WebView from
   * synthesizing a click on totals-card below if touch slightly off. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.search-paste-btn:hover { background: rgba(107, 147, 255, 0.28); }
.search-paste-btn:active { transform: scale(0.94); background: rgba(107, 147, 255, 0.34); }
/* Inline variant (Home + Leaderboard) — narrower paste segment to
 * fit the compact slots. */
.search-row--inline .search-paste-btn {
  width: 30px;
  font-size: 13px;
}
/* When paste is hidden (input has typed value), input directly meets
 * search-btn — keep the same seamless join via input's border-right:none
 * and search-btn's border-left:none. Both border-radius corners stay
 * rounded on the outer edges. (No special selector needed; the layered
 * border rules already produce this effect.) */

.search-btn {
  /* Round 67-fix (2026-05-06) — solid premium-blue background per user
   * direction: «верни иконку search-svg, сделай фон голубым просто».
   * Round 66's 3-stop blue→purple→pink gradient blended with the
   * search.svg lupa (which uses the SAME gradient on its strokes),
   * making the icon nearly invisible. Solid blue + native gradient
   * lupa gives clear contrast — the purple/pink portions of the
   * lupa's gradient stand out against the blue field. Inset top
   * sheen kept for depth. Paired with paste-btn's lighter blue tint
   * so the two segments are visually distinguishable. */
  padding: 10px 16px;
  font-size: 16px;
  flex-shrink: 0;
  border: 1px solid var(--premium-blue);
  border-left: none;
  border-radius: 0 14px 14px 0;
  background: var(--premium-blue);
  color: #fff;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.1s;
  box-shadow:
    -2px 0 8px rgba(107, 147, 255, 0.30),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.search-btn:active {
  opacity: 0.85;
  transform: scale(0.96);
}

/* ── Viewing Other User Banner ── */
.viewing-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 16px 8px;
  padding: 8px 14px;
  background: linear-gradient(135deg, rgba(107, 147, 255, 0.15), rgba(151, 111, 255, 0.10));
  border: 1px solid rgba(151, 111, 255, 0.25);
  border-radius: 12px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
}

.viewing-banner.hidden {
  display: none;
}

.viewing-back {
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  border: none;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  cursor: pointer;
}

.viewing-back:active {
  background: rgba(255, 255, 255, 0.25);
}

/* ── Totals Card — Telegram Premium gradient ── */
.totals-card {
  margin: 0 clamp(8px, 2vw, 24px) clamp(8px, 2vw, 16px);
  padding: clamp(16px, 4vw, 28px) clamp(16px, 3.5vw, 24px);
  background: linear-gradient(135deg, var(--premium-blue), var(--premium-purple), var(--premium-pink));
  background-size: 200% 200%;
  animation: fadeInUp 0.5s ease-out, premiumGradient 8s ease infinite;
  border-radius: 16px;
  text-align: center;
  position: relative;
  overflow: hidden;
}

.totals-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(circle at 20% 30%, rgba(255,255,255,0.1) 0%, transparent 50%);
  pointer-events: none;
}

.totals-title {
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.7);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 12px;
  position: relative;
}

/* Tap-affordance for the totals card — arrow next to the title hints
 * that you can tap the card to see the unique vs regular breakdown. */
.totals-title-arrow {
  display: inline-block;
  margin-left: 4px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  transform: translateY(-1px);
}

.totals-card--clickable {
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.12s ease;
}

.totals-card--clickable:active {
  transform: scale(0.985);
  filter: brightness(0.95);
}

/* ── Portfolio breakdown modal — Unique vs Regular split ── */
.breakdown-list {
  margin-top: 6px;
  padding: 0 4px;
}

.breakdown-row {
  margin-bottom: 6px;
}

.breakdown-row--tappable {
  cursor: pointer;
  transition: transform 80ms ease, background 120ms ease;
}

.breakdown-row--tappable .breakdown-row-head {
  background: rgba(255, 255, 255, 0.06);
}

.breakdown-row--tappable:active .breakdown-row-head {
  background: rgba(255, 255, 255, 0.10);
  transform: scale(0.985);
}

.breakdown-row-head {
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 12px;
  padding: 10px 14px;
}

.breakdown-row-arrow {
  font-size: 18px;
  color: var(--tg-theme-hint-color, rgba(255, 255, 255, 0.45));
  margin-left: 6px;
  flex-shrink: 0;
}

.breakdown-row-icon {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
}

.breakdown-row-label {
  flex: 1;
  min-width: 0;
}

.breakdown-row-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--tg-theme-text-color, #fff);
}

.breakdown-row-sub {
  font-size: 12px;
  color: var(--tg-theme-hint-color, rgba(255, 255, 255, 0.55));
  margin-top: 2px;
}

.breakdown-row-value {
  text-align: right;
  flex-shrink: 0;
}

.breakdown-row-stars {
  font-size: 15px;
  font-weight: 700;
  color: #ffd166;
}

.breakdown-row-fiat {
  font-size: 12px;
  color: var(--tg-theme-hint-color, rgba(255, 255, 255, 0.55));
  margin-top: 2px;
}

.breakdown-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Right padding is row-head's 14 px + space for the row's › arrow
   * (font-size 18 px + 6 px margin ≈ 24 px) so the Total value lines
   * up under the per-row amounts instead of being 24 px further right.
   * Tiny visual-alignment tax for a nicer column read. */
  padding: 14px 38px 14px 14px;
  margin-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.breakdown-footer-label {
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--tg-theme-hint-color, rgba(255, 255, 255, 0.55));
}

.breakdown-footer-value {
  text-align: right;
}

.breakdown-footer-stars {
  font-size: 18px;
  font-weight: 800;
  color: #ffd166;
}

.breakdown-footer-fiat {
  font-size: 13px;
  color: var(--tg-theme-hint-color, rgba(255, 255, 255, 0.55));
  margin-top: 2px;
}

.totals-primary {
  font-size: 36px;
  font-weight: 800;
  color: #ffffff;
  margin-bottom: 10px;
  position: relative;
  letter-spacing: -0.5px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  text-align: center;
}

.totals-primary .star-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  animation: starGlow 2.5s ease-in-out infinite;
}

.totals-primary .totals-num {
  line-height: 1;
  display: inline-block;
}

.totals-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  position: relative;
  text-align: center;
}

.totals-secondary {
  font-size: 17px;
  color: rgba(255, 255, 255, 0.78);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.totals-separator {
  color: rgba(255, 255, 255, 0.35);
  font-size: 17px;
}

/* ── Stats Row ── */
.stats-row {
  display: flex;
  margin: 0 clamp(8px, 2vw, 20px) clamp(12px, 3vw, 24px);
  gap: clamp(4px, 1.2vw, 10px);
  animation: fadeInUp 0.6s ease-out;
}

.stat-item {
  flex: 1;
  background: linear-gradient(135deg, rgba(107, 147, 255, 0.18) 0%, rgba(151, 111, 255, 0.15) 50%, rgba(228, 106, 206, 0.12) 100%);
  border: 1px solid rgba(151, 111, 255, 0.20);
  border-radius: 12px;
  padding: clamp(10px, 2.5vw, 16px) clamp(6px, 2vw, 12px);
  text-align: center;
  transition: transform 0.2s ease;
}

.stat-clickable {
  cursor: pointer;
  border-color: rgba(151, 111, 255, 0.30);
}

.stat-clickable:active {
  transform: scale(0.96);
  background: linear-gradient(135deg, rgba(107, 147, 255, 0.28) 0%, rgba(151, 111, 255, 0.25) 50%, rgba(228, 106, 206, 0.22) 100%);
}

.stat-disabled {
  pointer-events: none;
  opacity: 0.55;
}

.stat-item:active {
  transform: scale(0.96);
}

.stat-value {
  /* Aggressive clamp: on 320px the font drops to 11px so 3-cell rows with
   * long numbers ("3,536 / 3,634") still fit on one line without ellipsis.
   * Max 20px preserves the wide look on desktop-class viewports. */
  font-size: clamp(11px, 3.2vw + 2px, 20px);
  font-weight: 700;
  letter-spacing: -0.4px;
  animation: countUp 0.5s ease-out;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.15;
}
.stat-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: clamp(9px, 2.4vw, 12px);
  letter-spacing: 0.2px;
}
.stat-item {
  min-width: 0;
  padding: 12px 6px;
}

.stat-label {
  /* Round 68 — clamp() so labels scale on narrow viewports + JS
   * auto-shrink fallback for very long values. Round 69 (2026-05-06)
   * — overall range tightened smaller per user direction: «* unique
   * / * limited / portfolio сделать меньше». Was clamp(8, 2.2vw+1,
   * 11) → now clamp(7, 1.7vw + 0.5, 9). Max 9 px (was 11) reads as
   * a quieter caption against the louder gradient .stat-value, and
   * gives the JS auto-shrink more headroom before it has to step down
   * further. */
  font-size: clamp(7px, 1.7vw + 0.5px, 9px);
  font-weight: 500;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  margin-top: 4px;
  text-transform: uppercase;
  letter-spacing: clamp(0.1px, 0.15vw, 0.4px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (pointer: fine) {
  /* Round 73 (2026-05-06) — desktop-only +15 % bump per user direction:
   * «на пк версии слишком маленькие, сделай на 15% больше для пк».
   * Mobile clamp ceiling 9 px × 1.15 ≈ 10.35 px → 10.5 px. Padding
   * also gets a touch more headroom on desktop where the JS auto-
   * shrink almost never has to fire (cards ~140-200 px wide). Mobile
   * clamp range untouched — narrow viewports still scale down to 7 px. */
  .stat-label { font-size: 10.5px; }
}

/* Round 48 (2026-05-05) — Home stats-row tiles painted with inline
 * CSS gradients per design system spec. SVG-bg path was retired
 * (Round 35); inline gradients scale on every device, no iOS Safari
 * background-size quirks (see feedback_inline_css_gradients.md memory).
 *
 *   .stat-item--premium  → BLUE   (unique + limited stars stats)
 *   .stat-item--gain     → GREEN  (Portfolio PnL ≥ 0)
 *   .stat-item--loss     → RED    (Portfolio PnL < 0; toggled by JS) */
.stats-row .stat-item--premium,
.stats-row .stat-item--gain,
.stats-row .stat-item--loss {
  position: relative;     /* anchor for ::after foil sheen */
  overflow: hidden;       /* clip sheen to rounded corners */
  border-radius: 14px;
  /* Round 50 (2026-05-05) — shimmer animation per user request: same
   * `premiumGradient` keyframe used by the Portfolio Value totals-card
   * (style.css:105). Both background layers (radial highlight + linear
   * tier gradient) get sized to 200%×200% and pan together over 8 s,
   * giving the tiles a subtle living-colour feel that matches the hero
   * card above them.
   * !important needed because the higher-specificity
   * `.stat-item--portfolio.stat-item--gain/--loss` rules use the
   * `background:` shorthand which resets background-size to auto. */
  background-size: 200% 200% !important;
  animation: premiumGradient 8s ease infinite;
}
/* Round 49 (2026-05-05) — toned down ~15% per user feedback («слишком
 * яркие»). Three changes per tier:
 *   1. Radial sheen alpha 0.28/0.32 → 0.18 (less aggressive top-left highlight)
 *   2. Linear gradient stops shifted ~12% darker (HSL lightness drop)
 *   3. Outer box-shadow glow alpha 0.40-0.45 → 0.22 (subtler tile lift)
 * Borders + inset highlights stay so the tile still reads as raised. */
.stats-row .stat-item--premium {
  background:
    radial-gradient(140% 180% at 0% 0%, rgba(255,255,255,0.18) 0%, transparent 55%),
    linear-gradient(135deg, #5594D6 0%, #3373C7 50%, #1A4FAB 100%);
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.30),
    inset 0 -1px 0 rgba(0,0,0,0.10),
    0 4px 12px rgba(63,141,236,0.22);
}
.stats-row .stat-item--gain {
  background:
    radial-gradient(140% 180% at 0% 0%, rgba(255,255,255,0.18) 0%, transparent 55%),
    linear-gradient(135deg, #4DC585 0%, #2FA866 55%, #18915A 100%);
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.32),
    inset 0 -1px 0 rgba(0,0,0,0.10),
    0 4px 12px rgba(95,227,154,0.24);
}
.stats-row .stat-item--loss {
  background:
    radial-gradient(140% 180% at 0% 0%, rgba(255,255,255,0.18) 0%, transparent 55%),
    linear-gradient(135deg, #E26B6B 0%, #DC4444 55%, #C03030 100%);
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.32),
    inset 0 -1px 0 rgba(0,0,0,0.10),
    0 4px 12px rgba(255,82,82,0.22);
}
/* Shared diagonal foil sheen — sits above the gradient bg, below text.
 * Round 49: sheen alpha 0.20 → 0.12 to match the dimmer overall look. */
.stats-row .stat-item--premium::after,
.stats-row .stat-item--gain::after,
.stats-row .stat-item--loss::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(118deg,
    rgba(255,255,255,0) 30%,
    rgba(255,255,255,0.12) 48%,
    rgba(255,255,255,0) 60%);
  mix-blend-mode: overlay;
  z-index: 0;
}
.stats-row .stat-item--premium > *,
.stats-row .stat-item--gain > *,
.stats-row .stat-item--loss > * {
  position: relative;
  z-index: 1;     /* keep value/label above the ::after sheen */
}
/* White text on the gradient tiles. Value stays bold, label gets the
 * subtle uppercase + letter-spacing treatment per spec. Font-size
 * inherits the existing clamp() so digits never overflow narrow tiles. */
.stats-row .stat-item--premium .stat-value,
.stats-row .stat-item--gain .stat-value,
.stats-row .stat-item--loss .stat-value {
  color: #ffffff;
  font-weight: 800;
}
.stats-row .stat-item--premium .stat-label,
.stats-row .stat-item--gain .stat-label,
.stats-row .stat-item--loss .stat-label {
  color: rgba(255, 255, 255, 0.80);
  font-weight: 700;
  letter-spacing: 1.2px;
}
/* Higher-specificity override (.stat-item--portfolio + dynamic class)
 * so the green/red gradient wins over the legacy blue rule that comes
 * later in the file (.stats-row .stat-item--portfolio at ~line 4440). */
.stats-row .stat-item--portfolio.stat-item--gain {
  background:
    radial-gradient(140% 180% at 0% 0%, rgba(255,255,255,0.18) 0%, transparent 55%),
    linear-gradient(135deg, #4DC585 0%, #2FA866 55%, #18915A 100%);
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.32),
    inset 0 -1px 0 rgba(0,0,0,0.10),
    0 4px 12px rgba(95,227,154,0.24);
}
.stats-row .stat-item--portfolio.stat-item--loss {
  background:
    radial-gradient(140% 180% at 0% 0%, rgba(255,255,255,0.18) 0%, transparent 55%),
    linear-gradient(135deg, #E26B6B 0%, #DC4444 55%, #C03030 100%);
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.32),
    inset 0 -1px 0 rgba(0,0,0,0.10),
    0 4px 12px rgba(255,82,82,0.22);
}
/* Same recipe for label/value override. The legacy .stat-item--portfolio
 * .stat-label rule sets blue accent text — higher specificity flips
 * back to white-on-tier per spec. */
.stats-row .stat-item--portfolio.stat-item--gain .stat-label,
.stats-row .stat-item--portfolio.stat-item--loss .stat-label {
  color: rgba(255, 255, 255, 0.80);
}

/* ── View Tabs ── */
.view-tabs {
  display: flex;
  margin: 0 16px 12px;
  background: var(--tg-bg-secondary);
  border-radius: 12px;
  padding: 3px;
}

/* When hidden we still reserve the exact layout space (visibility instead of
 * display:none) so the profile doesn't "jump" as collections fetch resolves
 * and tabs toggle visible. The space is only fully collapsed on Home view
 * for own portfolio (handled by .view-tabs--collapsed below) where we know
 * collections won't appear. */
.view-tabs.hidden {
  visibility: hidden;
  pointer-events: none;
}

.view-tabs.view-tabs--collapsed {
  display: none;
}

/* Tighten the gap between the portfolio hero (#totals-card) and the
   Gifts/Collections switcher: the hero's 16px bottom margin made the row feel
   detached. Scoped to the adjacency so the hero's spacing to other content
   (when the tabs are collapsed/absent) is unchanged. Collapses to 16 - 10 = 6px. */
.totals-card + .view-tabs { margin-top: -10px; }

.view-tab {
  flex: 1;
  height: 20px;
  box-sizing: border-box;
  padding: 0 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  cursor: pointer;
  transition: background-color 0.2s, border-color 0.2s, color 0.2s, box-shadow 0.2s, transform 0.2s, opacity 0.2s;
}

.view-tab.active {
  background: linear-gradient(135deg, rgba(151, 111, 255, 0.25), rgba(107, 147, 255, 0.20));
  color: #fff;
}

/* ── Controls Row ── */
.controls-row {
  /* Round 85 — min-width:0 lets the inner sort-buttons row shrink past
   * its intrinsic width on tighter viewports. justify-content dropped:
   * with flex:1 on .sort-buttons it consumes the leftover space
   * naturally, no need for space-between (which only pushed the row
   * to the right edge regardless). */
  display: flex;
  align-items: center;
  padding: 0 clamp(12px, 3vw, 20px) clamp(6px, 2vw, 10px);
  gap: clamp(6px, 1.5vw, 12px);
  animation: fadeInUp 0.65s ease-out;
  min-width: 0;
}

.controls-row .section-header {
  /* Round 85 — flex:0 1 auto so GIFTS label is the FIRST item to give
   * up space when the row gets crowded (still readable; ellipsis only
   * fires on extreme narrow viewports where the label naturally
   * collapses). flex-shrink:0 was too rigid — pushed the buttons row
   * off-screen instead of itself shrinking gracefully. */
  padding: 0;
  animation: none;
  flex: 0 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 11px;
}

.section-header {
  padding: 4px clamp(14px, 4vw, 24px) clamp(6px, 2vw, 12px);
  font-size: 13px;
  font-weight: 600;
  color: var(--tg-theme-section-header-text-color, var(--tg-section-header));
  text-transform: uppercase;
  letter-spacing: 0.5px;
  animation: fadeInUp 0.65s ease-out;
}

/* Round 85 (2026-05-06) — architectural fix for the sort row.
 *
 * User pain: «не вмещается строка на пк, сделай так, чтобы она всегда
 * вмещалась — придумай умное решение, чтобы это больше не ломалось».
 *
 * Old recipe had three orthogonal failure modes any one of which broke
 * the layout for SOME viewport width:
 *   1. .sort-btn { flex-shrink: 0 }   → buttons never shrink, push past
 *      the right edge whenever intrinsic width > container width.
 *   2. .sort-buttons { overflow-x: auto } → silent horizontal scroll
 *      hides clipped buttons (the user can't see they're there).
 *   3. @media (min-width: 600px) { flex-wrap: wrap } → abrupt
 *      switch at 600 px boundary; viewports between 540–599 px hit
 *      the dead zone (no wrap yet, doesn't fit single-row).
 *
 * New recipe — fluid flex shrink + clamp() padding/font:
 *
 *   .sort-buttons    flex:1 1 auto, min-width:0  → row takes the
 *                                                   remaining space and
 *                                                   can shrink past its
 *                                                   intrinsic width.
 *   .sort-btn        flex:1 1 auto, min-width:0  → each button shares
 *                                                   the row width
 *                                                   proportionally, can
 *                                                   shrink past its own
 *                                                   intrinsic width.
 *   padding/font     clamp(min, vw-fluid, max)   → shrinks on narrow,
 *                                                   stays full size on
 *                                                   wide screens.
 *   text-overflow    ellipsis                    → last-resort safety
 *                                                   (won't fire at any
 *                                                   reasonable width
 *                                                   ≥ 320 px with
 *                                                   current 6 buttons).
 *
 * Math sanity at the worst case (1024 px PC viewport with 6 buttons +
 * GIFTS label): each button gets ≈ 130 px of width, more than enough
 * for the longest English label «Backdrop» (~64 px at 12 px font).
 * At 360 px iPhone-SE: each button gets ≈ 42 px, font clamps to 10 px,
 * and «Backdrop» fits without ellipsis (64 px → 50 px at 10 px font).
 *
 * No flex-wrap. No horizontal scroll. No abrupt media-query switch.
 * The same rule scales smoothly from 320 px to 1920 px. */
.sort-buttons {
  display: flex;
  flex: 1 1 auto;
  gap: clamp(2px, 0.6vw, 6px);
  min-width: 0;
}

.sort-btn {
  flex: 1 1 auto;
  min-width: 0;
  padding: clamp(4px, 1.1vw, 8px) clamp(6px, 1.5vw, 12px);
  font-size: clamp(10px, 2.2vw, 12px);
  font-weight: 600;
  border: 1px solid rgba(46, 166, 255, 0.15);
  border-radius: 8px;
  background: transparent;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}

.sort-btn.active {
  background: rgba(46, 166, 255, 0.20);
  border-color: var(--tg-accent);
  color: var(--tg-accent);
}

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

/* ── Active Filter Banner ── */
.active-filter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 16px 8px;
  padding: 8px 12px 8px 14px;
  background: rgba(151, 111, 255, 0.20);
  border: 1px solid rgba(151, 111, 255, 0.30);
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  animation: fadeIn 0.15s ease-out;
}

.active-filter.hidden {
  display: none;
}

/* Collection thumb shown in the drill-in filter banner, replacing the old
   generic 🎮 prefix (2026-05-26). Used on both own-home and foreign drill-ins. */
#active-filter-text { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.filter-chip-icon {
  width: 20px; height: 20px; border-radius: 5px; object-fit: cover; flex-shrink: 0;
  background: rgba(255, 255, 255, 0.08);
}

.active-filter-clear {
  background: rgba(255, 255, 255, 0.15);
  border: none;
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: background 0.15s;
}

.active-filter-clear:active {
  background: rgba(255, 255, 255, 0.30);
}

/* ── Dropdown Panel (overlay) ── */
.dropdown-panel {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  max-height: 75vh;
  overflow-y: auto;
  background: var(--tg-theme-bg-color, var(--tg-bg));
  border-top: 1px solid rgba(46, 166, 255, 0.20);
  border-radius: 20px 20px 0 0;
  animation: slideUp 0.2s ease-out;
  box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.5);
  padding-bottom: calc(env(safe-area-inset-bottom, 16px) + 24px);
  margin-bottom: 12px;
  margin-left: 8px;
  margin-right: 8px;
  border-radius: 20px;
  border: 1px solid rgba(46, 166, 255, 0.15);
}

.dropdown-panel.hidden {
  display: none !important;
}

.dropdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px 8px;
  position: sticky;
  top: 0;
  background: var(--tg-theme-bg-color, var(--tg-bg));
  z-index: 1;
}

.dropdown-search-wrap {
  padding: 0 16px 10px;
  position: sticky;
  top: 48px;
  background: var(--tg-theme-bg-color, var(--tg-bg));
  z-index: 1;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.dropdown-search {
  width: 100%;
  padding: 8px 12px;
  font-size: 14px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--tg-theme-text-color, var(--tg-text));
  outline: none;
}

.dropdown-search:focus {
  border-color: var(--tg-accent);
}

.dropdown-search::placeholder {
  color: var(--tg-theme-hint-color, var(--tg-hint));
}
.dropdown-collection-chips {
  display: flex;
  gap: 6px;
  padding: 4px 16px 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.dropdown-collection-chips::-webkit-scrollbar {
  display: none;
}
.dropdown-col-chip.active {
  background: var(--tg-accent);
  border-color: var(--tg-accent);
  color: #fff;
}

.dropdown-title {
  font-size: 16px;
  font-weight: 700;
}

.dropdown-apply {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 600;
  border: none;
  border-radius: 8px;
  background: var(--tg-accent);
  color: #fff;
  cursor: pointer;
}

.dropdown-apply:active {
  opacity: 0.8;
}

.dropdown-overlay {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: rgba(0, 0, 0, 0.4);
}

.dropdown-overlay.hidden {
  display: none !important;
}

.dropdown-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  cursor: pointer;
  transition: background 0.1s;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

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

.dropdown-item:active {
  background: rgba(46, 166, 255, 0.1);
}

.dropdown-item.selected {
  background: rgba(46, 166, 255, 0.12);
}

.dropdown-check {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 2px solid rgba(255, 255, 255, 0.2);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}

.dropdown-item.selected .dropdown-check {
  background: var(--tg-accent);
  border-color: var(--tg-accent);
  color: #fff;
}

.dropdown-item-left {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.dropdown-item-color {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* Round 31 (2026-05-04) — per-collection thumbnail (left of name) +
 * emoji fallback. Wrapper keeps the layout slot constant whether the
 * <img> loads, the fallback shows, or nothing is present. */
.dropdown-item-thumb-wrap {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.dropdown-item-thumb {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  object-fit: cover;
  display: block;
}
.dropdown-item-thumb-fallback {
  font-size: 18px;
  line-height: 1;
}
.dropdown-item-emoji {
  flex-shrink: 0;
  font-size: 16px;
  line-height: 1;
  width: 22px;
  text-align: center;
}

.dropdown-item-name {
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dropdown-item-right {
  font-size: 12px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  flex-shrink: 0;
  margin-left: 8px;
}

/* ── Filter Chips ── */
.filter-chips {
  display: flex;
  gap: 6px;
  padding: 0 16px 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.filter-chips::-webkit-scrollbar {
  display: none;
}

.filter-chips.hidden {
  display: none;
}

.filter-chip {
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 500;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: var(--tg-bg-secondary);
  color: var(--tg-theme-text-color, var(--tg-text));
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}

.filter-chip.active {
  background: var(--tg-accent);
  border-color: var(--tg-accent);
  color: #fff;
}

.filter-chip:active {
  transform: scale(0.95);
}

.filter-chip-color {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}

/* ── Group Grid Mode ── */
.lines-grid {
  /* Round 36-fix (2026-05-05) — original clamp added +8 px which was
   * imperceptible on Pro Max (user feedback: «вроде на широких
   * телефонах ничего не поменялось»). Lower bounds dropped to 4 px
   * (padding) and 3 px (gap), so wide phones (≥420 px) now gain
   * ~+18-22 px per tile vs the old fixed-16 layout. Desktop still
   * caps at 16/8 — no perceived change there. */
  padding: 0 clamp(2px, 1vw, 16px) 32px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(2px, 0.6vw, 8px);
}

/* Round 72 (2026-05-06) — Telegram-style 3-column gift grid for the
 * Collection drill-in (renderCollectionGiftsGrid in ui.js). Same
 * layered backdrop recipe as the modal hero / Market rows; square
 * cards with model thumb hero, name + price below, optional ×count
 * badge top-right. User feedback: «при заходе на его коллекцию,
 * нам надо сделать отображение гифтов такое же, как в телеграмме». */
/* Specificity 0,2,0 (two classes) so it wins over the generic
 * .lines-list { display: flex } rule below at line ~1738 regardless
 * of source order. */
.lines-list.lines-list--tg-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(4px, 1vw, 10px);
  padding: 0 clamp(8px, 2vw, 16px) 32px;
  flex-direction: initial;
  flex-wrap: initial;
}

.tg-grid-card {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.15s ease;
  background: linear-gradient(135deg, rgba(107, 147, 255, 0.18) 0%, rgba(151, 111, 255, 0.12) 100%);
  animation: fadeInUp 0.4s ease-out both;
  /* Off-screen grid cards skip layout + paint. The grid had no content-visibility
     before, so a big collection laid out + painted every card up front. ~115px is a
     3-col square card on a phone (aspect-ratio keeps it square once on-screen). */
  content-visibility: auto;
  contain-intrinsic-size: auto 115px;
}
.tg-grid-card:active { transform: scale(0.97); }

/* Layered render — radial gradient + tiled symbol mask, same recipe as
 * .modal-hero-card.gift-card-layered + .line-item.market-row.gift-card-layered.
 * applyCardLayers() sets the CSS vars at render time. */
.tg-grid-card.gift-card-layered {
  background: radial-gradient(circle at 50% 35%,
              var(--bg-center) 0%,
              var(--bg-edge)   85%);
}
.tg-grid-card.gift-card-layered::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--bg-pattern);
  -webkit-mask-image: var(--symbol-url);
          mask-image: var(--symbol-url);
  -webkit-mask-repeat: repeat;
          mask-repeat: repeat;
  -webkit-mask-size: 28px 28px;
          mask-size: 28px 28px;
  opacity: 0.45;
  pointer-events: none;
  z-index: 0;
}
/* No symbol in manifest → no pattern overlay (cleaner than rendering a
 * solid colour rectangle). */
.tg-grid-card.gift-card-layered:not(.gift-card-layered--with-symbol)::before {
  display: none;
}

.tg-grid-card-hero {
  /* Round 82 (2026-05-06) — proxy webp is the FULL TG-card composite
   * (gift artwork + actual backdrop + symbol pattern baked in by the
   * backend asset proxy). Filling 100 % of the card makes that
   * composite the entire surface, hiding the underlying CSS gradient
   * + symbol mask layer. User: «двойной backdrop у гифтов» — the
   * CSS layer's gradient was bleeding around the smaller proxy image
   * (was 62 % wide, centred), creating a visible second backdrop
   * ring that doesn't match the proxy's per-NFT canonical one.
   * Layered CSS bg now serves only as a fallback for cards whose
   * proxy 404s (model-thumb branch of the onerror chain). */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  object-fit: cover;
}

.tg-grid-card-name {
  position: absolute;
  bottom: 22px;
  left: 6px;
  right: 6px;
  font-size: clamp(10px, 2.4vw, 12px);
  font-weight: 700;
  color: var(--bg-text, #fff);
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  z-index: 2;
}
.tg-grid-card-price {
  position: absolute;
  bottom: 6px;
  left: 6px;
  right: 6px;
  font-size: clamp(9px, 2vw, 11px);
  font-weight: 600;
  color: var(--bg-text, #fff);
  text-align: center;
  opacity: 0.92;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  z-index: 2;
  font-variant-numeric: tabular-nums;
}
.tg-grid-card-count {
  position: absolute;
  top: 6px;
  right: 6px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 8px;
  z-index: 3;
  letter-spacing: 0.2px;
}

/* Round 76 — per-NFT serial «#NNNN» badge top-right, mirrors TG's
 * native «Gifts» tab. Slightly stronger contrast than the old count
 * badge because it carries informational signal (which mint of this
 * gift the user holds) rather than a multiplier. Tabular-nums so
 * varying serial widths align cleanly across the grid. */
.tg-grid-card-serial {
  position: absolute;
  top: 6px;
  right: 6px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 8px;
  z-index: 3;
  letter-spacing: 0.1px;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

.group-card {
  background: linear-gradient(135deg, rgba(107, 147, 255, 0.12) 0%, rgba(151, 111, 255, 0.08) 100%);
  border: 1px solid rgba(151, 111, 255, 0.12);
  border-radius: 12px;
  /* Round 36-fix3 — inner padding scales so wider phones get visibly
   * fatter cards (Pro Max 13 vs SE 10). */
  padding: clamp(10px, 3vw, 16px);
  text-align: center;
  cursor: pointer;
  transition: transform 0.15s;
  position: relative;
  overflow: hidden;
  /* G6 — first-load entrance. JS sets a per-tile animation-delay so the grid
   * cascades in; `backwards` holds the from-state during the delay. On a
   * background refresh the renderer sets `animation:none` inline (G2) so a
   * price tick never re-cascades the whole grid. */
  animation: fadeInUp 0.4s ease-out backwards;
}

.group-card:active {
  transform: scale(0.96);
}

/* G2/G6 — the grid entrance (tiles + list rows) is polish for genuine
 * first-appearance only; honour prefers-reduced-motion by disabling it. */
@media (prefers-reduced-motion: reduce) {
  .group-card,
  .line-item,
  .line-item--flat { animation: none !important; }
}

.group-thumb {
  /* Round 36-fix2 — bumped vw factor 13→16 so Pro Max (430) actually
   * gets a chunkier 68-70 px thumb (was stuck near 56 at 13vw). SE
   * (375) stays 60 — slight bump from the old fixed 56. */
  width: clamp(56px, 18vw, 84px);
  height: clamp(56px, 18vw, 84px);
  border-radius: 14px;
  object-fit: cover;
  margin: 0 auto 8px;
  display: block;
  /* No mix-blend-mode — `lighten` was a workaround for asset backgrounds
   * on dark UI but ate dark interior pixels of the gift icons across all
   * tiers. Native compositing reads cleaner everywhere. */
}

/* Emoji-as-thumb variant for the synthetic "Regular" tile — same square
 * footprint as image thumbs but renders the gift emoji centered on a soft
 * gradient background instead of an asset jpg. */
.group-thumb--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  line-height: 1;
  background: linear-gradient(135deg, rgba(99,102,241,0.18), rgba(46,166,255,0.12));
  border: 1px solid rgba(255,255,255,0.06);
}

.group-name {
  font-size: clamp(11px, 2.8vw, 14px);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 2px;
}

.group-count {
  font-size: 10px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  margin-bottom: 4px;
}

.group-value {
  font-size: clamp(12px, 3vw, 15px);
  font-weight: 700;
  color: var(--tg-accent);
}

/* Secondary "now <effective> ↑/↓" sub-line on the Group view's
 * Regular tile. Mirrors .regular-floor-now from the flat-list rows
 * — same dim treatment, same up/down colour family — so the
 * release-vs-floor reading is consistent across Group and flat
 * surfaces. Rendered ONLY when effective ≠ release (otherwise
 * markup is omitted upstream in renderGroupView). */
.group-value-floor {
  font-size: 0.78em;
  font-weight: 600;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  opacity: 0.8;
  white-space: nowrap;
}
.group-value-floor-label {
  opacity: 0.7;
  font-weight: 400;
  margin-right: 1px;
}
.group-value-floor-arrow {
  font-weight: 700;
  margin-left: 1px;
}
.group-value-floor--up   { color: #5fe39a; }   /* matches .regular-floor-now--up */
.group-value-floor--down { color: var(--tg-destructive); }

.group-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  background: var(--tg-accent);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 6px;
  min-width: 18px;
  text-align: center;
}

/* ── Lines List ── */
.lines-list {
  padding: 0 clamp(12px, 3vw, 20px) clamp(24px, 6vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.line-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  background: var(--tg-theme-secondary-bg-color, var(--tg-bg-secondary));
  border-left: 3px solid transparent;
  text-decoration: none;
  color: inherit;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
  animation: fadeInUp 0.4s ease-out backwards;
  /* Off-screen rows skip layout + paint, so a deep-paged List/# (thousands of accrued
     rows on a whale) costs ~nothing for the rows you can't see — the same windowing win
     Twitter/Instagram get by recycling, but browser-native. iOS 18+/Chromium honor it;
     older clients ignore it (no regression). `auto` makes the browser REMEMBER each
     row's real rendered height (flat rows measure ~65px, non-flat lines taller), so
     there is zero scrollbar drift on long whale lists; 70px is only the fallback used
     before a given row has ever been measured. */
  content-visibility: auto;
  contain-intrinsic-size: auto 70px;
}

.line-item:first-child {
  border-radius: 12px 12px 0 0;
}

.line-item:last-child {
  border-radius: 0 0 12px 12px;
}

.line-item:only-child {
  border-radius: 12px;
}

.line-item:active {
  opacity: 0.7;
  transform: scale(0.98);
}

/* Flat-view row (# sort). Shorter animation delay per row since the list
 * can be very long (1500+ for @monk) and a staggered 40 ms * N would
 * feel frozen. Also tighter vertical padding to fit more rows on screen. */
.lines-list--flat .line-item--flat {
  padding: clamp(8px, 2vw, 12px) clamp(10px, 2.5vw, 16px);
  animation-duration: 0.22s;
}

/* Phase 2b windowed recycler (gc:vlist). #lines-list becomes a relative positioning context;
 * JS sizes its height to total*ROW_H (66px) and absolutely positions each row via
 * transform:translateY(i*66). Rows are pinned to a FIXED 66px so the windowing math tiles
 * exactly, and .line-count is forced single-line so a long backdrop name can't grow a row
 * past ROW_H (which would drift every offset below it). content-visibility is off here (the
 * recycler itself keeps only ~one window of rows in the DOM). overflow-anchor:none stops the
 * browser's scroll anchoring from fighting the absolute layout. Specificity 0,2,0 beats the
 * base .lines-list flex rule. */
.lines-list.lines-list--virtual {
  display: block;
  position: relative;
  overflow-anchor: none;
  gap: 0;
}
.lines-list--virtual .line-item--flat {
  height: 66px;
  box-sizing: border-box;
  content-visibility: visible;
  animation: none;
}
.lines-list--virtual .line-item--flat .line-count {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Recycler placeholder: an in-range row whose data page is still in flight gets a pulsing
 * block at its slot (absolutely positioned by the recycler) instead of a blank gap during a
 * fast fling. Swapped for the real row the moment the page arrives. */
.lines-list--virtual .line-item--skeleton {
  height: 66px;
  box-sizing: border-box;
  padding: 8px 12px;
}
.lines-list--virtual .line-item--skeleton::after {
  content: "";
  display: block;
  height: 100%;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  animation: contribSkeletonPulse 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .lines-list--virtual .line-item--skeleton::after { animation: none; }
}
/* (removed 2026-05-03) Old flex rule for pill-inside-line-name — pill is
 * now a flex sibling via .line-name-row wrapper. The inner .line-name
 * keeps its base display:block so text-overflow:ellipsis works on long
 * titles. */

/* First-mint badge ("#1") — appears beside the line name on flat rows
 * (and we could extend to models view later). Gold chip, tight, no
 * underline. Backend sets gift_items[].is_first_mint. */
.flat-first-mint {
  display: inline-block;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #1a1a1a;
  background: linear-gradient(135deg, #FFE368 0%, #F6C91E 100%);
  border-radius: 999px;
  vertical-align: middle;
  box-shadow: 0 0 6px rgba(246, 201, 30, 0.45);
  flex-shrink: 0;
}
.lines-list-sentinel { pointer-events: none; }

/* Value tiers — full-row gradient by total USD value.
   NOTE (round 8 — backdrop colors on Market): when a `.market-row`
   carries a `data-bd-name` attribute, _renderGiftCard / _renderGroupCard
   set an inline `style.background` using the gift's actual backdrop
   palette (see _marketBackdropStyle in miniapp/js/app.js). Inline style
   beats the tier rules below by inline-style specificity, so we don't
   need a new selector here — Home (page-home) cards still get tier
   colors because they don't set data-bd-name. */

/* $1000+ — Trophy Gold */
.line-item[data-tier="gold"] {
  border-left-color: #FFC940;
  background: linear-gradient(90deg,
    rgba(255, 227, 104, 0.32) 0%,
    rgba(246, 201, 30, 0.22) 35%,
    rgba(245, 217, 139, 0.16) 70%,
    rgba(245, 217, 139, 0.10) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 243, 176, 0.28), 0 0 14px rgba(255, 201, 64, 0.14);
}

/* $100–$999 — Purple (Premium) */
.line-item[data-tier="purple"] {
  border-left-color: var(--premium-purple);
  background: linear-gradient(90deg, rgba(151, 111, 255, 0.33) 0%, rgba(151, 111, 255, 0.17) 50%, rgba(151, 111, 255, 0.10) 100%);
}

/* $10–$99 — Blue (Accent) */
.line-item[data-tier="blue"] {
  border-left-color: var(--tg-accent);
  background: linear-gradient(90deg, rgba(46, 166, 255, 0.27) 0%, rgba(46, 166, 255, 0.15) 50%, rgba(46, 166, 255, 0.09) 100%);
}

/* Under $10 — Soft blue-grey */
.line-item[data-tier="common"] {
  border-left-color: rgba(106, 179, 243, 0.40);
  background: linear-gradient(90deg, rgba(106, 179, 243, 0.19) 0%, rgba(106, 179, 243, 0.11) 50%, rgba(106, 179, 243, 0.07) 100%);
}
/* Round 33 (2026-05-05) — brand-design tier SVG bars are uploaded to
 * /assets/tiers/<tier>.svg but NOT yet wired to any DOM element. The
 * earlier Round 33 attempt swapped them in here on .line-item[data-tier]
 * and broke Price/Number/Model/Backdrop views (user feedback: «там не
 * должны отображаться 4 horizontal background SVGs»). Reverted to the
 * original CSS gradients above; the SVGs stay on CDN waiting for the
 * intended usage point to be specified. */

/* ── Gift Thumbnail ── */
.line-thumb {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  object-fit: cover;
  flex-shrink: 0;
  margin-right: 12px;
  background: var(--tg-bg-secondary);
}

.line-left {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  flex: 1;
}

.line-name {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.1px;
}

/* Wrapper for line-name + #1 first-mint pill on Price-sort rows. The pill
 * was previously inline INSIDE .line-name and got clipped by its
 * overflow:hidden + text-overflow:ellipsis. Lifting the pill to a
 * flex-sibling lets line-name keep its ellipsis behavior on long titles
 * while the pill stays fully visible (flex-shrink:0). Added 2026-05-03
 * after user screenshot of "Plush Pepe (Pumpkin) [clipped pill]". */
.line-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.line-name-row .line-name {
  min-width: 0;
  flex: 1 1 auto;
}

.line-count {
  font-size: 12px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  font-weight: 500;
}

.line-right {
  text-align: right;
  flex-shrink: 0;
  margin-left: 12px;
}

.line-floor {
  font-size: 15px;
  font-weight: 700;
  color: var(--tg-theme-text-color, var(--tg-text));
}

.line-floor .star-sm {
  color: var(--gold);
  font-size: 14px;
}
/* ── Error State ── */
.error-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px;
  animation: fadeIn 0.4s ease-out;
}

.error-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--tg-destructive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  font-weight: 700;
  color: #ffffff;
}

.error-text {
  font-size: 16px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  text-align: center;
  line-height: 1.5;
}

.btn-retry {
  padding: 14px 40px;
  font-size: 15px;
  font-weight: 600;
  color: var(--tg-theme-button-text-color, #ffffff);
  background: var(--tg-theme-button-color, var(--tg-button));
  border: none;
  border-radius: 12px;
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}

.btn-retry:active {
  opacity: 0.8;
  transform: scale(0.96);
}

/* ── Pages ── */
.page.hidden {
  display: none !important;
}

.page {
  padding-bottom: 70px;
}

/* G1 — tab-enter motion. The nav handler (app.js) toggles `.hidden`, so a
 * page only matches `:not(.hidden)` the moment it becomes the active tab —
 * that's when the keyframe replays. In-page refreshes (renderPortfolio,
 * leaderboard polls) never touch `.hidden`, so they don't re-trigger it. */
@keyframes pageIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.page:not(.hidden) {
  animation: pageIn 0.26s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .page:not(.hidden) { animation: none; }
}

.page-title {
  font-size: 22px;
  font-weight: 700;
  padding: clamp(16px, 4vw, 24px) clamp(14px, 3.5vw, 24px) 4px;
}

.page-subtitle {
  font-size: 13px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  padding: 0 clamp(14px, 3.5vw, 24px) clamp(12px, 3vw, 20px);
}
/* Rainbow gradient title — Telegram-Premium-style multi-stop background
 * that we mask through the text via background-clip. The animation
 * (`premiumGradient`) is the same one already used on the Portfolio Value
 * card, so the two headers feel related. */
.page-title--inline {
  padding: 0;
  flex-shrink: 0;
  font-size: 26px;
  font-weight: 800;
  line-height: 1.15;
  background: linear-gradient(
    100deg,
    #ff6ba8 0%,    /* pink */
    #ff9d6b 18%,   /* orange */
    #ffd166 36%,   /* gold */
    #5fe39a 56%,   /* green */
    #5ec1ff 74%,   /* sky blue */
    #976fff 92%    /* purple */
  );
  background-size: 200% 200%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  color: transparent;
  animation: premiumGradient 8s ease infinite;
}

/* PC TG sidepanel — title was eating into search-row width on
 * mouse-driven environments, clipping placeholder. (pointer: fine)
 * targets PC desktop without affecting touch (phone). User feedback
 * 2026-05-03: «на пк сделай Leaderboard меньше». */
@media (pointer: fine) {
  .page-title--inline {
    font-size: 20px;
  }
}/* Inherit the same font as .page-subtitle so both halves of the row look
 * identical in size, weight, and colour. The grey is identical too — only
 * tabular-nums and right-alignment distinguish the timer visually. */
.leaderboard-refresh-hint {
  font-size: 13px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  padding: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
  flex-shrink: 0;
}

/* ── Bottom Nav ── */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  justify-content: space-around;
  /* Round 33-fix (2026-05-05) — top padding 12 -> 4. The earlier 12 px
   * left a visible empty band above the icons (user feedback: «много
   * пустого места»). Bottom padding stays large to clear iOS home bar. */
  padding: 4px 0 calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--tg-theme-bg-color, var(--tg-bg));
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: transform 0.18s ease-out;
  /* On mobile when the soft keyboard opens, `position:fixed; bottom:0`
   * gets pushed up by the visual viewport collapse — looks ugly perched
   * above the keyboard. Slide the nav off-screen while any input is focused
   * (body.keyboard-open class added by app.js focus/blur listeners). */
}

body.keyboard-open .bottom-nav {
  transform: translateY(110%);
  pointer-events: none;
}

.nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  /* flex:1 + min-width:0 lets every item take an equal share of the
   * row regardless of count. Was padding:6px 24px which fixed 240 px
   * just on padding for 5 items — Settings got clipped on narrow
   * Telegram WebView viewports (~360-380 px). The flex layout
   * scales gracefully from 4 to 5+ items. */
  flex: 1 1 0;
  min-width: 0;
  /* Round 33-fix — was padding: 6px 4px. The 6 px top stacked with
   * .bottom-nav's old 12 px to make a fat band above the icons. Tight
   * 2 px top + 4 px sides keeps icon + label glued without hugging the
   * neighbour buttons horizontally. */
  padding: 2px 4px;
  background: none;
  border: none;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  cursor: pointer;
  /* G4 — snappy press feedback: the whole pill dips on tap (transform is
   * cheap, no reflow) and springs back. Colour keeps its gentle 0.15s. */
  transition: color 0.15s, transform 0.08s ease;
}
.nav-item:active {
  transform: scale(0.92);
}

.nav-item.active {
  color: var(--tg-accent);
}
/* Round 32 (2026-05-05) — brand SVG icon system. Replaces emoji /
 * HTML-entity glyphs across nav, settings, modals. Icons live at
 * /assets/icons/<name>.svg (32 files, 32x32 viewBox, gradient-filled).
 * Loaded as <img> so each SVG document keeps its own gradient IDs
 * isolated (no url(#brand) collisions across files). The .gc-icon
 * variants are sizing presets — the SVGs themselves carry the colour. */
.gc-icon {
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  pointer-events: none;
  user-select: none;
}
.gc-icon--nav  { width: 28px; height: 28px; }
.gc-icon--row  { width: 20px; height: 20px; margin-right: 8px; }
.gc-icon--btn  { width: 18px; height: 18px; }
.gc-icon--sm   { width: 14px; height: 14px; }
.gc-icon--lg   { width: 24px; height: 24px; }

/* Round 32-fix (2026-05-05) — user feedback «слишком темные на bottom
 * line». The earlier grayscale(0.7) + opacity 0.55 combo darkened
 * inactive icons into near-black blobs on the dark TG bg. Drop
 * grayscale entirely (keep the brand-gradient hue), use a softer
 * opacity step, and bump brightness so even the inactive icon reads
 * cleanly against the navy app background. Active gets full brightness
 * + a tiny scale lift for emphasis. */
.nav-item .gc-icon--nav {
  filter: brightness(1.15) opacity(0.65);
  /* G4 — springy pop on the active tab's icon (slight overshoot curve). */
  transition: filter 0.15s, transform 0.2s cubic-bezier(0.2, 1.3, 0.4, 1);
}
.nav-item.active .gc-icon--nav {
  filter: brightness(1.25);
  transform: scale(1.12);
}
/* G4 — honour reduced-motion: drop the press dip and the icon's spring
 * transition. The active icon keeps its larger size (a static emphasis,
 * not motion), it just snaps instead of springing. */
@media (prefers-reduced-motion: reduce) {
  .nav-item:active { transform: none; }
  .nav-item .gc-icon--nav,
  .nav-item.active .gc-icon--nav { transition: filter 0.15s; }
}

/* Round 32 — context-specific tweaks for places that previously held
 * a Unicode emoji and now hold a brand SVG. Each rule overrides the
 * size or alignment that the parent button/title was sized around. */

/* Search button — make SVG fit the round button */
.search-btn .gc-icon {
  /* Round 67-fix2 (2026-05-06) — added crispness without changing
   * the icon's native blue→purple→pink gradient identity. User:
   * «иконка search всё равно сливается на голубом фоне». Two changes:
   *   1) size 18 → 22 px so the strokes are wider on screen
   *   2) drop-shadow outline so each stroke gets a 1 px dark halo,
   *      pulling the icon visually forward from the blue field
   * Stays in native gradient — purple/pink stand out, the blue
   * portion of the lupa now has contrast via the shadow ring. */
  width: 22px;
  height: 22px;
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55))
          drop-shadow(0 0 1px rgba(0, 0, 0, 0.35));
}

/* Rate (like / dislike) — small gap so the count sits next to the icon */
.rate-btn { display: inline-flex; align-items: center; gap: 4px; }
.rate-btn .gc-icon { width: 18px; height: 18px; }

/* Sort button caret arrow — sits to the right of the label */
.sort-btn-caret { margin-left: 4px; opacity: 0.65; transition: opacity 0.15s; }
.sort-btn.active .sort-btn-caret { opacity: 1; }

/* Modal close X — keep the icon centred inside the existing round
 * .modal-close button. Override the inherited big font-size that was
 * sized for the × glyph. */
.modal-close { display: inline-flex; align-items: center; justify-content: center; }
.modal-close .gc-icon { width: 18px; height: 18px; }

/* Active-filter clear (Home top filter pill × button) */
.active-filter-clear { display: inline-flex; align-items: center; justify-content: center; }
.active-filter-clear .gc-icon { width: 12px; height: 12px; }

/* Market header bits */
.market-title-icon { width: 28px; height: 28px; }
.market-promote-icon { width: 16px; height: 16px; margin-right: 4px; }
.market-empty-icon .gc-icon { width: 36px; height: 36px; opacity: 0.6; }
.market-mylistings-toggle { display: inline-flex; align-items: center; gap: 6px; }
.market-mylistings-toggle .gc-icon { width: 14px; height: 14px; }

/* Market search clear (× inside the right of the input row) */
.market-search-clear { display: inline-flex; align-items: center; justify-content: center; }
.market-search-clear .gc-icon { width: 14px; height: 14px; }

.nav-label {
  font-size: 11px;
  font-weight: 600;
  /* Truncate long labels rather than wrap — keeps the row at a fixed
   * height even on the narrowest viewport. The 5 current labels
   * (Home/Top/Market/Portfolio/Settings) all fit at 11 px easily,
   * but i18n strings like Russian "Портфолио" are tighter. */
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Leaderboard ── */
.leaderboard-list {
  padding: 0 clamp(12px, 3vw, 20px) 80px;
}

.lb-item {
  display: flex;
  align-items: center;
  padding: 12px 14px;
  background: linear-gradient(90deg, rgba(46,166,255,0.16) 0%, rgba(46,166,255,0.09) 50%, rgba(46,166,255,0.04) 100%);
  border-left: 3px solid rgba(46,166,255,0.35);
  margin-bottom: 2px;
  gap: 12px;
  cursor: pointer;
  transition: opacity 0.15s, background 0.3s ease, border-color 0.3s ease;
}

.lb-item:first-child {
  border-radius: 12px 12px 0 0;
}

.lb-item:last-child {
  border-radius: 0 0 12px 12px;
  margin-bottom: 0;
}

.lb-item:only-child {
  border-radius: 12px;
}

.lb-item:active {
  opacity: 0.7;
}

/* Brand-new entry (under NEW_ENTRY_BADGE_SECONDS) — soft pink outline +
 * subtle inner glow so the row stands out without screaming. Animation
 * is a gentle pulse so fresh entries are easy to spot while scrolling. */
.lb-item--new {
  background: linear-gradient(90deg,
              rgba(255,180,210,0.18) 0%,
              rgba(255,180,210,0.10) 50%,
              rgba(255,180,210,0.05) 100%);
  border-left-color: rgba(255,130,190,0.70);
  box-shadow:
    inset 0 0 0 1px rgba(255,180,210,0.22),
    0 0 14px rgba(255,150,200,0.18);
  animation: lbNewPulse 3.2s ease-in-out infinite;
}

@keyframes lbNewPulse {
  0%, 100% { box-shadow: inset 0 0 0 1px rgba(255,180,210,0.20),
                        0 0 10px rgba(255,150,200,0.14); }
  50%      { box-shadow: inset 0 0 0 1px rgba(255,180,210,0.35),
                        0 0 20px rgba(255,150,200,0.28); }
}

.lb-new-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #fff;
  background: linear-gradient(135deg, #ff7fbf, #ff4d94);
  border-radius: 6px;
  text-transform: uppercase;
  vertical-align: middle;
  box-shadow: 0 1px 4px rgba(255,77,148,0.4);
}

/* ── Top-3 tier backgrounds ──
 * End stops were 0.05–0.06 alpha — practically invisible at the right
 * edge, which made the row look "muddy" because the dark page bg bled
 * through. Bumped end alphas to stay near the start (≈ 0.18–0.22) so the
 * tint reads uniformly across the whole row.
 *
 * #1 also moved away from the olive `#E6B84E` end colour to a cleaner
 * champagne luxury gold (#E5C36F-ish) — same palette as the Group view's
 * gold tile, so #1 reads consistently across both surfaces. */
/* Round 41-fix (2026-05-05) — Top-3 rows redone per design spec.
 * Reference SVGs (leaderboard-rank-N) were drawn for a 72 px tall row;
 * row was previously ~50-60 px so the bright SVG bg was getting clipped
 * top + bottom (user feedback: «бекдропы не на весь блок растянуты,
 * сверху и снизу темное пространство»). Fix:
 *   1. min-height 72 px so the row matches the design's vertical box.
 *   2. background-size 100% 100% stretches SVG to fully cover the row.
 *   3. border-radius 12 px on every top-3 row (not just first-child) +
 *      overflow:hidden so the SVG clips cleanly to the row's corners.
 *   4. Margin-bottom 6 px (was 2) — separates the bright tier rows
 *      visually so they don't merge into one block.
 *   5. Drop border-left/box-shadow — SVG carries every visual cue. */
/* Round 46 (2026-05-05) — Top-3 backgrounds now ship as inline CSS
 * gradients (radial highlight overlay + 105° linear ramp) instead of
 * SVG files. Per design system spec: scales perfectly on every device
 * (no iOS Safari stretching quirks), ~200 bytes vs 1KB SVG, gradient
 * angle stays consistent because the browser computes fresh per element.
 * Border-left dropped (gradient is full-bleed). Ink text colours per
 * tier so name/value read against the bright bg. */
.lb-item[data-rank="1"] {
  background:
    radial-gradient(140% 100% at 90% 110%, rgba(255,255,255,0.18), transparent 55%),
    linear-gradient(105deg,
      #FFE89B 0%,
      #FFCC4D 28%,
      #E89A1A 58%,
      #C97A0E 82%,
      #FFB733 100%);
  border-left: 0;
}
.lb-item[data-rank="2"] {
  background:
    radial-gradient(140% 100% at 90% 110%, rgba(255,255,255,0.18), transparent 55%),
    linear-gradient(105deg,
      #F5F9FF 0%,
      #C8D6E8 28%,
      #8FA3BF 58%,
      #6B7E9A 82%,
      #B8C8DC 100%);
  border-left: 0;
}
.lb-item[data-rank="3"] {
  background:
    radial-gradient(140% 100% at 90% 110%, rgba(255,255,255,0.18), transparent 55%),
    linear-gradient(105deg,
      #FFC9A8 0%,
      #F08C57 28%,
      #C9612C 58%,
      #9B431A 82%,
      #DD7A45 100%);
  border-left: 0;
}

/* Round 47 (2026-05-05) — text on top-3 matches rank 4+ exactly per
 * user feedback: «make for the top1,2,3 text as others in top 100».
 * Drop the per-tier ink colour, use white throughout. Add text-shadow
 * so the white reads cleanly against the bright tier gradient. */
.lb-item[data-rank="1"],
.lb-item[data-rank="2"],
.lb-item[data-rank="3"] {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}

.lb-rank {
  width: 28px;
  font-size: 16px;
  font-weight: 700;
  text-align: center;
  flex-shrink: 0;
  color: var(--tg-accent);
}

/* Round 51 (2026-05-05) — rank 4-100 polish per design spec.
 * Goal: rows feel like they belong to the same jewellery box as the
 * gold/platinum/copper medals — refined, depth, blue-toned — without
 * ever competing with the medal tiers. Five layers:
 *   1. 3-stop vertical gradient bg (top edge catches light, bottom recedes)
 *   2. Blue foil sheen ::after at 118° (same DNA as medal sheens, ×4 dimmer)
 *   3. Inset hairline highlight on top edge (rgba(140,180,255,0.06))
 *   4. Cool-blue gradient text on the rank numeral + drop-shadow
 *   5. Avatar inset highlight + soft drop shadow */
.lb-item[data-rank]:not([data-rank="1"]):not([data-rank="2"]):not([data-rank="3"]) {
  background: linear-gradient(180deg,
    rgba(46, 60, 80, 0.78) 0%,
    rgba(33, 44, 60, 0.78) 50%,
    rgba(26, 36, 52, 0.82) 100%);
  box-shadow: inset 0 1px 0 rgba(140, 180, 255, 0.06);
  position: relative;
}
.lb-item[data-rank]:not([data-rank="1"]):not([data-rank="2"]):not([data-rank="3"])::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(118deg,
    rgba(140, 180, 255, 0) 30%,
    rgba(140, 180, 255, 0.05) 48%,
    rgba(140, 180, 255, 0) 60%);
  mix-blend-mode: overlay;
  z-index: 0;
}
.lb-item[data-rank]:not([data-rank="1"]):not([data-rank="2"]):not([data-rank="3"]) > * {
  position: relative;
  z-index: 1;
}
/* Cool-blue gradient text on rank 4-100 numerals (medal echo). */
.lb-item[data-rank]:not([data-rank="1"]):not([data-rank="2"]):not([data-rank="3"]) .lb-rank {
  background: linear-gradient(180deg, #8FB4E8 0%, #5E89C4 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 1px 2px rgba(51, 115, 199, 0.35));
}
/* Round 51-fix (2026-05-05) — avatar inset highlight + drop shadow
 * removed per user feedback: «remove this small backgrounds on gifts».
 * The drop-shadow created a visible dark square behind the gift image,
 * making each avatar look like it had a fake background plate. Avatars
 * now sit directly on the row bg, same as top-3. */

/* Round 45 (2026-05-05) — top-3 text now matches rank 4+ exactly per
 * user feedback: «поправь текст на топ 1,2,3, сделай как у остальных».
 * Removed tinted rank glow + gradient text-clip + tier-coloured stars.
 * The rank number, name, stars value all use the standard recipe so
 * the only difference between top-3 and rank 4+ stays the bg gradient. */
.lb-rank-1,
.lb-rank-2,
.lb-rank-3 {
  /* Inherit the .lb-rank base color (var(--tg-accent) = blue) and drop
   * the tier-tinted glow shadow. */
  color: var(--tg-accent);
  text-shadow: none;
}
.lb-item[data-rank="1"] .lb-stars,
.lb-item[data-rank="2"] .lb-stars,
.lb-item[data-rank="3"] .lb-stars {
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  -webkit-text-fill-color: initial;
  /* `inherit` picks up the same colour as rank 4+ rows (TG theme text,
   * usually #F5F5F5) so top-3 looks identical to the rest. */
  color: inherit;
  filter: none;
  text-shadow: none;
}

.lb-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--tg-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}

.lb-avatar-img {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  object-fit: cover;
  flex-shrink: 0;
  /* No mix-blend-mode — `lighten` was erasing dark interior pixels of the
   * gift icon on every row (worst on tinted top-3, but visible on dark
   * default rows too once compared side-by-side). Render icons natively. */
}

.lb-info {
  flex: 1;
  min-width: 0;
}

.lb-name {
  font-size: 14px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 0.1px;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.lb-name-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.lb-name .lb-new-badge {
  flex-shrink: 0;
}

.lb-gifts {
  font-size: 11px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.42);
  letter-spacing: 0.1px;
  /* Round 42 (2026-05-05) — never wrap «@username · N gifts» onto a
   * 2nd line. Top-3 rows had bigger right-column values (8-digit stars
   * + USD), squeezing the left side enough that "gifts" wrapped down,
   * making top-3 rows visually taller than rank 4+. nowrap+ellipsis
   * keeps every row exactly 60 px regardless of name/count length. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lb-value {
  text-align: right;
  flex-shrink: 0;
}/* Round 47 — secondary text inherits from base .lb-gifts/.lb-ton
 * (rgba(255,255,255,0.42)) so top-3 looks identical to rank 4+. */

/* Round 64 (2026-05-05) — Round 47's "secondary text matches rank 4+"
 * worked for the dark rank-4+ bg but left @username and USD nearly
 * invisible on the bright gold/silver/bronze top-3 medals (42 % white
 * on a near-white bg → no contrast). User feedback: «текст плохо видно
 * на топ 1,2,3 что-то произошло». Bump opacity + add the same drop-
 * shadow already applied to .lb-name on top-3 (Round 47, line 2165) —
 * keeps "white throughout" but makes secondary text actually legible
 * against the medal gradients. Rank 4+ untouched. */
.lb-item[data-rank="1"] .lb-gifts,
.lb-item[data-rank="2"] .lb-gifts,
.lb-item[data-rank="3"] .lb-gifts,
.lb-item[data-rank="1"] .lb-ton,
.lb-item[data-rank="2"] .lb-ton,
.lb-item[data-rank="3"] .lb-ton {
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}

/* ── Settings ── */
.settings-list {
  padding: clamp(12px, 3vw, 20px);
}

.settings-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: clamp(11px, 2.6vw, 16px) clamp(12px, 3vw, 20px);
  background: var(--tg-theme-secondary-bg-color, var(--tg-bg-secondary));
  margin-bottom: 2px;
}

.settings-item:first-child {
  border-radius: 12px 12px 0 0;
}

.settings-item:last-child {
  border-radius: 0 0 12px 12px;
  margin-bottom: 0;
}

.settings-link {
  cursor: pointer;
  transition: opacity 0.15s;
}

.settings-link:active {
  opacity: 0.7;
}

.settings-label {
  display: flex;
  align-items: center;
  font-size: 14px;
  font-weight: 500;
}
.settings-label .gc-icon {
  /* Brand icons sit on baseline through inline-flex; no extra margin
   * — the .gc-icon--row preset already adds 8 px right gap. */
  flex-shrink: 0;
}
.page-subtitle--section {
  display: flex;
  align-items: center;
}
.page-subtitle--section .gc-icon {
  flex-shrink: 0;
}

/* ── Settings header with inline TON Connect button ─────────────────── */
/* "Settings" title on the left, Connect Wallet button (rendered by
 * @tonconnect/ui into #ton-connect-root) on the right — uses the empty
 * space next to the title instead of a dedicated row. */
.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: clamp(16px, 4vw, 24px) clamp(12px, 3vw, 20px) clamp(6px, 1.5vw, 10px);
}

.page-title--inline-tc {
  padding: 0;
  flex-shrink: 0;
}

.settings-header #ton-connect-root {
  display: flex;
  justify-content: flex-end;
  flex-shrink: 0;
}

/* ── Top Contributors list on Settings page ─────────────────────────── */

.page-subtitle--section {
  margin: 20px 16px 2px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--tg-theme-text-color, #fff);
  opacity: 0.92;
}

.page-subtitle-hint {
  margin: 0 16px 10px;
  font-size: 12px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
}

.contributors-list {
  padding: 0 16px 16px;
  /* Reserve space for 3 rows so the section height is stable the moment
   * Settings is opened — prevents layout jumping as real data arrives. */
  min-height: 180px;
}

.contributors-loading, .contributors-empty {
  padding: 20px 16px;
  text-align: center;
  font-size: 13px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.5));
}

/* Skeleton rows shown while the contributors list is loading. Same height
 * as real .contrib-item rows so there's no jump when real data replaces
 * the skeleton. The subtle pulse hints "still loading" without blinking.  */
.contrib-skeleton {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  margin-bottom: 2px;
  animation: contribSkeletonPulse 1.8s ease-in-out infinite;
}
.contrib-skeleton:first-child { border-radius: 12px 12px 0 0; }
.contrib-skeleton:last-child  { border-radius: 0 0 12px 12px; margin-bottom: 0; }
.contrib-skeleton-rank, .contrib-skeleton-avatar, .contrib-skeleton-text {
  background: rgba(255,255,255,0.08);
  border-radius: 6px;
}
.contrib-skeleton-rank { width: 18px; height: 14px; flex-shrink: 0; }
.contrib-skeleton-avatar { width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; }
.contrib-skeleton-text { flex: 1; height: 14px; }

@keyframes contribSkeletonPulse {
  0%, 100% { opacity: 0.65; }
  50%      { opacity: 1.0;  }
}

/* G3 — generic list-loading skeleton (leaderboard, portfolio hydration).
 * Reuses contribSkeletonPulse so every skeleton in the app breathes on the
 * same cadence. Each row's height is set inline to match the real list it
 * stands in for, so data swapping in causes no layout jump. The staggered
 * per-row delay makes the column shimmer top-to-bottom instead of blinking
 * in unison — reads as "alive" rather than a frozen placeholder. */
.gc-skel-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}
.gc-skel-row {
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  animation: contribSkeletonPulse 1.8s ease-in-out infinite;
}
.gc-skel-row:nth-child(2)    { animation-delay: 0.12s; }
.gc-skel-row:nth-child(3)    { animation-delay: 0.24s; }
.gc-skel-row:nth-child(4)    { animation-delay: 0.36s; }
.gc-skel-row:nth-child(5)    { animation-delay: 0.48s; }
.gc-skel-row:nth-child(n+6)  { animation-delay: 0.60s; }
@media (prefers-reduced-motion: reduce) {
  .gc-skel-row { animation: none; }
}

.contrib-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--tg-theme-secondary-bg-color, rgba(255,255,255,0.04));
  margin-bottom: 2px;
}
.contrib-item:first-child { border-radius: 12px 12px 0 0; }
.contrib-item:last-child  { border-radius: 0 0 12px 12px; margin-bottom: 0; }
.contrib-item:only-child  { border-radius: 12px; }

.contrib-item--tappable {
  cursor: pointer;
  transition: opacity 0.15s;
}
.contrib-item--tappable:active { opacity: 0.7; }

.contrib-rank {
  width: 26px;
  text-align: center;
  font-weight: 700;
  font-size: 14px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
  flex-shrink: 0;
}
.contrib-rank--top {
  font-size: 18px;
}

.contrib-avatar-img, .contrib-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}

.contrib-info {
  flex: 1;
  min-width: 0;
}
.contrib-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--tg-theme-text-color, #fff);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.contrib-sub {
  font-size: 11px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
  margin-top: 2px;
}

.settings-value {
  font-size: 14px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}

.settings-select {
  padding: 6px 10px;
  font-size: 13px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--tg-theme-text-color, var(--tg-text));
  outline: none;
}

/* ── User Collections ── */
.collection-card {
  background: linear-gradient(135deg, rgba(151, 111, 255, 0.15), rgba(107, 147, 255, 0.10));
  border: 1px solid rgba(151, 111, 255, 0.15);
  border-radius: 14px;
  padding: 14px 10px;
  text-align: center;
  position: relative;
}
.collection-title {
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 2px;
}

.collection-gifts {
  font-size: 11px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}

.collection-count {
  position: absolute;
  top: 6px;
  right: 6px;
  background: var(--tg-accent);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 6px;
}

/* ── Empty state ── */
.empty-state {
  padding: 40px 16px;
  text-align: center;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  font-size: 15px;
}

/* ── Regular (non-collectible) gifts section ── */
.regular-section {
  padding-top: 4px;
  margin-bottom: 32px;
}

.regular-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 10px 20px 10px;
}

.regular-section-sub {
  font-size: 11px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.48);
  text-transform: none;
  letter-spacing: 0.2px;
}

.regular-list {
  padding: 0 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Single column mirrors the collectibles list — at typical phone widths the
 * old 2-column grid squeezed each cell to ~140 px, which forced gift titles
 * to truncate to "Li…" and the count×price line to wrap onto two lines. */
.regular-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 12px;
  min-width: 0;
}

.regular-item-clickable {
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease;
}

.regular-item-clickable:active {
  transform: scale(0.97);
  background: rgba(255, 255, 255, 0.07);
}

.regular-thumb {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
}

.regular-thumb--emoji {
  object-fit: contain;
  padding: 4px;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.18), rgba(46, 166, 255, 0.10));
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.modal-list-thumb--emoji {
  object-fit: contain;
  padding: 4px;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.18), rgba(46, 166, 255, 0.10));
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.modal-list-item-clickable {
  cursor: pointer;
  transition: background 0.15s ease;
}

.modal-list-item-clickable:active {
  background: rgba(255, 255, 255, 0.06);
}

.regular-emoji {
  font-size: 24px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.regular-left {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.regular-title {
  font-size: 14px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.25;
}

/* "LIMITED" pill — shown next to the title for upgradeable LE StarGifts */
.limited-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: #ffd166;
  background: rgba(255, 209, 102, 0.12);
  border: 1px solid rgba(255, 209, 102, 0.35);
  border-radius: 4px;
  vertical-align: middle;
  text-transform: uppercase;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
/* "⛓ ON-CHAIN" variant — violet tint so it reads as a distinct badge
 * next to LIMITED (gold). Used on rows backed by the TON wallet fetch,
 * NOT by the Telegram inventory. */
.limited-pill.onchain-pill {
  color: #b6a0ff;
  background: rgba(155, 120, 255, 0.14);
  border-color: rgba(155, 120, 255, 0.40);
}

.regular-sub {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  font-variant-numeric: tabular-nums;
  /* Keep "32 × 41,000 ⭐" on one row — it should never wrap */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

/* Round 114 (2026-05-09) — floor side-note inside .regular-sub. Tints
   the live-market price with the premium-purple accent so users
   distinguish «what they paid» (dim hint colour, default .regular-sub)
   from «what it's worth now» (purple, this rule). The leading "·"
   plus the small font keep it as a side-note rather than competing
   with the row's right-side aggregate. */
.regular-sub-floor {
  color: var(--premium-purple);
}

/* Round 114.1 (2026-05-09) — same purple accent for the floor sub-line
   inside the regular-gift modal's per-item stat cell. Top line stays
   in the default modal-stat-value colour (release/purchase price);
   floor sits below in 12 px purple so users can compare at a glance.
   `.modal-stat-floor-label` dims the «floor» literal so the number
   reads as the primary information. */
.modal-stat-floor {
  font-size: 12px;
  color: var(--premium-purple);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.modal-stat-floor-label {
  opacity: 0.7;
  font-weight: 400;
}

.regular-right {
  text-align: right;
  flex-shrink: 0;
  white-space: nowrap;
}

.regular-total {
  font-size: 14px;
  font-weight: 700;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
}
/* Directional tint on the PRIMARY (current floor / effective) value
 * — user wants to read gain/loss at a glance from the headline number,
 * not from the secondary release line beneath it. Applied in ui.js
 * (renderRegularGifts + openRegularListModal + renderGroupView) when
 * effective ≠ release. Gold-bright stays as the neutral default. */
.regular-total--up,
.modal-list-stars--up,
.group-value--up      { color: #5fe39a; }
.regular-total--down,
.modal-list-stars--down,
.group-value--down    { color: var(--tg-destructive); }
.regular-total-arrow,
.modal-list-stars-arrow,
.group-value-arrow    { font-weight: 700; margin-left: 2px; }

/* Secondary "now <floor>" line under the right-side release aggregate,
   per contracts/requests/render_limited_floor_stars.md (2026-05-16).
   Smaller font + dimmed default colour so the release total stays the
   primary visual anchor; directional arrow tints the line green when
   the floor is above the release price (gainer) and red when it's
   below (loser). Hidden entirely when backend has no floor for the
   line (markup omitted upstream in ui.js renderRegularGifts). */
.regular-floor-now {
  font-size: 11px;
  font-weight: 600;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
  white-space: nowrap;
}
.regular-floor-now-label {
  opacity: 0.7;
  font-weight: 400;
  margin-right: 1px;
}
.regular-floor-now-arrow {
  font-weight: 700;
  margin-left: 1px;
}
.regular-floor-now--up   { color: #5fe39a; }   /* gainer green, matches PnL up */
.regular-floor-now--down { color: var(--tg-destructive); }
.regular-floor-now--flat { color: var(--tg-hint); }

/* ── Modal Overlay ──
 * Lighter dim + stronger blur so the underlying portfolio is faintly
 * visible behind the semi-transparent modal card. Together they read
 * as "same surface, peeled forward" rather than "solid black sheet". */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 1000;
  animation: fadeIn 0.15s ease-out;
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  overscroll-behavior: contain;
  touch-action: none;
}

/* Round 29 (2026-05-04) — defensive scroll lock. Was only firing when
 * an opener explicitly added .modal-open; the Promote modal + Home
 * Models/Backdrops dropdown forgot, leaving the page scrollable behind
 * the overlay (user feedback: «при клике на promote listings я могу с
 * телефона и пк листать вкладку на фоне, убери это»). The :has()
 * selectors lock body scroll automatically as long as any modal-overlay
 * or dropdown-overlay is visible (i.e. doesn't carry .hidden). Modern
 * Telegram WebViews support :has(); the explicit .modal-open class
 * stays as a fallback for any context where :has() fails. */
body.modal-open,
body:has(.modal-overlay:not(.hidden)),
body:has(.dropdown-overlay:not(.hidden)) {
  overflow: hidden;
}

.modal-overlay.hidden {
  display: none !important;
}

/* ── Modal Card (slides up from bottom) ── */
@keyframes slideUp {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

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

.modal-card {
  width: 100%;
  max-width: 480px;
  /* Semi-transparent dark surface — combined with the overlay's backdrop-blur
   * the underlying page peeks through. ~85 % alpha keeps text fully legible.
   * Local backdrop-filter handles iOS Safari quirk where overlay blur doesn't
   * propagate to the card's compositing layer. */
  background: rgba(20, 22, 30, 0.78);
  -webkit-backdrop-filter: blur(28px) saturate(140%);
  backdrop-filter: blur(28px) saturate(140%);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 20px 20px 0 0;
  padding: 0 clamp(12px, 3vw, 20px) clamp(12px, 3vw, 20px);
  animation: slideUp 0.25s ease-out;
  max-height: 85vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  /* Round 115 (2026-05-09) — defense in depth for content-driven height.
     User-reported on a Limited Gift modal: card extended to ~85 vh while
     content (hero + title + stat-grid + USD) only filled ~40 % of it,
     leaving a tall purple-fading-to-dark gradient strip below the
     content. Root cause inferred from CSS audit: the parent
     .modal-overlay is `display: flex; align-items: flex-end;` and on
     some iOS Safari / TG WebView builds the child's default
     `align-self: auto` was resolving to `stretch` (which would fill the
     cross-axis up to the parent's height), instead of inheriting the
     parent's `flex-end`. `flex: 0 0 auto` pins the card's flex-basis to
     content size and blocks any implicit grow. `align-self: flex-end`
     restates the parent's alignment so a buggy `auto → stretch`
     resolution can't sneak through. `min-height: 0` defeats the
     min-content fallback some engines use when overflow:auto interacts
     with flex children. List/full-height modals opt back in via the
     explicit .modal-fullscreen class which sets height: 90vh. */
  flex: 0 0 auto;
  align-self: flex-end;
  min-height: 0;
}

.modal-card.closing {
  animation: slideDown 0.2s ease-in forwards;
}

/* ── Modal Card themed by value tier ──
 * Bottom half of each gradient was solid `--tg-theme-bg-color`; replaced
 * with the semi-transparent surface used on the default modal so themed
 * cards blend visually with the blurred overlay instead of looking
 * abruptly opaque at the fold line. */
.modal-card[data-tier="gold"] {
  background: linear-gradient(180deg, rgba(255,227,104,0.38) 0%, rgba(246,201,30,0.22) 25%, rgba(20,22,30,0.78) 55%);
  border-top: 2px solid #FFC940;
  box-shadow: inset 0 1px 0 rgba(255,243,176,0.38), 0 0 22px rgba(255,201,64,0.18);
}

.modal-card[data-tier="purple"] {
  background: linear-gradient(180deg, rgba(151,111,255,0.33) 0%, rgba(151,111,255,0.17) 25%, rgba(20,22,30,0.78) 55%);
  border-top: 2px solid rgba(151,111,255,0.60);
}

.modal-card[data-tier="blue"] {
  background: linear-gradient(180deg, rgba(46,166,255,0.27) 0%, rgba(46,166,255,0.15) 25%, rgba(20,22,30,0.78) 55%);
  border-top: 2px solid rgba(46,166,255,0.50);
}

.modal-card[data-tier="common"] {
  background: linear-gradient(180deg, rgba(106,179,243,0.19) 0%, rgba(106,179,243,0.11) 25%, rgba(20,22,30,0.78) 55%);
  border-top: 2px solid rgba(106,179,243,0.40);
}

/* ── Modal stat cards themed ── */
.modal-card[data-tier="gold"] .modal-stat {
  background: linear-gradient(135deg, rgba(255,184,0,0.32), rgba(229,161,0,0.18));
  border: 1px solid rgba(255,202,40,0.50);
}

.modal-card[data-tier="purple"] .modal-stat {
  background: linear-gradient(135deg, rgba(151,111,255,0.33), rgba(151,111,255,0.17));
  border: 1px solid rgba(151,111,255,0.40);
}

.modal-card[data-tier="blue"] .modal-stat {
  background: linear-gradient(135deg, rgba(46,166,255,0.27), rgba(46,166,255,0.15));
  border: 1px solid rgba(46,166,255,0.35);
}

.modal-card[data-tier="common"] .modal-stat {
  background: linear-gradient(135deg, rgba(106,179,243,0.19), rgba(106,179,243,0.11));
  border: 1px solid rgba(106,179,243,0.30);
}

/* ── Modal Close Button ──
 * Anchored to the top-right of the overlay (not the card), so it floats
 * in the dimmed/blurred area ABOVE the card instead of clipping against
 * the card's rounded corner or its inner scroll box. The overlay has
 * display:flex with align-items:flex-end; using position:absolute takes
 * the close button out of that flow so the card still hugs the bottom. */
.modal-close {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  right: 12px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(20, 22, 30, 0.72);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
  color: #ffffff;
  font-size: 22px;
  font-weight: 500;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.15s, transform 0.1s;
  z-index: 10;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}

.modal-close:active {
  opacity: 0.65;
  transform: scale(0.93);
}

/* ── Modal Hero Image ── */
.modal-hero {
  display: flex;
  justify-content: center;
  padding: 16px 0 8px;
}

.modal-hero-img {
  width: 80px;
  height: 80px;
  border-radius: 18px;
  object-fit: cover;
  background: transparent;
  position: relative;
  z-index: 1;
}

/* Telegram-style layered hero card: radial backdrop gradient + tiled
 * tinted symbol pattern + model thumb on top. Wrapper is slightly
 * larger than the IMG so the gradient + pattern frame the model on
 * all four sides — same proportion the TG client uses on its gift
 * detail page. Inactive state (no .gift-card-layered) leaves the IMG
 * sitting bare so the modal looks identical to the pre-2026-05-04
 * render when the manifests fail to load. See applyCardLayers() in
 * ui.js + contracts/api_market_assets.md. */
.modal-hero-card {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 18px;
  overflow: hidden;
}
.modal-hero-card.gift-card-layered {
  background: radial-gradient(circle at 50% 35%,
              var(--bg-center) 0%,
              var(--bg-edge)   100%);
}
.modal-hero-card.gift-card-layered::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--bg-pattern);
  -webkit-mask-image: var(--symbol-url);
          mask-image: var(--symbol-url);
  -webkit-mask-repeat: repeat;
          mask-repeat: repeat;
  -webkit-mask-size: 36px 36px;
          mask-size: 36px 36px;
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}
/* Browsers without mask-image support (rare in modern TG WebView): the
 * pseudo above renders as a flat color square because mask-* is ignored.
 * The --with-symbol gate keeps the pseudo from appearing until JS
 * confirmed a symbol file actually exists in the manifest, so non-symbol
 * cards stay clean instead of getting a coloured rectangle overlay. */
.modal-hero-card.gift-card-layered:not(.gift-card-layered--with-symbol)::before {
  display: none;
}

/* ── Modal Collection & Model ── */
.modal-collection {
  text-align: center;
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 2px;
}

.modal-model {
  text-align: center;
  font-size: 13px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  margin-bottom: 10px;
}

/* ── Modal Body ── */
.modal-body {
  padding: 10px 0;
}

/* Round 62 (2026-05-05) — list-mode modal (Portfolio Value, unique,
 * limited, Portfolio breakdown) reuses the same modal card chassis as
 * the single-gift modal but rebuilds .modal-body content. The hero
 * card (80×80 px), collection name, model name and Telegram button
 * still render as empty/hidden inline elements above the rebuilt body
 * — that produced ~157 px of unused vertical space at the top. Class
 * `.modal-list-mode` collapses every part of the chassis that doesn't
 * belong on a list view, plus zeroes the body's top padding so the
 * actual content (title + list) starts right under the close button.
 *
 * User feedback: «в "Portfolio Value ›" и в "unique ›" при открытии
 * у нас много пустого пространства on the top of opened page,
 * неиспользуемого пространства, убери его».
 *
 * restoreModalBody() removes this class so a subsequent single-gift
 * modal renders the hero/collection/model again. */
.modal-card.modal-list-mode .modal-hero,
.modal-card.modal-list-mode .modal-collection,
.modal-card.modal-list-mode .modal-model,
.modal-card.modal-list-mode > #modal-tg-btn {
  display: none !important;
}
.modal-card.modal-list-mode .modal-body {
  padding-top: 0;
}

.modal-stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.modal-stat {
  background: var(--tg-theme-secondary-bg-color, var(--tg-bg-secondary));
  border-radius: 12px;
  padding: 10px;
  text-align: center;
}

.modal-stat-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}

.modal-stat-value {
  font-size: 16px;
  font-weight: 700;
}

.modal-usd {
  text-align: center;
  margin-top: 8px;
  font-size: 20px;
  font-weight: 700;
}

.modal-card[data-tier="gold"] .modal-usd { color: var(--gold-bright); text-shadow: 0 0 18px rgba(255,184,0,0.7); }
.modal-card[data-tier="purple"] .modal-usd { color: var(--premium-purple); }
.modal-card[data-tier="blue"] .modal-usd { color: var(--tg-accent); }
.modal-card[data-tier="common"] .modal-usd { color: var(--tg-theme-text-color, var(--tg-text)); }

/* ── Modal Button ── */
.modal-btn {
  display: block;
  width: 100%;
  padding: 14px;
  font-size: 15px;
  font-weight: 600;
  color: var(--tg-theme-button-text-color, #ffffff);
  background: var(--tg-theme-button-color, var(--tg-button));
  border: none;
  border-radius: 12px;
  cursor: pointer;
  text-align: center;
  transition: opacity 0.15s;
}

.modal-btn:active {
  opacity: 0.8;
}

/* ── Modal Gift Items List ── */
.modal-gift-items {
  max-height: 200px;
  overflow-y: auto;
  border-radius: 14px;
  margin-bottom: 12px;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.modal-gift-item {
  display: flex;
  align-items: center;
  padding: 12px 14px;
  text-decoration: none;
  color: inherit;
  margin-bottom: 2px;
  border-radius: 0;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}

.modal-card[data-tier="gold"] .modal-gift-item {
  background: linear-gradient(90deg, rgba(255,184,0,0.32) 0%, rgba(229,161,0,0.18) 50%, rgba(255,184,0,0.08) 100%);
  border-left: 3px solid var(--gold);
}
.modal-card[data-tier="purple"] .modal-gift-item {
  background: linear-gradient(90deg, rgba(151,111,255,0.33) 0%, rgba(151,111,255,0.17) 50%, rgba(151,111,255,0.10) 100%);
  border-left: 3px solid var(--premium-purple);
}
.modal-card[data-tier="blue"] .modal-gift-item {
  background: linear-gradient(90deg, rgba(46,166,255,0.27) 0%, rgba(46,166,255,0.15) 50%, rgba(46,166,255,0.09) 100%);
  border-left: 3px solid var(--tg-accent);
}
.modal-card[data-tier="common"] .modal-gift-item {
  background: linear-gradient(90deg, rgba(106,179,243,0.19) 0%, rgba(106,179,243,0.11) 50%, rgba(106,179,243,0.07) 100%);
  border-left: 3px solid rgba(106,179,243,0.40);
}

.modal-gift-item:first-child { border-radius: 12px 12px 0 0; }
.modal-gift-item:last-child { border-radius: 0 0 12px 12px; margin-bottom: 0; }
.modal-gift-item:only-child { border-radius: 12px; }
.modal-gift-item:active { opacity: 0.7; transform: scale(0.98); }

.mgi-number {
  font-size: 13px;
  font-weight: 700;
  color: var(--tg-accent);
  min-width: 70px;
}

.mgi-backdrop {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  padding-left: 4px;
}

.mgi-stars {
  font-size: 13px;
  font-weight: 700;
  margin-right: 6px;
}

.mgi-arrow {
  font-size: 18px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  opacity: 0.5;
}

/* ── ON SALE pill family — shared visual vocabulary ──
 * Bright red text on subtle red-tinted background. Placement rules:
 *   • .pf-sale-pill — Portfolio tab gift sheet (per-NFT list)
 *   • .mgi-sale-pill — Home gift modal items list (per-NFT list)
 *   • .flat-sale-pill — Home # / Price / Group renderers:
 *     - in Price-sort / Group-sort row: attached to .line-count
 *       (next to "N gifts" counter) so the pill reads "N gifts  ON SALE"
 *       making it clear the group has listed items
 *     - in # sort flat row: attached next to the #N number
 *
 * All three share the same red-accent look so users learn the signal
 * once and recognise it everywhere.
 */
.mgi-sale-pill,
.flat-sale-pill,
.pf-sale-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgba(232, 75, 75, 0.14);
  color: #ff5a5a;                      /* bright red text, readable on dark bg */
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  vertical-align: middle;
  line-height: 1.45;
  border: 1px solid rgba(232, 75, 75, 0.38);
}
.flat-sale-pill { font-size: 9px; padding: 0 6px; }

/* Phase B2 portfolio_chip surface (2026-05-13) — Boost CTA chip rendered
   next to the SALE pill on the user's own active marketplace listings
   in the per-model gifts sheet. Visually echoes .pf-sale-pill (same
   size + radius + uppercase) so the two read as a coherent badge pair,
   but uses the Telegram accent blue family to signal "action" vs the
   pill's red "status" color. Button-element (not span) so it's keyboard-
   accessible and gets the right :active feedback on tap. */
.pf-boost-chip {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  height: auto;
  border-radius: 999px;
  background: rgba(46, 166, 255, 0.16);
  color: #2ea6ff;                       /* matches accent blue used in CTAs */
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  vertical-align: middle;
  line-height: 1.55;
  border: 1px solid rgba(46, 166, 255, 0.44);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 120ms ease, transform 80ms ease;
}
.pf-boost-chip:hover { background: rgba(46, 166, 255, 0.24); }
.pf-boost-chip:active { transform: scale(0.96); background: rgba(46, 166, 255, 0.28); }

/* Phase C1 (2026-05-13) — `.market-promoted-badge` ("📌 BOOSTED · Xh"
   ribbon) was REMOVED 2026-05-14 per user request. The gold halo
   below (.market-row--top, applied by `_renderGiftCard` when
   gift.is_promoted is truthy) is now the only paid-promotion signal
   in the Market card. The `position: relative;` anchor is kept on
   .market-row--top in case a future surface needs a positioning
   context inside the promoted card. */
.line-item.market-row--top { position: relative; }

/* Phase C3 (2026-05-13) — live social-proof header line in the
   Promote modal. Renders only when >= 3 sellers boosted in last 24h
   (suppressed below threshold to avoid an anti-signal). Warm gold
   accent (same hue family as .market-row--top's halo) for visual
   coherence. */
.market-promote-social-proof {
  margin: 6px 0 -4px;                  /* tightens against the title above */
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: #ffce6b;                       /* warm gold accent (same family as market-row--top halo) */
  letter-spacing: 0.2px;
  text-shadow: 0 0 6px rgba(0, 0, 0, 0.35);
}

/* Phase D2 (2026-05-13) — 3-pack purchase button. Distinct visual
   from the single-promote buttons (warmer accent palette) to read
   as a "bundle deal" rather than another single boost. */
.market-promote-pack3-btn {
  display: block;
  width: 100%;
  margin: 6px 0 2px;
  padding: 12px 16px;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(255,180,80,0.18) 0%, rgba(255,140,60,0.16) 100%);
  color: #ffce6b;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.15px;
  border: 1px solid rgba(255, 180, 80, 0.42);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 120ms ease, transform 80ms ease;
}
.market-promote-pack3-btn:hover {
  background: linear-gradient(180deg, rgba(255,180,80,0.24) 0%, rgba(255,140,60,0.22) 100%);
}
.market-promote-pack3-btn:active {
  transform: scale(0.985);
  background: linear-gradient(180deg, rgba(255,180,80,0.30) 0%, rgba(255,140,60,0.28) 100%);
}
.market-promote-pack3-credits {
  margin-top: 6px;
  text-align: center;
  font-size: 11px;
  color: rgba(255, 206, 107, 0.78);
}
/* Hide pack3 section in single-confirm modal mode (chip surface) —
   single-confirm renders one specific listing only; pack3 broad-scope
   buying doesn't make sense in that focused flow. */
.market-promote-modal-card--single .market-promote-section--pack3 {
  display: none;
}
/* Optional fraction badge inside the group pill — dims the N/M
 * slightly so the main "ON SALE" reads first. */
.flat-sale-count {
  font-weight: 600;
  opacity: 0.78;
  font-size: 0.9em;
  margin-left: 2px;
  letter-spacing: 0.2px;
}

/* ── Fullscreen modal (Total view) ── */
.modal-fullscreen {
  max-height: 90vh;
  height: 90vh;
  display: flex;
  flex-direction: column;
}

.modal-fullscreen .modal-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 0;
}

.total-modal-title {
  font-size: 11px;
  font-weight: 500;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  text-align: center;
  padding: 4px 0 6px;
  flex-shrink: 0;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.55;
}

/* ── Portfolio value history chart (inside the breakdown modal) ──
 * Designed to keep the whole Value-over-time + breakdown view under a
 * single phone viewport height — tight padding, compact chart, no
 * "Portfolio breakdown" label duplicate. */
/* Modal "Value over time" card. Refreshed in 252z to match the
 * Portfolio palette: blue tinted glass background, larger inner
 * padding, more breathing room around axis labels. */
.pv-history {
  margin: 4px -4px 14px;
  padding: 14px 12px 10px;
  background: linear-gradient(135deg,
    rgba(106, 179, 243, 0.10) 0%,
    rgba(106, 179, 243, 0.04) 60%,
    rgba(106, 179, 243, 0.02) 100%);
  border: 1px solid rgba(106, 179, 243, 0.22);
  border-radius: 14px;
  box-shadow: 0 1px 12px rgba(106, 179, 243, 0.08);
}
.pv-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.pv-history-title {
  font-size: 11px;
  font-weight: 600;
  color: rgba(255,255,255,0.6);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.pv-history-ranges {
  display: flex;
  gap: 4px;
  background: rgba(255,255,255,0.04);
  padding: 3px;
  border-radius: 999px;
}
.pv-range-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: rgba(255,255,255,0.55);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 4px 9px;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease;
}
.pv-range-btn:active { background: rgba(255,255,255,0.06); }
.pv-range-btn--active {
  background: rgba(106, 179, 243, 0.22);
  color: #6ab3f3;
}

/* Free-tier lock state — Pro-gated ranges (30d / 90d / all) for users
 * without an active subscription. Padlock prefix tells them "this is
 * gated"; tap is intercepted by ui.js to open the Pro subscription
 * sheet instead of firing a fetch the backend would cap to 7 d anyway. */
.pv-range-btn--locked {
  color: rgba(255,255,255,0.3);
  opacity: 0.85;
}
.pv-range-btn--locked::before {
  content: "\01F512";  /* 🔒 */
  font-size: 9px;
  margin-right: 3px;
  vertical-align: 1px;
}
.pv-range-btn--locked:active {
  background: transparent;
}

/* ── Inline portfolio history chart on the Portfolio tab ───────────────────
 * Hidden behind a "Chart" toggle button by default. Tapping the toggle
 * expands a big interactive card with multi-tick Y axis, dated X axis,
 * touch crosshair + tooltip, and a linear/log scale switch.
 * Tapping the chart body NO LONGER opens the breakdown modal — all
 * interactions stay inline. */

/* Legacy "Chart" toggle button — retired 2026-05-15 when the hero
 * (#portfolioHero) became the tap-to-expand affordance. JS sets
 * `toggle.hidden = true` in _pfChartMount, but the `hidden` attribute
 * loses to `display: flex` below — hence the explicit override. The
 * DOM element stays for backward-compat (any stray reference is a
 * no-op against an invisible button) and the rest of the styling is
 * preserved in case the surface is ever re-enabled. */
.pf-history-toggle[hidden] { display: none !important; }

.pf-history-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: calc(100% - 32px);
  margin: 0 16px 12px;
  padding: 12px 16px;
  appearance: none;
  /* Same blue gradient as the Portfolio Value totals card on Home so
   * the chart sits inside the Portfolio palette per user direction. */
  background: linear-gradient(135deg,
    rgba(106, 179, 243, 0.22) 0%,
    rgba(106, 179, 243, 0.10) 100%);
  border: 1px solid rgba(106, 179, 243, 0.32);
  border-radius: 14px;
  color: #6ab3f3;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, transform 0.05s ease;
  box-shadow: 0 1px 12px rgba(106, 179, 243, 0.10);
}
.pf-history-toggle:active {
  background: linear-gradient(135deg,
    rgba(106, 179, 243, 0.32) 0%,
    rgba(106, 179, 243, 0.16) 100%);
  transform: scale(0.99);
}
.pf-history-toggle-icon {
  font-size: 18px;
  line-height: 1;
}
.pf-history-toggle-label { flex: 1; text-align: left; }
.pf-history-toggle-arrow {
  color: rgba(106, 179, 243, 0.7);
  font-size: 14px;
  transition: transform 0.2s ease;
}
.pf-history-toggle--open .pf-history-toggle-arrow { transform: rotate(180deg); }

.pf-history {
  margin: 0 16px 14px;
  padding: 14px 14px 10px;
  /* Match the Portfolio Value card's deep-blue tinted glass look so
   * inline chart and Home totals card feel like a set. */
  background: linear-gradient(135deg,
    rgba(106, 179, 243, 0.10) 0%,
    rgba(106, 179, 243, 0.04) 60%,
    rgba(106, 179, 243, 0.02) 100%);
  border: 1px solid rgba(106, 179, 243, 0.22);
  border-radius: 14px;
  -webkit-tap-highlight-color: transparent;
  position: relative;
}

.pf-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}
.pf-history-title {
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.02em;
  margin-right: auto;
}
.pf-history-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.pf-history-ranges {
  display: flex;
  gap: 2px;
}
.pf-range-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.55);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 4px 8px;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease;
}
.pf-range-btn:active { background: rgba(106, 179, 243, 0.12); }
.pf-range-btn--active {
  background: rgba(106, 179, 243, 0.22);
  color: #6ab3f3;
}
.pf-range-btn--locked {
  color: rgba(255, 255, 255, 0.3);
  opacity: 0.85;
}
.pf-range-btn--locked::before {
  content: "\01F512";  /* 🔒 */
  font-size: 9px;
  margin-right: 3px;
  vertical-align: 1px;
}
.pf-range-btn--locked:active { background: transparent; }

.pf-scale-btn {
  appearance: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: transparent;
  color: rgba(255, 255, 255, 0.7);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease;
}
.pf-scale-btn:active { background: rgba(255, 255, 255, 0.06); }
.pf-scale-btn[data-scale="log"] {
  color: #6ab3f3;
  border-color: rgba(106, 179, 243, 0.4);
}

.pf-history-body {
  position: relative;
  /* Bumped 220 → 320 to host the unified gc-chart layout
   * (stats strip + 300px SVG + reset row). User direction (1.5.3):
   * «расстяни вниз — слишком сжатый, куча пустого места». */
  min-height: 320px;
  user-select: none;
}
.pf-history-svg {
  width: 100%;
  height: 300px;
  display: block;
  cursor: crosshair;
}
.pf-history-skeleton {
  height: 320px;
  border-radius: 8px;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0.04) 0%,
    rgba(255, 255, 255, 0.08) 50%,
    rgba(255, 255, 255, 0.04) 100%);
  background-size: 200% 100%;
  animation: pfHistShimmer 1.4s linear infinite;
}
@keyframes pfHistShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pf-history-skeleton { animation: none; }
}
.pf-history-empty {
  height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  text-align: center;
  padding: 0 12px;
}

.pf-history-tooltip {
  position: absolute;
  display: none;
  pointer-events: none;
  top: 0;
  background: rgba(20, 28, 40, 0.96);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 6px 9px;
  font-size: 11px;
  line-height: 1.35;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(6px);
  z-index: 10;
}
.pf-history-tooltip .pf-tip-date {
  color: rgba(255, 255, 255, 0.55);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.02em;
}
.pf-history-tooltip .pf-tip-value {
  color: #fff;
  font-weight: 700;
  margin-top: 1px;
}
.pf-history-tooltip .pf-tip-meta {
  color: rgba(255, 255, 255, 0.55);
  font-size: 10px;
  margin-top: 1px;
}
.pv-history-body {
  position: relative;
  /* Bumped 240 → 320 — same change as the inline Portfolio chart so
   * both surfaces host the new gc-chart layout (stats strip + 300px
   * SVG + reset row) at exactly the same height. */
  min-height: 320px;
  /* No text-selection on the chart area — prevents the drag-to-pan
   * gesture from accidentally selecting axis labels on desktop. */
  user-select: none;
  -webkit-user-select: none;
}
.pv-history-svg { height: 300px; }
.pv-history-loading,
.pv-history-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 320px;
  color: rgba(255,255,255,0.5);
  font-size: 13px;
}
.pv-history-stats {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.pv-history-current {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
}
.pv-history-delta {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.pv-history-delta--up      { color: #8be247; }
.pv-history-delta--down    { color: #ff5971; }
.pv-history-delta--neutral { color: rgba(255,255,255,0.65); }
.pv-history-svg {
  width: 100%;
  height: 120px;   /* compact — fits chart + breakdown inside one viewport */
  display: block;
  touch-action: pan-y;   /* allow vertical page scroll past the chart */
  cursor: crosshair;
}
.pv-history-axis {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 10px;
  color: rgba(255,255,255,0.45);
  margin-top: 4px;
  letter-spacing: 0.02em;
  gap: 6px;
}
/* "Reset zoom" button appears in the middle of the x-axis label row
 * only when the user has zoomed. Tight pill so it doesn't shove the
 * date labels out of the padded area. */
.pv-history-reset-btn {
  appearance: none;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.14);
  color: #fff;
  padding: 2px 8px;
  font-size: 10px;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  margin-left: 4px;
}
.pv-history-reset-btn:active { opacity: 0.65; }

/* ── Unified portfolio-history chart (gc-chart-*) ─────────────────────
 * Both the modal Portfolio Value chart AND the inline Portfolio→Chart
 * card render via window.gcRenderHistoryChart (chart.js). These rules
 * style the shared DOM produced there. User direction (1.5.3): the two
 * charts must look + feel identical, only the data source differs.
 * Surrounding card chrome (title, range buttons, container) lives in
 * its own .pv-history-* / .pf-history-* class on each card. */

.gc-chart-svg {
  width: 100%;
  height: 300px;
  display: block;
  cursor: crosshair;
  /* Without an explicit touch-action the browser hijacks 1-finger
   * gestures for page panning, breaking the scrub crosshair. `none`
   * gives the JS handler full control. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

.gc-chart-stats {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
  /* Sit flush with the SVG below — no extra top padding so the value
   * headline lines up with the cards' content edge. */
}

.gc-chart-current {
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.gc-chart-delta {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.gc-chart-delta--up      { color: #8be247; }
.gc-chart-delta--down    { color: #ff5971; }
.gc-chart-delta--neutral { color: rgba(255, 255, 255, 0.7); }

.gc-chart-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 300px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  text-align: center;
  padding: 0 12px;
}

/* Reset-zoom row — appears under the SVG only when zoomed. The pill
 * stays small + uppercase so it doesn't compete with the chart visually,
 * just gives users a one-tap way to un-zoom. Double-tap and long-press
 * also reset (handled in chart.js gestures). */
.gc-chart-reset-row {
  display: flex;
  justify-content: center;
  margin-top: 6px;
}
.gc-chart-reset {
  appearance: none;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #fff;
  padding: 4px 12px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.15s, background 0.15s;
}
.gc-chart-reset:hover  { background: rgba(255, 255, 255, 0.12); }
.gc-chart-reset:active { opacity: 0.65; transform: scale(0.97); }

.total-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.total-footer {
  flex-shrink: 0;
  padding: 12px 0 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.total-footer-row {
  display: flex;
  justify-content: space-around;
  font-size: 15px;
  font-weight: 700;
  color: var(--tg-accent);
}
.modal-list-item {
  display: flex;
  align-items: center;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

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

.modal-list-thumb {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  margin-right: 10px;
}

.modal-list-emoji {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  flex-shrink: 0;
  margin-right: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: rgba(255, 255, 255, 0.05);
  line-height: 1;
}

.modal-list-info {
  flex: 1;
  min-width: 0;
}

.modal-list-name {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.modal-list-sub {
  font-size: 11px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}

.modal-list-value {
  text-align: right;
  flex-shrink: 0;
  margin-left: 8px;
}

.modal-list-stars {
  font-size: 13px;
  font-weight: 600;
}

.modal-list-ton {
  font-size: 11px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
}


/* ── Portfolio (Profit) tab ─────────────────────────────────────────────── */
.portfolio-ton {
  /* Inline SVG of the TON brand mark — sized to the surrounding text
   * height (1.2em square) with a touch of negative vertical align so it
   * sits visually centred on the baseline of the digits next to it. */
  width: 1.2em;
  height: 1.2em;
  display: inline-block;
  vertical-align: -0.22em;
  margin-left: 2px;
  filter: drop-shadow(0 0 4px rgba(0, 152, 234, 0.3));
  flex-shrink: 0;
}
.portfolio-profit {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.portfolio-profit-label {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.5);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.portfolio-profit-value {
  font-size: 18px;
  font-weight: 800;
}
.portfolio-profit-pct {
  font-size: 13px;
  font-weight: 700;
}
.portfolio-profit--up .portfolio-profit-value,
.portfolio-profit--up .portfolio-profit-pct {
  color: #8be247;
}
.portfolio-profit--down .portfolio-profit-value,
.portfolio-profit--down .portfolio-profit-pct {
  color: #ff5971;
}

/* ── Self-minted ratio chip on Portfolio card ──
 * Compact row below the PnL line showing "🎯 99% self-minted (3 535 / 3 536)".
 * Explains why PnL is gated: only self-minted gifts have a known purchase
 * basis. Transferred / marketplace gifts contribute 0 on both sides until
 * the user enters a custom price override. */
/* ══ "Set the price" banner — matched to the reference render (.pf-unpriced):
   purple→gold gradient card, ◎ icon tile, bold title + sub line, gold count
   badge, › chevron. ══ */
.pf-unpriced {
  display: flex;
  align-items: center;
  gap: 11px;
  /* Match the Portfolio Value hero card's width exactly (user request): same
     horizontal margin + an explicit width so the <button> fills the row instead
     of shrinking to its content. */
  width: calc(100% - 2 * clamp(12px, 3vw, 20px));
  margin: 10px clamp(12px, 3vw, 20px) 0;
  padding: 11px 13px;
  border-radius: 14px;
  cursor: pointer;
  text-align: left;
  background: linear-gradient(110deg, rgba(151,111,255,0.24), rgba(255,206,72,0.12) 90%);
  border: 1px solid rgba(174,140,255,0.42);
  box-shadow: 0 6px 18px -8px rgba(151,111,255,0.6);
  transition: transform 0.12s;
}
.pf-unpriced[hidden] { display: none; }
.pf-unpriced:active { transform: scale(0.985); }
.pf-unpriced-ic {
  flex-shrink: 0;
  width: 34px; height: 34px;
  border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px;
  color: #E9DCFF;
  background: rgba(151,111,255,0.3);
  border: 1px solid rgba(174,140,255,0.5);
  box-shadow: 0 0 14px rgba(151,111,255,0.4);
}
.pf-unpriced-tx { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pf-unpriced-tx b { font: 800 14.5px var(--font-sans, inherit); color: #fff; letter-spacing: -0.2px; }
.pf-unpriced-tx span { font: 600 11.5px var(--font-sans, inherit); color: rgba(233,220,255,0.8); }
.pf-unpriced-n {
  flex-shrink: 0;
  min-width: 22px; height: 22px;
  padding: 0 7px;
  border-radius: 999px;
  background: #FFCE48; color: #3A2270;
  font: 900 12px var(--font-sans, inherit);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 12px rgba(255,206,72,0.5);
}
.pf-unpriced-ar { flex-shrink: 0; color: rgba(233,220,255,0.55); font-size: 18px; font-weight: 700; }

/* Round 22 — "Refreshing portfolio…" label shown in place of the
 * "set the price" chip while the backend is still on fast-path
 * (snapshot blob, ownership not yet classified). Same vertical slot
 * + same border-top divider as the chip so the totals card height
 * doesn't jump when full-compute lands and we swap labels. Soft
 * pulsing opacity reads as "in progress, not stuck". */
.portfolio-refreshing {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.72);
  letter-spacing: 0.02em;
  animation: pf-refreshing-pulse 1.6s ease-in-out infinite;
}
.portfolio-refreshing[hidden] { display: none; }
@keyframes pf-refreshing-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.95; }
}

/* ── Unpriced-gifts sheet ──
 * Opens from the self-minted chip. Lists collections whose non-self-minted
 * gifts lack a purchase-price override, grouped so one tap sets price for
 * the whole collection. Reuses the .pf-sheet bottom-sheet chrome. */
.pf-unpriced-sheet-inner {
  padding: 18px 16px 20px;
  max-height: 80vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.pf-unpriced-body { position: relative; }
.pf-unpriced-title {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  padding-right: 32px;
}
.pf-unpriced-icon { margin-right: 2px; }
.pf-unpriced-sub {
  margin-top: 4px;
  font-size: 12px;
  color: rgba(255,255,255,0.62);
  padding-right: 32px;
}
.pf-unpriced-list { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
.pf-unpriced-empty {
  padding: 20px 8px;
  text-align: center;
  font-size: 13px;
  color: rgba(255,255,255,0.55);
}
.pf-unpriced-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease;
}
.pf-unpriced-row:active { background: rgba(255,255,255,0.09); }
.pf-unpriced-thumb {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  background: rgba(255,255,255,0.04);
}
.pf-unpriced-meta { flex: 1; min-width: 0; }
.pf-unpriced-name {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pf-unpriced-override {
  margin-top: 2px;
  font-size: 11px;
  color: #e3d6ff;
  opacity: 0.85;
}
.pf-unpriced-badge {
  min-width: 28px;
  padding: 3px 8px;
  background: rgba(255, 160, 90, 0.22);
  color: #ffcca2;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  text-align: center;
}
.pf-unpriced-badge--done {
  background: rgba(70, 200, 120, 0.24);
  color: #b6f4cf;
}
.pf-unpriced-footnote {
  margin-top: 14px;
  font-size: 11px;
  color: rgba(255,255,255,0.45);
  line-height: 1.4;
  text-align: center;
}

/* Mini chip on model tiles: "🎯 8/10" when partial, "🎯" when all self. */
.pf-tile-sm-chip {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  margin-top: 1px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  color: rgba(255,255,255,0.85);
  background: rgba(0,0,0,0.45);
  border-radius: 8px;
  letter-spacing: 0.02em;
  pointer-events: none;
}
.pf-tile-sm-chip--all {
  background: rgba(70, 200, 120, 0.28);
  color: #b6f4cf;
}
.pf-tile-sm-chip--override {
  background: rgba(155, 120, 255, 0.32);
  color: #e3d6ff;
}

/* Per-gift 🎯 badge in the detail modal's item list — small inline
 * icon after the gift number so users see which NFTs they minted. */
.pf-self-badge {
  display: inline-block;
  font-size: 11px;
  margin-left: 3px;
  opacity: 0.85;
  vertical-align: baseline;
}
.pf-sheet-item--self .pf-sheet-item-num {
  color: #b6f4cf;
}

/* `.pf-sale-pill` was duplicated here; the newer unified definition
 * for the whole sale-pill family lives higher in the file (search
 * for "ON SALE pill family"). Kept comment only. */

/* ── Per-gift list: 2-column grid of compact tiles ──
 * Mirrors the Group view's 3-col .lines-grid layout but uses 2 columns so
 * each tile has horizontal room for the purchase → floor numbers plus a
 * profit badge. Tiles inherit the .group-card visual vocabulary (gradient
 * bg, rounded corners, scale-on-tap) so the two tabs feel like one family.
 */
/* ══ Edge glass-row list ══
 * Single column of glass rows: 44px thumb · name+meta · right-aligned PnL ·
 * chevron. A left edge-stripe + halo encodes the PnL SIGN (green profit /
 * red loss); profit rows pulse gently; unpriced rows are neutral (no stripe,
 * no halo, floor-only) so a missing cost basis never reads as break-even. */
.portfolio-list {
  padding: 0 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.pf-tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 62px;
  padding: 8px 12px;
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(18px) saturate(1.5);
  backdrop-filter: blur(18px) saturate(1.5);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28);
  transition: transform 0.15s;
  animation: pfRowIn 0.5s ease-out both;
}
.pf-tile:active { transform: scale(0.985); }
/* Left edge-stripe — the at-a-glance PnL-sign signal. */
.pf-row-stripe {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: transparent;
}
.pf-tile--up .pf-row-stripe   { background: linear-gradient(180deg, #6FF2B6, #33C98A); }
.pf-tile--down .pf-row-stripe { background: linear-gradient(180deg, #FF8A97, #E04150); }
/* Profit: green-tinted border + inset green halo that pulses left↔right.
 * Loss: red-tinted border + soft static red drop halo. */
.pf-tile--up {
  border-color: rgba(77, 227, 154, 0.30);
  box-shadow: inset 16px 0 26px -22px rgba(90, 230, 170, 0.5), 0 8px 22px rgba(0, 0, 0, 0.28);
  animation: pfRowIn 0.5s ease-out both, glassEdgeUp 3.8s ease-in-out 0.5s infinite;
}
.pf-tile--down {
  border-color: rgba(255, 107, 120, 0.28);
  box-shadow: 0 8px 24px -6px rgba(255, 80, 95, 0.34);
}
@keyframes pfRowIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes glassEdgeUp {
  0%, 100% { box-shadow: inset 16px 0 26px -22px rgba(90, 230, 170, 0.5), 0 8px 22px rgba(0, 0, 0, 0.28); }
  50%      { box-shadow: inset -16px 0 26px -22px rgba(90, 230, 170, 0.5), 0 8px 22px rgba(0, 0, 0, 0.28); }
}
.pf-tile-thumb-wrap {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
}
.pf-tile-thumb {
  width: 44px;
  height: 44px;
  border-radius: 11px;
  object-fit: cover;
  display: block;
  background: rgba(255, 255, 255, 0.04);
}
/* Backdrop-colour dot — top-right corner of the thumb. */
.pf-tile-dot {
  position: absolute;
  right: -3px; top: -3px;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 2.5px solid #0e1626;
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
}
.pf-row-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.pf-tile-name {
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pf-tile-prices {
  font-size: 11.5px;
  font-weight: 600;
  color: #708499;
  display: flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pf-tile-prices-arrow {
  color: rgba(255, 255, 255, 0.35);
  font-size: 10px;
}
.pf-row-pnl {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  gap: 1px;
}
.pf-tile-profit {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.2px;
  font-variant-numeric: tabular-nums;
}
.pf-tile-profit-pct {
  display: none;   /* hidden by default — only the $ shows; the % toggle (.pf-list--pct-only) swaps it in for the $ */
  font-size: 11px;
  font-weight: 700;
}
.pf-tile--up .pf-tile-profit,
.pf-tile--up .pf-tile-profit-pct { color: #6FF2B6; }
.pf-tile--down .pf-tile-profit,
.pf-tile--down .pf-tile-profit-pct { color: #FF8A97; }

/* Unpriced rows: neutral glass — NO stripe, NO halo, NO pulse, floor-only,
 * desaturated thumb. A missing cost basis must never read as break-even. */
.pf-tile--unpriced {
  border-color: rgba(255, 255, 255, 0.10);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.24);
}
.pf-tile--unpriced .pf-tile-thumb {
  filter: grayscale(0.9) opacity(0.6);
}
.pf-tile--unpriced .pf-tile-name { color: rgba(255, 255, 255, 0.78); }
.pf-tile--unpriced .pf-tile-profit,
.pf-tile--unpriced .pf-tile-profit-pct {
  color: rgba(255, 255, 255, 0.45);
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: lowercase;
}
/* Reduced motion: keep the colour signal, drop the row enter + pulse. */
@media (prefers-reduced-motion: reduce) {
  .pf-tile, .pf-tile--up, .pf-tile--down { animation: none !important; }
}

.portfolio-footnote {
  text-align: center;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.35);
  margin-top: 10px;
  padding: 0 20px 80px;
  line-height: 1.4;
}

/* Round 17 — empty-state for the Portfolio per-gift grid. Replaces the
 * silent blank container that appeared when linesRaw filtered to 0
 * lines (transferred-only users on fast-path) — user reported
 * "портфолио иногда багает и не показывает ничего". */
.portfolio-empty-state {
  text-align: center;
  padding: 30px 20px;
  color: var(--tg-theme-hint-color, var(--tg-hint, #708499));
  font-size: 14px;
  opacity: 0.85;
}

/* ══ Edge controls — 3-way sort (segmented) · winners/losers filter ·
   % display toggle. Glass pills, scoped to #page-portfolio so Home/LB
   sort buttons keep their own style. ══ */
/* ══ Edge controls — matched to the reference render (Portfolio Edge):
   compact Sort pill (Profit ▾) + 3-button segmented filter (All · ▲winners ·
   ▼losers, coloured dots) + a right-aligned % toggle. ══ */
#page-portfolio .pf-ctrls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px clamp(12px, 3vw, 20px) 12px;
}
#page-portfolio .pf-sort {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 13px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #fff;
  font: 700 13px var(--font-sans, inherit);
  cursor: pointer;
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  transition: transform 0.12s;
}
#page-portfolio .pf-sort:active { transform: scale(0.96); }
#page-portfolio .pf-sort .pf-sort-lbl { font-weight: 700; }
#page-portfolio .pf-sort .car { font-size: 9px; opacity: 0.7; margin-left: 1px; }
#page-portfolio .pf-seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  height: 34px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}
#page-portfolio .pf-seg button {
  border: none;
  background: none;
  border-radius: 999px;
  color: rgba(255, 255, 255, 0.62);
  font: 800 12px var(--font-sans, inherit);
  padding: 0 11px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  transition: 0.14s;
}
#page-portfolio .pf-seg button .ic { width: 8px; height: 8px; border-radius: 50%; }
#page-portfolio .pf-seg button[data-f="up"] .ic { background: #3DDC84; }
#page-portfolio .pf-seg button[data-f="down"] .ic { background: #FF5E6C; }
#page-portfolio .pf-seg button.on {
  color: #fff;
  background: rgba(255, 255, 255, 0.16);
}
#page-portfolio .pf-pct {
  margin-left: auto;
  flex-shrink: 0;
  width: 36px;
  height: 34px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.6);
  font: 900 13px var(--font-sans, inherit);
  cursor: pointer;
  transition: 0.14s;
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}
#page-portfolio .pf-pct:active { transform: scale(0.96); }
#page-portfolio .pf-pct.on {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}

/* % toggle: percent replaces the value on priced rows; unpriced rows (no
   .pf-tile--has-pct) keep their value text per the design tokens. */
.pf-list--pct-only .pf-tile--has-pct .pf-tile-profit { display: none; }
.pf-list--pct-only .pf-tile--has-pct .pf-tile-profit-pct {
  display: block;
  font-size: 12px;
  font-weight: 800;
  margin-top: 0;
}

/* Portfolio drilldown bar */
.pf-drilldown-bar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 2px 8px;
}
.pf-back-btn,
.pf-override-all-btn {
  padding: 7px 12px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.04);
  color: #fff;
  cursor: pointer;
}
.pf-override-all-btn {
  background: rgba(46,166,255,0.18);
  border-color: rgba(46,166,255,0.35);
  color: #6ab3f3;
}
.pf-back-btn:active,
.pf-override-all-btn:active { transform: scale(0.96); }
.pf-drilldown-spacer { width: 90px; }
.pf-drilldown-title {
  flex: 1;
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pf-collection-tile {
  position: relative;
}
.pf-tile-chev {
  flex: 0 0 auto;
  margin-left: 2px;
  color: rgba(255, 255, 255, 0.3);
  font-size: 18px;
  font-weight: 700;
}

/* On-chain diagnostic banner — explains WHY the wallet bucket is
 * empty (tonapi error / no whitelist match / backend pricing failure).
 * Shown briefly at the top of the screen so the user knows the app
 * tried rather than silently gave up. */
.gc-onchain-banner {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  left: 50%;
  transform: translateX(-50%);
  max-width: 92vw;
  padding: 10px 16px;
  border-radius: 12px;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  z-index: 2000;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  animation: gcBannerSlideIn 0.2s ease-out;
}
.gc-onchain-banner--error   { background: #b04444; }
.gc-onchain-banner--success { background: #2e8b57; }
@keyframes gcBannerSlideIn {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Gift detail sheet overlay.
 *
 * The overlay's height shrinks to match the area ABOVE the on-screen
 * keyboard. Combined with `align-items: flex-end` below, any child
 * sheet naturally docks flush to the keyboard top — no tracking, no
 * transforms, no jitter.
 *
 * Two heights declared in order:
 *   1. `calc(100vh - var(--gc-kbd-h))` — fallback. --gc-kbd-h is set
 *      from JS (Telegram `viewportChanged` with isStateStable, or a
 *      debounced visualViewport listener) to the current stable
 *      keyboard height. On browsers without dvh support this is
 *      what drives the layout.
 *   2. `100dvh` — override. Modern browsers (iOS 16.4+, recent
 *      Android) track the visual viewport natively, so the overlay
 *      shrinks automatically without us needing to update any JS
 *      var. Older engines ignore the unknown unit and keep the
 *      calc() fallback.
 *
 * The JS pre-applies the last known keyboard height from
 * localStorage on boot, so the SECOND time a user opens the price
 * sheet the overlay is already the right size — no snap when the
 * keyboard animates in. */
.pf-sheet-overlay {
  position: fixed; inset: 0;
  /* NOTE: 100dvh was previously set AFTER the calc() line so modern
   * browsers used the native dvh tracking. That caused the "sheet
   * drives in as the keyboard rises" effect users complained about:
   * dvh shrinks continuously during the kbd animation, the overlay
   * followed live. The calc() path is driven by JS which updates
   * --gc-kbd-h only at stable viewport events, so the overlay sizes
   * correctly from frame one (we pre-apply the stored kbd height in
   * _pfPromptPrice) and only changes at discrete stable points. */
  height: calc(100vh - var(--gc-kbd-h, 0px));
  background: rgba(0,0,0,0.7);
  z-index: 1000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Smooth any small mismatch between stored/actual keyboard height
   * instead of snapping — 120ms is subtle enough that the height
   * change reads as "settling" rather than animation. */
  transition: height 120ms ease;
}
.pf-sheet-overlay.hidden { display: none; }
/* Adaptive first-open defer: backdrop appears immediately so the
 * tap is acknowledged, but the sheet + close button stay invisible
 * until the keyboard has finished rising. JS removes this class
 * once Telegram's viewportChanged fires stable (or after a 500ms
 * safety timeout). Transforms pause so the slide-up plays when the
 * sheet actually becomes visible, not while it's hidden. */
.pf-sheet-overlay .pf-sheet,
.pf-sheet-overlay .pf-sheet-close {
  transition: opacity 160ms ease;
}
.pf-sheet-overlay--deferred .pf-sheet,
.pf-sheet-overlay--deferred .pf-sheet-close {
  opacity: 0;
  animation-play-state: paused;
}
/* Legacy class `.pf-sheet-overlay--kbd` used to re-anchor the price
 * sheet to the top half of the viewport while the numpad was open. In
 * practice it made the sheet LEAP from bottom to top on every focus
 * event and back on every blur — users reported "UI скачет". The new
 * approach keeps the sheet pinned to the bottom and lets `dvh` /
 * `--gc-vvh` (visual-viewport height, set from JS) naturally shrink
 * the usable space so the numpad just stacks underneath. */
.pf-sheet {
  /* Round 38-fix (2026-05-05) — positioning context for the close button.
   * User feedback: «close buttons должны быть недалеко от открытого окна,
   * сейчас они находят в самом верху приложения». The button used to be
   * a sibling of .pf-sheet positioned against the overlay (top of viewport,
   * far from a bottom-anchored sheet). Now the close button sits inside
   * .pf-sheet at top-right, so it floats right above the sheet content
   * regardless of how tall the sheet is. */
  position: relative;
  background: linear-gradient(180deg, #1a2436, #141c2c);
  border-top-left-radius: 22px;
  border-top-right-radius: 22px;
  width: 100%;
  max-width: 560px;
  /* `dvh` shrinks with the on-screen keyboard so the sheet never
   * exceeds the visible area even without explicit JS adjustment. */
  max-height: 85vh;
  max-height: 85dvh;
  overflow-y: auto;
  padding-bottom: env(safe-area-inset-bottom, 12px);
  /* NOTE: the keyboard-lift transform used to live here so ALL
   * bottom-sheets would rise above the numpad. That broke the
   * "back" path: when the price sheet closed, the underlying
   * Unpriced/Gift sheet inherited the lift and then visibly slid
   * DOWN over the ~250ms iOS keyboard-dismiss animation — the
   * "прыгает при возврате назад" bug. The transform now lives on
   * .pf-price-sheet only (the single sheet that actually has a
   * focused input). The other sheets sit at their natural bottom
   * position; if the keyboard is still up they stay behind it for
   * the dismiss animation, which looks natural.
   */
}
/* Suppresses the slide-up animation when a bottom sheet is being
 * *restored* from a temporary stash (i.e. re-shown after another
 * sheet closed on top of it). Without this, Unpriced would re-play
 * its translate-from-100% every time the user dismissed Price — the
 * "скачет" reports. JS adds this class right before removing
 * `.hidden`, then strips it on the next frame so subsequent fresh
 * opens animate normally. */
.pf-sheet--no-anim,
.pf-sheet-overlay.pf-sheet-overlay--no-anim .pf-sheet {
  animation: none !important;
}
@keyframes pfSheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.pf-sheet-body { padding: 10px 18px 18px; position: relative; }
/* Round 38-fix — anchored to the SHEET (top-right corner), not the
 * viewport. .pf-sheet is now position:relative so this absolute floats
 * right above the sheet body. Stays put while sheet body scrolls
 * because it lives outside .pf-sheet-body in the DOM. */
.pf-sheet-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(20, 22, 30, 0.72);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
  color: #ffffff;
  font-size: 22px;
  font-weight: 500;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.15s, transform 0.1s;
  z-index: 10;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  line-height: 1;
}
.pf-sheet-close:active {
  opacity: 0.65;
  transform: scale(0.93);
}
/* Round 38 (2026-05-05) — pf-sheet-close now wraps an <img class="gc-icon">
 * pointing at /assets/icons/close.svg (was a × glyph). Sized inside the
 * 36 px round button to match .modal-close vocabulary across the app. */
.pf-sheet-close .gc-icon { width: 18px; height: 18px; }
/* Edge portrait frame — 110×110 art in a backdrop-coloured border + ring,
 * with a PnL-sign halo (green profit / red loss; neutral for unpriced). */
.pf-sheet-frame {
  position: relative;
  width: 110px; height: 110px;
  margin: 12px auto 14px;
  border-radius: 26px;
  padding: 2px;
  border: 2px solid var(--bd, #5b6b8c);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.08);
}
.pf-sheet-frame-img {
  display: block;
  width: 100%; height: 100%;
  border-radius: 22px;
  object-fit: cover;
  background: rgba(255, 255, 255, 0.04);
}
.pf-sheet-frame--up   { box-shadow: 0 0 0 4px rgba(77, 227, 154, 0.30), 0 8px 30px -6px rgba(77, 227, 154, 0.45); }
.pf-sheet-frame--down { box-shadow: 0 0 0 4px rgba(255, 107, 120, 0.30), 0 8px 30px -6px rgba(255, 107, 120, 0.45); }
.pf-sheet-frame--unpriced { box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.10); }
.pf-sheet-title {
  text-align: center;
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  margin-bottom: 2px;
}
.pf-sheet-count {
  text-align: center;
  font-size: 12px;
  color: rgba(255,255,255,0.5);
  margin-bottom: 14px;
}
.pf-sheet-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 16px;
}
.pf-sheet-cell {
  background: rgba(255,255,255,0.04);
  border-radius: 10px;
  padding: 8px 10px;
  text-align: center;
}
.pf-sheet-lbl {
  font-size: 10px;
  color: rgba(255,255,255,0.45);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 3px;
}
.pf-sheet-val {
  font-size: 15px;
  font-weight: 700;
  color: #fff;
}
.pf-sheet--up { color: #8be247 !important; }
.pf-sheet--down { color: #ff5971 !important; }
.pf-custom-pill {
  font-size: 9px;
  background: rgba(46,166,255,0.25);
  color: #6ab3f3;
  padding: 2px 5px;
  border-radius: 5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  margin-left: 4px;
  vertical-align: middle;
}
.pf-sheet-action {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 12px;
  font-size: 14px;
  font-weight: 600;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.04);
  color: #fff;
  border-radius: 12px;
  cursor: pointer;
}
.pf-sheet-action:active { transform: scale(0.98); }
.pf-sheet-action--primary {
  background: var(--tg-accent, #2ea6ff);
  border-color: var(--tg-accent, #2ea6ff);
  color: #fff;
}

/* Blue variant of stats-row button — specifically for the Portfolio
 * shortcut on user profiles (self + viewed). Purple-family siblings
 * stay on their gradient; this one pops accent-blue so users can
 * immediately see "that\'s the PnL surface". */
.stats-row .stat-item--portfolio {
  background: linear-gradient(135deg, rgba(46, 166, 255, 0.20) 0%,
                                      rgba(46, 166, 255, 0.12) 100%);
  border-color: rgba(46, 166, 255, 0.35);
}
.stats-row .stat-item--portfolio:active {
  background: linear-gradient(135deg, rgba(46, 166, 255, 0.30) 0%,
                                      rgba(46, 166, 255, 0.18) 100%);
}
.stats-row .stat-item--portfolio .stat-label {
  color: rgba(46, 166, 255, 0.85);
}

/* Per-gift PnL clarifier: small tinted note under the totals grid */
.pf-sheet-pergift {
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.7);
  margin: -4px 0 10px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.03);
  border-radius: 8px;
}
.pf-sheet-pergift b { font-weight: 700; }
.pf-sheet-pergift.pf-sheet--up b { color: #8be247; }
.pf-sheet-pergift.pf-sheet--down b { color: #ff5971; }

/* Individual-gifts list inside the detail sheet — same visual vocabulary
 * as the Home-page modal-gift-items list: numbered rows, backdrop name,
 * per-item stars, chevron. */
/* Edge inventory slots — 2-col grid of gift thumbs, each framed in its
 * backdrop-trait colour. Tapping a slot opens that gift on Telegram. */
.pf-sheet-slots-title {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.45);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 2px 0 8px;
}
.pf-sheet-slots {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 9px;
  margin-bottom: 14px;
}
.pf-slot {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  text-decoration: none;
  color: #fff;
  overflow: hidden;
  transition: transform 0.12s;
}
.pf-slot:active { transform: scale(0.97); }
.pf-slot-thumb {
  width: 46px; height: 46px;
  flex: 0 0 auto;
  border-radius: 11px;
  object-fit: cover;
  border: 2px solid var(--bd, #5b6b8c);
  background: rgba(255, 255, 255, 0.04);
}
.pf-slot-num {
  font-size: 13px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.92);
  font-variant-numeric: tabular-nums;
}
.pf-slot-first {
  position: absolute;
  top: 5px; right: 6px;
  font-size: 8.5px;
  font-weight: 900;
  color: #0e1626;
  background: #FFCE48;
  padding: 0 4px;
  border-radius: 5px;
}
.pf-slot-sale {
  position: absolute;
  bottom: 5px; right: 6px;
  font-size: 8px;
  font-weight: 900;
  letter-spacing: 0.04em;
  color: #fff;
  background: #EC3942;
  padding: 1px 5px;
  border-radius: 5px;
}
/* Boost listing — compact pin in the slot's top-left; label clipped to the
 * disc so only the 📌 shows (full chip lives in the Market tab). */
.pf-slot .pf-boost-chip {
  position: absolute;
  top: 5px; left: 5px;
  width: 22px; height: 22px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  font-size: 11px;
  line-height: 22px;
  text-align: center;
  border-radius: 50%;
}

/* Count pill for model tiles — shows how many individual gifts the
 * user owns for that (collection, model) combo. Top-right corner like
 * the Group view's .group-badge. */
.pf-tile-count {
  position: absolute;
  bottom: -5px;
  right: -7px;
  background: rgba(14, 22, 38, 0.92);
  color: #ffffff;
  font-size: 10px;
  font-weight: 800;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  min-width: 20px;
  text-align: center;
  letter-spacing: 0.02em;
  z-index: 2;
  pointer-events: none;
}
/* Tint the badge for up/down tiles so it reads in harmony */
.pf-tile--up .pf-tile-count {
  background: rgba(139, 226, 71, 0.25);
  color: #8be247;
}
.pf-tile--down .pf-tile-count {
  background: rgba(255, 89, 113, 0.25);
  color: #ff5971;
}

/* Price-input modal (Stars ⇄ TON).
 *
 * Inherits all chrome from .pf-sheet (dark bg, rounded top corners,
 * 85dvh max-height, slide-up animation). The only override is a
 * slightly narrower max-width so the sheet matches the visual
 * weight of the compact price form, and bottom safe-area padding
 * so the Save button doesn't collide with the home indicator.
 *
 * No align-items override, no transform, no --gc-kbd-h consumer —
 * the shared overlay already docks the sheet flush to the top of
 * the on-screen keyboard via its height: 100dvh / calc() fallback. */
#pf-price-sheet { z-index: 1100; }
.pf-price-sheet {
  max-width: 560px;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
}
.pf-price-body { padding: 18px 20px 20px; position: relative; }
.pf-price-title { text-align: center; font-size: 15px; font-weight: 700; color: #fff; padding: 0 24px 14px; line-height: 1.3; }
.pf-price-unit-toggle { display: flex; gap: 6px; margin-bottom: 12px; padding: 4px; background: rgba(255,255,255,0.04); border-radius: 10px; }
.pf-unit-btn { flex: 1; padding: 8px 10px; font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.55); background: transparent; border: none; border-radius: 8px; cursor: pointer; }
.pf-unit-btn.active { background: rgba(46, 166, 255, 0.22); color: #6ab3f3; }

/* Scope selector in _pfPromptPrice — chooses whether the entered price
 * applies to a single gift/line or the entire collection. Styled like
 * the unit toggle for visual continuity but with less emphatic active
 * state (the UNIT toggle is the primary conversion knob). */
.pf-price-scope-toggle {
  display: flex;
  gap: 4px;
  margin-bottom: 10px;
  padding: 3px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
}
.pf-scope-btn {
  flex: 1;
  padding: 7px 8px;
  font-size: 11px;
  font-weight: 600;
  color: rgba(255,255,255,0.55);
  background: transparent;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.15s, color 0.15s;
}
.pf-scope-btn.active {
  background: rgba(255,255,255,0.10);
  color: #ffffff;
}
.pf-price-input-row { display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 10px 14px; margin-bottom: 6px; }
.pf-price-input { flex: 1; background: transparent; border: none; outline: none; color: #fff; font-size: 20px; font-weight: 700; min-width: 0; font-family: inherit; }
.pf-price-input::placeholder { color: rgba(255,255,255,0.25); }
.pf-price-unit-suffix { color: rgba(255,255,255,0.55); font-weight: 700; font-size: 14px; }
.pf-price-preview { text-align: center; font-size: 12px; color: rgba(255,255,255,0.6); min-height: 16px; padding: 6px 2px 14px; }
.pf-price-preview--hint { color: rgba(255,255,255,0.35); font-style: italic; }
.pf-price-actions { display: flex; gap: 8px; }
.pf-price-actions .pf-sheet-action { margin-top: 0; flex: 1; }/* Global currency picker (opens from Settings) */
.ccy-picker-sheet { max-width: 420px; }
.ccy-picker-body { padding: 18px 20px 20px; }
.ccy-picker-title {
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  margin-bottom: 14px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255,255,255,0.7);
}
.ccy-picker-opts {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ccy-opt {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.04);
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.ccy-opt:active { transform: scale(0.98); }
.ccy-opt.active {
  border-color: var(--tg-accent, #2ea6ff);
  background: rgba(46,166,255,0.14);
  color: var(--tg-accent, #2ea6ff);
}
.ccy-opt-sym {
  width: 34px; height: 34px;
  border-radius: 10px;
  background: rgba(255,255,255,0.06);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
  font-weight: 700;
  flex-shrink: 0;
}
.ccy-opt.active .ccy-opt-sym {
  background: rgba(46,166,255,0.25);
  color: var(--tg-accent, #2ea6ff);
}

/* Primary-highlight variant for Settings items — Currency + Language.
 * Accent-tinted gradient + blue left-bar + bolder text so these sit
 * visually "above the fold" of the settings list. */
.settings-item--primary {
  /* Pink highlight — Currency + Language are the main personalization
   * settings, we want them to pop above the rest of the list. */
  background: linear-gradient(90deg,
    rgba(255, 90, 200, 0.20) 0%,
    rgba(255, 90, 200, 0.10) 60%,
    rgba(255, 90, 200, 0.04) 100%);
  border: 1px solid rgba(255, 90, 200, 0.35);
  border-left: 4px solid #ff5ac8;
  padding-left: 12px;
  box-shadow: 0 2px 10px rgba(255, 90, 200, 0.12);
}
.settings-item--primary .settings-label {
  color: #fff;
  font-weight: 700;
}
.settings-item--primary .settings-value {
  color: #ff80d5;
  font-weight: 700;
}
.settings-item--primary:active { transform: scale(0.99); }

/* Locked variant — Free user sees Currency + Language as Pro-only. The
 * pink highlight is dimmed and a 🔒 padlock prefixes the value, hinting
 * the row is gated. Tap is intercepted by app.js to open the Pro sheet. */
.settings-item--locked {
  opacity: 0.6;
  filter: saturate(0.5);
}
.settings-item--locked .settings-value::before {
  content: "\01F512";  /* 🔒 */
  margin-right: 6px;
  font-size: 13px;
  opacity: 0.85;
}

/* ── Pro Subscription row + sheet (Telegram Stars, 100 ⭐ / month) ──────
 * Distinct gold-tinted variant so the upsell stands out from the pink
 * Currency/Language pair. Same base shape (.settings-item) so radii at
 * list edges still apply. */
.settings-item--pro {
  background: linear-gradient(90deg,
    rgba(255, 199, 64, 0.22) 0%,
    rgba(255, 199, 64, 0.10) 60%,
    rgba(255, 199, 64, 0.04) 100%);
  border: 1px solid rgba(255, 199, 64, 0.40);
  border-left: 4px solid #ffc740;
  padding-left: 12px;
  box-shadow: 0 2px 10px rgba(255, 199, 64, 0.14);
}
.settings-item--pro .settings-label {
  color: #fff;
  font-weight: 700;
}
.settings-item--pro .settings-value {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: #ffd97a;
  font-weight: 700;
}
.settings-item--pro:active { transform: scale(0.99); }
.settings-pro-status--active {
  color: #ffd97a !important;
}
.settings-value-arrow { opacity: 0.7; }

#settings-pro-row {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(255, 199, 64, 0.2);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

/* Subscription bottom-sheet — reuses .pf-sheet-overlay chrome */
.sub-sheet {
  background: linear-gradient(180deg,
    rgba(28, 22, 8, 0.98),
    rgba(20, 16, 6, 0.98));
  border-top: 1px solid rgba(255, 199, 64, 0.25);
  box-shadow: 0 -8px 30px rgba(255, 199, 64, 0.08);
}
.sub-sheet-body {
  padding: 18px 18px 20px;
  text-align: center;
}
.sub-sheet-icon {
  font-size: 38px;
  line-height: 1;
  margin-top: 4px;
  filter: drop-shadow(0 2px 8px rgba(255, 199, 64, 0.4));
}
.sub-sheet-title {
  margin-top: 8px;
  font-size: 18px;
  font-weight: 700;
  color: #fff;
}
.sub-sheet-price {
  margin-top: 10px;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.sub-sheet-price-amt {
  font-size: 36px;
  font-weight: 800;
  color: #ffd97a;
  letter-spacing: -0.02em;
}
.sub-sheet-price-star {
  font-size: 22px;
  margin-left: 2px;
}
.sub-sheet-price-period {
  font-size: 14px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
  margin-left: 2px;
}
.sub-sheet-tagline {
  margin-top: 4px;
  font-size: 13px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.62));
  padding: 0 12px;
}
.sub-sheet-status {
  margin-top: 10px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(139, 226, 71, 0.12);
  color: #b6e88c;
  font-size: 13px;
}
.sub-sheet-status--active .sub-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #8be247;
  box-shadow: 0 0 8px rgba(139, 226, 71, 0.6);
}
/* Trial banner — warm amber to differentiate from a paid green-active.
 * Tells comp/giveaway users their access is finite without doom-styling. */
.sub-sheet-status--trial {
  background: rgba(255, 184, 0, 0.13);
  color: #ffd166;
}
.sub-sheet-status--trial .sub-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ffb800;
  box-shadow: 0 0 8px rgba(255, 184, 0, 0.55);
}
.sub-sheet-perks {
  list-style: none;
  margin: 18px auto 0;
  padding: 0 8px;
  text-align: left;
  max-width: 320px;
}
.sub-sheet-perks li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  font-size: 14px;
  color: var(--tg-theme-text-color, #fff);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.sub-sheet-perks li:last-child { border-bottom: none; }
.sub-perk-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 199, 64, 0.18);
  color: #ffd97a;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
}
.sub-sheet-cta {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 14px 16px;
  border: none;
  border-radius: 12px;
  background: linear-gradient(135deg, #ffd97a 0%, #ffc740 100%);
  color: #1a1408;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.1s, opacity 0.15s;
  box-shadow: 0 4px 16px rgba(255, 199, 64, 0.30);
}
.sub-sheet-cta:active { transform: scale(0.98); opacity: 0.9; }
.sub-sheet-cta:disabled { opacity: 0.6; cursor: default; }

/* "Pay with balance" — secondary (outlined) CTA below the Stars button, beta only */
.sub-balance-pay { width: 100%; }
.sub-balance-pay.hidden { display: none; }
.sub-or {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 10px; font-size: 12px; letter-spacing: 0.5px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.45)); text-transform: uppercase;
}
.sub-or::before, .sub-or::after { content: ''; flex: 1; height: 1px; background: rgba(255,255,255,0.12); }
.sub-balance-cta {
  display: block; width: 100%; padding: 13px 16px;
  border: 1px solid rgba(255,217,122,0.5); border-radius: 12px;
  background: rgba(255,217,122,0.10); color: #ffd97a;
  font-size: 15px; font-weight: 700; cursor: pointer;
  transition: transform 0.12s ease, opacity 0.12s ease;
}
.sub-balance-cta:active { transform: scale(0.98); opacity: 0.9; }
.sub-balance-cta:disabled { opacity: 0.6; cursor: default; }
.sub-balance-hint {
  margin-top: 7px; text-align: center; font-size: 12px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
}
.sub-sheet-cta--manage {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border: 1px solid rgba(255, 199, 64, 0.4);
  box-shadow: none;
}
.sub-sheet-fineprint {
  margin-top: 12px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.45));
  padding: 0 4px;
}

/* ══ END Portfolio ══ */


/* ─── Mobile tap reliability (iOS / Telegram WebView) ─── */
/* tap-target-fix: disable tap-highlight flash + enable fast tap.
 * touch-action: manipulation lets the browser skip the 300ms double-tap
 * detection, so single tap fires immediately. */
#settings-currency-row,
#settings-language-row,
#portfolio-title-row {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(255, 90, 200, 0.2);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}


/* ════════════════════════════════════════════════════════════════════
   MARKET — cross-user listings page.
   Mirror the visual language used elsewhere (dark surface +
   .tg-accent borders + leaderboard's NEW-style halo for promoted
   gifts re-themed in gold for "TOP").
   ════════════════════════════════════════════════════════════════════ */

#page-market {
  /* Side padding tightened 12px → 6px (1.5.32) — user feedback: «по
   * бокам много лишнего пространства». Inner row margins also drop
   * 16px → 12px (see .market-sort-row, .market-filter-row,
   * .market-search-row, .market-priceband-row, .market-list, .market-header
   * below). Total side gutter goes 28px → 18px = ~10px reclaim each side
   * (~20px wider content), geometry preserved (everything still aligns
   * to a single inner-column edge). */
  padding: 16px 6px 96px;
}

/* Minimalism pass (1.5.31) — single colored accent per section, strict
 * type scale, generous whitespace. Title is the typographic anchor in
 * solid white; stats are caption-text neutrals; the gold CTA is the only
 * gradient in the header so the eye lands on the action. Previous
 * "compact" header used a rainbow gradient for the title + a blue→pink
 * gradient for stats + a gold CTA + TOP pill on cards = 4 competing
 * accents. Now it's exactly one. */
.market-header {
  /* Round 61-fix5 (2026-05-05) — back to a single flex-row container,
   * but now with `align-items: center` (not the old flex-end). Per user
   * direction: «Put them in one parent container with display: flex,
   * use flex-direction: row, and set align-items: center. The icon,
   * 'Market', and the stats text should all sit visually centered in
   * a single row with equal spacing». The previous Round-61 grid solved
   * the wrapping bug but bottom-aligned cells, leaving the icon visually
   * pulled down past the "Market" glyphs (text bottom < icon bottom by
   * ~2 px because the 28 px icon is taller than the 26 px text line-box).
   * flex-wrap + flex-basis:100% on .market-cta-row keeps the CTA on its
   * own line below — same effect grid gave us, no row mismatch.
   *
   * Wrapping safety (the original Round-61 motivation): .market-stats
   * has `min-width:0; overflow:hidden` and a clamp() font on stat
   * values, so a longer number can't push the row into a second line. */
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 12px;
  row-gap: 18px;
  text-align: left;
  padding: 18px 12px 14px;
  margin: 0;
}

.market-title {
  /* Round 61-fix5 (2026-05-05) — flex row, centred. line-height:1
   * (down from 1.05) so the text line-box height matches the glyph
   * height — no descender padding to nudge the visual centre. margin:0
   * kills the default browser h1 top/bottom margin. Parent .market-header
   * is now flex with align-items:center, so the title's centre lines up
   * with the stats' centre. */
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  min-width: 0;
  margin: 0;
  letter-spacing: 0.01em;
  /* Premium gradient — same 3-stop blue→purple→pink as the totals-card
   * gradient on Home (.totals-card linear-gradient at #6b93ff →#976fff
   * →#e46ace). This is the app's hero-text recipe; using it on the
   * Market title keeps the page in the family instead of feeling like
   * a colder, isolated section. The previous solid-white title was
   * accurate to "minimalism" but inconsistent with the rest of the app. */
  background: linear-gradient(135deg, #6b93ff 0%, #976fff 55%, #e46ace 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

@media (pointer: fine) {
  .market-title { font-size: 22px; }
  /* (.market-title-icon desktop sizing override is below the
   * unconditional .market-title-icon rule — see Round 61-fix9.) */
}

.market-title-icon {
  /* Round 61-fix9 (2026-05-05) — header-scoped asset, not a global SVG
   * rewrite. fix8 normalised the shared gift.svg viewBox to make the
   * Market header self-balance, but that rippled into every gift.svg
   * usage (nav button, empty state, etc.) — broke layout on desktop.
   *
   * Per user direction: «do not fix this globally by changing gift.svg
   * for the entire app … create a Market-header-specific icon variant
   * or a dedicated CSS class only for this row».
   *
   * Solution: gift-header.svg is a sibling asset with viewBox `4 8 24 24`
   * (square crop with box-body cy at geometric centre). The shared
   * gift.svg keeps its original `0 0 32 32` viewBox; other usages are
   * untouched. .market-title-icon points at the header variant via
   * src in index.html.
   *
   * No CSS transform: the header asset is self-balancing. align-items:
   * center on .market-title is enough. */
  display: block;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  color: #fff;
  -webkit-text-fill-color: #fff;
}

@media (pointer: fine) {
  /* Round 61-fix9 — desktop already shrinks .market-title text 26→22 px
   * (rule above near .market-title), but the icon stayed at 28 px →
   * over-dominated the smaller glyphs. 24 px keeps the icon a hair
   * larger than cap-height (a common "icon-with-label" ratio) without
   * crowding the row. NB: this @media block sits AFTER the unconditional
   * .market-title-icon rule deliberately — equal-specificity rules
   * resolve by order, so a media-query block placed earlier would lose. */
  .market-title-icon { width: 24px; height: 24px; }
}

/* Subtitle "All gifts on sale across users" is redundant with the page
 * title — the user just clicked the 🛒 Market nav button, they know
 * what page they're on. Hidden via CSS to avoid editing backend agent's
 * shared HTML structure. Removed from the visible flow without removing
 * the data-i18n hook (still available for future re-introduction).
 * User feedback 2026-05-04: «слишком много пустого пространства / сделай
 * красивее». */
.market-subtitle { display: none; }

/* Stats ribbon — single line with gradient-colored numbers + muted
 * lowercase labels, separated by subtle dot dividers. Reads like a
 * Premium-style data strip and takes ~24px of vertical space instead
 * of the previous 80+. */
.market-stats {
  /* Round 61-fix5 (2026-05-05) — sibling flex item of .market-title in
   * .market-header. flex:1 1 auto so it grows to fill remaining width;
   * justify-content:flex-end pushes the stat tiles to the right edge.
   * align-items:center keeps stat value+label centred relative to the
   * title icon and "Market" text. min-width:0 + overflow:hidden so a
   * long number can't tip the row into wrapping (the original Round-61
   * defence against «съехала строка»). */
  flex: 1 1 auto;
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  align-items: center;
  gap: 16px;
  margin: 0;
  font-variant-numeric: tabular-nums;
  flex-wrap: nowrap;
  min-width: 0;
  overflow: hidden;
}

.market-stat {
  /* Round 61-fix5 — value + label centred together, so the stat tile's
   * vertical centre matches the title row's centre. */
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  padding: 0;
  position: relative;
  /* Round 53 — never wrap a stat's value+label pair onto two lines. */
  white-space: nowrap;
  min-width: 0;
}
.market-stat + .market-stat::before {
  content: '·';
  position: absolute;
  left: -10px;
  color: rgba(112, 132, 153, 0.40);
  font-size: 14px;
  line-height: 1;
}
/* Drop the third "collections" stat — sellers + listings is enough
 * signal; collections count is a curiosity, not a decision-maker. The
 * value still loads in the DOM (backend agent's HTML), we just hide it
 * to keep the stats line lean. User feedback 2026-05-04: «стремимся в
 * минимализм». */
.market-stat:nth-child(3) { display: none; }

.market-stat-value {
  display: inline-block;
  font-weight: 800;
  /* Round 61-fix5 — line-height:1 so the value's box height matches
   * its glyph height; eliminates descender padding that would offset
   * the visual centre when align-items:center is applied on the parent. */
  line-height: 1;
  /* Round 53 — clamp() scales the digit size when the bar is cramped
   * (long numbers + narrow viewport), so 7-8 digit values still fit
   * the row on iPhone SE. */
  font-size: clamp(11px, 3.6vw, 15px);
  /* Stat numbers pop with the same premium gradient as the title — the
   * app's pattern is "hero text gets the gradient, body text is white".
   * Previously these were flat white at 14px which made the strip read
   * as caption-grey. */
  background: linear-gradient(135deg, #6b93ff 0%, #976fff 60%, #e46ace 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.market-stat-label {
  display: inline-block;
  /* Round 61-fix5 — same line-height:1 reasoning as .market-stat-value:
   * pack the box to the glyph height so center alignment is honest. */
  line-height: 1;
  font-size: 11px;
  color: var(--tg-hint, #708499);
  text-transform: lowercase;
  letter-spacing: 0.01em;
}

.market-promote-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 20px;
  margin-top: 0;
  background: linear-gradient(135deg, #FFD96A 0%, #FFA53D 50%, #FF6F9E 100%);
  color: #1c1409;
  font-weight: 700;
  font-size: 13px;
  border-radius: 12px;
  border: none;
  box-shadow: 0 4px 14px rgba(255,160,80,0.30);
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.15s;
}

.market-promote-cta:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(255,160,80,0.45); }
.market-promote-cta:active { transform: translateY(0); }

.market-promote-icon { font-size: 14px; }

/* Sort row — quiet neutrals so the page reads as a calm scan;
 * inactive buttons fade into the background, the active one stands
 * out with a single solid purple wash + thin border. No more competing
 * blue→purple gradient. */
/* Round 27 (2026-05-04) — flex wrapper for sort-row + Clear button.
 * Clear sits OUTSIDE the scrollable sort-row so it's always visible on
 * narrow screens. Margin moved here from .market-sort-row. */
.market-sort-wrapper {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: clamp(8px, 2.4vw, 14px) clamp(8px, 2.4vw, 14px) 0;
  /* Round 25 — lock height so toggling Clear doesn't shift filter /
   * price-band rows. 36 px = sort-btn outer height + sub-pixel slack. */
  min-height: 36px;
}

.market-sort-row {
  display: flex;
  align-items: center;
  /* Flex child of .market-sort-wrapper. min-width:0 needed so flex
   * items don't blow out the parent (default flex min-width: auto). */
  flex: 1 1 auto;
  min-width: 0;
  gap: 8px;
  overflow-x: auto;
  padding: 2px 1px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* Fade right edge so users see there's more to scroll instead of a
   * hard clip (user 2026-05-04: «"market_" cuts off mid-word»).
   * 24px gradient fade = enough to telegraph "more →". */
  -webkit-mask-image: linear-gradient(to right,
    #000 0, #000 calc(100% - 24px), transparent 100%);
          mask-image: linear-gradient(to right,
    #000 0, #000 calc(100% - 24px), transparent 100%);
}
.market-sort-row::-webkit-scrollbar { display: none; }

.market-sort-btn {
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: 14px;
  /* Round 29 (2026-05-04) — softer / lighter blue palette per user
   * feedback («сделай кнопки более светло-голубыми, в стилистике
   * приложения»). Was rgba(46,166,255,*) (app primary accent — too
   * saturated for inactive sort buttons), now sits closer to the
   * dropdown-panel pastel family (rgba(120,180,255,*)). Active state
   * keeps a single solid wash instead of the blue→purple gradient so
   * the row reads as one consistent palette. */
  background: rgba(120, 180, 255, 0.08);
  color: #c8d4e3;
  border: 1px solid rgba(120, 180, 255, 0.20);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s, border 0.15s;
}
.market-sort-btn:hover {
  background: rgba(120, 180, 255, 0.16);
  color: #fff;
  border-color: rgba(120, 180, 255, 0.36);
}
.market-sort-btn.active {
  background: rgba(120, 180, 255, 0.28);
  color: #fff;
  border-color: rgba(120, 180, 255, 0.55);
  border-width: 1.5px;
}
/* Narrow viewport (phone) — tighter padding so all 6 buttons have a
 * fighting chance of fitting without scroll. Combined with the mask
 * fade, the layout never visually clips mid-word. */
@media (max-width: 480px) {
  .market-sort-btn { padding: 6px 10px; font-size: 11px; }
}

/* Filter row — same border + background recipe as .search-input
 * (style.css:435) so dropdowns match the rest of the app's input
 * vocabulary. Subtle purple tint + 12px radius. */
.market-filter-row {
  display: flex;
  gap: 8px;
  margin: clamp(8px, 2.4vw, 14px) clamp(8px, 2.4vw, 14px) clamp(12px, 3vw, 20px);
  align-items: center;
}

.market-filter-select {
  flex: 1 1 0;
  min-width: 0;
  /* Round 29 — shrink right caret padding 28→22 + left padding 12→10 so
   * the longest placeholder ("Collections" 11 chars) doesn't clip on
   * narrow Telegram Desktop viewports (user feedback: «надпись
   * Collections не вмещается в ui на пк»). Native <select> doesn't
   * honour text-overflow:ellipsis, so the only lever is more text room. */
  padding: 8px 22px 8px 10px;
  border-radius: 12px;
  /* Purple-tinted recipe — matches Home .search-input + Settings input
   * vocabulary. Gives the dropdowns visible warmth instead of reading
   * as detached neutral grey on the dark background. */
  background: rgba(151, 111, 255, 0.08);
  color: var(--tg-theme-text-color, var(--tg-text));
  border: 1px solid rgba(151, 111, 255, 0.22);
  font-size: 13px;
  font-weight: 500;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  outline: none;
  transition: border-color 0.2s, background 0.2s;
  /* Caret arrow drawn as inline SVG so it doesn't break alignment on
   * narrow widths the way background-image positioning did. Stroke
   * tinted to premium-purple to match the input border family. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23976fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 7px center;
  background-size: 9px 6px;
}
.market-filter-select:focus {
  border-color: var(--premium-purple);
  background-color: rgba(151, 111, 255, 0.14);
}

/* Native <option> elements inside the market filter dropdowns —
 * Telegram WebView (Android + Desktop) renders the browser's default
 * white-on-white popup which is unreadable on the app's dark theme.
 * Styling <option> is limited (no border-radius, no padding control on
 * most platforms) but background + color ARE respected by Chromium /
 * Webkit / Gecko, which covers all Telegram clients. User feedback
 * 2026-05-04: «выпадающий список белый, ничего не видно — сделай как
 * у sort на home». Color recipe matches the .dropdown-panel + dropdown
 * items at style.css:1028 (Home filter pattern). */
.market-filter-select option {
  background-color: #1c1f2b;
  color: #ffffff;
  padding: 8px 12px;
  font-size: 14px;
}
.market-filter-select option:checked,
.market-filter-select option:hover {
  background-color: rgba(151, 111, 255, 0.30);
  color: #ffffff;
}
.market-filter-select option[value=""] {
  /* "All models" / "All backdrops" — placeholder, slightly muted */
  color: var(--tg-hint, #97a1ad);
}

.market-filter-clear {
  /* Sits at the end of .market-sort-row (after `#`). Round 25
   * (2026-05-04): font-size + font-weight matched EXACTLY to
   * .market-sort-btn (12px / 600) so the row height doesn't grow
   * when Clear pops in/out — earlier 13px / 500 made the button
   * 3 px taller, which pushed the filter row + price row + list
   * down 3 px each Apply. Red accent still reads as "destructive"
   * (clear-all) without the size mismatch. */
  flex: 0 0 auto;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  background: rgba(255,90,90,0.12);
  color: #ff8a8a;
  border: 1px solid rgba(255,90,90,0.30);
  border-radius: 14px;
  cursor: pointer;
  white-space: nowrap;
}
.market-filter-clear:active { opacity: 0.75; }

/* Listing list — 2-column responsive grid */
.market-list-wrap {
  position: relative;
  /* Min-height 70vh — backend agent shipped this in 1.5.32-fix to stop
   * Chromium scroll-anchoring from yanking the viewport when filters
   * narrow the list (cards remove → wrap collapses → scroll-anchor
   * compensates → page jumps). Reserving viewport height keeps the
   * wrap stable through filter churn. overflow-anchor:none disables
   * the anchoring algorithm outright as a belt-and-braces second guard. */
  min-height: 70vh;
  overflow-anchor: none;
}

/* Market list — vertical row stack matching the Price-view .lines-list
 * convention from style.css:1370. Each card is a .line-item (full Price
 * styling reused — tier gradients, line-thumb, line-name etc.) plus a
 * .market-row marker class for Market-only overrides (TOP halo, link
 * cursor). Single-column always: rows are info-dense (gift_name +
 * subtitle + price), splitting into multi-column would just make text
 * less readable on phones. */
.market-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 0 clamp(8px, 2.4vw, 16px);
}

/* .line-item base styling already covers: thumb left, line-left middle,
 * line-right (price) right; .line-item[data-tier=…] applies the gold/
 * purple/blue gradients. We only need Market-specific overrides below. */

/* Make the entire row clickable as a link without underlines or
 * default link colors. */
a.line-item.market-row {
  text-decoration: none;
  color: inherit;
}

/* TOP halo on promoted Market rows — gold/peach gradient + pulsing
 * border, matches the badge palette. Same shape as .lb-item--new from
 * the leaderboard but warmer to read as "promoted" rather than "new". */
.line-item.market-row--top {
  border: 1px solid rgba(255, 200, 90, 0.55);
  /* Round 15 (2026-05-04) — dropped the gold gradient `background:
   * !important` that was overriding the layered TG-card backdrop. The
   * gold border + box-shadow halo + pulse animation alone signal
   * "promoted"; the actual gift backdrop now shows through underneath
   * just like any non-promoted listing. User: «Promoted листинги
   * отображать как обычные гифты, покрытые золотой рамкой».
   * Round 16 — toned the halo opacities down (.30/.28 → .22/.18) so
   * the gold reads as a frame, not a tint that competes with the
   * actual backdrop colour. Pulse keyframes adjusted to match. */
  box-shadow:
    inset 0 0 0 1px rgba(255,200,90,0.22),
    0 0 14px rgba(255,180,80,0.18);
  animation: marketTopPulse 6s ease-in-out infinite;
  border-radius: 12px;
}
/* Round 16 — promoted rows get a LIGHTER dark overlay so the gift's
 * backdrop colour (e.g. Cobalt Blue) reads bright through the gold
 * halo. Without this the cobalt blue darkened by 0.35 + the gold
 * halo combo looked uniformly dark across all promoted listings.
 * Specificity (0,3,0) beats the base .line-item.gift-card-layered
 * rule (0,2,0). */
.line-item.market-row--top.gift-card-layered {
  background:
    linear-gradient(rgba(15, 17, 24, 0.18), rgba(15, 17, 24, 0.18)),
    var(--proxy-url, none) top left / 150% auto no-repeat,
    radial-gradient(circle at 22px 50%,
                    var(--bg-center) 0%,
                    var(--bg-edge)   80%);
}

@keyframes marketTopPulse {
  0%, 100% {
    box-shadow: inset 0 0 0 1px rgba(255,200,90,0.20),
                0 0 9px rgba(255,180,80,0.14);
  }
  50% {
    box-shadow: inset 0 0 0 1px rgba(255,200,90,0.42),
                0 0 18px rgba(255,180,80,0.26);
  }
}

/* "listed Xh ago" footer — backend renders this inside each card to
 * surface freshness. User feedback 2026-05-04: «сделай прозрачным и
 * намного меньше». Tiny (9px), 50% opacity, lowercase — visible to
 * users who scan for it but doesn't compete with name/price. Fresh
 * listings (<24h) get a subtle green tint via .market-card--fresh-new. */
.market-card-fresh {
  font-size: 9px;
  color: var(--tg-hint, #708499);
  opacity: 0.50;
  letter-spacing: 0.02em;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.market-card-fresh.market-card--fresh-new {
  color: #5fe39a;
  opacity: 0.70;
}

/* Discount badge — REMOVED in 1.5.31. Discount is now encoded by
 * coloring the price itself green (.line-floor--discount). Removing
 * the standalone pill drops one element, clears one accent, and frees
 * the .market-card-meta-row for owner+time-ago. The badge would
 * compete with the price for the same eye-track. */
.market-card-discount { display: none; }

/* Card meta row (level-3 hierarchy) — small, single line under the
 * model · backdrop subtitle. Holds @owner (clickable, premium-blue)
 * and "· Xh ago" (hint-grey, 50% opacity). Tertiary signal — readable
 * but doesn't compete with name/price. */
.market-card-meta-row {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: 11px;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.market-card-meta-row .market-card-fresh {
  margin-top: 0;
  font-size: 11px;
  opacity: 0.50;
}

/* Discount price — when the listing is below cached floor, the price
 * itself goes green with a subtle glow. Backend agent (1.5.32-fix
 * c4a58bb5) also added a "−N%" pill next to the price (.line-discount-pill
 * below) — both work together: green price gives the at-a-glance signal,
 * the pill quantifies HOW MUCH below floor when the user wants to compare
 * deals on the % OFF sort tab. */
.line-floor--discount {
  color: #5fe39a;
  text-shadow: 0 0 12px rgba(95, 227, 154, 0.35);
}

/* Inline "−64%" pill rendered next to the price by _renderGiftCard()
 * when discount_pct > 0. Same green family as .line-floor--discount but
 * compact (10px) so it sits next to the price without breaking the row.
 * Cap at 99% in JS already; CSS just needs to not wrap. */
.line-discount-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 800;
  color: #1c2e1d;
  background: linear-gradient(135deg, #7fe8a4, #4dd189);
  border-radius: 999px;
  letter-spacing: 0.02em;
  vertical-align: middle;
  white-space: nowrap;
  box-shadow: 0 0 6px rgba(77, 209, 137, 0.30);
}

/* TON-priced listing — backend renders direct "0.5 TON" text instead of
 * the reactive currency span (TON listings can't hot-swap to USD/stars
 * because the listing IS in TON). Lighter weight than the stars price
 * to telegraph "different currency, same row position". */
.line-floor-ton {
  font-weight: 700;
  color: #5ec1ff;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.line-floor--discount .line-floor-ton { color: #5fe39a; }

/* Stars-listed Market price — gold to mirror the ⭐ icon palette and
 * read as a sibling signal to the blue .line-floor-ton above (TON
 * listings). Class is set in _renderGiftCard's else branch so it only
 * applies to Market rows; Home/Portfolio prices keep the default text
 * colour. Discount rows still go green via the override below. */
.line-item.market-row .line-floor-stars { color: var(--gold); }
.line-item.market-row .line-floor--discount .line-floor-stars { color: #5fe39a; }
/* Backend missed the price (high-TON listings sometimes leave
 * resell_price_*, price_stars_eq all null/0). _renderGiftCard
 * renders "—" with this class so the user doesn't read it as "free". */
.line-item.market-row .line-floor-stars--unknown {
  color: var(--tg-theme-hint-color, var(--tg-hint, #708499));
  font-weight: 600;
  opacity: 0.7;
}

/* Market row compaction — shorter cards, smaller text. Scoped to
 * .market-row only; Home / Portfolio rows keep the original sizing.
 * Vertical padding and thumb size drive the overall height; text
 * tiers shrink in proportion so the visual hierarchy stays. */
.line-item.market-row {
  padding: 10px 14px;
}
.line-item.market-row .line-thumb {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  margin-right: 10px;
}
.line-item.market-row .line-name { font-size: 13px; }
.line-item.market-row .line-name-row { gap: 5px; }
.line-item.market-row .line-gift-number { font-size: 11px; }
.line-item.market-row .line-count { font-size: 11px; }
.line-item.market-row .line-floor { font-size: 13px; }
.line-item.market-row .line-floor .star-sm { font-size: 12px; }
.line-item.market-row .market-card-meta-row { font-size: 10px; }
.line-item.market-row .market-card-meta-row .market-card-fresh { font-size: 9px; }
.line-item.market-row .line-discount-pill { font-size: 9px; padding: 1px 5px; }

/* ── Market row layered backdrop (TG-card style) ────────────────────────────
 * Each individual Market listing wears its gift's actual backdrop as a
 * radial gradient + tiled tinted symbol pattern — same recipe as the
 * modal hero card. _renderGiftCard sets the CSS vars + class inline at
 * render time (or applyBackdropsToAll upgrades cold-cache cards once
 * the manifest loads). Group cards are unchanged — their backdrop comes
 * from a sample listing and would mislead. Promoted .market-row--top
 * still wins via its !important gold halo.
 *
 * Radial centred at 22 px from the left ≈ behind the 32 px thumb (which
 * sits at padding-left 14 + half thumb 16 = ~22 px from row edge), so
 * the brightest backdrop spot frames the gift like the TG client. Edge
 * colour saturates by 80 % so the right end of long rows isn't washed. */
.line-item.gift-card-layered {
  position: relative;
  overflow: hidden;
  /* Round 11 (2026-05-04) — backdrop comes from a slice of the actual
   * proxy webp (the gift's TG-rendered card image, already loaded for
   * the thumb so this is bandwidth-free). The webp is scaled to row
   * width and positioned at `bottom center` so we see the bottom strip:
   * pure backdrop + symbols at TG's natural baked size, no model. The
   * dark overlay damps saturation so text stays legible. The radial
   * gradient is the visual fallback when the proxy 404s (rare on
   * Market — every active collection has a working endpoint).
   *
   * Background stack (top → bottom):
   *   1. linear-gradient overlay — mutes the slice for text contrast
   *   2. var(--proxy-url) bottom slice — authentic TG backdrop+symbols
   *   3. radial-gradient fallback — paints when the slice is `none`
   *      or its URL 404s
   */
  background:
    linear-gradient(rgba(15, 17, 24, 0.35), rgba(15, 17, 24, 0.35)),
    var(--proxy-url, none) top left / 150% auto no-repeat,
    radial-gradient(circle at 22px 50%,
                    var(--bg-center) 0%,
                    var(--bg-edge)   80%);
  border-left: 3px solid var(--bg-center, transparent);
}
/* Lift card content above the background layers. */
.line-item.gift-card-layered > * {
  position: relative;
  z-index: 1;
}
/* Text crispness on the layered backdrop. Round 13 (2026-05-04):
 * dropped `-webkit-font-smoothing: antialiased` — on Windows /
 * Telegram Desktop it disables subpixel rendering and text starts to
 * read as soft / "shakal'd" (user feedback with screenshot). Default
 * smoothing (subpixel-antialiased) is sharper on every desktop +
 * matches mobile native. Text-shadow blur dropped to 0 — a sharp
 * 1 px drop offset acts as a clean outline against the busy raster
 * background instead of haloing the letters. */
.line-item.gift-card-layered .line-name {
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}
/* Round 53 (2026-05-05) — WCAG contrast fix per user feedback.
 * General rule: body text on tier-tinted Market rows must be either
 * pure white or rgba(255,255,255,0.65+). NEVER use a tier-family colour
 * for text on a same-tier background. Tier hue belongs to the surface
 * only — text stays neutral. */

/* Gift ID (#339333) — was a darker shade of the row hue, lost on
 * orange/copper/gold rows. White at 55% with a soft shadow reads as
 * a secondary identifier without competing with the gift name. */
.line-item.gift-card-layered .line-gift-number {
  color: rgba(255, 255, 255, 0.55) !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* Model · Backdrop subtitle — bumped to 0.85 (was 0.55) so it survives
 * every tier color, with a stronger drop-shadow per spec. */
.line-item.gift-card-layered .line-count {
  color: rgba(255, 255, 255, 0.85);
  opacity: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Username + timestamp meta-row — neutral 65% white across every tier
 * background, never tinted to match the row. */
.line-item.gift-card-layered .market-card-meta-row {
  color: rgba(255, 255, 255, 0.65);
  opacity: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.line-item.gift-card-layered .market-card-fresh:not(.market-card--fresh-new) {
  color: rgba(255, 255, 255, 0.65);
  opacity: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Stars / TON values — force solid white on tier rows (was tier-family
 * gold/blue which disappeared into a same-tier bg). The ⭐ icon stays
 * gold, the diamond ⟁ stays blue — colour signal lives on the icon,
 * the digit reads against a neutral ink. !important needed because
 * `.line-item.market-row .line-floor-stars { color: var(--gold) }` and
 * `.line-floor-ton { color: #5ec1ff }` win on plain specificity. */
.line-item.gift-card-layered .line-floor,
.line-item.gift-card-layered .line-floor-stars,
.line-item.gift-card-layered .line-floor-ton {
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}
/* Discount listings keep their green colour signal (it's actively
 * informational — "below floor"), but with a darker shadow for readability. */
.line-item.gift-card-layered .line-floor--discount .line-floor-stars,
.line-item.gift-card-layered .line-floor--discount .line-floor-ton {
  color: #6fffae !important;
  -webkit-text-fill-color: #6fffae !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}

/* ── Market facet picker (custom dropdown for Collections / Models /
 *    Backdrops) ───────────────────────────────────────────────────────
 * Native <select> with 3170 options is unusable on mobile. _openFacetPicker
 * (app.js) replaces the dropdown with a modal sheet containing a search
 * input + filterable list. Same .modal-overlay / .modal-card chassis
 * as openGiftModal so the slide-up animation + dismiss behaviour are
 * inherited for free. */
.market-facet-sheet {
  display: flex;
  flex-direction: column;
  max-height: 80vh;
  padding: 14px 14px 16px;
  gap: 10px;
}/* Round 30 (2026-05-04) — "Show All" / "Show N" apply button at the
 * top-right of the picker header. Same recipe as Home's .dropdown-apply
 * (style.css:1138) so the two pickers read as the same family. Sits
 * between the title and the × close button. */
.market-facet-apply {
  appearance: none;
  -webkit-appearance: none;
  margin-left: auto;
  margin-right: 8px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  border: none;
  border-radius: 8px;
  background: var(--tg-accent, #2ea6ff);
  color: #fff;
  cursor: pointer;
}/* Round 30 — picker items now mirror Home's .dropdown-item layout
 * (style.css:1164): flex row with optional emoji/color square on the
 * left, name truncating with ellipsis, check indicator on the right. */
.market-facet-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  color: var(--tg-theme-text-color, var(--tg-text));
  cursor: pointer;
  transition: background 0.12s ease;
}/* Group header — separator row that appears when sort=group and the
 * gift_name changes between consecutive cards. Subtle band that reads
 * as a divider, not as a row, so it doesn't compete with the cards. */
.market-group-header {
  display: flex;
  align-items: center;
  padding: 12px 4px 6px;
  margin-top: 4px;
  border-top: 1px solid rgba(151, 111, 255, 0.18);
}
.market-group-header:first-child {
  margin-top: 0;
  border-top: none;
  padding-top: 4px;
}
.market-group-header-name {
  font-size: 13px;
  font-weight: 700;
  color: #d8c8ff;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* Gift number "#582" inline next to the gift name. Restored 2026-05-04
 * per user feedback after 1.5.31 minimalism dropped it. Rendered in a
 * muted weight so it reads as a secondary identifier — bold name +
 * subtle number, eye still hits the name first. font-variant-numeric
 * keeps digits aligned. */
.line-gift-number {
  color: var(--tg-hint, #97a1ad);
  font-weight: 600;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  margin-left: 2px;
}

/* Aggregated Group-view card — backend agent's Round 4 ship: when
 * sort=group, _renderGroupCard renders one row per (gift_name × model)
 * with a listing count + price-range instead of a single listing's
 * price. Same .line-item shell so tier gradients and halo rules apply
 * automatically; only the inner text spans need styling. */
.market-group-card { cursor: pointer; }
.market-group-card-model {
  /* Model name in muted parens after the bold gift name —
   * "Plush Pepe (Kung Fu Pepe)". Keeps secondary visual weight. */
  color: var(--tg-hint, #97a1ad);
  font-weight: 500;
}
.market-group-count {
  /* Listing count line: "12 listings · from" */
  color: var(--tg-hint, #97a1ad);
  font-size: 11.5px;
}
.market-group-from {
  opacity: 0.7;
  margin-left: 2px;
}
.market-group-range {
  /* Price-range upper bound, right-aligned under the lower price */
  display: block;
  font-size: 10px;
  color: var(--tg-hint, #97a1ad);
  margin-top: 2px;
  text-align: right;
}

/* Tappable seller @username inside .line-count subtitle — visually
 * identifies as a clickable filter without feeling like a link. */
.market-card-owner {
  color: var(--premium-blue, #5ec1ff);
  cursor: pointer;
  font-weight: 600;
  text-decoration: none;
  transition: opacity 0.15s;
}
.market-card-owner:hover { opacity: 0.85; }
.market-card-owner:active { opacity: 0.65; }

/* Inline TOP pill — same visual vocabulary as .flat-first-mint (#1
 * gold chip from style.css:1394) but with "TOP" label. Sits in the
 * .line-name-row next to the gift name, flex-shrink: 0. */
.market-top-pill {
  display: inline-block;
  padding: 1px 6px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.10em;
  color: #1c1409;
  background: linear-gradient(135deg, #ffe07a, #ff8a3d);
  border-radius: 999px;
  vertical-align: middle;
  box-shadow: 0 0 6px rgba(255, 150, 80, 0.50);
  flex-shrink: 0;
  text-transform: uppercase;
  line-height: 1.4;
}

/* Loading + empty states */
.market-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 30px 0;
  gap: 8px;
}

.market-loading-spinner {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid rgba(46,166,255,0.20);
  border-top-color: #2EA6FF;
  animation: spin 0.8s linear infinite;
}

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

.market-loading-text {
  color: var(--tg-hint, #708499);
  font-size: 12px;
}

.market-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 36px 16px;
  gap: 8px;
}
.market-empty-icon { font-size: 36px; opacity: 0.6; }
.market-empty-text { color: var(--tg-hint, #97a1ad); font-size: 13px; text-align: center; }

.market-error {
  padding: 24px;
  text-align: center;
  color: #ff8a8a;
}/* Promote modal */
.market-promote-modal-card {
  background: #1f2632;
  padding: 20px 18px 24px;
}

/* Round 117 (2026-05-13) — single-confirm mode for the promote modal.
   When the user comes from the Portfolio chip we already know which
   listing to boost, so the "Or all your gifts at once" section is
   irrelevant. Before this round the JS hid it with inline
   `style.display = 'none'` and restored it on close via a data-attr
   marker dance — fragile and the source of the snake_case / camelCase
   bug in Round 116.2. CSS-driven hide is the single source of truth:
   JS only toggles the modifier class, CSS owns visibility.
   The class is added by openPromoteModal({preselect}) and removed by
   _closePromoteModal — so reopening the modal in full-picker mode
   naturally restores the "all" section. */
.market-promote-modal-card--single .market-promote-section--all {
  display: none;
}

.market-promote-title {
  font-size: 18px;
  font-weight: 700;
  text-align: center;
  background: linear-gradient(135deg, #ffd96a, #ff6f9e);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-bottom: 4px;
}

.market-promote-sub {
  text-align: center;
  font-size: 12px;
  color: var(--tg-hint, #97a1ad);
  margin-bottom: 16px;
}

.market-promote-section {
  margin-bottom: 14px;
}

.market-promote-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--tg-hint, #97a1ad);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 6px;
}

.market-promote-mygifts {
  /* Round 39 — was max-height: 240px which clipped the list to ~3 visible
   * rows even though scrolling was enabled. Bumped so power-sellers can
   * actually see ≥10 listings without thumb-scrolling, while still
   * leaving room for the modal header + Promote-all CTA below. */
  max-height: 50vh;
  overflow-y: auto;
  background: rgba(0,0,0,0.18);
  border-radius: 10px;
  padding: 6px;
}

/* Round 39 — sort header above the gift list. Sticky so it stays
 * visible while the user scrolls through long lists. The toggle is
 * a tiny round button showing the current direction arrow. */
.market-promote-sort-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 6px 6px;
  position: sticky;
  top: 0;
  background: rgba(20, 22, 30, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 2;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  margin-bottom: 4px;
}
.market-promote-sort-label {
  font-size: 11px;
  color: var(--tg-theme-hint-color, var(--tg-hint));
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.market-promote-sort-toggle {
  appearance: none;
  -webkit-appearance: none;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  border: 1px solid rgba(151, 111, 255, 0.30);
  background: rgba(151, 111, 255, 0.14);
  color: #fff;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, transform 0.1s;
}
.market-promote-sort-toggle:hover { background: rgba(151, 111, 255, 0.24); }
.market-promote-sort-toggle:active { transform: scale(0.92); }

.market-promote-loading,
.market-promote-mygifts-empty {
  padding: 10px;
  text-align: center;
  color: var(--tg-hint, #97a1ad);
  font-size: 12px;
}

.market-promote-gift {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(255,255,255,0.03);
  margin-bottom: 4px;
}

.market-promote-gift-info { flex: 1; min-width: 0; }
.market-promote-gift-title {
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.market-promote-gift-price {
  font-size: 11px;
  color: #ffd96a;
}

.market-promote-gift-btn {
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(255,217,106,0.20), rgba(255,111,158,0.20));
  border: 1px solid rgba(255,200,90,0.40);
  color: #ffd96a;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}
.market-promote-gift-btn:hover { background: linear-gradient(135deg, rgba(255,217,106,0.32), rgba(255,111,158,0.32)); }
/* "Pay with balance" — secondary boost CTA from the in-app Stars wallet (beta only) */
.market-promote-balance-btn {
  display: block; width: 100%; margin-top: 10px; padding: 11px 14px;
  border-radius: 11px; border: 1px solid rgba(255,200,90,0.45);
  background: rgba(255,217,106,0.10); color: #ffd96a;
  font-size: 14px; font-weight: 700; cursor: pointer;
  transition: transform 0.12s ease, opacity 0.12s ease;
}
.market-promote-balance-btn:active { transform: scale(0.98); opacity: 0.9; }
.market-promote-balance-btn:disabled { opacity: 0.6; cursor: default; }
.market-promote-balance-hint {
  margin-top: 6px; text-align: center; font-size: 12px;
  color: var(--tg-theme-hint-color, rgba(255,255,255,0.55));
}
/* Disabled state — JS adds this class on per-row Promote buttons when
 * the user already has an active "all" promo (single-pin would stack).
 * Visually grayed + non-clickable. Backend agent (handoff item 5)
 * shipped the toggle but not the CSS, so the buttons looked enabled
 * even when they shouldn't fire. Added in 1.5.31. */
.market-promote-gift-btn--disabled,
.market-promote-gift-btn--disabled:hover {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  background: linear-gradient(135deg, rgba(150,150,150,0.10), rgba(150,150,150,0.10));
  border-color: rgba(150,150,150,0.20);
  color: #97a1ad;
}

.market-promote-all-btn {
  width: 100%;
  padding: 12px;
  background: linear-gradient(135deg, #FFD96A 0%, #FFA53D 50%, #FF6F9E 100%);
  color: #1c1409;
  font-weight: 700;
  font-size: 13px;
  border: none;
  border-radius: 14px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(255,160,80,0.30);
}
.market-promote-all-btn--disabled,
.market-promote-all-btn--disabled:hover {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  background: linear-gradient(135deg, #555, #555);
  color: #c2c8d0;
  box-shadow: none;
}

.market-promote-active {
  margin-top: 12px;
  padding: 10px 12px;
  background: rgba(255,200,90,0.10);
  border: 1px solid rgba(255,200,90,0.30);
  border-radius: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.market-promote-active-icon {
  font-size: 14px;
  color: #ffd96a;
}

.market-promote-active-text {
  font-size: 12px;
  color: #f5deb3;
  flex: 1;
}


/* ════════════════════════════════════════════════════════════════════
   Round 3 — additional Market UI
     • CTA row (Promote + My listings)
     • Infinite-scroll sentinel + end marker
     • Promo-history Settings section (Active vs Past)
     • Admin Analytics panel
   ════════════════════════════════════════════════════════════════════ */

/* CTA row holds the gold Promote button + the My listings toggle.
 * Vertical spacing already controlled by .market-stats margin-bottom
 * (14px) — keep this row's margin at 0 so the rhythm reads cleanly. */
.market-cta-row {
  /* Round 61-fix5 — parent .market-header is back to flex-wrap. The
   * `flex-basis: 100%` hack forces this row onto a new flex line below
   * the title+stats row. Grid is gone, so we own row placement again
   * via this trick. */
  flex-basis: 100%;
  display: flex;
  gap: 8px;
  justify-content: flex-start;
  flex-wrap: wrap;
  margin-top: 0;
}

.market-mylistings-toggle {
  padding: 10px 14px;
  background: rgba(46,166,255,0.12);
  color: #d0d8e1;
  border: 1px solid rgba(46,166,255,0.30);
  border-radius: 14px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.15s;
}
.market-mylistings-toggle:hover {
  background: rgba(46,166,255,0.20);
  color: #fff;
}
.market-mylistings-toggle.active {
  background: linear-gradient(135deg, rgba(46,166,255,0.28), rgba(151,111,255,0.28));
  color: #fff;
  border-color: rgba(46,166,255,0.55);
}

/* Infinite-scroll sentinel — invisible to users, only the JS observer
   notices when it intersects the viewport. Reserve a tiny height so
   layout doesn't collapse to 0px when there are no rows. */
.market-infinite-sentinel {
  height: 1px;
  width: 100%;
  margin-top: 4px;
}

.market-loadmore-fallback {
  display: flex;
  justify-content: center;
  margin: 12px 0;
}

.market-loadmore-btn {
  padding: 10px 22px;
  background: rgba(46,166,255,0.12);
  color: #d0d8e1;
  border: 1px solid rgba(46,166,255,0.30);
  border-radius: 14px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.market-loadmore-btn:hover {
  background: rgba(46,166,255,0.20);
  color: #fff;
}

.market-end-marker {
  text-align: center;
  color: var(--tg-hint, #708499);
  font-size: 11px;
  font-style: italic;
  padding: 16px 0;
}

/* Loading spinner shown at the bottom while fetching the next page */
.market-list-wrap .market-loading--inline {
  position: relative;
  background: transparent;
}

/* Promo-history Settings panel */
.settings-promo-history {
  padding: 0 14px;
}

.settings-promo-empty {
  text-align: center;
  color: var(--tg-hint, #97a1ad);
  font-size: 12px;
  padding: 20px 8px;
}

.settings-promo-group:not(:empty) {
  margin-bottom: 12px;
}

.settings-promo-group-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--tg-hint, #97a1ad);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin: 8px 4px 4px;
}

.settings-promo-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  margin-bottom: 6px;
}

.settings-promo-row--active {
  background: linear-gradient(135deg, rgba(255,200,90,0.10), rgba(255,160,80,0.08));
  border-color: rgba(255,200,90,0.30);
}

.settings-promo-row-icon {
  font-size: 16px;
  width: 28px;
  text-align: center;
}

.settings-promo-row-body {
  flex: 1;
  min-width: 0;
}

.settings-promo-row-title {
  font-size: 12px;
  font-weight: 600;
  color: #fff;
}

.settings-promo-row-meta {
  font-size: 11px;
  color: var(--tg-hint, #97a1ad);
  margin-top: 2px;
}

.settings-promo-row-status {
  flex: 0 0 auto;
  text-align: right;
  font-size: 10px;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 6px;
  letter-spacing: 0.05em;
}

.settings-promo-status--active {
  background: linear-gradient(135deg, #ffe07a, #ff8a3d);
  color: #1c1409;
  text-transform: uppercase;
}

.settings-promo-status--expired {
  background: rgba(255,255,255,0.06);
  color: var(--tg-hint, #97a1ad);
  text-transform: uppercase;
}

/* Past-promotions collapsible toggle — keeps Settings short by default;
   one tap reveals the full expired list. Same haptic+chevron pattern
   as the pf-history-toggle on the Portfolio page. */
.settings-promo-past-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  padding: 10px 12px;
  margin: 8px 0 6px;
  color: var(--tg-hint, #97a1ad);
  font: inherit;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.settings-promo-past-toggle:active {
  background: rgba(255,255,255,0.05);
}
.settings-promo-past-toggle-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.settings-promo-past-toggle-count {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 8px;
  background: rgba(255,255,255,0.08);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0;
}
.settings-promo-past-toggle-arrow {
  font-size: 12px;
  line-height: 1;
  transition: transform 0.18s ease;
}
.settings-promo-past-toggle--open .settings-promo-past-toggle-arrow {
  transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) {
  .settings-promo-past-toggle-arrow { transition: none; }
}

/* Admin Analytics panel — same visual language as the existing
   stats cards on Home (totals-card / stats-row / etc) */
.settings-admin-stats {
  padding: 0 14px;
}

.settings-admin-loading {
  text-align: center;
  color: var(--tg-hint, #97a1ad);
  font-size: 12px;
  padding: 18px 0;
}

.admin-stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 14px;
}

.admin-stat-card {
  background: linear-gradient(135deg, rgba(46,166,255,0.10), rgba(151,111,255,0.08));
  border: 1px solid rgba(46,166,255,0.20);
  border-radius: 12px;
  padding: 10px 12px;
}

.admin-stat-card-value {
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  line-height: 1.2;
}

.admin-stat-card-label {
  font-size: 10px;
  color: var(--tg-hint, #97a1ad);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 2px;
}

.admin-stat-card-delta {
  display: inline-block;
  margin-left: 5px;
  font-size: 10px;
  font-weight: 700;
}
.admin-stat-card-delta--up   { color: #6dffa3; }
.admin-stat-card-delta--down { color: #ff8a8a; }

.admin-stats-section {
  margin: 14px 0 6px;
  font-size: 11px;
  font-weight: 700;
  color: var(--tg-hint, #97a1ad);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.admin-stats-bar-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 0;
  font-size: 12px;
  border-bottom: 1px dashed rgba(255,255,255,0.04);
}
.admin-stats-bar-row:last-child { border-bottom: none; }
.admin-stats-bar-label { color: #d0d8e1; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-stats-bar-value { color: #ffd96a; font-weight: 700; padding-left: 8px; }

.admin-stats-day-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 0;
  font-size: 11px;
  border-bottom: 1px dashed rgba(255,255,255,0.04);
}
.admin-stats-day-row:last-child { border-bottom: none; }
.admin-stats-day-row-date { color: var(--tg-hint, #97a1ad); }
.admin-stats-day-row-meta { color: #d0d8e1; }
.admin-stats-day-row-meta-stars { color: #ffd96a; font-weight: 700; }


/* ════════════════════════════════════════════════════════════════════
   Round 2 round-trip fix (2026-05-05)
     • Search row + active-filter chips
     • Price-band (Min/Max + Apply)
     • Halo-cap (handoff item 10) — was using wrong .market-card--top
       selector; the actual rendered class is .market-row--top
   Palette matches the 1.5.31 minimalism direction (rgba 0.04/0.10
   neutrals, premium-purple accents on focus/active).
   ════════════════════════════════════════════════════════════════════ */

.market-search-row {
  display: flex;
  position: relative;
  margin: clamp(8px, 2.4vw, 14px) clamp(8px, 2.4vw, 14px) 0;
}

.market-search-input {
  flex: 1;
  min-width: 0;
  padding: 9px 36px 9px 14px;
  border-radius: 12px;
  /* Purple-tinted — same recipe as Home .search-input (#search-row-home)
   * so all input fields across the app share one visual language. */
  background: rgba(151, 111, 255, 0.08);
  border: 1px solid rgba(151, 111, 255, 0.22);
  color: var(--tg-theme-text-color, var(--tg-text));
  font-size: 13px;
  outline: none;
  transition: border-color 0.2s, background 0.2s;
}
.market-search-input:focus {
  border-color: var(--premium-purple, #976FFF);
  background: rgba(151,111,255,0.14);
}
.market-search-input::placeholder { color: rgba(151,161,173,0.7); }

.market-search-clear {
  position: absolute;
  right: 8px; top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: var(--tg-hint, #97a1ad);
  font-size: 18px;
  width: 24px; height: 24px;
  border-radius: 999px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.market-search-clear:hover { background: rgba(255,255,255,0.08); color: #fff; }

.market-active-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: clamp(6px, 1.6vw, 10px) clamp(8px, 2.4vw, 14px) 0;
}

.market-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px 3px 10px;
  background: rgba(151,111,255,0.18);
  border: 1px solid rgba(151,111,255,0.40);
  border-radius: 999px;
  font-size: 11px;
  color: #d8c8ff;
  cursor: pointer;
  transition: background 0.15s;
}
.market-filter-chip:hover { background: rgba(151,111,255,0.28); }

.market-filter-chip-x {
  /* Round 38 — chip × is now an <img>, not a text glyph. Tiny (10 px)
   * so the chip stays compact. font-size still listed in case any
   * other rule reaches for it as fallback text size. */
  width: 10px;
  height: 10px;
  font-size: 14px;
  line-height: 1;
  opacity: 0.65;
  margin-left: 2px;
}
.market-filter-chip:hover .market-filter-chip-x { opacity: 1; }

/* Price-band (Min/Max + Apply) */
.market-priceband-row {
  display: flex;
  gap: 8px;
  margin: clamp(6px, 1.6vw, 10px) clamp(8px, 2.4vw, 14px) clamp(10px, 2.4vw, 14px);
}

.market-priceband-input {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  border-radius: 12px;
  /* Purple-tinted — same family as .market-search-input + .market-filter-select */
  background: rgba(151, 111, 255, 0.08);
  border: 1px solid rgba(151, 111, 255, 0.22);
  color: var(--tg-theme-text-color, var(--tg-text));
  font-size: 13px;
  outline: none;
  appearance: none;
  -moz-appearance: textfield;
}
.market-priceband-input::-webkit-outer-spin-button,
.market-priceband-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.market-priceband-input::placeholder { color: rgba(151,161,173,0.6); }
.market-priceband-input:focus {
  border-color: var(--premium-purple, #976FFF);
  background: rgba(151,111,255,0.10);
}

.market-priceband-apply {
  flex: 0 0 auto;
  padding: 8px 14px;
  border-radius: 12px;
  background: rgba(151,111,255,0.22);
  border: 1.5px solid rgba(151,111,255,0.55);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.market-priceband-apply:hover {
  background: rgba(151,111,255,0.32);
  border-color: rgba(151,111,255,0.75);
}

/* Halo-cap — only first 5 promoted rows pulse. Beyond that, the gold
 * border + TOP badge are signal enough; pulsing 20+ rows simultaneously
 * was visually overwhelming and ate battery on long pages. The selector
 * was previously written as .market-card--top in style.css but the
 * rendered class is .market-row--top (set in _renderGiftCard). */
.line-item.market-row--top:nth-of-type(n+6) {
  animation: none;
}

/* ════════════════════════════════════════════════════════════════════════
   Portfolio Hero (pv2-*) — animated gradient hero card on #page-portfolio.
   Replaces the legacy .portfolio-card surface (Purchase → Floor → PnL).
   All classes are pv2-* namespaced — no collision with existing styles.
   Single source of truth: scratch_portfolio_integrated.html.
   Filed 2026-05-14 via contracts/requests/portfolio-hero-integration.md.
   ════════════════════════════════════════════════════════════════════════ */
.pv2-hero {
  position: relative;
  /* Horizontal margin matches the legacy .portfolio-card so the hero
     sits inside the page padding instead of edge-to-edge (otherwise it
     "breaks out" of the UI on narrow viewports). */
  margin: 4px clamp(12px, 3vw, 20px) clamp(8px, 2.5vw, 12px);
  border-radius: 18px;
  padding: clamp(12px, 3.2vw, 16px) clamp(13px, 3.5vw, 16px) clamp(10px, 2.6vw, 12px);
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(155deg, #5B7BE0 0%, #6B6FE3 30%, #8B6BE0 60%, #9B6FD8 100%);
  background-size: 200% 200%;
  animation: pv2HeroShift 14s ease infinite;
  box-shadow:
    0 8px 24px -8px rgba(108,96,224,0.45),
    inset 0 1px 0 rgba(255,255,255,0.18),
    inset 0 -1px 0 rgba(0,0,0,0.20);
  color: #fff;
}
@keyframes pv2HeroShift {
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}
.pv2-hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(circle at 14% 18%, rgba(255,255,255,0.22) 0%, transparent 45%),
    radial-gradient(circle at 86% 90%, rgba(0,0,0,0.22) 0%, transparent 55%);
}
.pv2-hero-sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg,
    rgba(255,255,255,0) 30%,
    rgba(255,255,255,0.10) 50%,
    rgba(255,255,255,0) 70%);
  mix-blend-mode: overlay;
}
.pv2-hero-stars { position: absolute; inset: 0; pointer-events: none; }
.pv2-hero-stars i {
  position: absolute; width: 2px; height: 2px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 5px rgba(255,255,255,0.9);
  opacity: 0.5;
  animation: pv2Twinkle 3.6s ease-in-out infinite;
}
.pv2-hero-stars i:nth-child(2){ animation-delay: 0.7s; }
.pv2-hero-stars i:nth-child(3){ animation-delay: 1.4s; }
.pv2-hero-stars i:nth-child(4){ animation-delay: 2.1s; }
.pv2-hero-stars i:nth-child(5){ animation-delay: 2.8s; }
@keyframes pv2Twinkle {
  0%,100% { opacity: 0.25; transform: scale(0.85); }
  50%     { opacity: 0.85; transform: scale(1.2);  }
}

.pv2-hero-head {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
}
.pv2-hero-eyebrow {
  font-size: 9px; font-weight: 800; letter-spacing: 1.4px; text-transform: uppercase;
  color: rgba(255,255,255,0.65);
  display: inline-flex; align-items: center; gap: 5px;
  min-width: 0;
}
.pv2-hero-eyebrow > span:last-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pv2-hero-eyebrow-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: #5fe39a;
  box-shadow: 0 0 8px rgba(95,227,154,0.85);
  animation: pv2Blink 2s ease-in-out infinite;
}
@keyframes pv2Blink { 0%,100%{opacity:1} 50%{opacity:.4} }

.pv2-hero-currency {
  display: inline-flex;
  padding: 2px;
  border-radius: 999px;
  background: rgba(0,0,0,0.32);
  border: 1px solid rgba(255,255,255,0.12);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  flex-shrink: 0;
}
.pv2-hero-currency button {
  appearance: none; border: 0; background: transparent;
  padding: 3px 8px;
  font-size: 10px; font-weight: 800;
  color: rgba(255,255,255,0.65);
  cursor: pointer; border-radius: 999px;
  font-family: inherit; letter-spacing: 0.3px;
  transition: background 0.15s, color 0.15s;
  line-height: 1.2;
}
.pv2-hero-currency button.active {
  background: rgba(255,255,255,0.20);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30);
}

.pv2-hero-value {
  position: relative; z-index: 1;
  /* center-align (was baseline) so the small TON SVG / Stars glyph
   * sits visually next to the BIG number's centre, not its baseline.
   * Baseline alignment plus the inline TON SVG's `vertical-align:-0.15em`
   * combined to drop the icon visibly below the digit row — user
   * feedback: «иконку ton и stars поправь, они как бы внизу текста». */
  display: flex; align-items: center; gap: 6px;
  margin-top: 6px;
  min-width: 0;
}
.pv2-hero-value-num {
  font-size: clamp(28px, 9vw, 38px); font-weight: 800; letter-spacing: -1.4px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: 0 1px 0 rgba(0,0,0,0.12);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
.pv2-hero-value-glyph {
  font-size: 20px; line-height: 1;
  filter: drop-shadow(0 0 6px rgba(255,209,102,0.55));
  flex-shrink: 0;
  display: inline-flex; align-items: center;
}
/* Override the inline `vertical-align:-0.15em` on TON brand SVGs
 * (set inside the TON_ICON_SVG string in portfolio-hero.js + the
 * gcCurrency.tonIcon() return value in currency.js). Inside the hero
 * we always want SVGs visually centred against their adjacent digits
 * — both for the big value, the PnL chip number, and the Purchase
 * sub-line. `!important` is needed because inline styles otherwise
 * win over the cascade. Scoped to .pv2-hero so other surfaces
 * (Home cards, Leaderboard rows, etc.) keep their existing offset. */
.pv2-hero svg { vertical-align: middle !important; }

.pv2-hero-pnl {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 5px;
  margin-top: 8px;
  padding: 3px 9px 3px 6px;
  border-radius: 999px;
  background: rgba(95,227,154,0.16);
  border: 1px solid rgba(95,227,154,0.30);
  color: #B4F0CC;
  font-size: 11px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  max-width: 100%;
}
.pv2-hero-pnl.down {
  background: rgba(255,138,138,0.16);
  border-color: rgba(255,138,138,0.30);
  color: #FFC6C6;
}
.pv2-hero-pnl-arrow {
  width: 12px; height: 12px; border-radius: 50%;
  background: rgba(95,227,154,0.36);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9px;
  color: #fff; line-height: 1;
  flex-shrink: 0;
}
.pv2-hero-pnl.down .pv2-hero-pnl-arrow { background: rgba(255,138,138,0.36); }
.pv2-hero-pnl-sep { opacity: 0.5; font-weight: 700; padding: 0 1px; }
.pv2-hero-pnl-pct { opacity: 0.9; font-weight: 700; }

/* Purchase sub-line under PnL chip — restores info that was shown
   side-by-side in the old .portfolio-card (Purchase $X → Floor $Y). */
.pv2-hero-purchase {
  position: relative; z-index: 1;
  margin-top: 4px;
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.35px; text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  font-variant-numeric: tabular-nums;
}
.pv2-hero-purchase-label { opacity: 0.7; }
.pv2-hero-purchase svg { width: 0.95em; height: 0.95em; vertical-align: -0.15em; margin-left: 0.1em; }

.pv2-hero-spark {
  position: relative; z-index: 1;
  margin: 8px 0 6px;
  height: 56px;
}
.pv2-hero-spark svg {
  width: 100%; height: 100%; display: block;
  overflow: visible;
}

.pv2-range {
  position: relative; z-index: 1;
  display: flex; gap: 2px;
  margin-top: 4px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(0,0,0,0.28);
  border: 1px solid rgba(255,255,255,0.10);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
}
.pv2-range button {
  flex: 1; appearance: none; border: 0; background: transparent;
  padding: 4px 6px; border-radius: 999px;
  cursor: pointer;
  color: rgba(255,255,255,0.60);
  font-size: 10px; font-weight: 800; letter-spacing: 0.2px;
  font-family: inherit;
  transition: background 0.15s, color 0.15s;
  min-width: 0;
}
.pv2-range button.active {
  background: rgba(255,255,255,0.20);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30);
}
/* Pro-gated ranges — same hard-cap as #pf-history-ranges (_PF_CHART_FREE_RANGES).
   Tapping a locked range opens the upgrade-to-Pro sheet. */
.pv2-range button.pv2-range-btn--locked {
  opacity: 0.4; cursor: not-allowed;
}
.pv2-range button.pv2-range-btn--locked::after {
  content: " \1F512"; font-size: 9px;
}

/* Refreshing badge — shown when /api/valuation/cached returned
   compute_state="fast_path" (backend hasn't classified ownership yet,
   so PnL / purchase numbers are phantoms). Toggled via data-refreshing
   on #portfolioHero. */
.pv2-hero[data-refreshing] .pv2-hero-pnl,
.pv2-hero[data-refreshing] .pv2-hero-purchase {
  opacity: 0.45;
}

/* ── Tap-to-expand: chart lives INSIDE the hero ───────────────────────
 * app.js _pfChartMount moves #pf-history into #portfolioHero so the
 * hero is one continuous block that grows when the user taps. CSS
 * below strips pf-history's own card chrome (background, border,
 * margin) so it sits flush inside the hero gradient. */
.pv2-hero #pf-history {
  position: relative; z-index: 1;
  margin: 12px -4px 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
/* The chart's own range picker, body, and tooltip stay styled as
 * before — only the OUTER container gets neutralised. */
.pv2-hero #pf-history-head,
.pv2-hero .pf-history-head {
  margin-bottom: 8px;
}
.pv2-hero #pf-history-body,
.pv2-hero .pf-history-body {
  background: rgba(0, 0, 0, 0.18);
  border-radius: 10px;
  padding: 6px 4px;
}
/* When the chart is open, hide the compact-mode sparkline + range
 * tabs to avoid duplication with the chart's own surface. The hero
 * eyebrow + value + PnL + purchase stay visible — they're the always-
 * on summary above the expanded chart. */
.pv2-hero--chart-open .pv2-hero-spark,
.pv2-hero--chart-open .pv2-range {
  display: none;
}

/* ════════════════════════════════════════════════════════════════════════
 * Prediction market + in-app Stars wallet (beta) — see js/predmarket.js
 * ════════════════════════════════════════════════════════════════════════ */
:root {
  --pm-yes: #34C759;       /* YES — iOS green */
  --pm-yes-soft: rgba(52, 199, 89, 0.16);
  --pm-no: var(--tg-destructive);
  --pm-no-soft: rgba(236, 57, 66, 0.16);

  /* ── V5 Lux redesign tokens ─────────────────────────────────────────────── */
  --pm-bg-1: #0a1420; --pm-bg-2: #0e1a2a; --pm-bg-3: #0c1725; --pm-bg-4: #0e1422;
  --pm-card: #232E3C; --pm-card-2: #1c2733; --pm-input: #101A24;
  --pm-fg: #F5F5F5; --pm-fg-2: #cbd6e4; --pm-hint: #708499; --pm-hint-2: #4a5664;
  --pm-gold-1: #FFE38A; --pm-gold-2: #FFCA28; --pm-gold-3: #E5A100;
  --pm-gold-text: #FFD680; --pm-gold-warm: #FFE5A8;
  --pm-yes-2: #5fe39a; --pm-yes-soft-2: rgba(52, 199, 89, 0.28);
  --pm-no-2: #FF8085; --pm-no-soft-2: rgba(236, 57, 66, 0.28);
  --pm-purple: #976FFF; --pm-purple-2: #C4A8FF; --pm-purple-soft: rgba(151, 111, 255, 0.16); --pm-info: #6AB3F3;
  --pm-blue: #6AB3F3; --pm-blue-2: #7DD0FF;
  --pm-border: rgba(255,255,255,0.06); --pm-border-2: rgba(151, 111, 255, 0.14);
  --pm-r-pill: 999px; --pm-r-sm: 8px; --pm-r-md: 12px; --pm-r-lg: 14px; --pm-r-xl: 18px; --pm-r-hero: 20px;
}

/* ── Header: gold wordmark + gold balance pill + round "+" top-up ──────────── */
.pm-header { display: flex; align-items: center; gap: 7px; padding: 2px 0 0; container-type: inline-size; }
.pm-wordmark {
  /* Responsive size so the WHOLE word "Predictions" always fits next to the
     Invite pill + balance pill (gradient-clipped text can't show an ellipsis,
     so it must scale, not clip). Sized off the header's own width via container
     units: 100cqi = header content width; subtract ~238px for the two
     fixed-width pills + gaps, divide by the word's px-per-font-px ratio. Caps at
     20px (handoff §4) on normal/wide phones, floors at 11px. The plain 17px
     fallback covers webviews without container-query support.
     margin-right:auto keeps the pills hard-right; overflow:hidden is a
     last-resort guard only. */
  font-size: 17px;
  font-size: clamp(11px, calc((100cqi - 238px) / 6.2), 20px);
  font-weight: 800; letter-spacing: -0.4px; line-height: 1.1; margin: 0 auto 0 0;
  min-width: 0; flex: 0 1 auto; overflow: hidden; white-space: nowrap;
  background: linear-gradient(180deg, var(--pm-gold-1) 0%, var(--pm-gold-2) 45%, var(--pm-gold-3) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 10px rgba(255, 184, 0, 0.32));
}
.pm-balance-pill {
  flex-shrink: 0; padding: 5px 6px 5px 12px; border-radius: var(--pm-r-pill);
  background: linear-gradient(180deg, rgba(255, 184, 0, 0.16) 0%, rgba(229, 161, 0, 0.08) 100%);
  border: 1px solid rgba(255, 205, 80, 0.40);
  box-shadow: inset 0 1px 0 rgba(255, 230, 150, 0.18), 0 2px 10px rgba(255, 184, 0, 0.16);
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
}
.pm-balance-pill:active { transform: scale(0.985); }
.pm-balance-num { font-size: 15px; font-weight: 800; color: var(--pm-gold-text); letter-spacing: 0.1px; font-variant-numeric: tabular-nums; }
.pm-topup-btn {
  width: 26px; height: 26px; border-radius: 999px; border: 0; cursor: pointer; padding: 0; margin: 0;
  background: linear-gradient(135deg, var(--pm-gold-1) 0%, var(--pm-gold-2) 50%, var(--pm-gold-3) 100%);
  color: #1a1205; font-size: 16px; font-weight: 900; line-height: 1; font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 2px 6px rgba(229, 161, 0, 0.32);
}
.pm-topup-btn:active { transform: scale(0.96); }
.pm-star { flex-shrink: 0; vertical-align: -2px; filter: drop-shadow(0 0 2px rgba(255,184,0,0.45)); }
.pm-num { font-variant-numeric: tabular-nums; letter-spacing: 0.1px; }

/* ── Segmented tabs (Markets / My bets) with sliding gold indicator ───────── */
.pm-seg {
  position: relative; display: flex; gap: 0; padding: 3px;
  background: linear-gradient(180deg, rgba(255,255,255,0.02) 0%, rgba(255,255,255,0.04) 100%);
  border: 1px solid rgba(255, 205, 80, 0.14); border-radius: var(--pm-r-md);
  box-shadow: inset 0 1px 0 rgba(255, 230, 150, 0.04); margin-top: 14px;
}
.pm-seg-slider {
  position: absolute; top: 3px; left: 3px; height: calc(100% - 6px); width: calc(50% - 6px);
  background: linear-gradient(180deg, rgba(255, 227, 138, 0.22) 0%, rgba(229, 161, 0, 0.10) 100%), rgba(20, 14, 6, 0.6);
  border: 1px solid rgba(255, 205, 80, 0.42); border-radius: 9px;
  box-shadow: inset 0 1px 0 rgba(255, 245, 200, 0.32), 0 2px 12px rgba(255, 184, 0, 0.20);
  transition: transform 0.28s cubic-bezier(0.5, 0.1, 0.25, 1); pointer-events: none;
}
.pm-seg[data-active="1"] .pm-seg-slider { transform: translateX(100%); }
/* Two-tab strip (Markets / My bets) — default 50% slider, indices 0..1. */
.pm-seg--2 .pm-seg-slider { width: calc(50% - 6px); }
.pm-seg--2[data-active="0"] .pm-seg-slider { transform: translateX(0); }
.pm-seg--2[data-active="1"] .pm-seg-slider { transform: translateX(100%); }
/* Three-tab strip (Markets / Events / My bets) — slider becomes 1/3 wide and
   slides between indices 0..2. data-active is the integer column index. */
.pm-seg--3 .pm-seg-slider { width: calc(33.333% - 4px); }
.pm-seg--3[data-active="0"] .pm-seg-slider { transform: translateX(0); }
.pm-seg--3[data-active="1"] .pm-seg-slider { transform: translateX(100%); }
.pm-seg--3[data-active="2"] .pm-seg-slider { transform: translateX(200%); }
.pm-seg-tab {
  flex: 1; min-width: 0; position: relative; z-index: 1; padding: 8px 10px;
  background: transparent; border: 0; cursor: pointer; font-family: inherit;
  color: rgba(245, 245, 245, 0.55); font-size: 13px; font-weight: 700; letter-spacing: 0.2px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: color 0.2s ease;
}
.pm-seg-tab.active { color: var(--pm-gold-warm); text-shadow: 0 0 12px rgba(255, 205, 80, 0.45); }
.pm-seg-count {
  font-size: 10.5px; font-weight: 700; padding: 1px 6px; border-radius: var(--pm-r-pill);
  background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.45); font-variant-numeric: tabular-nums;
  transition: background 0.2s ease, color 0.2s ease;
}
.pm-seg-count.active {
  background: linear-gradient(180deg, rgba(255, 227, 138, 0.28) 0%, rgba(229, 161, 0, 0.16) 100%);
  color: var(--pm-gold-warm); border: 1px solid rgba(255, 205, 80, 0.32); text-shadow: 0 0 6px rgba(255, 205, 80, 0.45);
}

/* ── Markets list container + empty state ─────────────────────────────────── */
#pm-list { padding: 14px 0 24px; }
.pm-empty { color: var(--pm-hint); text-align: center; padding: 36px 16px; font-size: 14px; }

/* ── Featured hero card ───────────────────────────────────────────────────── */
.pm-hero {
  position: relative; border-radius: var(--pm-r-xl); overflow: hidden; cursor: pointer;
  background: linear-gradient(160deg, #1a2434 0%, var(--pm-bg-2) 100%);
  border: 1px solid rgba(255, 205, 80, 0.32);
  box-shadow: 0 0 26px rgba(255, 205, 80, 0.12), inset 0 1px 0 rgba(255, 230, 150, 0.06);
  margin: 14px 0;
}
.pm-hero-glow {
  position: absolute; right: -50px; top: -40px; width: 230px; height: 230px;
  background: radial-gradient(circle at center, color-mix(in oklab, var(--g, #ff9d6b) 33%, transparent) 0%, transparent 60%);
  filter: blur(10px);
}
.pm-hero-art {
  position: absolute; right: -20px; top: 14px; width: 150px; height: 150px; object-fit: contain;
  opacity: 0.92; filter: drop-shadow(0 4px 22px rgba(0,0,0,0.45));
}
.pm-hero-inner { position: relative; padding: 14px 16px; }
.pm-badge-featured {
  display: inline-flex; align-items: center; font-size: 9px; font-weight: 800; letter-spacing: 0.8px;
  padding: 3px 8px; border-radius: var(--pm-r-pill);
  background: linear-gradient(135deg, var(--pm-gold-1) 0%, var(--pm-gold-2) 45%, var(--pm-gold-3) 100%);
  color: #1a1205; box-shadow: inset 0 1px 0 rgba(255,255,255,0.45);
}
.pm-hero-title { margin-top: 8px; font-size: 17px; font-weight: 700; line-height: 1.22; letter-spacing: -0.2px; max-width: 64%; color: var(--pm-fg); }
.pm-hero-stats { margin-top: 12px; display: flex; align-items: flex-end; gap: 12px; }
.pm-hero-pct { font-size: 32px; font-weight: 800; line-height: 1; letter-spacing: -1.2px; font-variant-numeric: tabular-nums; }
.pm-hero-pct .pm-pct-sign { font-size: 16px; opacity: 0.6; }
.pm-hero-pct--yes { color: var(--pm-yes-2); }
.pm-hero-pct--no  { color: var(--pm-no-2); }
.pm-hero-pct-label { font-size: 10px; font-weight: 700; letter-spacing: 0.4px; margin-top: 2px; }
.pm-hero-pct-label--yes { color: var(--pm-yes-2); }
.pm-hero-pct-label--no  { color: var(--pm-no-2); }
.pm-hero-pctline { display: inline-flex; align-items: baseline; gap: 7px; }
.pm-hero-pct-side { font-size: 19px; font-weight: 800; letter-spacing: -0.2px; line-height: 1; }
.pm-hero-pct-side--yes { color: var(--pm-yes-2); }
.pm-hero-pct-side--no  { color: var(--pm-no-2); }
.pm-hero-delta { margin-left: 4px; }
.pm-hero-spark { margin-left: auto; margin-right: 4px; }
.pm-hero-actions { display: flex; gap: 8px; margin-top: 12px; }
.pm-action {
  flex: 1; padding: 11px 13px; border-radius: var(--pm-r-md); border: 1px solid; cursor: pointer; font-family: inherit;
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left;
}
.pm-action:active { transform: scale(0.985); }
.pm-action-label { font-size: 11px; font-weight: 800; letter-spacing: 0.4px; }
.pm-action-payout { font-size: 12px; font-weight: 700; opacity: 0.9; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 4px; }
.pm-action-foot { font-size: 10px; font-weight: 600; opacity: 0.6; }
.pm-action--yes { background: rgba(52, 199, 89, 0.18); border-color: rgba(52, 199, 89, 0.45); color: var(--pm-yes-2); box-shadow: inset 0 1px 0 rgba(95, 227, 154, 0.18); }
.pm-action--no  { background: rgba(236, 57, 66, 0.16); border-color: rgba(236, 57, 66, 0.45); color: var(--pm-no-2); box-shadow: inset 0 1px 0 rgba(255, 128, 133, 0.18); }
.pm-hero-meta { margin-top: 10px; display: flex; gap: 14px; align-items: center; font-size: 11px; color: var(--pm-hint); }
.pm-hero-meta-closes { margin-left: auto; }
.pm-meta-num { display: inline-flex; align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }

/* ── Filter chips ─────────────────────────────────────────────────────────── */
/* Filter chips auto-fit the row (flex:1, equal cells) so all four always show
   without a cut-off / horizontal scroll, on any screen width. */
/* Market-name search (Predict page, Markets tab). Static row above #pm-list;
 * dark-glass pill on the --pm-* palette (loupe left, clear × right). Horizontal
 * insets come from #page-predictions' 16px page padding, so margins are vertical. */
.pm-search-row { display: flex; align-items: center; position: relative; margin: 10px 0 0; }
.pm-search-loupe { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--pm-hint); pointer-events: none; }
.pm-search-input {
  flex: 1; min-width: 0;
  padding: 10px 38px 10px 38px;
  border-radius: var(--pm-r-pill);
  background: var(--pm-input); border: 1px solid var(--pm-border-2);
  color: var(--pm-fg); font-family: inherit; font-size: 13.5px;
  outline: none; transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.pm-search-input::placeholder { color: var(--pm-hint); }
.pm-search-input:focus { border-color: rgba(255, 202, 40, 0.45); background: #0c1622; box-shadow: 0 0 0 2px rgba(255, 202, 40, 0.16); }
.pm-search-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.06); border: none; border-radius: var(--pm-r-pill);
  color: var(--pm-hint); cursor: pointer; transition: background 0.15s ease;
}
.pm-search-clear:hover { background: rgba(255,255,255,0.12); }
.pm-search-clear:active { transform: translateY(-50%) scale(0.92); }
.pm-search-clear .gc-icon { width: 13px; height: 13px; opacity: 0.78; }
.pm-search-clear:hover .gc-icon { opacity: 1; }
.pm-chips { display: flex; gap: 6px; margin: 10px 0 14px; padding: 0; }
.pm-chip {
  flex: 1 1 0; min-width: 0; cursor: pointer; font-family: inherit; padding: 7px 6px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0; color: rgba(245, 245, 245, 0.68);
  background: linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.015) 100%);
  border: 1px solid rgba(255,255,255,0.07); border-radius: var(--pm-r-pill);
  white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  transition: transform 0.12s ease, background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.pm-chip:active { transform: scale(0.96); }
.pm-chip-count { font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45); padding: 1px 5px; border-radius: var(--pm-r-pill); background: rgba(255,255,255,0.05); letter-spacing: 0; font-variant-numeric: tabular-nums; flex-shrink: 0; }
.pm-chip.active {
  color: var(--pm-fg);
  background: linear-gradient(180deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.06) 100%), rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.16); box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 2px 6px rgba(0,0,0,0.18);
}
.pm-chip.active .pm-chip-count { background: rgba(255,255,255,0.16); color: rgba(255,255,255,0.88); }
.pm-chip--hot { color: #FFCA9A; background: linear-gradient(180deg, rgba(255, 122, 61, 0.16) 0%, rgba(224, 57, 92, 0.10) 100%); border-color: rgba(255, 122, 61, 0.32); box-shadow: inset 0 1px 0 rgba(255, 200, 130, 0.18); }
.pm-chip--hot.active { color: #FFE2C9; background: linear-gradient(180deg, rgba(255, 122, 61, 0.32) 0%, rgba(224, 57, 92, 0.20) 100%); border-color: rgba(255, 122, 61, 0.55); box-shadow: inset 0 1px 0 rgba(255, 230, 195, 0.22), 0 2px 10px rgba(255, 122, 61, 0.18); }
.pm-chip--urgent { color: #FFD680; background: linear-gradient(180deg, rgba(255, 184, 0, 0.10) 0%, rgba(255, 184, 0, 0.04) 100%); border-color: rgba(255, 184, 0, 0.26); }

/* ── Standard market card ─────────────────────────────────────────────────── */
.pm-card {
  position: relative; background: var(--pm-card); border-radius: var(--pm-r-lg);
  border: 1px solid var(--pm-border-2); padding: 12px 14px 12px 18px; margin-bottom: 8px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04); overflow: hidden;
  display: flex; align-items: center; gap: 11px; cursor: pointer;
}
/* Entry animation runs ONLY for cards freshly inserted by _pmReconcile (they get
   .pm-enter) — never on an in-place refresh, so the list no longer re-cascades on
   every odds/pool update. */
.pm-card.pm-enter { animation: fadeInUp 0.35s ease-out backwards; }
.pm-card:active { transform: scale(0.97); transition: transform 0.06s ease-out; }
.pm-card--closed { opacity: 0.82; }
.pm-card-stripe { position: absolute; left: 0; top: 12px; bottom: 12px; width: 3px; background: var(--tier, #5fe39a); opacity: 0.75; }
.pm-card--closed .pm-card-stripe { opacity: 0.3; }
.pm-card-art {
  position: relative; flex-shrink: 0; width: 44px; height: 44px; border-radius: 10px;
  background: radial-gradient(ellipse at center, color-mix(in oklab, var(--tier, #5fe39a) 20%, transparent) 0%, transparent 70%), var(--pm-bg-2);
  display: inline-flex; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,0.04); overflow: hidden;
}
.pm-card-art img { width: 92%; height: 92%; object-fit: contain; }
/* Monogram shown when a market has no gift image (user-created markets, or a
   gift whose thumb isn't cached). Sits on the tier-tinted art box so every
   single-market card reads as one design. */
.pm-card-mono { font-size: 19px; font-weight: 800; color: rgba(255,255,255,0.92); line-height: 1; letter-spacing: -0.5px; }
.pm-pos-dot { position: absolute; top: -3px; right: -3px; width: 12px; height: 12px; border-radius: 999px; border: 2px solid var(--pm-card); }
.pm-pos-dot--yes { background: var(--pm-yes); }
.pm-pos-dot--no  { background: var(--pm-no); }
.pm-card-body { flex: 1; min-width: 0; }
.pm-card-title-row { display: flex; align-items: center; gap: 6px; }
.pm-card-title { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--pm-fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pm-card-meta { display: flex; gap: 10px; align-items: center; margin-top: 6px; font-size: 11px; color: var(--pm-hint); }
.pm-card-meta-closes { margin-left: auto; }
.pm-card-meta-closes.urgent { color: var(--pm-gold-2); font-weight: 700; }
.pm-card-pct { flex-shrink: 0; min-width: 56px; text-align: right; }
.pm-card-pct-num { font-size: 24px; font-weight: 800; line-height: 1; letter-spacing: -0.8px; font-variant-numeric: tabular-nums; }
.pm-card-pct-num span { font-size: 13px; opacity: 0.65; }
.pm-card-pct--yes .pm-card-pct-num { color: var(--pm-yes); }
.pm-card-pct--no  .pm-card-pct-num { color: var(--pm-no); }
.pm-card--closed .pm-card-pct-num { color: var(--pm-hint) !important; }
.pm-card-pct-side { font-size: 10px; font-weight: 700; color: var(--pm-hint); margin-top: 2px; letter-spacing: 0.4px; }

/* ── Probability bar (spectrum + needle) ──────────────────────────────────── */
.pm-bar { margin-top: 5px; }
.pm-bar--spectrum { position: relative; height: 5px; border-radius: 3px; overflow: hidden; background: rgba(255,255,255,0.04); }
/* Odds glide when _pmReconcile patches --yes on the live node (was a hard snap). */
.pm-bar--spectrum::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: var(--yes, 50%); background: linear-gradient(90deg, var(--pm-yes) 0%, var(--pm-yes-2) 100%); transition: width 0.5s cubic-bezier(0.2,0.8,0.3,1); }
.pm-bar--spectrum::after { content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: calc(100% - var(--yes, 50%)); background: linear-gradient(90deg, var(--pm-no) 0%, #c92e36 100%); transition: width 0.5s cubic-bezier(0.2,0.8,0.3,1); }
.pm-bar-needle { position: absolute; top: -2px; bottom: -2px; width: 2px; background: rgba(255,255,255,0.92); box-shadow: 0 0 6px rgba(0,0,0,0.6); left: calc(var(--yes, 50%) - 1px); transition: left 0.5s cubic-bezier(0.2,0.8,0.3,1); }

/* ── Binary (YES/NO) card — fully fluid, identical on PC + phone ──────────────
   The fixed right-side % column was reserving the same pixels regardless of the
   (narrower) PC mini-app window, so the question clipped + the stats wrapped to
   3–4 lines on desktop. Now the % sits INLINE beside the bar; only the thumb
   (46px) and the % label (min-width:52px) are fixed — everything else flexes.
   Verified identical at 320 / 340 / 390px. */
.pm-card { align-items: flex-start; }
.pm-card-art { width: 40px; height: 40px; border-radius: 12px; }   /* = event accordion tile (40px) */
.pm-card-title-row { align-items: flex-start; }
/* Question wraps to max 2 lines and is never clipped (was 1-line ellipsis, which
   the fixed column squeezed down to "Will bt…"). */
.pm-card-title {
  font-size: 14px; font-weight: 700; letter-spacing: -0.1px;
  white-space: normal; text-overflow: clip; line-height: 1.25; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
/* ONE badge chip on both screens — Markets `.pm-tag` (NEW/HOT) and My-markets
   `.v6m-badge` (Live/Resolved/…) now share identical size/padding/radius/type;
   only the per-state color + label differ. */
.pm-card-title-row .pm-tag,
.pm-card-title-row .v6m-badge {
  font-size: 9px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase;
  padding: 3px 7px; border-radius: 6px;
}
/* Tier-tinted thumbnail glyph / id chip (replaces the hollow-letter monogram). */
.pm-card-glyph { font-size: 27px; font-weight: 800; line-height: 1; color: var(--tier, #fff); }   /* fills the 40px tile like the event's gift image */
.pm-card-idchip { font-size: 11px; font-weight: 800; line-height: 1; letter-spacing: -0.5px; color: var(--tier, #fff); font-variant-numeric: tabular-nums; }
/* Bar row: bar (flex) + inline leading-% label (fixed min-width, never wraps). */
.pm-card-barrow { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.pm-card-barrow .pm-bar { flex: 1; min-width: 0; margin-top: 0; }
.pm-card-pct-inline {
  flex-shrink: 0; min-width: 52px; text-align: right; white-space: nowrap;
  font-size: 11.5px; font-weight: 700; color: var(--pm-hint); font-variant-numeric: tabular-nums;
}
.pm-card-pct-inline b { font-size: 14px; font-weight: 800; letter-spacing: -0.4px; }
.pm-card-pct-inline--yes { color: var(--pm-yes); }
.pm-card-pct-inline--no  { color: var(--pm-no); }
.pm-card-pct-inline--closed { color: var(--pm-hint); }
/* Stats row: pool · bets · time on ONE line (never wrap); chevron pushed right. */
.pm-card-meta { gap: 5px; flex-wrap: nowrap; }
.pm-card-meta > span { white-space: nowrap; flex-shrink: 0; }
.pm-card-meta-closes { margin-left: 0; }
.pm-meta-sep { opacity: 0.45; flex-shrink: 0; }
.pm-card-meta .pm-card-chev { margin-left: auto; width: 20px; height: 20px; align-self: center; flex-shrink: 0; }
/* Resolved My-markets card dims to 0.82 (operator spec) — single source, so the
   inner .pm-card--closed doesn't double-dim inside the wrapper. */
.pm-mm-card--resolved { opacity: 0.82; }
.pm-mm-card .pm-card--closed { opacity: 1; }

/* ── Binary card — exact match to "Binary Card — Fluid.html" (.bcf-*) ─────────
   Operator's 5 design-match fixes; reference values applied verbatim. */
/* 1 · Bar: 8px pill, red track + rounded green fill, no needle. */
.pm-card-barrow .pm-bar { height: 8px; border-radius: 999px; background: linear-gradient(90deg, #ec3942, #c92e36); overflow: hidden; position: relative; }
.pm-card-barrow .pm-bar--spectrum::before { width: var(--yes, 50%); border-radius: 999px; background: linear-gradient(90deg, #3fae6f, #5fe39a); }
.pm-card-barrow .pm-bar--spectrum::after { display: none; }
.pm-card-barrow .pm-bar-needle { display: none; }
/* 2 · Bar ↔ % on one centered row, 9px gap. */
.pm-card-barrow { gap: 9px; align-items: center; margin-top: 0; }
/* 3 · Vertical rhythm — 12×14 padding, 9px between title-row → bar → stats. */
/* Tighter vertical density so single binary cards match the (denser)
   multi-outcome event cards in the Markets list — operator: "reduce the size
   of single markets to match markets with a couple of outcomes". */
.pm-card { padding: 10px 14px; }
.pm-card-title-row { margin-bottom: 7px; }
.pm-card-meta { margin-top: 7px; gap: 7px; font-size: 11.5px; }
/* Markets filter chips (All/Hot/Ending) were `flex:1 1 0` (equal-width), so on a
   wide/high-res PC window they stretched into big pills. Size them to content,
   matching the My-markets chip row — compact, never stretched. */
#pm-list .pm-chips { flex-wrap: nowrap; overflow-x: auto; gap: 6px; scrollbar-width: none; -ms-overflow-style: none; }
#pm-list .pm-chips::-webkit-scrollbar { display: none; }
#pm-list .pm-chips .pm-chip { flex: 0 0 auto; padding: 6px 10px; font-size: 11.5px; }
/* ── Single-card foot mirrors the multi-outcome event card's mini-row ─────────
   Date (period) on the LEFT, pool ⭐ · bets on the RIGHT; text sizes + colors
   taken from the event card (.pm-evt-minirow #708499 / .pm-evt-minilead
   #5b6b7d). The thumb tile + the leading % are matched too. */
.pm-card-meta { justify-content: flex-start; gap: 6px; color: #708499; font-size: 10.5px; margin-top: 0; }  /* = event mini-row: 10.5px; gap ~4px (the bar-row overhang already adds it) */
.pm-card-meta-date { flex-shrink: 0; white-space: nowrap; font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: #5b6b7d; }
.pm-card-meta-stats { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0; }
.pm-card-meta-stats .pm-meta-sep { color: rgba(255,255,255,0.25); }
/* % beside the bar: the % itself is tier-coloured (inline style); the side word
   (YES/NO) is a muted suffix like the event's period. No more green/red. */
.pm-card-pct-inline { color: #708499; }
.pm-card-pct-inline--closed b { color: var(--pm-hint) !important; }
/* Thumb tile = event card's gift tile (stronger tier radial + tier glow). */
.pm-card-art {
  background: radial-gradient(ellipse at center, color-mix(in oklab, var(--tier, #5fe39a) 34%, transparent), transparent 70%), #0e1a2a;
  border-color: rgba(255,255,255,0.10);
  box-shadow: 0 4px 14px color-mix(in oklab, var(--tier, #5fe39a) 33%, transparent), inset 0 1px 0 rgba(255,255,255,0.06);
}
/* 4 · % label — 13px / 800, tabular, exact lead colors. */
.pm-card-pct-inline { font-size: 13px; font-weight: 800; letter-spacing: 0.2px; }
.pm-card-pct-inline b { font-size: 13px; font-weight: 800; letter-spacing: 0.2px; }
.pm-card-pct-inline--yes { color: #5fe39a; }
.pm-card-pct-inline--no  { color: #ff6b6b; }
.pm-card-pct-inline--closed { color: #9aa7b8; }
.pm-meta-sep { color: rgba(255,255,255,0.25); opacity: 1; }
/* 5 · Thumb radial glow (was flat) + brighter tier-tinted glyph / id chip. */
.pm-card-art { background: radial-gradient(ellipse at center, color-mix(in oklab, var(--tier, #5fe39a) 20%, transparent), transparent 70%), #0e1a2a; border-color: rgba(255,255,255,0.06); }
.pm-card-glyph { color: color-mix(in oklab, var(--tier, #5fe39a) 70%, #fff); }
.pm-card-idchip { color: color-mix(in oklab, var(--tier, #5fe39a) 80%, #fff); }
/* Uniform single-market card height without a dead gap under 1-line titles.
   The body is a flex column whose min-height equals a 2-line card's natural
   height (73px). On a 1-line card the leftover line of space is split by the two
   `margin-top:auto` anchors — a little above the title, the rest above the meta
   — so title+bar sit slightly off the top (not jammed against it) and the
   date·pool·bets row pins to the BOTTOM, aligned with 2-line cards. 2-line cards
   have no slack (content == min-height) so they're unchanged. Shared
   renderMarketCard → covers Markets + My-markets. */
.pm-card-body { display: flex; flex-direction: column; min-height: 73px; }
.pm-card-title-row { margin-top: auto; }
.pm-card-meta { margin-top: auto; }

/* ── Tags (HOT / NEW / ENDING / RESOLVED) ─────────────────────────────────── */
.pm-tag { font-size: 9px; font-weight: 800; letter-spacing: 0.6px; padding: 3px 7px; border-radius: var(--pm-r-pill); white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; }
.pm-tag--hot      { background: rgba(255, 107, 53, 0.16);  border: 1px solid rgba(255, 107, 53, 0.35);  color: #FFB077; }
.pm-tag--new      { background: rgba(151, 111, 255, 0.16); border: 1px solid rgba(151, 111, 255, 0.35); color: #C4A8FF; }
.pm-tag--ending   { background: rgba(255, 202, 40, 0.16);  border: 1px solid rgba(255, 202, 40, 0.35);  color: var(--pm-gold-2); }
.pm-tag--resolved { background: var(--pm-yes-soft);        border: 1px solid rgba(52, 199, 89, 0.35);   color: var(--pm-yes-2); }
.pm-tag--resolved.no { background: var(--pm-no-soft); border-color: rgba(236, 57, 66, 0.35); color: var(--pm-no-2); }

/* ── Delta (odds movement ↑/↓) ────────────────────────────────────────────── */
.pm-delta { margin-left: 4px; font-variant-numeric: tabular-nums; }
.pm-delta--up   { color: var(--pm-yes-2); }
.pm-delta--down { color: #FF5252; }

/* Bottom sheets (bet + top-up) — mirrors .pf-sheet chrome */
.pm-sheet-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.7);
  z-index: 1000; display: flex; align-items: flex-end; justify-content: center;
  /* Absorb wheel/touch events that land on the dimmed scrim — without this
     iOS WKWebView lets the touch pass through to the page underneath and
     rubber-band the body. Combined with body.pm-overlay-scroll-lock below. */
  overscroll-behavior: contain;
  touch-action: none;
}
/* Children (the sheet + its interactive contents) need their own touch
   handling — restore default touch-action on the sheet so taps/scrolls
   inside the sheet (gift grid scroll, button taps) work normally. */
.pm-sheet-overlay > * { touch-action: auto; }
.pm-sheet-overlay.hidden { display: none; }

/* Body scroll-lock — toggled by predmarket.js showOverlay / hideOverlay
   when ANY pm overlay (deposit, referral, market-detail, etc.) is open.
   The fixed-position trick (`position:fixed; width:100%`) would also
   preserve scroll position on iOS but introduces a flash; plain
   overflow:hidden is enough for the TG WebView's body scroll. */
body.pm-overlay-scroll-lock {
  overflow: hidden;
  touch-action: none;
}
.pm-sheet {
  position: relative;
  background: #1b2736;
  border-top-left-radius: 20px; border-top-right-radius: 20px;
  width: 100%; max-width: 560px;
  max-height: 88vh; max-height: 88dvh; overflow-y: auto;
  padding: 20px 18px calc(env(safe-area-inset-bottom, 12px) + 18px);
  animation: pmSheetUp 0.28s ease-out;
}
@keyframes pmSheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.pm-sheet-close {
  position: absolute; top: 12px; right: 14px;
  width: 30px; height: 30px; border-radius: 50%;
  border: none; background: var(--tg-bg-input); color: var(--tg-hint);
  font-size: 15px; cursor: pointer; line-height: 30px; text-align: center;
}
.pm-sheet-close:active { opacity: 0.7; }
.pm-sheet-title { font-size: 17px; font-weight: 700; color: var(--tg-text); margin: 0 30px 4px 0; line-height: 1.3; }
.pm-sheet-sub { color: var(--tg-hint); font-size: 13px; margin: 0 0 14px; }

/* Yes/No toggle */
.pm-side-row { display: flex; gap: 10px; margin: 14px 0; }
.pm-side-btn {
  flex: 1; padding: 14px 8px; border-radius: 12px; cursor: pointer;
  border: 2px solid var(--tg-separator); background: var(--tg-bg-input);
  color: var(--tg-hint); font-size: 15px; font-weight: 700;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
}
.pm-side-btn--yes.active { border-color: var(--pm-yes); background: var(--pm-yes-soft); color: var(--pm-yes); }
.pm-side-btn--no.active { border-color: var(--pm-no); background: var(--pm-no-soft); color: var(--pm-no); }
.pm-side-btn:active { transform: scale(0.98); }

/* Stake input + quick picks */
.pm-stake-input {
  width: 100%; box-sizing: border-box;
  background: var(--tg-bg-input); border: 1px solid var(--tg-separator);
  border-radius: 12px; padding: 13px 16px; color: var(--tg-text);
  font-size: 16px; outline: none; margin-bottom: 10px;
}
.pm-stake-input:focus { border-color: var(--tg-accent); }
.pm-quick-row { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.pm-quick, .pm-topup-quick {
  flex: 1; min-width: 56px; padding: 10px 6px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--tg-separator); background: var(--tg-bg-input);
  color: var(--tg-text); font-size: 14px; font-weight: 600;
}
.pm-quick:active, .pm-topup-quick:active { background: var(--tg-bg-secondary); transform: scale(0.97); }

.pm-est { color: var(--tg-text); font-size: 14px; margin: 4px 0 16px; min-height: 20px; }
.pm-est b { color: var(--gold-bright); }
.pm-est-hint { color: var(--tg-hint); font-size: 12px; }

.pm-bet-foot { display: flex; align-items: center; gap: 12px; }
.pm-bal { color: var(--tg-hint); font-size: 13px; }
.pm-bal span { color: var(--gold-bright); font-weight: 600; }
.pm-place-btn {
  margin-left: auto; flex: 1;
  background: linear-gradient(135deg, var(--premium-blue) 0%, var(--premium-purple) 100%);
  color: #fff; font-weight: 700; font-size: 16px;
  border: none; border-radius: 12px; padding: 14px; cursor: pointer;
  transition: opacity 0.15s ease, transform 0.12s ease;
}
.pm-place-btn:active { transform: scale(0.98); }
.pm-place-btn:disabled { opacity: 0.5; cursor: default; }
#pm-topup-go { margin-top: 4px; }

/* Deposit-gifts entry on the top-up sheet (ships dark; shown only when
   /api/wallet/balance reports gift_exchange_enabled). Secondary to "Top up". */
.pm-deposit-btn {
  width: 100%; box-sizing: border-box; margin-top: 10px;
  background: var(--tg-bg-input); color: var(--tg-text);
  font-weight: 600; font-size: 15px;
  border: 1px solid var(--tg-separator); border-radius: 12px; padding: 13px;
  cursor: pointer; transition: opacity 0.15s ease, transform 0.12s ease;
}
.pm-deposit-btn:active { transform: scale(0.98); opacity: 0.85; }
#pm-deposit-step { margin-top: 2px; }
.pm-deposit-countdown {
  text-align: center; font-size: 13px; font-weight: 600;
  color: var(--gold-bright); margin: 0 0 14px;
}
.pm-deposit-wait {
  text-align: center; font-size: 12px; color: var(--tg-hint); margin-top: 12px;
}
.pm-deposit-wait--ok {           /* credited: "✅ +N⭐ — gift" */
  color: var(--pm-yes); font-weight: 700; font-size: 14px;
}
/* Copyable custody @handle (the address to transfer gifts to) */
.pm-deposit-handle {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; box-sizing: border-box; margin: 0 0 12px; padding: 12px;
  background: var(--tg-bg-input); border: 1px dashed var(--tg-separator);
  border-radius: 12px; cursor: pointer;
  color: var(--gold-bright); font-weight: 700; font-size: 16px;
  transition: opacity 0.15s ease, transform 0.12s ease;
}
.pm-deposit-handle:active { transform: scale(0.99); opacity: 0.85; }
.pm-deposit-copy-hint { color: var(--tg-hint); font-weight: 600; font-size: 12px; }
/* Guided deposit picker — grid of the user's depositable gifts + per-gift price */
.pm-gift-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin: 4px 0 6px; max-height: 46vh; overflow-y: auto;
}
.pm-gift-card {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 6px 12px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--tg-separator); background: var(--tg-bg-input);
  color: var(--tg-text); transition: transform 0.12s ease, border-color 0.15s ease;
}
.pm-gift-card:active { transform: scale(0.97); }
.pm-gift-card-img {
  position: relative; width: 56px; height: 56px; border-radius: 10px;
  background: var(--tg-bg-secondary); overflow: hidden;
}
.pm-gift-card-img::before {           /* 🎁 placeholder when no thumbnail (or it 404s) */
  content: "🎁"; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; font-size: 26px;
}
.pm-gift-card-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pm-gift-card-name {
  font-size: 11px; line-height: 1.25; text-align: center;
  max-height: 28px; overflow: hidden; color: var(--tg-text);
}
.pm-gift-card-price { font-size: 13px; font-weight: 700; color: var(--gold-bright); }
.pm-gift-card-x { color: var(--tg-hint); font-weight: 600; font-size: 10px; }
.pm-gift-empty {
  grid-column: 1 / -1; text-align: center; color: var(--tg-hint);
  font-size: 13px; padding: 24px 0;
}
/* "Send any collectible" — deposit a gift not in the picker (e.g. hidden gifts) */
.pm-deposit-any {
  display: block; width: 100%; box-sizing: border-box; margin-top: 6px;
  background: none; border: none; cursor: pointer;
  color: var(--tg-accent, #3390ec); font-size: 13px; text-align: center; padding: 8px;
}
.pm-deposit-any:active { opacity: 0.7; }
.pm-deposit-receive {
  text-align: center; font-size: 15px; font-weight: 700;
  color: var(--gold-bright); margin: 0 0 12px;
}
/* Deposit send-step — numbered 1-2-3 guide (top-apps style). Drives the user
   through open → transfer → credit with a clear visual stepper. */
.pm-dep-steps {
  list-style: none; margin: 14px 0 6px; padding: 0;
  display: flex; flex-direction: column; gap: 15px;
}
.pm-dep-step { display: flex; align-items: flex-start; gap: 12px; }
.pm-dep-step-n {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; color: #1a1205;
  background: linear-gradient(145deg, #FFE38A, #E5A100);
  box-shadow: 0 1px 6px rgba(229, 161, 0, 0.35);
}
.pm-dep-step-body { flex: 1 1 auto; min-width: 0; }
.pm-dep-step-t { font-size: 14px; font-weight: 700; color: var(--tg-text); line-height: 1.3; }
.pm-dep-step-d { font-size: 12px; color: var(--tg-hint); line-height: 1.35; margin-top: 3px; }
/* The address chip + receive amount live inside steps 2 and 3 — align them left
   and tighten margins so they read as part of the step, not standalone blocks. */
.pm-dep-step-body .pm-deposit-handle { margin: 9px 0 7px; font-size: 15px; }
.pm-dep-step-body .pm-deposit-receive { text-align: left; font-size: 15px; margin: 4px 0 2px; }
/* ── Gift withdrawal (Stars → collectible) ──────────────────────────────────
   Reuses the deposit grid/card; adds an entry-button tint, a 2-up grid so the
   "Withdraw — N⭐" CTA fits on one line, and a locked (on-cooldown) card state. */
.pm-withdraw-btn { border-color: rgba(229, 161, 0, 0.45); color: var(--gold-bright); }
/* minmax(0,1fr) lets the two columns shrink below their content (a plain 1fr
   floors at min-content, so the lock label forced horizontal scroll). */
#pm-withdraw-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pm-gift-card--locked { opacity: 0.55; cursor: default; }
.pm-gift-card--locked:active { transform: none; }
.pm-gift-card-lock {
  font-size: 11px; font-weight: 700; color: var(--tg-hint); white-space: nowrap;
}
/* Model sub-label under the collection name — disambiguates same-collection gifts. */
.pm-gift-card-model {
  font-size: 10px; line-height: 1.2; color: var(--tg-hint); text-align: center;
  margin-top: -3px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Rich withdraw card — full Telegram-style gift render: proxy composite image
   (model+backdrop+symbol) on its backdrop gradient + collection · model · backdrop
   · #num, same info set as the inventory. */
#pm-withdraw-grid .pm-gift-card-img { width: 74px; height: 74px; border-radius: 14px; }
.pm-wd-serial {
  position: absolute; top: 4px; right: 4px; z-index: 2;
  font-size: 9px; font-weight: 700; color: #fff; letter-spacing: 0.2px;
  background: rgba(0, 0, 0, 0.42); border-radius: 6px; padding: 1px 5px;
}
.pm-wd-meta {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 10px; color: var(--tg-hint); line-height: 1.25; margin-top: 1px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pm-wd-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: var(--tg-separator); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12) inset;
}
/* ── Referral / rakeback — header Invite button + sheet ─────────────────────── */
/* Invite button — lives in the Predictions header next to the balance pill.
   Visual treatment is .iv-btn--liquid (see "Invite feature" block at the end of
   this file). flex-shrink:0 keeps the pill intact (the wordmark yields first);
   .hidden handles the dark launch (id beats the global .hidden on a tie). */
#pm-invite-btn { flex-shrink: 0; }
#pm-invite-btn.hidden { display: none; }
.pm-ref-link { font-size: 14px; }
#pm-ref-link-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.pm-ref-share { margin: 0 0 16px; }
.pm-ref-earn {
  text-align: center; padding: 16px 12px; margin: 4px 0 12px; border-radius: 16px;
  background: var(--tg-bg-input); border: 1px solid rgba(255, 205, 80, 0.30);
}
.pm-ref-earn-label { font-size: 11px; color: var(--tg-hint); text-transform: uppercase; letter-spacing: 0.6px; }
.pm-ref-earn-value { font-size: 38px; font-weight: 800; color: var(--gold-bright); line-height: 1.1; margin: 3px 0 0; }
.pm-ref-star { font-size: 22px; }
.pm-ref-earn-sub { font-size: 12px; color: var(--tg-hint); margin-top: 7px; line-height: 1.3; }
.pm-ref-earn-meta { font-size: 11px; color: var(--tg-hint); opacity: 0.8; margin-top: 3px; }
.pm-ref-example { text-align: center; font-size: 12px; color: var(--tg-hint); margin: 8px 0 2px; }
/* Claim button now wears .iv-claim-btn; the design's disabled look (dim fill +
   muted text) is keyed on the id so it wins over the .iv-claim-btn class rule. */
#pm-ref-claim:disabled { background: rgba(255,255,255,0.05); color: rgba(255,255,255,0.40); box-shadow: none; cursor: default; }
.pm-ref-referees { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; max-height: 32vh; overflow-y: auto; }
.pm-ref-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 10px; background: var(--tg-bg-input);
}
.pm-ref-row-id { font-size: 13px; color: var(--tg-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pm-ref-row-when { color: var(--tg-hint); font-size: 11px; }
.pm-ref-row-earned { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--gold-bright); }

/* ════════════════════════════════════════════════════════════════════════
   Invite feature — V3 "liquid sweep" button + "Showcase" referral sheet.
   Design handoff: miniapp/assets/Invite Handoff.html. The .iv-* classes are
   self-contained; the sheet reuses the .pm-sheet / .pm-sheet-overlay shell for
   show/hide + slide-up, and .iv-sheet only re-tints its background.
   ════════════════════════════════════════════════════════════════════════ */
@keyframes iv-sweep { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }

/* "Invite & Earn" full-width settings CTA (design: assets/Invite Earn Button.html).
   Replaces the plain "Invite friends" settings row; reuses iv-sweep above. Sits
   in the Settings list (which already has side padding, so no edge bleed); gated
   like the old row via #settings-referral-row.hidden. */
.iv-btn--row {
  display: flex; align-items: center; gap: 12px; width: 100%; height: 52px;
  box-sizing: border-box; padding: 0 14px; margin: 8px 0;
  border: none; cursor: pointer; font-family: inherit; border-radius: 12px;
  background: linear-gradient(115deg, #E5A100 0%, #FFCA28 10%, #FFE38A 18%, #4A7BD8 36%, #1E47B8 52%, #0E2A6E 68%, #E5A100 86%, #FFCA28 100%);
  background-size: 220% 220%; animation: iv-sweep 7s ease-in-out infinite;
  box-shadow: 0 0 0 1px rgba(255,245,200,0.45), 0 0 22px rgba(255,184,0,0.30), inset 0 1px 0 rgba(255,255,255,0.30), inset 0 -2px 8px rgba(0,0,0,0.30), 0 4px 14px rgba(14,42,110,0.35);
  transition: transform 0.15s ease;
}
.iv-btn--row:active { transform: scale(0.985); }
.iv-btn--row .iv-people { width: 22px; height: 22px; filter: drop-shadow(0 1px 2px rgba(14,42,110,0.6)); flex-shrink: 0; }
.iv-btn--row .iv-label { flex: 1; text-align: left; font-size: 15px; font-weight: 800; letter-spacing: 0.1px; color: #FFFBE5; text-shadow: 0 1px 4px rgba(14,42,110,0.75), 0 0 8px rgba(255,205,80,0.4); }
.iv-btn--row .iv-pct { font-size: 11px; font-weight: 900; letter-spacing: 0.4px; padding: 4px 8px; border-radius: 999px; background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); color: #1a1205; border: 0.5px solid rgba(255,245,200,0.55); box-shadow: inset 0 1px 0 rgba(255,255,255,0.60), 0 1px 3px rgba(14,42,110,0.50); flex-shrink: 0; }
#settings-referral-row.hidden { display: none; }
@keyframes iv-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.25); opacity: 0.6; } }
@keyframes iv-wink  { 0%, 100% { opacity: 0; transform: scale(0.6); } 50% { opacity: 1; transform: scale(1); } }

.iv-btn { position: relative; display: inline-flex; align-items: center; border: none; cursor: pointer; padding: 0; font-family: inherit; transition: transform 0.15s ease; font-variant-numeric: tabular-nums; }
.iv-btn:active { transform: scale(0.95); }
.iv-btn--liquid {
  height: 34px; padding: 0 5px 0 11px; border-radius: 999px; gap: 6px;
  background: linear-gradient(115deg, #E5A100 0%, #FFCA28 10%, #FFE38A 18%, #4A7BD8 36%, #1E47B8 52%, #0E2A6E 68%, #E5A100 86%, #FFCA28 100%);
  background-size: 220% 220%; animation: iv-sweep 7s ease-in-out infinite;
  box-shadow: 0 0 0 1px rgba(255,245,200,0.45), 0 0 16px rgba(255,184,0,0.32), inset 0 1px 0 rgba(255,255,255,0.30), inset 0 -2px 6px rgba(0,0,0,0.30);
}
.iv-btn--liquid .iv-people { width: 15px; height: 15px; filter: drop-shadow(0 1px 2px rgba(14,42,110,0.6)); }
.iv-btn--liquid .iv-label { font-size: 12.5px; font-weight: 800; letter-spacing: 0.3px; color: #FFFBE5; text-shadow: 0 1px 4px rgba(14,42,110,0.7), 0 0 8px rgba(255,205,80,0.4); }
.iv-btn--liquid .iv-pct { font-size: 10.5px; font-weight: 900; letter-spacing: 0.4px; padding: 3px 7px; border-radius: 999px; background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); color: #1a1205; border: 0.5px solid rgba(255,245,200,0.5); box-shadow: inset 0 1px 0 rgba(255,255,255,0.60), 0 1px 3px rgba(14,42,110,0.45); }

/* Sheet shell tint — reuses .pm-sheet for layout/slide-up; only the surface +
   chrome colours change so the dark navy reads in any Telegram theme. */
.iv-sheet { background: radial-gradient(ellipse 120% 50% at 50% 0%, rgba(58,111,224,0.30) 0%, transparent 55%), radial-gradient(ellipse 80% 40% at 80% 100%, rgba(255,184,0,0.10) 0%, transparent 60%), linear-gradient(180deg, #0c1a35 0%, #0a1424 60%, #07101e 100%); color: #F5F5F5; }
.iv-sheet .pm-sheet-close { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.10); color: rgba(255,255,255,0.75); }
.iv-sheet .pm-gift-empty { color: rgba(255,255,255,0.5); }
.iv-sheet-grip { width: 38px; height: 4px; border-radius: 999px; background: rgba(255,255,255,0.20); margin: 0 auto 10px; }

.iv-hero { position: relative; padding: 6px 0 8px; text-align: center; }
.iv-hero-eyebrow { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 6px; font-size: 9.5px; font-weight: 900; letter-spacing: 1.2px; text-transform: uppercase; padding: 4px 10px 4px 8px; border-radius: 999px; background: linear-gradient(180deg, rgba(255,184,0,0.18) 0%, rgba(229,161,0,0.08) 100%); border: 1px solid rgba(255,205,80,0.40); color: #FFE5A8; box-shadow: inset 0 1px 0 rgba(255,245,200,0.20); }
.iv-hero-eyebrow .iv-dot { width: 6px; height: 6px; border-radius: 999px; background: #5fe39a; box-shadow: 0 0 6px rgba(95,227,154,0.8); animation: iv-pulse 1.6s ease-in-out infinite; }
.iv-hero-title { position: relative; z-index: 1; margin: 12px 0 4px; font-size: 26px; font-weight: 800; letter-spacing: -0.6px; line-height: 1.1; color: #F5F5F5; }
.iv-hero-pct { background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 45%, #E5A100 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; filter: drop-shadow(0 0 14px rgba(255,184,0,0.40)); font-weight: 900; }
.iv-hero-sub { position: relative; z-index: 1; font-size: 13.5px; line-height: 1.45; color: rgba(245,245,245,0.65); max-width: 290px; margin: 0 auto; }
.iv-sparkles { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.iv-wink { animation: iv-wink 2.4s ease-in-out infinite; }
.iv-wink-1 { animation-delay: 0s; } .iv-wink-2 { animation-delay: 0.8s; } .iv-wink-3 { animation-delay: 1.4s; }

.iv-earned { margin: 16px 0 12px; padding: 18px 18px 16px; border-radius: 18px; background: radial-gradient(ellipse 80% 70% at 50% 0%, rgba(255,184,0,0.18) 0%, transparent 65%), linear-gradient(160deg, #1a2540 0%, #0e1a30 60%, #0a1424 100%); border: 1px solid rgba(255,205,80,0.32); box-shadow: inset 0 1px 0 rgba(255,245,200,0.10), 0 0 26px rgba(255,184,0,0.14); }
.iv-earned-eyebrow { font-size: 10px; font-weight: 800; letter-spacing: 1.4px; text-transform: uppercase; color: rgba(255,229,168,0.85); text-align: center; }
.iv-earned-row { display: flex; align-items: flex-end; justify-content: center; gap: 8px; margin-top: 6px; }
.iv-earned-num { font-size: 56px; font-weight: 900; letter-spacing: -2.2px; line-height: 1; background: linear-gradient(180deg, #FFF6CC 0%, #FFE38A 30%, #FFCA28 65%, #C68B00 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; filter: drop-shadow(0 0 18px rgba(255,184,0,0.40)); font-variant-numeric: tabular-nums; }
.iv-earned-star { margin-bottom: 7px; line-height: 0; }
.iv-progress-wrap { margin-top: 14px; padding: 10px 12px; border-radius: 12px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); }
.iv-progress-row { display: flex; align-items: center; justify-content: space-between; font-size: 11px; font-weight: 700; letter-spacing: 0.3px; margin-bottom: 6px; }
.iv-progress-label { color: rgba(255,255,255,0.55); text-transform: uppercase; letter-spacing: 0.8px; }
.iv-progress-num { color: #FFE5A8; font-variant-numeric: tabular-nums; }
.iv-progress-bar { height: 6px; border-radius: 999px; background: rgba(255,255,255,0.06); overflow: hidden; }
.iv-progress-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); box-shadow: 0 0 12px rgba(255,184,0,0.55); transition: width 0.5s ease; }
.iv-earned-foot { display: flex; justify-content: center; gap: 14px; margin-top: 12px; font-size: 11px; color: rgba(255,255,255,0.50); }
.iv-earned-foot b { color: rgba(255,255,255,0.78); font-weight: 700; }
.iv-claim-btn { margin-top: 14px; width: 100%; height: 44px; border-radius: 12px; border: none; cursor: pointer; font-family: inherit; font-size: 14px; font-weight: 800; letter-spacing: 0.2px; background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); color: #1a1205; box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), 0 0 18px rgba(255,184,0,0.40), 0 4px 12px rgba(229,161,0,0.40); }
.iv-claim-btn:active { transform: scale(0.98); }

/* Manual invite-code redeem box (referral sheet; shown only to not-yet-referred
   users). Mirrors the gold sheet styling: tinted input + gold Redeem button. */
.iv-redeem { margin-top: 16px; padding: 13px 14px 14px; border-radius: 14px; background: rgba(255,255,255,0.035); border: 1px solid rgba(255,205,80,0.18); }
.iv-redeem-label { font-size: 12px; font-weight: 700; color: rgba(255,229,168,0.92); margin-bottom: 10px; }
.iv-redeem-row { display: flex; gap: 8px; }
.iv-redeem-input { flex: 1; min-width: 0; height: 44px; padding: 0 14px; border-radius: 12px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,205,80,0.22); color: rgba(255,229,168,0.95); font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: 0.4px; outline: none; -webkit-appearance: none; }
.iv-redeem-input::placeholder { color: rgba(255,255,255,0.34); font-weight: 500; letter-spacing: 0; }
.iv-redeem-input:focus { border-color: rgba(255,205,80,0.5); background: rgba(255,255,255,0.06); }
.iv-redeem-btn { flex-shrink: 0; height: 44px; padding: 0 18px; border-radius: 12px; border: none; cursor: pointer; font-family: inherit; font-size: 13px; font-weight: 800; letter-spacing: 0.2px; background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); color: #1a1205; box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), 0 3px 10px rgba(229,161,0,0.35); }
.iv-redeem-btn:active { transform: scale(0.97); }
.iv-redeem-btn:disabled { opacity: 0.55; cursor: default; box-shadow: none; }
.iv-redeem-msg { margin-top: 9px; font-size: 12px; font-weight: 600; line-height: 1.35; }
.iv-redeem-msg.ok { color: var(--iv-success, #5fe39a); }
.iv-redeem-msg.err { color: #ff8f8f; }

.iv-link-row { display: flex; gap: 8px; margin-top: 16px; cursor: pointer; }
.iv-link-input { flex: 1; min-width: 0; height: 44px; padding: 0 14px; border-radius: 12px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,205,80,0.22); display: flex; align-items: center; font-size: 13px; font-weight: 600; letter-spacing: 0.1px; color: rgba(255,229,168,0.92); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
.iv-link-copy { width: 44px; height: 44px; border-radius: 12px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.10); color: rgba(255,229,168,0.92); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.iv-share-btn { margin-top: 10px; width: 100%; height: 52px; border-radius: 14px; border: none; cursor: pointer; font-family: inherit; font-size: 15px; font-weight: 800; letter-spacing: 0.2px; color: #FFFBE5; background: linear-gradient(115deg, #E5A100 0%, #FFCA28 8%, #FFE38A 16%, #4A7BD8 38%, #1E47B8 55%, #0E2A6E 72%, #E5A100 92%, #FFCA28 100%); background-size: 220% 220%; animation: iv-sweep 7s ease-in-out infinite; box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), inset 0 -2px 8px rgba(0,0,0,0.35), 0 0 0 1px rgba(255,245,200,0.55), 0 0 22px rgba(255,184,0,0.35), 0 6px 18px rgba(14,42,110,0.45); display: inline-flex; align-items: center; justify-content: center; gap: 9px; text-shadow: 0 1px 4px rgba(14,42,110,0.55); }
.iv-share-btn:active { transform: scale(0.98); }

.iv-h { font-size: 10px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase; color: rgba(255,255,255,0.50); margin: 22px 2px 10px; display: flex; align-items: baseline; gap: 8px; }
.iv-h-count { font-size: 10px; font-weight: 700; color: rgba(255,229,168,0.70); font-variant-numeric: tabular-nums; margin-left: auto; }
.iv-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 6px; }
.iv-step { text-align: center; padding: 12px 8px 14px; border-radius: 12px; background: linear-gradient(180deg, rgba(58,111,224,0.10) 0%, rgba(14,42,110,0.10) 100%); border: 1px solid rgba(255,205,80,0.15); }
.iv-step-n { width: 24px; height: 24px; border-radius: 999px; margin: 0 auto 6px; background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%); color: #1a1205; font-size: 11px; font-weight: 900; display: inline-flex; align-items: center; justify-content: center; box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), 0 2px 6px rgba(229,161,0,0.35); }
.iv-step-title { font-size: 11px; font-weight: 800; color: #fff; letter-spacing: 0.1px; line-height: 1.2; }
.iv-step-sub { font-size: 10.5px; color: rgba(255,255,255,0.55); margin-top: 3px; line-height: 1.3; }
.iv-ref-card { border-radius: 12px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.05); overflow: hidden; }
.iv-ref-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid rgba(255,255,255,0.04); font-size: 12.5px; }
.iv-ref-row:last-child { border-bottom: none; }
.iv-ref-av { width: 32px; height: 32px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; color: #fff; flex-shrink: 0; }
.iv-ref-name { font-size: 13px; font-weight: 700; color: #F5F5F5; line-height: 1.15; }
.iv-ref-meta { font-size: 11px; color: rgba(255,255,255,0.45); margin-top: 2px; }
.iv-ref-amt { font-size: 13px; font-weight: 800; color: #FFE5A8; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 3px; margin-left: auto; }

/* Prediction icons (multi-colour gradient SVGs from /assets/prediction-icons,
 * rendered as-is). Sizing only. */
.pm-ic { width: 15px; height: 15px; flex-shrink: 0; vertical-align: middle; }
/* Limited-gift icon next to a market name (backend image_url; hidden on 404) */
.pm-gift-ic {
  width: 20px; height: 20px; border-radius: 5px; object-fit: cover;
  vertical-align: -4px; margin-right: 6px; flex-shrink: 0;
}
.pm-side-btn { display: flex; align-items: center; justify-content: center; gap: 6px; }
.pm-side-btn .pm-ic { width: 18px; height: 18px; }
.pm-est { display: flex; align-items: center; gap: 6px; }
.pm-est .pm-ic { width: 18px; height: 18px; }

/* Card footer — volume + deadline (countdown) */
.pm-card-foot {
  display: flex; align-items: center; gap: 14px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--tg-separator);
}
.pm-foot-item { display: inline-flex; align-items: center; gap: 5px; color: var(--tg-hint); font-size: 12px; }

/* Running position + success flash in the bet sheet (multi-bet UX) */
.pm-position { font-size: 13px; color: var(--tg-hint); margin: 2px 0 10px; }
.pm-position.hidden { display: none; }
.pm-pos-yes { color: var(--pm-yes); }
.pm-pos-no { color: var(--pm-no); }

/* ── Bet-placed confirmation (non-blocking, layered) ───────────────────────
   No modal popup (you stack bets fast) — these cues make a placed bet
   unmistakable: button success flash + floating stake chip + position bump +
   a brief balance pulse (the count-down itself is driven in JS). */
.pm-place-btn--ok {
  background: var(--pm-yes) !important;   /* green flash over the blue→purple gradient */
  opacity: 1 !important;                  /* stay bright even while disabled */
  animation: pmOkPop 0.3s ease-out;
}
@keyframes pmOkPop {
  0%   { transform: scale(0.98); }
  45%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.pm-fly-chip {
  position: absolute; left: 50%; bottom: 64px;
  transform: translateX(-50%);
  font-size: 15px; font-weight: 800; letter-spacing: 0.2px;
  padding: 4px 11px; border-radius: 999px; color: #fff;
  pointer-events: none; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0,0,0,0.28);
  animation: pmFlyUp 0.95s cubic-bezier(0.22,1,0.36,1) forwards;
}
.pm-fly-chip--yes { background: var(--pm-yes); }
.pm-fly-chip--no  { background: var(--pm-no); }
@keyframes pmFlyUp {
  0%   { opacity: 0; transform: translate(-50%, 10px) scale(0.85); }
  18%  { opacity: 1; transform: translate(-50%, 0) scale(1.05); }
  100% { opacity: 0; transform: translate(-50%, -52px) scale(1); }
}
.pm-pos-bump { animation: pmPosBump 0.5s ease-out; }
@keyframes pmPosBump {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.pm-bal-flash { animation: pmBalFlash 0.6s ease-out; }
@keyframes pmBalFlash {
  0%   { filter: brightness(1.9); }
  100% { filter: brightness(1); }
}

/* ── "My bets" tab container ──────────────────────────────────────────────── */
.pm-mybets { padding: 0; }  /* full-bleed like Markets #pm-list (was 0 2px) so cards match width */
.pm-mybets.hidden { display: none; }

/* Section headers */
.pm-sect-hdr { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; color: rgba(255,255,255,0.45); margin: 14px 2px 8px; display: flex; align-items: baseline; gap: 8px; }
.pm-sect-hdr-count { color: rgba(255,255,255,0.3); font-weight: 500; letter-spacing: 0.4px; }
.pm-sect-hdr-right { margin-left: auto; color: var(--pm-hint); font-size: 10px; font-weight: 500; }

/* Stats strip */
.pm-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin: 12px 0; }
.pm-stat { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.05); border-radius: var(--pm-r-md); padding: 7px 8px; }
.pm-stat-label { font-size: 9px; font-weight: 800; letter-spacing: 0.5px; color: var(--pm-hint); }
.pm-stat-value { font-size: 16px; font-weight: 800; letter-spacing: -0.3px; margin-top: 3px; line-height: 1; font-variant-numeric: tabular-nums; color: var(--pm-fg); display: inline-flex; align-items: baseline; gap: 3px; }
.pm-stat-value--gold { color: var(--pm-gold-2); }
.pm-stat-value--pos  { color: var(--pm-yes-2); }
.pm-stat-value--neg  { color: var(--pm-no-2); }
.pm-stat-value--neutral { color: var(--pm-fg-2); }
.pm-stat-unit { font-size: 10px; font-weight: 700; letter-spacing: 0; color: var(--pm-hint); }
.pm-stat-suffix { font-size: 9px; font-weight: 600; color: rgba(112,132,153,0.85); margin-top: 2px; white-space: nowrap; }

/* Position / settled group + rows */
.pm-list { background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.04); border-radius: var(--pm-r-lg); padding: 0 12px; }
.pm-row { padding: 12px 4px; display: flex; align-items: center; gap: 11px; border-bottom: 1px solid rgba(255,255,255,0.05); }
.pm-row:last-child { border-bottom: 0; }
.pm-row-art { position: relative; flex-shrink: 0; width: 40px; height: 40px; border-radius: 10px; background: radial-gradient(ellipse at center, color-mix(in oklab, var(--tier, #5fe39a) 20%, transparent) 0%, transparent 70%), var(--pm-bg-2); display: inline-flex; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,0.04); overflow: hidden; }
.pm-row-art img { width: 92%; height: 92%; object-fit: contain; }
.pm-side-badge { position: absolute; bottom: -3px; right: -3px; padding: 1px 5px; border-radius: 5px; color: #fff; font-size: 8px; font-weight: 900; letter-spacing: 0.5px; border: 2px solid var(--pm-bg-1); }
.pm-side-badge--yes { background: var(--pm-yes); }
.pm-side-badge--no  { background: var(--pm-no); }
.pm-row-body { flex: 1; min-width: 0; }
.pm-row-title { font-size: 13.5px; font-weight: 600; color: var(--pm-fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pm-row-sub { margin-top: 4px; font-size: 11px; color: var(--pm-hint); display: flex; gap: 8px; align-items: center; }
.pm-row-sub > .sep { color: var(--pm-hint-2); }
.pm-live-pct { font-weight: 700; font-variant-numeric: tabular-nums; }
.pm-live-pct--good { color: var(--pm-yes-2); }
.pm-live-pct--mid  { color: var(--pm-fg-2); }
.pm-live-pct--bad  { color: var(--pm-no-2); }
.pm-row-sub .closes { margin-left: auto; }
.pm-row-sub .closes.urgent { color: var(--pm-gold-2); font-weight: 700; }
/* Open-position right column: two stacked, right-aligned stat lines
   (TO WIN / BET) so the figures never collide on one line. */
.pm-row-right { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex-shrink: 0; min-width: 72px; }
.pm-row-stat { display: flex; align-items: baseline; gap: 5px; line-height: 1.05; }
.pm-row-stat-l { font-size: 9px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase; }
.pm-row-stat-v { font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 3px; }
.pm-row-stat--win .pm-row-stat-l { color: var(--pm-gold-2); }
.pm-row-stat--win .pm-row-stat-v { font-size: 16px; font-weight: 800; color: var(--pm-gold-2); letter-spacing: -0.3px; }
.pm-row-stat--bet .pm-row-stat-l { color: var(--pm-hint); }
.pm-row-stat--bet .pm-row-stat-v { font-size: 12px; font-weight: 700; color: var(--pm-hint); }
/* "bought N%" entry-price chip in the sub-line (shows only when avg_buy_pct ships). */
.pm-buy-pct { color: var(--pm-fg-2); font-weight: 700; font-variant-numeric: tabular-nums; }
.pm-row-right-eyebrow { font-size: 9px; font-weight: 800; letter-spacing: 0.4px; color: var(--pm-gold-2); }
.pm-row-right-amt { font-size: 15px; font-weight: 800; color: var(--pm-gold-2); line-height: 1; letter-spacing: -0.3px; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 3px; justify-content: flex-end; }
.pm-row-right-delta { font-size: 10px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 2px; justify-content: flex-end; }
.pm-row-right-delta--pos { color: var(--pm-yes-2); }
.pm-row-right-delta--neg { color: var(--pm-no-2); }
/* Secondary "BET {stake}" line under the TO WIN payout on open positions. */
.pm-row-right-bet { font-size: 10px; font-weight: 700; color: var(--pm-hint); margin-top: 3px; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 2px; justify-content: flex-end; }
.pm-result { display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px; border-radius: var(--pm-r-pill); font-size: 10px; font-weight: 800; letter-spacing: 0.3px; }
.pm-result--won  { background: var(--pm-yes-soft); border: 1px solid rgba(52, 199, 89, 0.32); color: var(--pm-yes-2); }
.pm-result--lost { background: var(--pm-no-soft);  border: 1px solid rgba(236, 57, 66, 0.32); color: var(--pm-no-2); }
.pm-result--refunded { background: rgba(112,132,153,0.16); border: 1px solid rgba(112,132,153,0.3); color: var(--pm-fg-2); }
.pm-row-settle-amt { font-size: 14px; font-weight: 800; margin-top: 4px; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 3px; justify-content: flex-end; }
.pm-row-settle-amt--pos { color: var(--pm-yes-2); }
.pm-row-settle-amt--neg { color: var(--pm-no-2); }

/* Wallet history ledger */
.pm-day { font-size: 9px; font-weight: 800; letter-spacing: 0.8px; color: var(--pm-hint); margin: 12px 4px 6px; }
.pm-tx { background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.04); border-radius: var(--pm-r-lg); padding: 12px 16px; margin-bottom: 6px; display: flex; align-items: center; gap: 12px; }
.pm-tx-icon { width: 34px; height: 34px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.pm-tx-icon--topup  { background: rgba(255, 184, 0, 0.16); color: var(--pm-gold-2); }
.pm-tx-icon--bet    { background: var(--pm-purple-soft);   color: #C4A8FF; }
.pm-tx-icon--payout { background: var(--pm-yes-soft);      color: var(--pm-yes-2); }
.pm-tx-icon--refund { background: rgba(112,132,153,0.16);  color: var(--pm-fg-2); }
.pm-tx-body { flex: 1; min-width: 0; }
.pm-tx-title { font-size: 13.5px; font-weight: 600; color: var(--pm-fg); display: flex; align-items: center; gap: 8px; }
.pm-tx-side { font-size: 9px; font-weight: 800; letter-spacing: 0.5px; padding: 1.5px 5px; border-radius: 4px; }
.pm-tx-side--yes { background: var(--pm-yes-soft); color: var(--pm-yes-2); }
.pm-tx-side--no  { background: var(--pm-no-soft);  color: var(--pm-no-2); }
.pm-tx-market { font-size: 11px; color: var(--pm-hint); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pm-tx-right { text-align: right; flex-shrink: 0; }
.pm-tx-amt { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; display: inline-flex; align-items: baseline; gap: 3px; }
.pm-tx-amt--credit { color: var(--pm-yes-2); }
.pm-tx-amt--debit  { color: var(--pm-fg); }
.pm-tx-time { font-size: 10px; color: var(--pm-hint); margin-top: 2px; }

/* ── Skeleton cards (loading) — preserved ─────────────────────────────────── */
.pm-skel { pointer-events: none; }
.pm-skel-line, .pm-skel-bar, .pm-skel-chip {
  background: rgba(255,255,255,0.08); border-radius: 6px;
  animation: pmSkel 1.4s ease-in-out infinite;
}
.pm-skel-title { height: 16px; width: 70%; margin-bottom: 12px; }
.pm-skel-bar { height: 22px; width: 100%; border-radius: 8px; margin-bottom: 12px; }
.pm-skel-meta { display: flex; gap: 8px; }
.pm-skel-chip { height: 20px; width: 64px; }
@keyframes pmSkel { 0%, 100% { opacity: 0.45; } 50% { opacity: 0.9; } }

/* ── Win banner — preserved ───────────────────────────────────────────────── */
.pm-banner {
  display: flex; align-items: center; gap: 8px;
  margin: 0 2px 12px; padding: 10px 12px; border-radius: 12px;
  background: var(--pm-yes-soft); color: var(--pm-yes);
  font-size: 14px; font-weight: 700; animation: fadeInUp 0.4s ease-out;
}
.pm-banner.hidden { display: none; }
.pm-banner-msg { flex: 1; min-width: 0; }
.pm-banner-x { background: transparent; border: none; color: inherit; opacity: 0.65; font-size: 14px; cursor: pointer; flex-shrink: 0; }
.pm-banner--err { background: var(--pm-no-soft); color: var(--pm-no); }

/* ── V5 redesign: page gutters + empty-count guard + gold nav pill ─────────── */
/* No ancestor (.state/.page/body) sets horizontal padding, and the redesign
 * dropped the .market-list gutter from #pm-list — so give the whole Prediction
 * page a 16px side gutter (matches the design's .pm-content). Side-only padding
 * keeps .page's padding-bottom:70px (clearance for the fixed bottom-nav). */
#page-predictions { padding-left: 16px; padding-right: 16px; }
.pm-seg-count:empty { display: none; }

/* Gold "Predict" treatment in the bottom nav: gold label + a soft gold halo
 * behind the icon glyph (no fragile extra elements). */
.nav-item[data-page="predictions"].active { color: var(--pm-gold-2); }
.nav-item[data-page="predictions"].active .nav-label { color: var(--pm-gold-2); text-shadow: 0 0 8px rgba(255, 205, 80, 0.4); }
.nav-item[data-page="predictions"].active .gc-icon--nav {
  border-radius: 9px;
  background: radial-gradient(circle at 50% 45%, rgba(255, 200, 80, 0.30) 0%, rgba(255, 184, 0, 0.12) 65%, transparent 80%);
  filter: brightness(1.15) drop-shadow(0 0 6px rgba(255, 200, 80, 0.6));
}

/* ════════════════════════════════════════════════════════════════════════
   MARKET DETAIL V2 — full-screen page that opens on a market tap.
   Page gutters mirror #page-predictions; bottom padding clears the sticky
   bet bar + the global nav. The bet bar is position:fixed but lives inside
   #page-market-detail, so it only shows while the detail page is visible.
   ════════════════════════════════════════════════════════════════════════ */
#page-market-detail { padding: 8px 14px 112px; }

/* Top row — back / breadcrumb / share */
.pm-detail-top { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.pm-detail-iconbtn {
  width: 34px; height: 34px; border-radius: 999px;
  background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.10);
  color: #fff; cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.10);
}
.pm-detail-iconbtn:active { transform: scale(0.96); }
.pm-detail-iconbtn--ghost { color: var(--pm-fg-2); }
.pm-detail-breadcrumb {
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--pm-purple-2); padding: 5px 10px; border-radius: 999px;
  background: rgba(151, 111, 255, 0.14); border: 1px solid rgba(151, 111, 255, 0.28);
}

/* Hero — tier-gradient backdrop + glowing artwork. Set --tier inline. */
.pm-detail-hero {
  --tier: #ff9d6b; position: relative; border-radius: var(--pm-r-hero); overflow: hidden;
  background:
    radial-gradient(ellipse 110% 70% at 100% 0%, color-mix(in oklab, var(--tier) 33%, transparent) 0%, transparent 60%),
    radial-gradient(ellipse 80% 60% at 0% 100%, rgba(151, 111, 255, 0.22) 0%, transparent 60%),
    linear-gradient(160deg, #1f2a3c 0%, #131e2e 60%, var(--pm-bg-2) 100%);
  border: 1.5px solid rgba(255, 205, 80, 0.30);
  box-shadow: 0 0 30px color-mix(in oklab, var(--tier) 20%, transparent), inset 0 1px 0 rgba(255,255,255,0.06);
}
.pm-detail-hero-glow {
  position: absolute; right: -50px; top: -30px; width: 240px; height: 240px;
  background: radial-gradient(circle at center, color-mix(in oklab, var(--tier) 53%, transparent) 0%, color-mix(in oklab, var(--tier) 20%, transparent) 35%, transparent 65%);
  filter: blur(14px); pointer-events: none;
}
.pm-detail-hero-inner { position: relative; padding: 12px 12px 11px; }
.pm-detail-hero-row { display: flex; gap: 11px; align-items: flex-start; }
.pm-detail-hero-art {
  position: relative; flex-shrink: 0; width: 56px; height: 56px; border-radius: 14px;
  background: radial-gradient(circle at center, color-mix(in oklab, var(--tier) 40%, transparent) 0%, transparent 70%), var(--pm-bg-2);
  border: 1px solid rgba(255,255,255,0.10);
  display: inline-flex; align-items: center; justify-content: center; overflow: hidden;
  box-shadow: 0 6px 22px color-mix(in oklab, var(--tier) 33%, transparent), inset 0 1px 0 rgba(255,255,255,0.08);
}
.pm-detail-hero-art img { width: 92%; height: 92%; object-fit: contain; }
.pm-detail-hero-titlecol { flex: 1; min-width: 0; }
.pm-detail-tagrow { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; flex-wrap: wrap; }
.pm-detail-gift-chip {
  font-size: 10px; font-weight: 700; letter-spacing: 0.4px;
  color: var(--tier, var(--pm-gold-2)); padding: 3px 8px; border-radius: 999px;
  background: color-mix(in oklab, var(--tier, var(--pm-gold-2)) 12%, transparent);
  border: 1px solid color-mix(in oklab, var(--tier, var(--pm-gold-2)) 33%, transparent);
}
.pm-detail-hero-question { font-size: 15px; font-weight: 700; color: #FFFFFF; line-height: 1.2; letter-spacing: -0.2px; }

/* Big odds + sparkline */
.pm-detail-stats { margin-top: 10px; display: flex; align-items: flex-end; gap: 14px; }
.pm-detail-oddslabel { font-size: 11px; font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; margin-bottom: 2px; }
.pm-detail-oddslabel--yes { color: var(--pm-yes-2); }
.pm-detail-oddslabel--no  { color: var(--pm-no-2); }
.pm-detail-bignum { font-size: 40px; font-weight: 900; letter-spacing: -1.8px; line-height: 0.9; font-variant-numeric: tabular-nums; }
.pm-detail-bignum--yes { color: var(--pm-yes-2); text-shadow: 0 0 24px rgba(95, 227, 154, 0.4); }
.pm-detail-bignum--no  { color: var(--pm-no-2);  text-shadow: 0 0 24px rgba(255, 128, 133, 0.4); }
.pm-detail-bignum-pct  { font-size: 19px; opacity: 0.6; }
.pm-detail-bignum-line { display: inline-flex; align-items: baseline; gap: 9px; }
.pm-detail-bignum-side { font-size: 24px; font-weight: 800; letter-spacing: -0.4px; line-height: 1; }
.pm-detail-bignum-side--yes { color: var(--pm-yes-2); }
.pm-detail-bignum-side--no  { color: var(--pm-no-2); }
.pm-detail-delta { margin-top: 8px; display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; }
.pm-detail-delta--up   { background: rgba(95, 227, 154, 0.18); border: 1px solid rgba(95, 227, 154, 0.40); color: var(--pm-yes-2); }
.pm-detail-delta--down { background: rgba(255, 82, 82, 0.18); border: 1px solid rgba(255, 82, 82, 0.40); color: var(--pm-no-2); }
.pm-detail-spark { flex: 0 1 150px; min-width: 0; margin-left: auto; margin-right: -4px; }
.pm-detail-spark-axis { display: flex; justify-content: flex-end; font-size: 9px; color: rgba(255,255,255,0.4); margin-top: 4px; font-weight: 700; letter-spacing: 0.3px; white-space: nowrap; }

/* Pool / Bets / Closes mini-tiles */
.pm-detail-mini-grid { margin-top: 10px; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 7px; }
.pm-detail-mini { padding: 8px 9px; border-radius: 11px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06); }
.pm-detail-mini-label { font-size: 9px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; }
.pm-detail-mini-value { font-size: 14px; font-weight: 800; margin-top: 2px; display: inline-flex; align-items: baseline; gap: 4px; color: #fff; font-variant-numeric: tabular-nums; }
.pm-detail-mini--purple { background: linear-gradient(135deg, rgba(151, 111, 255, 0.22) 0%, rgba(151, 111, 255, 0.08) 100%); border: 1px solid rgba(151, 111, 255, 0.32); }
.pm-detail-mini--purple .pm-detail-mini-label { color: var(--pm-purple-2); }
.pm-detail-mini--blue { background: linear-gradient(135deg, rgba(94, 193, 255, 0.22) 0%, rgba(94, 193, 255, 0.08) 100%); border: 1px solid rgba(94, 193, 255, 0.32); }
.pm-detail-mini--blue .pm-detail-mini-label { color: var(--pm-blue-2); }
.pm-detail-mini--gold { background: linear-gradient(135deg, rgba(255, 202, 40, 0.18) 0%, rgba(229, 161, 0, 0.06) 100%); border: 1px solid rgba(255, 202, 40, 0.32); }
.pm-detail-mini--gold .pm-detail-mini-label { color: var(--pm-gold-2); }
.pm-detail-mini--gold.urgent { background: linear-gradient(135deg, rgba(255, 202, 40, 0.32) 0%, rgba(255, 122, 61, 0.16) 100%); border-color: rgba(255, 122, 61, 0.50); }
.pm-detail-mini--gold.urgent .pm-detail-mini-value { color: #FFB077; }

/* Your position — purple receipt (render only if user has a stake) */
.pm-detail-yours {
  margin-top: 8px; padding: 10px 12px; border-radius: var(--pm-r-lg);
  background:
    radial-gradient(ellipse 60% 100% at 100% 0%, rgba(255, 202, 40, 0.18) 0%, transparent 60%),
    linear-gradient(135deg, rgba(151, 111, 255, 0.22) 0%, rgba(110, 75, 200, 0.10) 60%, rgba(35, 46, 60, 0.4) 100%);
  border: 1px solid rgba(151, 111, 255, 0.36);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 4px 16px rgba(151, 111, 255, 0.10);
}
.pm-detail-yours-eyebrow {
  font-size: 9px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px;
  background: linear-gradient(135deg, var(--pm-purple-2) 0%, var(--pm-purple) 100%);
  color: #fff; box-shadow: inset 0 1px 0 rgba(255,255,255,0.45); display: inline-flex; align-items: center;
}
.pm-detail-yours-row { display: flex; gap: 14px; align-items: center; margin-top: 6px; }
.pm-detail-yours-col { flex: 1; }
.pm-detail-yours-stake { display: flex; align-items: baseline; gap: 5px; font-variant-numeric: tabular-nums; }
.pm-detail-yours-amt { font-size: 18px; font-weight: 800; }
.pm-detail-yours-amt--yes { color: var(--pm-yes-2); text-shadow: 0 0 12px rgba(95, 227, 154, 0.4); }
.pm-detail-yours-amt--no  { color: var(--pm-no-2); }
.pm-detail-yours-side { font-size: 10px; font-weight: 800; letter-spacing: 0.5px; margin-left: 2px; }
.pm-detail-yours-side--yes { color: var(--pm-yes-2); }
.pm-detail-yours-side--no  { color: var(--pm-no-2); }
.pm-detail-yours-pays {
  margin-top: 6px; font-size: 11px; color: var(--pm-fg-2);
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: 999px;
  background: linear-gradient(180deg, rgba(255, 184, 0, 0.16) 0%, rgba(229, 161, 0, 0.06) 100%);
  border: 1px solid rgba(255, 205, 80, 0.32);
}
.pm-detail-yours-pays-amt { color: var(--pm-gold-2); font-weight: 800; font-variant-numeric: tabular-nums; }

/* Place a bet — gradient header + chunky YES/NO toggle */
.pm-detail-place { margin-top: 8px; border-radius: var(--pm-r-md); overflow: hidden; background: var(--pm-card-2); border: 1px solid rgba(255,255,255,0.08); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04); }
.pm-detail-place-head { padding: 6px 12px; background: linear-gradient(135deg, #6B93FF 0%, var(--pm-purple) 50%, #E46ACE 100%); display: flex; align-items: center; gap: 8px; }
.pm-detail-place-head-title { font-size: 12px; font-weight: 800; color: #fff; letter-spacing: 0.4px; text-transform: uppercase; }
.pm-detail-place-head-sub { margin-left: auto; font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.7); }
.pm-detail-place-body { padding: 11px; }
.pm-detail-sides { display: flex; gap: 8px; }
.pm-detail-side { flex: 1; padding: 10px 10px; border-radius: 11px; cursor: pointer; font-family: inherit; display: flex; flex-direction: column; gap: 3px; align-items: flex-start; transition: background 0.15s ease, border-color 0.15s ease; }
.pm-detail-side-row { display: flex; justify-content: space-between; width: 100%; align-items: baseline; }
.pm-detail-side-label { font-size: 13px; font-weight: 900; letter-spacing: 0.5px; }
.pm-detail-side-pct { font-size: 15px; font-weight: 900; font-variant-numeric: tabular-nums; }
.pm-detail-side-mult { font-size: 9.5px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 2px 6px; border-radius: 4px; }
.pm-detail-side--yes { background: rgba(52, 199, 89, 0.08); border: 2px solid rgba(52, 199, 89, 0.24); }
.pm-detail-side--yes .pm-detail-side-label { color: var(--pm-yes-2); }
.pm-detail-side--yes .pm-detail-side-pct { color: #a9d8b8; }
.pm-detail-side--yes .pm-detail-side-mult { background: rgba(52, 199, 89, 0.10); color: var(--pm-yes-2); }
.pm-detail-side--yes.active { background: linear-gradient(135deg, rgba(52, 199, 89, 0.42) 0%, rgba(52, 199, 89, 0.18) 100%); border-color: var(--pm-yes); box-shadow: 0 4px 16px rgba(52, 199, 89, 0.25), inset 0 1px 0 rgba(255,255,255,0.20); }
.pm-detail-side--yes.active .pm-detail-side-pct { color: var(--pm-yes-2); }
.pm-detail-side--yes.active .pm-detail-side-mult { background: rgba(52, 199, 89, 0.24); color: #fff; }
.pm-detail-side--no { background: rgba(236, 57, 66, 0.08); border: 2px solid rgba(236, 57, 66, 0.24); }
.pm-detail-side--no .pm-detail-side-label { color: var(--pm-no-2); }
.pm-detail-side--no .pm-detail-side-pct { color: #d8a4a7; }
.pm-detail-side--no .pm-detail-side-mult { background: rgba(236, 57, 66, 0.10); color: var(--pm-no-2); }
.pm-detail-side--no.active { background: linear-gradient(135deg, rgba(236, 57, 66, 0.42) 0%, rgba(236, 57, 66, 0.18) 100%); border-color: var(--pm-no); box-shadow: 0 4px 16px rgba(236, 57, 66, 0.25), inset 0 1px 0 rgba(255,255,255,0.20); }
.pm-detail-side--no.active .pm-detail-side-pct { color: var(--pm-no-2); }
.pm-detail-side--no.active .pm-detail-side-mult { background: rgba(236, 57, 66, 0.24); color: #fff; }

/* Stake + payout combo */
.pm-detail-stake { margin-top: 8px; display: flex; align-items: stretch; background: linear-gradient(135deg, var(--pm-bg-1) 0%, #131e2e 100%); border-radius: 12px; border: 1px solid rgba(255, 205, 80, 0.18); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04); overflow: hidden; }
.pm-detail-stake-col { flex: 1; padding: 9px 12px; }
.pm-detail-stake-input { width: 100%; box-sizing: border-box; background: transparent; border: 0; outline: none; color: #fff; font-size: 20px; font-weight: 900; letter-spacing: -0.5px; font-variant-numeric: tabular-nums; padding: 0; font-family: inherit; }
.pm-detail-stake-divider { width: 2px; background: linear-gradient(180deg, transparent 0%, rgba(255, 205, 80, 0.5) 50%, transparent 100%); }
.pm-detail-stake-label { font-size: 9px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; color: var(--pm-hint); }
.pm-detail-stake-label--gold { color: var(--pm-gold-2); }
.pm-detail-stake-val { display: flex; align-items: baseline; gap: 4px; margin-top: 2px; font-variant-numeric: tabular-nums; }
.pm-detail-stake-val-num { font-size: 20px; font-weight: 900; color: #fff; letter-spacing: -0.5px; }
.pm-detail-payout-col { background: linear-gradient(135deg, rgba(255, 202, 40, 0.10) 0%, transparent 100%); }
.pm-detail-payout-num { font-size: 20px; font-weight: 900; letter-spacing: -0.5px; background: linear-gradient(180deg, var(--pm-gold-1) 0%, var(--pm-gold-2) 50%, var(--pm-gold-3) 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent; filter: drop-shadow(0 0 6px rgba(255, 184, 0, 0.4)); }
.pm-detail-payout-profit { font-size: 10px; color: var(--pm-yes-2); font-weight: 700; margin-top: 2px; display: inline-flex; align-items: baseline; gap: 3px; font-variant-numeric: tabular-nums; }

/* Quick picks */
.pm-detail-quick { display: flex; gap: 6px; margin-top: 8px; }
.pm-detail-quick-btn { flex: 1; padding: 8px 4px; border-radius: 10px; cursor: pointer; font-family: inherit; font-variant-numeric: tabular-nums; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); color: var(--pm-fg-2); font-size: 12.5px; font-weight: 800; transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; }
.pm-detail-quick-btn.active { background: linear-gradient(180deg, rgba(255, 227, 138, 0.32) 0%, rgba(229, 161, 0, 0.16) 100%); border-color: rgba(255, 205, 80, 0.50); color: var(--pm-gold-warm); box-shadow: inset 0 1px 0 rgba(255, 245, 200, 0.32), 0 2px 8px rgba(255, 184, 0, 0.18); text-shadow: 0 0 6px rgba(255, 205, 80, 0.35); }

/* Rules card */
.pm-detail-rules { margin-top: 8px; padding: 10px 12px; border-radius: var(--pm-r-lg); background: linear-gradient(135deg, rgba(106, 179, 243, 0.10) 0%, rgba(151, 111, 255, 0.10) 100%); border: 1px solid rgba(106, 179, 243, 0.22); display: flex; gap: 10px; align-items: flex-start; }
.pm-detail-rules-ic { width: 28px; height: 28px; border-radius: 9px; flex-shrink: 0; background: linear-gradient(135deg, var(--pm-blue) 0%, var(--pm-purple) 100%); display: inline-flex; align-items: center; justify-content: center; box-shadow: inset 0 1px 0 rgba(255,255,255,0.32), 0 2px 8px rgba(106, 179, 243, 0.25); }
.pm-detail-rules-eyebrow { font-size: 11px; font-weight: 800; color: var(--pm-blue-2); letter-spacing: 0.5px; text-transform: uppercase; margin-bottom: 3px; }
.pm-detail-rules-text { font-size: 11.5px; color: var(--pm-fg-2); line-height: 1.45; }
.pm-detail-rules-text b { color: #fff; font-weight: 600; }
.pm-detail-rules-text .yes { color: var(--pm-yes-2); font-weight: 700; }
.pm-detail-rules-text .no { color: var(--pm-no-2); font-weight: 700; }
.pm-detail-rules-text .resolver { color: var(--pm-blue); font-weight: 600; }

/* Recent bets */
.pm-detail-bets { background: rgba(255,255,255,0.02); border-radius: var(--pm-r-lg); border: 1px solid rgba(255,255,255,0.06); padding: 2px 12px; }
.pm-detail-bet { padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.05); display: flex; align-items: center; gap: 10px; font-size: 12px; }
.pm-detail-bet:last-child { border-bottom: none; }
.pm-detail-avatar { width: 24px; height: 24px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; font-size: 10.5px; font-weight: 800; color: #fff; box-shadow: inset 0 1px 0 rgba(255,255,255,0.32), 0 2px 6px rgba(0,0,0,0.3); flex-shrink: 0; }
.pm-detail-avatar--p1 { background: linear-gradient(135deg, #FF6BA8 0%, #9b5bff 100%); }
.pm-detail-avatar--p2 { background: linear-gradient(135deg, #5ec1ff 0%, #5fe39a 100%); }
.pm-detail-avatar--p3 { background: linear-gradient(135deg, #FFCA28 0%, #FF7A3D 100%); }
.pm-detail-avatar--p4 { background: linear-gradient(135deg, #9b5bff 0%, #5ec1ff 100%); }
.pm-detail-avatar--p5 { background: linear-gradient(135deg, #5fe39a 0%, #FFCA28 100%); }
.pm-detail-avatar--p6 { background: linear-gradient(135deg, #FF6BA8 0%, #FFCA28 100%); }
.pm-detail-bet-name { color: var(--pm-fg); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; }
.pm-detail-bet-side { font-size: 10px; font-weight: 800; letter-spacing: 0.4px; padding: 2px 7px; border-radius: 5px; flex-shrink: 0; }
.pm-detail-bet-side--yes { background: rgba(52, 199, 89, 0.22); color: var(--pm-yes-2); border: 1px solid rgba(52, 199, 89, 0.40); }
.pm-detail-bet-side--no  { background: rgba(236, 57, 66, 0.22); color: var(--pm-no-2);  border: 1px solid rgba(236, 57, 66, 0.40); }
.pm-detail-bet-amt { color: var(--pm-gold-2); font-weight: 700; display: inline-flex; align-items: baseline; gap: 2px; font-variant-numeric: tabular-nums; }
.pm-detail-bet-time { margin-left: auto; color: var(--pm-hint); font-size: 11px; flex-shrink: 0; }

/* Sticky bet bar — fixed above the global nav (only visible while this page is) */
.pm-detail-betbar {
  position: fixed; bottom: 64px; left: 0; right: 0; z-index: 60;
  background: linear-gradient(180deg, rgba(14, 26, 42, 0) 0%, rgba(14, 26, 42, 0.85) 30%, rgba(14, 26, 42, 0.96) 100%);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  padding: 11px 14px; border-top: 1px solid rgba(255, 205, 80, 0.16);
  display: flex; align-items: center; gap: 10px;
}
.pm-detail-balpill { padding: 6px 10px 6px 12px; border-radius: 999px; background: linear-gradient(180deg, rgba(255, 184, 0, 0.18) 0%, rgba(229, 161, 0, 0.08) 100%); border: 1px solid rgba(255, 205, 80, 0.40); box-shadow: inset 0 1px 0 rgba(255, 230, 150, 0.18); display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pm-detail-balpill-num { font-size: 14px; font-weight: 800; color: var(--pm-gold-text); font-variant-numeric: tabular-nums; }
.pm-detail-cta { flex: 1; min-width: 0; padding: 12px 14px; border-radius: 12px; border: 0; cursor: pointer; font-family: inherit; color: #fff; font-weight: 900; font-size: 14px; letter-spacing: 0.2px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.pm-detail-cta:disabled { opacity: 0.5; }
.pm-detail-cta--yes { background: linear-gradient(135deg, var(--pm-yes-2) 0%, var(--pm-yes) 60%, #22a147 100%); box-shadow: 0 6px 20px rgba(52, 199, 89, 0.40), inset 0 1px 0 rgba(255,255,255,0.30); }
.pm-detail-cta--no  { background: linear-gradient(135deg, var(--pm-no-2) 0%, var(--pm-no) 60%, #b9242c 100%); box-shadow: 0 6px 20px rgba(236, 57, 66, 0.40), inset 0 1px 0 rgba(255,255,255,0.30); }
/* Creator "Propose result" CTA (premium gradient, distinct from bet yes/no). */
.pm-detail-cta--propose { background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%); box-shadow: 0 6px 20px rgba(99,102,241,0.42), inset 0 1px 0 rgba(255,255,255,0.22); }
.pm-detail-cta-w { font-weight: 700; opacity: 0.9; flex-shrink: 0; }
.pm-detail-cta-strong { font-weight: 900; font-variant-numeric: tabular-nums; flex-shrink: 0; }
.pm-detail-cta-arrow { margin-left: 4px; padding: 2px 8px; border-radius: 999px; background: rgba(0,0,0,0.18); font-size: 12px; font-weight: 800; display: inline-flex; align-items: baseline; gap: 3px; font-variant-numeric: tabular-nums; flex-shrink: 0; }
.pm-detail-cta > svg { flex-shrink: 0; }
/* The bet CTA is a fixed-width flex row. Keep Bet / stake / payout at natural size
   (flex-shrink:0 above) and let ONLY the outcome label shrink + ellipsis, so a long
   N-way outcome name never grows the button to multiple lines. Defined after
   .pm-detail-cta-w so its flex-shrink:1 wins for the label (it carries both classes). */
.pm-detail-cta-label { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Desktop-only refinements (phone untouched) ─────────────────────────────
   Telegram Desktop/Web renders the web-view larger than a phone. A GENTLE 0.92
   zoom trims the excess while keeping text readable (the earlier 0.85 made it
   too small). Plus the "Your position" block is grouped so its two sides don't
   spread apart and waste space. android/ios never get .pm-desktop. */
html.pm-desktop #md-content { zoom: 0.92; }
html.pm-desktop .pm-detail-yours { padding: 9px 12px; }
html.pm-desktop .pm-detail-yours-row { gap: 18px; margin-top: 5px; }
html.pm-desktop .pm-detail-yours-col { flex: 0 1 auto; }
html.pm-desktop .pm-detail-yours-pays { margin-top: 4px; }

/* ════════════════════════════════════════════════════════════════════════
   V8 "Vault + Liquid Glass" Home redesign. Scoped to #page-home.hm-v8 so the
   whole block is INERT until app.js adds the class — it cannot affect the live
   screen mid-build. Maps the V8 spec onto the EXISTING home markup/ids (no hook
   changes). Bottom nav intentionally untouched. Source: assets/V8 Spec Sheet.html
   + assets/home-v8-preview.html. Decisions: real gift composites (no tier
   palette), our ton.org diamond, perf-guarded motion, fitted toolbar.
   ════════════════════════════════════════════════════════════════════════ */
/* hmv8-sweep + hmv8-flicker removed (2026-05-26): the card shine bar and the
   pulsing top-right corner glow were both "moving light" the user asked to kill.
   The static warm top-right glow (core + halo) was removed too (2026-05-26, user
   request) — the home background is just the navy vault + a faint blue bottom-left glow. */

/* ── screen shell: vault ── */
/* overflow-x:clip — keep any wide child from creating horizontal scroll; without
   it iOS lets the whole page pan sideways and
   the user can drag it out of view (2026-05-26 bug report). clip (not hidden)
   leaves vertical scrolling untouched. */
/* min-height:100dvh — when the list is short (1-few gifts, e.g. after a filter)
   the page box was only as tall as its content, so the body's (different) navy
   gradient showed below it as a hard seam / "split background" — on own home AND
   foreign profiles (2026-05-26 report). Filling the viewport makes the V8
   background cover the whole screen; with many gifts the page already exceeds
   100dvh so this is a no-op there. (100vh fallback for older WebViews.) */
#page-home.hm-v8{position:relative;overflow-x:clip;max-width:100%;min-height:100vh;min-height:100dvh;
  background:
    radial-gradient(ellipse 70% 45% at 0% 100%, rgba(40,80,170,.20) 0%, transparent 65%),
    linear-gradient(165deg,#0E1B3B 0%,#0B1530 50%,#060B22 100%);}
/* (removed) #page-home.hm-v8::before corner glow — was a blurred gold radial that
   pulsed via hmv8-flicker. The static warm corner glow was also removed
   (2026-05-26, user request); no warm light remains. */
#page-home.hm-v8 > *{position:relative;z-index:1;}

/* ── header ── */
/* avatar: single clean gold ring (kill the base blue→purple→pink ::after ring),
   36px to match the preview; gear badge scaled to suit. */
#page-home.hm-v8 .user-avatar{width:36px;height:36px;font-size:18px;
  box-shadow:0 0 0 2px rgba(255,205,80,.55),inset 0 1.5px 0 rgba(255,255,255,.3),0 4px 14px rgba(0,0,0,.4);}
#page-home.hm-v8 .user-avatar::after{display:none;}
#page-home.hm-v8 .user-avatar-gear{right:-3px;top:-3px;width:16px;height:16px;border-width:1.5px;}
#page-home.hm-v8 .user-avatar-gear .gc-icon{width:10px;height:10px;}
#page-home.hm-v8 .user-name{color:#fff;font-weight:800;font-size:15px;}

/* search: one glass pill (not 3 connected segments) — borderless input,
   subtle paste icon, 28px circular gold button. Matches home-v8-preview.html. */
/* Round 124 (2026-05-27) — stable-width pill. Base .search-row--inline is
   `flex:1` (basis 0) + `margin-left:auto`; the auto-margin ate the free space
   so flex-grow never fired and the pill collapsed to its min-width:140px floor
   ("Search @u" clipped) with a dead gap to its left. Switch to a fixed width
   (clamped on small screens) and don't grow/shrink — now .user-info is the
   element that gives up space, so the NAME truncates (ellipsis above) while the
   search stays usable. margin-left:auto (inherited) still pins it flush-right. */
#page-home.hm-v8 .search-row--inline{display:flex;align-items:center;gap:6px;flex:0 0 auto;width:clamp(152px,46vw,170px);height:34px;padding:3px 3px 3px 14px;
  border-radius:999px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.22);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.30);-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3);}
#page-home.hm-v8 .search-input{flex:1;min-width:0;padding:0;border:none;border-radius:0;background:transparent;color:#fff;
  font-weight:600;font-size:12.5px;box-shadow:none;}
#page-home.hm-v8 .search-input:focus{border:none;background:transparent;box-shadow:none;}
#page-home.hm-v8 .search-input::placeholder{color:rgba(255,255,255,.55);}
#page-home.hm-v8 .search-paste-btn{width:auto;min-width:0;flex-shrink:0;padding:0 2px;border:none;background:transparent;
  color:rgba(255,255,255,.5);font-size:14px;box-shadow:none;}
#page-home.hm-v8 .search-btn{width:28px;height:28px;min-width:28px;flex-shrink:0;padding:0;border:none;border-radius:50%;
  background:linear-gradient(135deg,#FFE9B0,#FFCA28 55%,#DC9400);color:#2A1A04;
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.8),0 2px 10px rgba(255,184,0,.45);}
#page-home.hm-v8 .search-btn img,#page-home.hm-v8 .search-btn .gc-icon{filter:brightness(0);opacity:.82;width:14px;height:14px;}
/* Search typeahead dropdown fix (2026-05-26): the V8 layering rule
   `#page-home.hm-v8 > *{z-index:1}` puts the header and the totals card in their
   OWN stacking contexts at the same z-index, so the absolutely-positioned
   suggestions list (z-index:50, nested in the header) painted BEHIND the totals
   card — the typeahead "stopped working" after the V8 redesign. Lift the header
   above its siblings so the dropdown shows; widen it (the V8 search pill is only
   ~210px) and right-anchor it so it stays on-screen. */
#page-home.hm-v8 .header{position:relative;z-index:20;}
#page-home.hm-v8 .search-suggestions{left:auto;right:0;min-width:240px;max-width:78vw;}

/* Round 125 (2026-05-28) — entrance-animation freeze fix (ROOT CAUSE of the
   "blank top after refresh" bug). .header/.stats-row/.controls-row/.section-header
   still animate `fadeInUp` (opacity 0→1). When Home first paints while the
   Telegram WebView is hidden (a refresh or launch where the native transition
   covers the view), the Web Animations timeline is frozen at the 0% keyframe
   (opacity:0) and NEVER resumes once shown — these STATIC above-the-fold
   elements render permanently blank, while the gift grid (its cards are built
   AFTER the page is visible) shows fine. The JS `_entranceAnimUnstick` watchdog
   (app.js, 2026-05-27) IS deployed but is a reactive backstop with timing gaps —
   it still missed this refresh case. The deterministic fix is to not gate
   visibility on an animation at all. V8 already does this for .totals-card + .stat-item
   (animation:none). Extend it to the rest of the V8 Home above-the-fold chrome
   so a frozen timeline can't hide content. Scoped to #page-home.hm-v8 — other
   pages' entrance animations are untouched. */
#page-home.hm-v8 .header,
#page-home.hm-v8 .stats-row,
#page-home.hm-v8 .controls-row,
#page-home.hm-v8 .section-header { animation: none !important; }

/* ── foreign profile (viewing another user) — re-skin the like/dislike rating,
   name-link chevron + avatar thumb from the legacy purple/blue palette to the
   V8 gold/glass theme so other users' profiles match (not "old"). ── */
#page-home.hm-v8 .user-avatar-img{border-radius:50%!important;}
#page-home.hm-v8 .user-name-link{color:#fff;}
#page-home.hm-v8 .user-name-arrow{color:rgba(255,205,100,.9);}
#page-home.hm-v8 .rate-btn{border:1px solid rgba(255,255,255,.20);border-radius:999px;color:#fff;
  background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,.03));
  -webkit-backdrop-filter:blur(14px) saturate(1.3);backdrop-filter:blur(14px) saturate(1.3);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);}
#page-home.hm-v8 .rate-btn.voted{border-color:rgba(255,205,100,.55);
  background:linear-gradient(135deg,rgba(255,215,140,.26),rgba(255,170,50,.08));
  box-shadow:0 0 0 2px rgba(255,200,90,.20),inset 0 1px 0 rgba(255,255,255,.3);}
#page-home.hm-v8 .profile-views{color:rgba(255,255,255,.6);}
#page-home.hm-v8 .viewing-banner{border:1px solid rgba(255,205,100,.4);
  background:linear-gradient(135deg,rgba(255,215,140,.16),rgba(255,170,50,.05));color:#fff;}

/* ── hero (totals-card) ── */
#page-home.hm-v8 .totals-card{position:relative;border-radius:22px!important;padding:18px 20px 16px;min-height:134px;overflow:hidden;text-align:left;
  margin:0 0 16px!important;animation:none!important;background-size:auto!important;
  background:
    radial-gradient(ellipse 90% 70% at 95% -10%, rgba(255,210,120,.36) 0%, transparent 55%),
    radial-gradient(ellipse 60% 60% at 0% 110%, rgba(60,95,180,.22) 0%, transparent 60%),
    linear-gradient(160deg,#1B2C58 0%,#142046 50%,#0D1530 100%)!important;
  border:1.5px solid rgba(255,205,100,.62)!important;
  box-shadow:inset 0 1.5px 0 rgba(255,240,180,.30),0 14px 40px rgba(0,0,0,.55),0 0 28px rgba(255,180,80,.22)!important;}
/* (removed) .totals-card::before sweeping shine — see hmv8-sweep note above. */
#page-home.hm-v8 .totals-card > *{position:relative;z-index:2;}
#page-home.hm-v8 .totals-title{display:flex;align-items:center;justify-content:center;gap:6px;font:800 11px var(--font-sans,inherit);margin-bottom:0;
  letter-spacing:1.4px;text-transform:uppercase;color:transparent;
  background:linear-gradient(180deg,#FFE38A,#FFCA28 50%,#C98800);-webkit-background-clip:text;background-clip:text;}
#page-home.hm-v8 .totals-title-arrow{-webkit-text-fill-color:rgba(255,210,120,.6);}
#page-home.hm-v8 .totals-primary{font-size:44px;font-weight:800;line-height:1;letter-spacing:-1.6px;margin-top:10px;margin-bottom:0;
  display:flex;align-items:flex-end;justify-content:center;gap:8px;}
/* the number text itself (set as a gold-clip span by JS); the unit (★/ton/$)
   sits beside it so the gradient never clips an emoji */
#page-home.hm-v8 .hmv8-numtext{font-variant-numeric:tabular-nums;color:transparent;
  background:linear-gradient(180deg,#FFF5D0,#FFD86B 40%,#E5A100 80%,#B27000);-webkit-background-clip:text;background-clip:text;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.4)) drop-shadow(0 0 16px rgba(255,184,0,.3));}
/* Single-currency card: show ONLY the selected currency (the big primary,
   painted by renderHeroV8). The secondary row that mirrored the other two
   currencies is hidden so the block stays compact with no leftover gap below
   the value. The ★/▽/$ switcher (which picks the currency) is unchanged. */
#page-home.hm-v8 .totals-row{display:none;}

/* currency switcher (added to the hero by JS) */
#page-home.hm-v8 .hmv8-cur{position:absolute!important;right:12px;top:50%;transform:translateY(-50%);z-index:3;display:inline-flex;flex-direction:column;align-items:stretch;gap:3px;padding:2px;
  border-radius:999px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  -webkit-backdrop-filter:blur(22px) saturate(1.5);backdrop-filter:blur(22px) saturate(1.5);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.36),inset 1px 0 0 rgba(255,255,255,.10),inset -1px 0 0 rgba(255,255,255,.10),inset 0 -1px 0 rgba(255,255,255,.04),0 6px 16px rgba(0,0,0,.28);}
/* font bumped 11px → 15px so the unicode ★ + $ glyphs (text characters,
   sized by the button's font-box) render at the same visual size as the
   TON SVG sibling (16×16, ~12.5px effective after the viewBox tighten in
   commit 4419808). At 11px the text chars were ~9px effective while TON
   was ~12.5px — visibly mismatched. (2026-05-28) */
#page-home.hm-v8 .hmv8-cur button{height:22px;min-width:22px;padding:0 3px;border:1px solid transparent;border-radius:999px;background:none;cursor:pointer;
  color:rgba(255,255,255,.86);font:800 15px var(--font-sans,inherit);display:inline-flex;align-items:center;justify-content:center;transition:transform .12s;}
#page-home.hm-v8 .hmv8-cur button:active{transform:scale(.94);}
#page-home.hm-v8 .hmv8-cur button.on{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.28);color:#fff;box-shadow:inset 0 1.5px 0 rgba(255,255,255,.45);}
#page-home.hm-v8 .hmv8-cur svg{fill:currentColor;width:16px;height:16px;}

/* Portfolio P&L chip — moved into the hero, pinned bottom-right, centred under
   the ★/▽/$ switcher. Follows the global currency (value span carries
   data-stars-value so applyToDom reformats on switch); ▲/green = profit,
   ▼/red = loss (triangle + gain/loss class set by JS from the P&L sign).
   Tappable → Portfolio page (ui.js guards the card's breakdown-sheet handler). */
#page-home.hm-v8 .hmv8-pnl{position:absolute!important;left:50%;bottom:14px;transform:translateX(-50%);z-index:3;
  display:inline-flex;align-items:center;justify-content:center;gap:5px;height:25px;padding:0 11px;
  border:1px solid rgba(255,255,255,.18);border-radius:999px;cursor:pointer;
  background:rgba(255,255,255,.08);-webkit-backdrop-filter:blur(14px) saturate(1.3);backdrop-filter:blur(14px) saturate(1.3);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);
  font:800 13px/1 var(--font-sans,inherit);font-variant-numeric:tabular-nums;color:#fff;white-space:nowrap;transition:transform .12s;}
#page-home.hm-v8 .hmv8-pnl:active{transform:translateX(-50%) scale(.95);}
#page-home.hm-v8 .hmv8-pnl-tri{font-size:9px;line-height:1;}
#page-home.hm-v8 .hmv8-pnl-val svg{width:11px;height:11px;fill:currentColor;-webkit-text-fill-color:currentColor;vertical-align:-1px;}
#page-home.hm-v8 .hmv8-pnl.stat-item--gain{color:#7CFFC0;border-color:rgba(140,255,200,.42);background:linear-gradient(135deg,rgba(140,255,200,.22),rgba(52,199,89,.07));}
#page-home.hm-v8 .hmv8-pnl.stat-item--loss{color:#FF9AA0;border-color:rgba(255,128,133,.42);background:linear-gradient(135deg,rgba(255,128,133,.22),rgba(236,57,66,.07));}

/* ── stats ── */
#page-home.hm-v8 .stats-row{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
/* background-size:auto + animation:none kill the base premiumGradient shimmer
   (style.css ~1067) that was zooming/panning the gold gradient → "dirty". */
#page-home.hm-v8 .stat-item{border-radius:14px;padding:10px 12px 9px;border:1px solid rgba(255,255,255,.20);
  background:linear-gradient(135deg,rgba(255,255,255,.14),rgba(255,255,255,.04));background-size:auto!important;animation:none!important;
  -webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.34),0 6px 16px rgba(0,0,0,.28);}
/* gold/mint sit over a white-glass base so the translucent tint reads as BRIGHT
   glass on the near-black vault (the bare 0.22 spec value mocks up bright only on
   a light panel; on the dark vault it composites to a muddy gray-gold). */
#page-home.hm-v8 .stat-item--premium{background:linear-gradient(135deg,rgba(255,205,120,.30),rgba(255,165,55,.10));background-size:auto!important;animation:none!important;border-color:rgba(255,224,150,.50);}
#page-home.hm-v8 .stat-item--portfolio{background:linear-gradient(135deg,rgba(140,255,200,.27),rgba(52,199,89,.09));background-size:auto!important;animation:none!important;border-color:rgba(140,255,200,.46);}
/* Kill the base foil-sheen ::after (a bright diagonal highlight stripe) on the V8
   stat tiles — it read as a "flash light" on unique / limited / portfolio
   (2026-05-26 request). animation was already none; this removes the static streak. */
#page-home.hm-v8 .stat-item::after{display:none!important;}
#page-home.hm-v8 .stat-value{font:800 16px/1 var(--font-sans,inherit);letter-spacing:-.4px;font-variant-numeric:tabular-nums;color:#fff;}
#page-home.hm-v8 .stat-item--premium .stat-value{color:#FFF1C9;}
#page-home.hm-v8 .stat-item--portfolio .stat-value{color:#DCFCE9;}
#page-home.hm-v8 .stat-label{margin-top:5px;font:700 10.5px/1 var(--font-sans,inherit);letter-spacing:.4px;text-transform:uppercase;color:rgba(255,255,255,.80);}

/* ── sort toolbar ── */
#page-home.hm-v8 #gifts-controls .section-header{display:none;}
#page-home.hm-v8 .sort-buttons{display:flex;align-items:center;gap:3px;width:100%;padding:3px;height:34px;border-radius:999px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  -webkit-backdrop-filter:blur(16px) saturate(1.4);backdrop-filter:blur(16px) saturate(1.4);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.32),0 6px 16px rgba(0,0,0,.28);}
#page-home.hm-v8 .sort-btn{height:28px;border-radius:999px;border:1px solid transparent;background:none;
  color:rgba(255,255,255,.86);font:700 12px var(--font-sans,inherit);display:inline-flex;align-items:center;justify-content:center;gap:4px;flex:1 1 0;min-width:0;padding:0 5px;}
#page-home.hm-v8 #sort-group,#page-home.hm-v8 #sort-list{flex:0 0 28px;width:28px;padding:0;}
#page-home.hm-v8 #sort-price,#page-home.hm-v8 #sort-number{flex:0 0 auto;padding:0 11px;font-weight:900;font-size:14px;}
#page-home.hm-v8 .sort-btn.active{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.28);color:#fff;box-shadow:inset 0 1.5px 0 rgba(255,255,255,.45);}
#page-home.hm-v8 .sort-btn svg{width:14px;height:14px;}

/* ── gift tiles (group view) — single neutral frame, real composite art ── */
/* Fixed 4-col grid (matches the iPhone "actual design"). Was
   auto-fill minmax(82px,1fr), which dropped to 3 cols on the narrower Telegram
   Desktop mini-app window (<~365px) → bigger cards / fewer per row vs phone.
   Pinning 4 keeps the layout identical across phone + desktop; cards scale to
   the window width. (Own + foreign profiles share this #lines-list grid.) */
#page-home.hm-v8 .lines-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
#page-home.hm-v8 .group-card{display:flex;flex-direction:column;position:relative;border-radius:13px;padding:6px 6px 8px;overflow:hidden;
  background:linear-gradient(170deg,rgba(25,40,80,.85),rgba(15,25,60,.92))!important;border:1px solid rgba(255,255,255,.09)!important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07),inset 0 -1px 0 rgba(0,0,0,.12),0 4px 12px rgba(0,0,0,.3)!important;}
#page-home.hm-v8 .group-thumb{width:100%;aspect-ratio:1;height:auto;border-radius:9px;margin-bottom:5px;object-fit:cover;
  background:radial-gradient(ellipse at 50% 35%, rgba(120,150,210,.18), rgba(8,14,32,.6));}
/* Count chip — V8 Spec Sheet §"Gift grid" line 1082: a CONTAINED dark-navy
   pill with sky-blue ink, NOT a transparent floating number. The earlier
   transparent treatment read as "numbers out of the card" (2026-05-26
   report) because a number jammed in the corner with no container looks
   detached. top/right = 9px (spec's plate-relative 5px + our card's 6px
   padding ≈ sits just inside the artwork's top-right corner). */
#page-home.hm-v8 .group-badge{position:absolute;top:9px;right:9px;min-width:22px;height:20px;padding:0 7px;border-radius:999px;
  background:rgba(10,18,42,.92);color:#6BC8FF;font:800 11px/1 var(--font-sans,inherit);font-variant-numeric:tabular-nums;
  display:inline-flex;align-items:center;justify-content:center;text-align:center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 2px 6px rgba(0,0,0,.4);z-index:2;text-shadow:none;border:0;}
#page-home.hm-v8 .group-name{font:800 10.5px/1.1 var(--font-sans,inherit);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;margin-bottom:3px;}
#page-home.hm-v8 .group-value{margin-top:auto;display:inline-flex;align-items:center;justify-content:center;gap:4px;width:100%;overflow:hidden;font:800 13px var(--font-sans,inherit);font-variant-numeric:tabular-nums;letter-spacing:-.2px;
  color:transparent;background:linear-gradient(180deg,#FFE38A,#FFCA28 50%,#C98800);-webkit-background-clip:text;background-clip:text;}
/* glyph (★/ton/$) keeps its own fill — the text-clip gradient would otherwise paint it transparent */
#page-home.hm-v8 .group-value svg{width:11px;height:11px;flex-shrink:0;-webkit-text-fill-color:initial;}
#page-home.hm-v8 .group-value>span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}

/* ── Gifts | Collections tabs (shown on viewed profiles) → V8 dark-glass housing
   with a gold active cell, replacing the old purple pill so the viewed-profile
   chrome matches the home (2026-05-26: "make one source of design"). ── */
#page-home.hm-v8 .view-tabs{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.10);border-radius:14px;padding:3px;
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);}
#page-home.hm-v8 .view-tab{color:rgba(255,255,255,.60);border:1px solid transparent;border-radius:11px;font-weight:700;}
#page-home.hm-v8 .view-tab.active{background:linear-gradient(135deg,rgba(255,205,120,.30),rgba(255,165,55,.12));
  border-color:rgba(255,224,150,.45);color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.20);}

/* ── Collections grid cards → mirror the V8 gift tile: navy glass frame, real
   collection artwork, sky-blue count chip. Replaces the old purple/🎮 card that
   showed no actual collection art (2026-05-26 report). #user-collections-grid
   carries .lines-grid, so it already lays out in the same grid as the gifts. ── */
#page-home.hm-v8 .collection-card{display:flex;flex-direction:column;position:relative;border-radius:13px;padding:6px 6px 8px;overflow:hidden;text-align:center;
  background:linear-gradient(170deg,rgba(25,40,80,.85),rgba(15,25,60,.92));border:1px solid rgba(255,255,255,.09);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07),inset 0 -1px 0 rgba(0,0,0,.12),0 4px 12px rgba(0,0,0,.3);}
#page-home.hm-v8 .collection-card:active{background:linear-gradient(170deg,rgba(35,52,96,.9),rgba(20,32,72,.95));}
#page-home.hm-v8 .collection-thumb{width:100%;aspect-ratio:1;height:auto;border-radius:9px;margin-bottom:5px;object-fit:cover;
  background:radial-gradient(ellipse at 50% 35%,rgba(120,150,210,.18),rgba(8,14,32,.6));}
#page-home.hm-v8 .collection-icon{display:flex;align-items:center;justify-content:center;aspect-ratio:1;margin-bottom:5px;font-size:34px;line-height:1;
  border-radius:9px;background:radial-gradient(ellipse at 50% 35%,rgba(120,150,210,.18),rgba(8,14,32,.6));}
#page-home.hm-v8 .collection-title{font:800 10.5px/1.1 var(--font-sans,inherit);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:3px;}
#page-home.hm-v8 .collection-gifts{font:700 9.5px var(--font-sans,inherit);color:rgba(255,205,110,.85);}
#page-home.hm-v8 .collection-count{position:absolute;top:9px;right:9px;min-width:22px;height:20px;padding:0 7px;border-radius:999px;
  background:rgba(10,18,42,.92);color:#6BC8FF;font:800 11px/1 var(--font-sans,inherit);font-variant-numeric:tabular-nums;
  display:inline-flex;align-items:center;justify-content:center;text-align:center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 2px 6px rgba(0,0,0,.4);z-index:2;}

/* ── list view + collection drill-in rows + filter chips/banner ──
   re-skin from the old white-flat / purple / blue palette to V8 dark glass +
   gold. Rows mirror the group-tile glass; values are already gold-bright. ── */
#page-home.hm-v8 .active-filter{background:linear-gradient(135deg,rgba(255,215,140,.16),rgba(255,170,50,.05));border:1px solid rgba(255,205,100,.40);}
#page-home.hm-v8 .filter-chip{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);color:rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);}
#page-home.hm-v8 .filter-chip.active{background:linear-gradient(135deg,rgba(255,215,140,.26),rgba(255,170,50,.08));border-color:rgba(255,205,100,.55);color:#fff;}
#page-home.hm-v8 .regular-item{background:linear-gradient(170deg,rgba(28,44,84,.60),rgba(16,26,58,.78));border:1px solid rgba(255,255,255,.09);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 3px 10px rgba(0,0,0,.22);}
#page-home.hm-v8 .regular-item-clickable:active{background:linear-gradient(170deg,rgba(38,56,100,.70),rgba(22,34,72,.85));}
#page-home.hm-v8 .regular-thumb--emoji,#page-home.hm-v8 .modal-list-thumb--emoji{background:radial-gradient(ellipse at 50% 35%,rgba(120,150,210,.18),rgba(8,14,32,.6));border-color:rgba(255,255,255,.08);}
#page-home.hm-v8 .regular-title{font-weight:700;}
#page-home.hm-v8 .regular-sub-floor{color:rgba(255,205,110,.85);}

/* ── gift-detail modal — drop the 4-tier (gold/purple/blue/common) palette for a
   single V8 gold/glass treatment. GLOBAL (the modal is a fixed overlay OUTSIDE
   #page-home); placed after the base tier rules so same-specificity wins. ── */
.modal-card[data-tier="gold"],.modal-card[data-tier="purple"],.modal-card[data-tier="blue"],.modal-card[data-tier="common"]{
  background:linear-gradient(180deg,rgba(255,213,120,.20) 0%,rgba(255,180,60,.07) 22%,rgba(18,22,34,.84) 52%);
  border-top:2px solid rgba(255,205,100,.62);
  box-shadow:inset 0 1px 0 rgba(255,240,180,.30),0 0 22px rgba(255,190,70,.14);}
.modal-card[data-tier="gold"] .modal-stat,.modal-card[data-tier="purple"] .modal-stat,.modal-card[data-tier="blue"] .modal-stat,.modal-card[data-tier="common"] .modal-stat{
  background:linear-gradient(135deg,rgba(255,215,140,.16),rgba(255,255,255,.04));border:1px solid rgba(255,255,255,.14);}
.modal-card[data-tier="gold"] .modal-usd,.modal-card[data-tier="purple"] .modal-usd,.modal-card[data-tier="blue"] .modal-usd,.modal-card[data-tier="common"] .modal-usd{
  color:var(--gold-bright);text-shadow:0 0 18px rgba(255,184,0,.45);}
.modal-card .modal-btn{background:linear-gradient(135deg,#FFE9B0,#FFCA28 55%,#DC9400);color:#2A1A04;box-shadow:0 4px 14px rgba(255,184,0,.28);}
.modal-stat-floor{color:rgba(255,205,110,.85);}

/* ── states: error retry button → V8 gold (was tg-button blue). Error icon
   stays red (semantic), loading/empty text stay neutral. Global. ── */
.btn-retry{background:linear-gradient(135deg,#FFE9B0,#FFCA28 55%,#DC9400);color:#2A1A04;box-shadow:0 4px 14px rgba(255,184,0,.30);}
.btn-retry:active{opacity:.9;}

/* ── Model/Backdrop trait dropdown sheet — V8 gold/glass (global overlay; was
   tg-accent blue: "Show All" button, selected rows, checkboxes, chips). ── */
.dropdown-panel,.dropdown-header,.dropdown-search-wrap{background:#121a30;}
.dropdown-panel{border:1px solid rgba(255,205,100,.22);}
.dropdown-search:focus{border-color:rgba(255,205,100,.55);}
.dropdown-col-chip.active{background:linear-gradient(135deg,rgba(255,215,140,.26),rgba(255,170,50,.08));border-color:rgba(255,205,100,.55);color:#fff;}
.dropdown-apply{background:linear-gradient(135deg,#FFE9B0,#FFCA28 55%,#DC9400);color:#2A1A04;box-shadow:0 2px 10px rgba(255,184,0,.30);}
.dropdown-item:active{background:rgba(255,255,255,.06);}
.dropdown-item.selected{background:rgba(255,205,100,.12);}
.dropdown-item.selected .dropdown-check{background:linear-gradient(135deg,#FFD98C,#FFB43A);border-color:rgba(255,205,100,.6);color:#2A1A04;}

/* ── sort toolbar Model/Backdrop chevron (▾) per spec: 9px · opacity .72 ── */
#page-home.hm-v8 .sort-caret{font-size:9px;opacity:.72;margin-left:2px;}

/* ── iOS tap reliability — without touch-action:manipulation the WebView keeps a
   double-tap-zoom delay/ambiguity, so rapid taps on the sort tabs got eaten and
   needed 2-3 presses (2026-05-26 report). Applies to every tappable home control. */
#page-home.hm-v8 .sort-btn,#page-home.hm-v8 .hmv8-cur button,#page-home.hm-v8 .group-card,
#page-home.hm-v8 .stat-item,#page-home.hm-v8 .rate-btn,#page-home.hm-v8 .search-btn,
#page-home.hm-v8 .regular-item{touch-action:manipulation;}
.dropdown-item,.dropdown-apply,.dropdown-col-chip{touch-action:manipulation;}
/* (reduced-motion block removed — the V8 home no longer has any animations.) */

/* ════════════════════════════════════════════════════════════════════
   Share button (referral market-share) — GiftChecker Design System handoff
   (miniapp/assets/Gift Checker Design System.html). CALM pill in the
   market-detail header (static — must not fight the YES/NO bet buttons);
   LOUD full-width CTA at the post-bet moment (animated gold→blue→gold
   sweep + "+50%" chip). Only the two used variants are included.
   ════════════════════════════════════════════════════════════════════ */
@keyframes sh-sweep{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
.sh-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;padding:0;font-family:inherit;transition:transform .15s ease;font-variant-numeric:tabular-nums;flex-shrink:0}
.sh-btn:active{transform:scale(.95)}
.sh-btn[data-size="md"]{height:34px;padding:0 12px;gap:7px;font-size:12.5px}
.sh-btn .sh-label{letter-spacing:.2px;white-space:nowrap;font-weight:800}
.sh-btn .sh-arrow{display:block}
/* calm pill — header (no animation) */
.sh-btn--pill{border-radius:999px;background:linear-gradient(155deg,#1E47B8 0%,#0E2A6E 100%);box-shadow:inset 0 1px 0 rgba(255,245,200,.22),inset 0 -1px 0 rgba(0,0,0,.30),0 0 0 1px rgba(255,205,80,.55),0 0 14px rgba(255,184,0,.22),0 2px 6px rgba(14,42,110,.45)}
.sh-btn--pill .sh-label{background:linear-gradient(180deg,#FFE38A 0%,#FFCA28 50%,#E5A100 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-shadow:0 0 14px rgba(255,205,80,.20)}
.sh-btn--pill .sh-arrow{filter:drop-shadow(0 0 3px rgba(255,205,80,.55))}
/* loud full-width CTA — post-bet */
.sh-cta{width:100%;border-radius:14px;border:none;cursor:pointer;font-family:inherit;padding:12px 16px;display:flex;align-items:center;gap:12px;text-align:left;background:linear-gradient(115deg,#E5A100 0%,#FFCA28 8%,#FFE38A 16%,#4A7BD8 38%,#1E47B8 55%,#0E2A6E 72%,#E5A100 92%,#FFCA28 100%);background-size:220% 220%;animation:sh-sweep 7s ease-in-out infinite;box-shadow:inset 0 1px 0 rgba(255,255,255,.35),inset 0 -2px 8px rgba(0,0,0,.35),0 0 0 1px rgba(255,245,200,.55),0 0 22px rgba(255,184,0,.30),0 6px 18px rgba(14,42,110,.45);color:#FFFBE5;transition:transform .15s ease;margin-top:10px}
.sh-cta:active{transform:scale(.985)}
.sh-cta-icon{width:38px;height:38px;border-radius:999px;background:rgba(14,42,110,.35);border:1px solid rgba(255,245,200,.45);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:inset 0 1px 0 rgba(255,245,200,.30)}
.sh-cta-icon .sh-arrow{filter:drop-shadow(0 0 4px rgba(255,245,200,.55))}
.sh-cta-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.sh-cta-title{font-size:15px;font-weight:800;letter-spacing:.1px;color:#FFFBE5;text-shadow:0 1px 4px rgba(14,42,110,.75),0 0 8px rgba(255,205,80,.4)}
.sh-cta-sub{font-size:11.5px;font-weight:600;color:rgba(255,251,229,.85);text-shadow:0 1px 3px rgba(14,42,110,.7)}
.sh-cta-chip{font-size:11px;font-weight:900;letter-spacing:.4px;padding:5px 9px;border-radius:999px;background:linear-gradient(180deg,#FFE38A 0%,#FFCA28 50%,#E5A100 100%);color:#1A1205;border:.5px solid rgba(255,245,200,.55);box-shadow:inset 0 1px 0 rgba(255,255,255,.60),0 1px 3px rgba(14,42,110,.50);flex-shrink:0;white-space:nowrap}
@media (prefers-reduced-motion: reduce){.sh-cta{animation:none}}

/* ══ Server Status sheet (Settings → Server Status) ═══════════════════════════
   Sits on the existing .pm-sheet overlay frame; this block adds the status-
   specific elements (pill, recheck chip, data-safe card, component rows). */

.status-sheet-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.status-sheet-head-icon { width: 22px; height: 22px; color: var(--tg-text); flex-shrink: 0; }.status-recheck {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--tg-bg-input); color: var(--tg-hint);
  border: none; border-radius: 999px;
  padding: 6px 12px; font-size: 12px; font-weight: 600;
  cursor: pointer; margin-bottom: 14px; font-family: inherit;
}
.status-recheck:active { opacity: 0.7; }
.status-recheck.is-fetching .status-recheck-spinner { animation: statusSpin 1s linear infinite; display: inline-block; }
@keyframes statusSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }.status-banner.hidden { display: none; }

.status-section-label {
  font-size: 12px; font-weight: 600; color: var(--tg-hint);
  margin: 16px 0 8px;
}
.status-section-label.hidden { display: none; }

.status-safe-card {
  background: var(--tg-bg-input);
  border-radius: 14px;
  padding: 14px;
  display: flex; flex-direction: column; gap: 12px;
}
.status-safe-row { display: flex; align-items: flex-start; gap: 12px; }
.status-safe-icon {
  font-size: 16px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.status-safe-text  { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.status-safe-title { font-size: 14px; font-weight: 600; color: var(--tg-text); }
.status-safe-sub   { font-size: 13px; color: var(--tg-hint); line-height: 1.4; }.status-limited-list {
  background: rgba(240, 170, 50, 0.10);
  border-radius: 14px;
  overflow: hidden;
}
.status-limited-list.hidden { display: none; }
.status-limited-item {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(240, 170, 50, 0.15);
  font-size: 14px; color: var(--tg-text);
}
.status-limited-item:last-child { border-bottom: none; }.user-avatar-status.hidden { display: none; }

/* ── Deposit overlay redesign + TON deposit tab ────────────────────────────
   3-tab strip (Stars / TON / Gifts) inside #pm-topup-overlay. One visual
   language across every tab: same row component, same primary CTA, persistent
   wallet pill on the TON tab. Reference: @virus_play_bot top-up sheet (the
   operator-supplied screenshots in the contract file). Existing .pm-sheet,
   .pm-quick-row, .pm-stake-input, .pm-place-btn, .pm-deposit-btn stay as the
   shared atoms — only the new structure on top is novel. */

/* Sheet head — title left, close right (the close was floated absolutely
   before; the new layout flows it inline so the tab strip can be sticky
   under the head without overlapping). */
.pm-sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin: 0 0 8px;
}
.pm-sheet-head-title {
  font-size: 19px; font-weight: 700; color: var(--tg-text);
  letter-spacing: 0.2px; line-height: 1.2;
}
/* When the head is present, the close button sits inline (override the
   absolute positioning from the legacy .pm-sheet-close). */
.pm-sheet-head .pm-sheet-close { position: static; flex: 0 0 30px; }

/* Tab strip — pill row that scrolls horizontally on narrow screens but
   stays a static row on phone widths. Sticky under the head while the
   active pane scrolls below. */
.pm-tabs {
  position: sticky; top: 0; z-index: 2;
  display: flex; gap: 6px; margin: 0 -2px 14px;
  padding: 4px 2px;
  background: linear-gradient(180deg, #1b2736 0%, #1b2736 70%, rgba(27,39,54,0));
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.pm-tabs::-webkit-scrollbar { display: none; }
.pm-tab {
  flex: 1 1 0; min-width: 92px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 12px; border-radius: 999px;
  border: 1px solid var(--tg-separator);
  background: transparent;
  color: var(--tg-hint);
  font-size: 14px; font-weight: 600; line-height: 1; cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
}
.pm-tab:active { transform: scale(0.97); }
.pm-tab--active {
  background: var(--tg-bg-input);
  color: var(--tg-text);
  border-color: var(--tg-accent);
}
.pm-tab-ic { font-size: 15px; line-height: 1; }
.pm-tab-lbl { letter-spacing: 0.1px; }
.pm-tab-badge {
  font-size: 11px; font-weight: 700;
  padding: 2px 6px; border-radius: 999px;
  background: rgba(46, 195, 99, 0.22); color: #4ed68f;
  margin-left: 2px;
}
.pm-tab-badge.hidden { display: none; }

/* Generic tab pane — no extra chrome, just a hidden/visible toggle that
   plays nicely with the existing .hidden utility. */
.pm-tab-pane.hidden { display: none; }

/* ── TON tab — wallet pill / Connect CTA ─────────────────────────────────── */
.pm-ton-wallet { margin: 4px 0 10px; }
.pm-ton-wallet-connect {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; box-sizing: border-box;
  background: linear-gradient(135deg, #0098ea 0%, #0072c2 100%);
  color: #fff; font-weight: 700; font-size: 15px;
  border: none; border-radius: 12px; padding: 13px;
  cursor: pointer; transition: opacity 0.15s ease, transform 0.12s ease;
}
.pm-ton-wallet-connect:active { transform: scale(0.98); opacity: 0.92; }
.pm-ton-wallet-ic { font-size: 16px; line-height: 1; }
.pm-ton-wallet-lbl { letter-spacing: 0.2px; }

.pm-ton-wallet-disc {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  width: 100%; box-sizing: border-box;
  background: rgba(0, 152, 234, 0.10);
  color: var(--tg-text);
  border: 1px solid rgba(0, 152, 234, 0.35);
  border-radius: 12px; padding: 11px 14px;
  font-size: 14px; cursor: pointer;
  font-family: inherit;
}
.pm-ton-wallet-disc:active { opacity: 0.85; }
.pm-ton-wallet-addr { font-weight: 700; letter-spacing: 0.3px; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.pm-ton-wallet-x { font-size: 12px; color: var(--tg-hint); }

/* Bonus banner (e.g. "Get +10% extra Stars when you pay in TON"). */
.pm-bonus-banner {
  text-align: center;
  background: rgba(46, 195, 99, 0.10);
  border: 1px solid rgba(46, 195, 99, 0.28);
  border-radius: 10px;
  padding: 8px 12px; margin: 4px 0 12px;
  color: #6ad99d; font-size: 12.5px; font-weight: 600;
  line-height: 1.4;
}
.pm-bonus-banner.hidden { display: none; }

/* Quick-pick rows — Stars amount + bonus pill on the left, TON cost on the
   right. Mirrors the @virus_play_bot reference structure within our dark
   theme aesthetic. */
.pm-ton-rows {
  display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px;
}
.pm-ton-empty {
  color: var(--tg-hint); font-size: 13px; text-align: center; padding: 12px 0;
}
.pm-ton-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; width: 100%; box-sizing: border-box;
  background: var(--tg-bg-input); color: var(--tg-text);
  border: 1px solid var(--tg-separator); border-radius: 14px;
  padding: 12px 14px; cursor: pointer;
  font-family: inherit; font-size: 15px;
  transition: border-color 0.12s ease, transform 0.12s ease, background 0.12s ease;
}
.pm-ton-row:active { transform: scale(0.99); background: var(--tg-bg-secondary, #243349); }
.pm-ton-row-amt {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 700;
}
.pm-ton-row-stars { color: var(--gold-bright, #f5b75a); }
.pm-ton-bonus {
  font-size: 11.5px; font-weight: 700;
  color: #6ad99d; background: rgba(46, 195, 99, 0.20);
  border-radius: 999px; padding: 2px 7px;
  letter-spacing: 0.2px;
}
.pm-ton-row-cost {
  font-weight: 700; color: var(--tg-text);
  letter-spacing: 0.2px;
}

/* Live "≈ X TON" preview under the custom amount input. */
.pm-ton-preview {
  color: var(--tg-hint); font-size: 13px; line-height: 1.4;
  margin: -4px 0 10px; padding: 0 2px;
}
.pm-ton-preview.hidden { display: none; }
.pm-ton-preview b { color: var(--tg-text); font-weight: 700; }

/* Stale rate warning (visible when /rate returns stale=true). */
.pm-ton-stale {
  margin-top: 10px; padding: 8px 12px; border-radius: 10px;
  background: rgba(245, 183, 90, 0.12);
  border: 1px solid rgba(245, 183, 90, 0.28);
  color: var(--gold-bright, #f5b75a);
  font-size: 12px; text-align: center;
}
.pm-ton-stale.hidden { display: none; }

/* TON wait sub-view — large amount preview while polling /status. */
.pm-ton-wait-row {
  display: flex; flex-direction: column; align-items: center;
  gap: 4px; margin: 18px 0 8px;
}
.pm-ton-wait-amt {
  font-size: 28px; font-weight: 800;
  color: var(--gold-bright, #f5b75a);
  letter-spacing: 0.4px;
}
.pm-ton-wait-bonus {
  font-size: 12.5px; font-weight: 700;
  color: #6ad99d;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Leaderboard V3 J — "Deep Dive" Liquid Glass redesign
 * ───────────────────────────────────────────────────────────────────────────
 * Reference: miniapp/assets/V3 J · Deep Dive.html
 * Scope token: `#page-leaderboard.lb-v3` — every selector below is anchored
 * to that scope so the previous styles (.lb-item bright top-3, .lb-header
 * etc.) are dead code only when `.lb-v3` is on the page div. The V3 markup
 * uses `.vk-*` class names (vk = "V-king" / "vk" prefix from the handoff)
 * plus retains the legacy `.lb-item` + `.lb-gifts` classes so the existing
 * shrink-to-fit observer (app.js ~5597) keeps measuring `gifts` lines.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Force dark navy page bg + two corner aurora overlays — design
   spec §2 "Frame background (page)". Matches the look of the Home V8 hero. */
#page-leaderboard.lb-v3 {
  color: #F5F5F5;
  background:
    radial-gradient(ellipse 90% 50% at 10% 0%, rgba(46,166,255,0.10) 0%, transparent 55%),
    radial-gradient(ellipse 70% 50% at 90% 100%, rgba(151,111,255,0.07) 0%, transparent 55%),
    linear-gradient(160deg, #0a1420 0%, #0e1a2a 30%, #0c1725 60%, #0e1422 100%);
  min-height: 100vh;
  padding-bottom: 80px;
}

/* Drifting aurora behind the slab + Your-rank — design §7 "Animations" */
@keyframes lbV3Aurora {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50%      { transform: translate(8%, -6%) rotate(8deg); }
}

/* ── Header (wordmark + currency switcher + search) ── */
#page-leaderboard.lb-v3 .vk-header {
  position: relative;
  padding: 14px 16px 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 5;
}
#page-leaderboard.lb-v3 .vk-titlerow {
  display: flex;
  align-items: center;
  gap: 10px;
}
#page-leaderboard.lb-v3 .vk-wordmark {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.4px;
  line-height: 1.1;
  background: linear-gradient(180deg, #FFF5D0, #FFD86B 40%, #E5A100 85%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.4)) drop-shadow(0 0 14px rgba(255,184,0,0.30));
  flex: 1;
  /* Kill the old animated rainbow gradient inherited from .page-title--inline */
  animation: none;
}
/* Smaller wordmark on desktop / pointer:fine — matches existing .page-title--inline rule */
@media (pointer: fine) {
  #page-leaderboard.lb-v3 .vk-wordmark { font-size: 18px; }
}

/* Currency switcher — pill, 30px tall. Active button = gold lozenge for stars,
   neutral blue glass for TON/USD (per design §9 note 6). */
#page-leaderboard.lb-v3 .vk-cur {
  display: inline-flex;
  align-items: center;
  height: 30px;
  border-radius: 999px;
  padding: 2px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  backdrop-filter: blur(22px) saturate(1.6);
  box-shadow:
    inset 0 1.5px 0 rgba(255,255,255,0.30),
    inset 0 -1px 0 rgba(255,255,255,0.04),
    0 6px 16px rgba(0,0,0,0.28);
  flex-shrink: 0;
}
#page-leaderboard.lb-v3 .vk-cur button {
  min-width: 30px;
  height: 26px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: rgba(255,255,255,0.70);
  font: 800 12px var(--font-sans, inherit);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.12s;
}
#page-leaderboard.lb-v3 .vk-cur button:active { transform: scale(0.94); }
#page-leaderboard.lb-v3 .vk-cur button svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
  opacity: 0.85;
}
/* Active state — uniform neutral-glass lozenge for ALL currencies (Stars,
   TON, USD share the same halo per user 2026-05-28 direction: «make
   selected currency in one color - transparent. the halo for stars-ton
   currency is different»). The earlier gold-on-Stars special case was
   removed for this consistency. */
#page-leaderboard.lb-v3 .vk-cur button.on {
  background: rgba(255,255,255,0.16);
  border-color: rgba(255,255,255,0.28);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    inset 0 -1px 0 rgba(0,0,0,0.10);
}

/* Search row — blue-glass with paste + submit buttons */
#page-leaderboard.lb-v3 .vk-search {
  position: relative;
  display: flex;
  align-items: stretch;
  height: 38px;
  /* The V3 element carries BOTH `vk-search` and legacy `search-row
     search-row--inline` classes (kept so existing autocomplete/Enter
     handlers keep firing). Legacy `.search-row` adds a clamp horizontal +
     bottom padding and a fadeInUp animation that shrank the inner input
     visually + visibly resized the row on every page activation. Zero them
     out within V3 scope so layout matches the Deep Dive design exactly. */
  padding: 0;
  margin: 0;
  animation: none;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(106,179,243,0.16) 0%, rgba(46,166,255,0.05) 50%, rgba(107,147,255,0.14) 100%);
  border: 1px solid rgba(106,179,243,0.30);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.28),
    inset 0 -1px 0 rgba(46,166,255,0.16),
    0 4px 14px rgba(46,166,255,0.10);
  /* `overflow: hidden` was clipping the absolutely-positioned
     `.search-suggestions` dropdown below the row → autocomplete
     suggestions were invisible on Top (bug 2026-05-28). The submit
     button's right corner is now explicitly rounded (see
     `.vk-search-submit` rule) so removing the parent clip is safe. */
  flex: none;
  min-width: 0;
}
#page-leaderboard.lb-v3 .vk-search::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 55%;
  background: radial-gradient(ellipse 80% 100% at 30% 0%, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0) 70%);
  pointer-events: none;
}
/* Input — extra-specific selector (input.search-input) so it WINS over the
   legacy `.search-input` rules (border, bg, padding, radius, focus halo)
   even when properties don't overlap exactly. text-align:left guards
   against any inherited centering. */
#page-leaderboard.lb-v3 .vk-search input.search-input,
#page-leaderboard.lb-v3 .vk-search input {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  outline: none;
  color: #fff;
  font: 600 13px var(--font-sans, inherit);
  padding: 0 12px;
  text-align: left;
  letter-spacing: -0.1px;
  position: relative;
  text-shadow: 0 1px 1px rgba(0,0,0,0.20);
  height: 100%;
  box-sizing: border-box;
}
/* Override the legacy `.search-input:focus` glow inside V3 — V3's halo is
   the .vk-search row border (the segment-by-segment border-color shift
   that the legacy rule shipped fights the seamless slab look). */
#page-leaderboard.lb-v3 .vk-search input.search-input:focus,
#page-leaderboard.lb-v3 .vk-search input:focus {
  border: none;
  background: transparent;
  box-shadow: none;
}
#page-leaderboard.lb-v3 .vk-search input::placeholder { color: rgba(255,255,255,0.55); }
#page-leaderboard.lb-v3 .vk-search-paste,
#page-leaderboard.lb-v3 .vk-search-submit {
  flex-shrink: 0;
  width: 38px;
  border: none;
  border-left: 1px solid rgba(255,255,255,0.10);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.12s, filter 0.15s, transform 0.12s;
}
#page-leaderboard.lb-v3 .vk-search-paste { background: rgba(107,147,255,0.16); }
#page-leaderboard.lb-v3 .vk-search-paste:hover { background: rgba(107,147,255,0.26); }
#page-leaderboard.lb-v3 .vk-search-paste:active { background: rgba(107,147,255,0.34); transform: scale(0.94); }
#page-leaderboard.lb-v3 .vk-search-submit {
  background: linear-gradient(135deg, #6B93FF, #976FFF);
  /* Round the right edge to match the parent .vk-search radius — needed
     after dropping `overflow: hidden` on the parent (otherwise the button's
     rectangular right corner pokes past the parent's rounded edge). */
  border-radius: 0 12px 12px 0;
}
#page-leaderboard.lb-v3 .vk-search-submit:hover { filter: brightness(1.08); }
#page-leaderboard.lb-v3 .vk-search-submit:active { transform: scale(0.94); }
#page-leaderboard.lb-v3 .vk-search-paste svg,
#page-leaderboard.lb-v3 .vk-search-submit svg { width: 16px; height: 16px; opacity: 0.92; }

/* Suggestions dropdown — keep absolute positioning under the search row */
#page-leaderboard.lb-v3 .vk-search .search-suggestions {
  /* Sit just below the search row */
  top: 100%;
  margin-top: 6px;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(14, 25, 40, 0.92);
  border: 1px solid rgba(106,179,243,0.30);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  box-shadow: 0 8px 24px rgba(0,0,0,0.45);
  color: #fff;
}

/* ── Your-rank pinned card — same Liquid Glass medium as slab ── */
#page-leaderboard.lb-v3 .tr-you {
  position: relative;
  overflow: hidden;
  margin: 8px 16px 14px;
  height: 58px;
  padding: 0 18px;
  display: grid;
  grid-template-columns: 30px 36px 1fr auto;
  gap: 12px;
  align-items: center;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(106,179,243,0.18) 0%, rgba(46,166,255,0.08) 45%, rgba(107,147,255,0.18) 100%);
  border: 1px solid rgba(106,179,243,0.34);
  -webkit-backdrop-filter: blur(28px) saturate(190%);
  backdrop-filter: blur(28px) saturate(190%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.32),
    inset 0 -1px 0 rgba(46,166,255,0.20),
    inset 0 14px 24px -14px rgba(255,255,255,0.24),
    0 10px 28px rgba(46,166,255,0.18),
    0 6px 18px rgba(0,0,0,0.32);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
#page-leaderboard.lb-v3 .tr-you::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 60%;
  background: radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0) 65%);
  pointer-events: none;
  z-index: 0;
  border-radius: 18px 18px 0 0;
}
#page-leaderboard.lb-v3 .tr-you::after {
  content: '';
  position: absolute;
  inset: -30%;
  background:
    radial-gradient(ellipse 50% 70% at 20% 30%, rgba(46,166,255,0.22) 0%, transparent 65%),
    radial-gradient(ellipse 60% 50% at 80% 70%, rgba(151,111,255,0.20) 0%, transparent 65%);
  filter: blur(18px);
  animation: lbV3Aurora 22s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}
#page-leaderboard.lb-v3 .tr-you > * { position: relative; z-index: 1; }
#page-leaderboard.lb-v3 .tr-you-rank {
  font-size: 14px;
  font-weight: 800;
  color: #fff;
  letter-spacing: -0.5px;
  text-align: center;
}
#page-leaderboard.lb-v3 .tr-you-rank::before {
  content: '#';
  font-size: 10px;
  color: rgba(255,255,255,0.55);
  margin-right: 1px;
  vertical-align: 2px;
}
#page-leaderboard.lb-v3 .tr-you-avatar,
#page-leaderboard.lb-v3 .tr-you .lb-avatar,
#page-leaderboard.lb-v3 .tr-you .lb-avatar-img {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
}
#page-leaderboard.lb-v3 .tr-you-avatar,
#page-leaderboard.lb-v3 .tr-you .lb-avatar {
  border-radius: 50%;
  background: linear-gradient(135deg, #6B93FF, #976FFF);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  border: 0;
}
/* TG profile photo / row top-gift thumbnail inside the Your-rank card —
   styled as a CIRCLE (radius 50%) per V3 J · Deep Dive spec for
   `.tr-you-avatar`. The user IS the viewer, so a circular profile chip
   reads correctly regardless of whether the source is a TG photo (most
   common) or a square gift thumbnail (fallback). */
#page-leaderboard.lb-v3 .tr-you .lb-avatar-img {
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid rgba(255,255,255,0.18);
  box-shadow: 0 2px 6px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.15);
}
/* When rank is unknown (no leaderboard backing, no scan in users[]),
   suppress the leading "#" decoration — "#—" reads as a broken layout. */
#page-leaderboard.lb-v3 .lb-self-rank--unknown::before {
  content: none !important;
}
#page-leaderboard.lb-v3 .tr-you-info { min-width: 0; }
#page-leaderboard.lb-v3 .tr-you-name {
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#page-leaderboard.lb-v3 .tr-you-meta {
  font-size: 10.5px;
  color: rgba(255,255,255,0.55);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#page-leaderboard.lb-v3 .tr-you-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  font-weight: 800;
  letter-spacing: -0.2px;
}
#page-leaderboard.lb-v3 .tr-you-stars-num {
  font-size: 14px;
  background: linear-gradient(180deg, #FFFCE3 0%, #FFE38A 35%, #FFCA28 70%, #C98800 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-weight: 800;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.45)) drop-shadow(0 0 6px rgba(255,184,0,0.20));
}

/* ── Single Liquid-Glass slab containing all rows ── */
#page-leaderboard.lb-v3 .vk-slab {
  position: relative;
  margin: 0 16px 8px;
  padding: 0;
  border-radius: 24px;
  background: linear-gradient(180deg, rgba(106,179,243,0.16) 0%, rgba(46,166,255,0.06) 40%, rgba(107,147,255,0.16) 100%);
  -webkit-backdrop-filter: blur(28px) saturate(190%);
  backdrop-filter: blur(28px) saturate(190%);
  border: 1px solid rgba(106,179,243,0.30);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.30),
    inset 0 -1px 0 rgba(46,166,255,0.20),
    inset 0 14px 24px -14px rgba(255,255,255,0.22),
    0 16px 40px rgba(46,166,255,0.18),
    0 10px 30px rgba(0,0,0,0.32);
  overflow: hidden;
}
#page-leaderboard.lb-v3 .vk-slab::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 60%;
  background: radial-gradient(ellipse 130% 100% at 50% 0%, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0) 65%);
  pointer-events: none;
  z-index: 1;
}
#page-leaderboard.lb-v3 .vk-slab::after {
  content: '';
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(ellipse 40% 60% at 25% 30%, rgba(46,166,255,0.22) 0%, transparent 60%),
    radial-gradient(ellipse 50% 40% at 75% 70%, rgba(151,111,255,0.18) 0%, transparent 60%);
  filter: blur(20px);
  animation: lbV3Aurora 18s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}

/* ── Row — all 58px, identical grid 1-N. Top 1-3 differ ONLY in tint/edge ── */
#page-leaderboard.lb-v3 .vk-row {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 30px 36px 1fr auto;
  gap: 12px;
  align-items: center;
  height: 58px;
  min-height: 58px;
  padding: 0 18px;
  margin: 0;
  border: 0;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  border-radius: 0;
  background: none;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  text-shadow: none;
  /* Kill legacy gradient + sheen ::after from .lb-item rules */
  box-shadow: none;
}
#page-leaderboard.lb-v3 .vk-row:last-child { border-bottom: 0; }
/* Suppress the legacy rank-4+ sheen ::after that was added via the old
   `.lb-item[data-rank]:not([data-rank="1|2|3"])::after` rule */
#page-leaderboard.lb-v3 .vk-row::after { display: none; content: none; }

/* Rank cell — generic (4+) */
#page-leaderboard.lb-v3 .vk-strip {
  text-align: center;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: rgba(255,255,255,0.65);
  text-shadow: 0 1px 1px rgba(0,0,0,0.20);
  /* Kill legacy .lb-rank cool-blue gradient text-clip */
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  -webkit-text-fill-color: initial;
  filter: none;
}
/* Avatar — both <img> and initial-letter <div> variants land on the row's
   2nd grid column. _resolveAvatarHtml emits BOTH (img with onerror→div fallback)
   so the row grid receives two children for the avatar slot; we span them
   together with display:contents on the wrapper... but since the wrapper
   is absent (avatar HTML is concatenated as siblings), we instead make sure
   each is sized and the second (.lb-avatar) is display:none initially. */
#page-leaderboard.lb-v3 .vk-row > .lb-avatar-img,
#page-leaderboard.lb-v3 .vk-row > .lb-avatar {
  width: 36px;
  height: 36px;
  border-radius: 11px;
  object-fit: cover;
  border: 1px solid rgba(255,255,255,0.18);
  box-shadow: 0 2px 6px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.15);
  align-self: center;
  background: rgba(255,255,255,0.04);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}
/* Initial-letter fallback (`<div class="lb-avatar" style="display:none">`)
   stays hidden by inline-style until the <img> errors out. The onerror swap
   flips its display to flex; our `display:flex` above wins ONLY when JS
   removes the inline display:none. */

#page-leaderboard.lb-v3 .vk-row .vk-info {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
#page-leaderboard.lb-v3 .vk-row .vk-name {
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.1px;
  text-shadow: 0 1px 1px rgba(0,0,0,0.20);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
#page-leaderboard.lb-v3 .vk-row .vk-name-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
#page-leaderboard.lb-v3 .vk-row .vk-gifts,
#page-leaderboard.lb-v3 .vk-row .lb-gifts {
  font-size: 10.5px;
  color: rgba(255,255,255,0.55);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#page-leaderboard.lb-v3 .vk-row .vk-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  text-align: right;
}
#page-leaderboard.lb-v3 .vk-row .vk-stars-num {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.2px;
  background: linear-gradient(180deg, #FFFCE3 0%, #FFE38A 35%, #FFCA28 70%, #C98800 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.45)) drop-shadow(0 0 6px rgba(255,184,0,0.20));
  white-space: nowrap;
}
#page-leaderboard.lb-v3 .vk-star-svg {
  width: 13px;
  height: 13px;
  filter: drop-shadow(0 0 6px rgba(255,184,0,0.45));
  flex-shrink: 0;
}
/* Hide the foil-gold ⭐ next to row + self values when the active currency
   isn't stars — TON/USD render their own unit symbol inside the
   .vk-stars-num text (TON_ICON, '$') so a trailing gold star would be a
   misleading second unit glyph. Bug caught 2026-05-28 ("icon of the stars
   is still present nearby valuation" when switching to TON/USD). */
#page-leaderboard.lb-v3:not([data-cur="stars"]) .vk-star-svg {
  display: none;
}

/* ── Top 1-2-3 row tints — vertical gradient + 3px inset left edge + foil rank.
   The 3px edge is the LAST shadow in the stack (order-sensitive per design §9
   note 4) so it composites over the inner highlights. */
#page-leaderboard.lb-v3 .vk-row[data-rank="1"] {
  background: linear-gradient(180deg, rgba(255,213,95,0.22) 0%, rgba(255,180,40,0.08) 50%, rgba(46,166,255,0.05) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,235,160,0.36),
    inset 0 -1px 0 rgba(255,180,40,0.16),
    inset 0 8px 14px -8px rgba(255,235,160,0.22),
    inset 3px 0 0 rgba(255,213,95,0.85);
  border-bottom-color: rgba(255,213,95,0.18);
  --g1: #FFE38A; --g2: #FFCA28; --g3: #C68C20; --gglow: rgba(255,200,80,0.60);
}
#page-leaderboard.lb-v3 .vk-row[data-rank="2"] {
  background: linear-gradient(180deg, rgba(220,230,245,0.20) 0%, rgba(180,200,230,0.06) 50%, rgba(46,166,255,0.05) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.40),
    inset 0 -1px 0 rgba(180,200,230,0.14),
    inset 0 8px 14px -8px rgba(255,255,255,0.22),
    inset 3px 0 0 rgba(220,230,245,0.85);
  border-bottom-color: rgba(220,230,245,0.18);
  --g1: #F4F8FF; --g2: #D5DEEC; --g3: #97A4BA; --gglow: rgba(220,230,245,0.40);
}
#page-leaderboard.lb-v3 .vk-row[data-rank="3"] {
  background: linear-gradient(180deg, rgba(224,148,96,0.20) 0%, rgba(180,100,60,0.08) 50%, rgba(46,166,255,0.05) 100%);
  box-shadow:
    inset 0 1px 0 rgba(244,180,140,0.36),
    inset 0 -1px 0 rgba(180,100,60,0.16),
    inset 0 8px 14px -8px rgba(244,180,140,0.22),
    inset 3px 0 0 rgba(224,148,96,0.85);
  border-bottom-color: rgba(224,148,96,0.18);
  --g1: #F4CFA8; --g2: #D28352; --g3: #8C4E2A; --gglow: rgba(224,148,96,0.50);
}
#page-leaderboard.lb-v3 .vk-row[data-rank="1"] .vk-strip,
#page-leaderboard.lb-v3 .vk-row[data-rank="2"] .vk-strip,
#page-leaderboard.lb-v3 .vk-row[data-rank="3"] .vk-strip {
  background: linear-gradient(180deg, var(--g1), var(--g2) 50%, var(--g3));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 0 4px var(--gglow));
  text-shadow: none;
  font-weight: 800;
}

/* ── NEW badge (preserved) ── */
#page-leaderboard.lb-v3 .vk-row .lb-new-badge {
  flex-shrink: 0;
  margin-left: 6px;
}
/* Quietly disable the legacy lbNewPulse animation in V3 scope — the slab's
   aurora already gives the rows life; another oscillating outline glow would
   read as visual noise. The NEW badge itself still appears. */
#page-leaderboard.lb-v3 .vk-row.lb-item--new {
  animation: none;
}

/* ── Empty state ── */
#page-leaderboard.lb-v3 .vk-slab .empty-state {
  padding: 32px 16px;
  text-align: center;
  color: rgba(255,255,255,0.55);
}

/* ── Subtitle row (kept for refresh-hint), restyled dark ── */
#page-leaderboard.lb-v3 .lb-subtitle-row {
  padding: 0 16px 10px;
}
#page-leaderboard.lb-v3 .page-subtitle--inline {
  color: rgba(255,255,255,0.55);
  font-size: 12px;
  font-weight: 500;
}
#page-leaderboard.lb-v3 .leaderboard-refresh-hint {
  color: rgba(255,255,255,0.42);
}
/* The legacy outer container of #leaderboard-list (`.leaderboard-list` adds
   bottom padding for the nav clear). The `.vk-slab` class is also on the
   same element — we keep both so app.js+other code keep working — but in V3
   the slab provides its own margin, so kill the legacy padding. */
#page-leaderboard.lb-v3 .leaderboard-list.vk-slab {
  padding: 0;
}

/* PC / wide-viewport — keep the page comfortably bounded so the slab doesn't
   stretch full-width across an ultrawide window (e.g. TG Desktop side panel).
   Matches the design's 380px frame intent but adapts up to 560px for PC. */
@media (min-width: 600px) {
  #page-leaderboard.lb-v3 .vk-header,
  #page-leaderboard.lb-v3 .tr-you,
  #page-leaderboard.lb-v3 .vk-slab,
  #page-leaderboard.lb-v3 .lb-subtitle-row {
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
  }
  #page-leaderboard.lb-v3 .vk-header { padding-left: 16px; padding-right: 16px; }
}

/* Respect reduced-motion — kill the aurora drift */
@media (prefers-reduced-motion: reduce) {
  #page-leaderboard.lb-v3 .vk-slab::after,
  #page-leaderboard.lb-v3 .tr-you::after { animation: none; }
}

/* ═════════════════════════════════════════════════════════════════════════
 * Deposit Sheet V5 — full redesign for the Predictions "+" deposit modal
 * ─────────────────────────────────────────────────────────────────────────
 * Reference: miniapp/assets/Deposit page_files/_bootstrap.html (designer's
 * "Deposit Sheet V5 · Developer Handoff"). All `.ds-*` classes live ONLY
 * inside #pm-topup-overlay so they can't bleed into other pages.
 * Tokens are scoped to the overlay too (`#pm-topup-overlay { --ds-… }`)
 * so the legacy .pm-* sheet styles still work elsewhere.
 * ═════════════════════════════════════════════════════════════════════════ */
#pm-topup-overlay {
  /* Stack above the create/settings wizard (.pm-sheet-overlay z:1000) so the
     deposit page opens ON TOP when reached from the fee-gate / not-enough-Stars
     confirms (the wizard comes later in the DOM, so an equal z would hide the
     deposit sheet behind it). The create form stays mounted underneath →
     closing the deposit sheet returns to it. */
  z-index: 1100;
  /* Surface */
  --ds-bg:            #14202d;
  --ds-bg-tint:       rgba(255, 184, 0, 0.06);
  --ds-bg-card-dark:  rgba(0, 0, 0, 0.20);
  --ds-bg-chip:       rgba(255, 255, 255, 0.04);
  --ds-bg-hint:       rgba(255, 255, 255, 0.02);
  /* Gold */
  --ds-gold-1:  #FFE38A;
  --ds-gold-2:  #FFCA28;
  --ds-gold-3:  #E5A100;
  --ds-gold-text: #FFD680;
  --ds-gold-ink:  #1a1205;
  --ds-gold-border: rgba(255, 205, 80, 0.18);
  --ds-gold-border-strong: rgba(255, 205, 80, 0.40);
  --ds-gold-card-edge: rgba(255, 205, 80, 0.15);
  --ds-gold-glow:   rgba(255, 184, 0, 0.25);
  --ds-gold-glow-strong: rgba(255, 184, 0, 0.35);
  /* Premium */
  --ds-premium-1: #6B93FF;
  --ds-premium-2: #976FFF;
  --ds-premium-3: #E46ACE;
  --ds-premium-border: rgba(151, 111, 255, 0.25);
  --ds-premium-active-bg: linear-gradient(180deg, rgba(151,111,255,0.32), rgba(151,111,255,0.10));
  --ds-premium-active-border: rgba(151, 111, 255, 0.65);
  /* Green / bonus */
  --ds-green:        #5fe39a;
  --ds-green-tint-2: rgba(95, 227, 154, 0.14);
  --ds-green-border: rgba(95, 227, 154, 0.40);
  --ds-green-tab-on:  rgba(95, 227, 154, 0.22);
  --ds-green-tab-off: rgba(95, 227, 154, 0.10);
  /* Text + border */
  --ds-text:    #F5F5F5;
  --ds-text-2:  rgba(255, 255, 255, 0.85);
  --ds-text-3:  rgba(255, 255, 255, 0.55);
  --ds-text-4:  rgba(255, 255, 255, 0.45);
  --ds-border:  rgba(255, 255, 255, 0.06);
  /* Radii */
  --ds-r-sm:  9px;
  --ds-r-md: 10px;
  --ds-r-lg: 12px;
  --ds-r-xl: 14px;
  --ds-r-sheet: 22px;
  --ds-r-pill: 999px;
  /* Shadows */
  --ds-shadow-sheet: 0 -10px 36px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 230, 150, 0.10);
  --ds-shadow-gold:  inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 4px 16px rgba(255, 184, 0, 0.35);
  --ds-shadow-prem:  0 6px 18px rgba(151, 111, 255, 0.40), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  --ds-shadow-tab-underline: 0 0 8px rgba(255, 184, 0, 0.6);
  /* Gradients */
  --ds-grad-gold: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%);
  --ds-grad-premium: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  --ds-grad-amount-hero: linear-gradient(135deg, rgba(107,147,255,0.10), rgba(151,111,255,0.08), rgba(228,106,206,0.06));
  --ds-grad-tab-underline: linear-gradient(90deg, transparent 0%, #FFCA28 50%, transparent 100%);
  --ds-grad-gift-card: linear-gradient(180deg, rgba(255,205,80,0.05) 0%, rgba(255,255,255,0.02) 100%);
  --ds-grad-bonus: linear-gradient(135deg, rgba(95,227,154,0.30), rgba(95,227,154,0.14));
}

@keyframes dsFadeInUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
@keyframes dsFadeIn   { from { opacity: 0; } to { opacity: 1; } }
@keyframes dsPremiumGradient { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }

/* Sheet container — replaces .pm-sheet visual layer for the V5 overlay.
   Fixed 480px height per design §8 (Edge cases — "do not let body content
   push the sheet taller"). */
/* Sheet sizing per design §"Deposit Sheet V5" handoff (2026-05-28):
   - width: full viewport (no horizontal margin)
   - height: 480px fixed (does NOT change between Stars / TON / Gifts tabs)
   - padding: 18px L/R/top, 22px bottom (+ iOS safe-area)
   - border-radius: 22px 22px 0 0 (top corners only)
   - border: 1px solid rgba(255,205,80,0.18) on top + sides (no bottom)
   - anchored to bottom of the .pm-sheet-overlay (which is fixed; inset:0
     with flex-end alignment — so position:absolute bottom:0 is implicit). */
#pm-topup-overlay .ds-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 480px;
  box-sizing: border-box;
  padding: 18px 18px calc(22px + env(safe-area-inset-bottom, 0px));
  background:
    radial-gradient(120% 60% at 50% 0%, var(--ds-bg-tint) 0%, transparent 60%),
    var(--ds-bg);
  border-radius: var(--ds-r-sheet) var(--ds-r-sheet) 0 0;
  border: 1px solid var(--ds-gold-border);
  border-bottom: none;
  box-shadow: var(--ds-shadow-sheet);
  color: var(--ds-text);
  display: flex; flex-direction: column;
  animation: dsFadeInUp 0.32s ease-out;
  overflow: hidden;
}

/* Head — gold-clipped title + circular close button */
#pm-topup-overlay .ds-head { display: flex; align-items: center; margin-bottom: 14px; }
#pm-topup-overlay .ds-title {
  font-size: 20px; font-weight: 800; letter-spacing: -0.4px;
  background: var(--ds-grad-gold);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 8px var(--ds-gold-glow));
}
#pm-topup-overlay .ds-close {
  margin-left: auto;
  width: 30px; height: 30px; padding: 0;
  border-radius: var(--ds-r-pill);
  border: 1px solid var(--ds-gold-border-strong);
  background: rgba(255, 205, 80, 0.06);
  color: var(--ds-gold-text);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
#pm-topup-overlay .ds-close:active { transform: scale(0.92); transition: transform 0.08s; }

/* Tabs — underline + gold glow on active */
#pm-topup-overlay .ds-tabs {
  display: flex; margin-bottom: 14px;
  border-bottom: 1px solid var(--ds-border);
}
#pm-topup-overlay .ds-tab {
  position: relative; flex: 1;
  padding: 10px 4px 11px;
  border: none; background: none; cursor: pointer;
  color: var(--ds-text-3);
  font-family: inherit;
  font-size: 13.5px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 6px;
}
#pm-topup-overlay .ds-tab[aria-selected="true"] { color: var(--ds-gold-text); }
#pm-topup-overlay .ds-tab[aria-selected="true"]::after {
  content: ''; position: absolute;
  left: 20%; right: 20%; bottom: -1px;
  height: 2.5px; border-radius: 2px;
  background: var(--ds-grad-tab-underline);
  box-shadow: var(--ds-shadow-tab-underline);
}
#pm-topup-overlay .ds-tab .ds-bonus {
  padding: 1px 5px; border-radius: var(--ds-r-pill);
  background: var(--ds-green-tab-off);
  color: var(--ds-green);
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.2px;
}
#pm-topup-overlay .ds-tab[aria-selected="true"] .ds-bonus { background: var(--ds-green-tab-on); }

/* Body — flex column, fills remaining height. Inner .ds-body__scroll
   absorbs any overflow (the Custom keypad on TON otherwise pushes the
   CTA past the fixed 480px sheet edge on smaller phones + PC side-panel
   widths — bug 2026-05-28); the CTA pins to the bottom of .ds-body via
   flex-shrink:0 so the primary action stays reachable even when the
   scrollable middle has to scroll. */
#pm-topup-overlay .ds-body { flex: 1; display: flex; flex-direction: column; min-height: 0; position: relative; }
#pm-topup-overlay .ds-body.hidden { display: none !important; }
#pm-topup-overlay .ds-body__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  /* Slim scrollbar — matches .ds-gifts-scroll */
  scrollbar-width: thin;
}
#pm-topup-overlay .ds-body__scroll::-webkit-scrollbar { width: 4px; }
#pm-topup-overlay .ds-body__scroll::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 4px; }
#pm-topup-overlay .ds-body__scroll::-webkit-scrollbar-track { background: transparent; }

/* Amount hero — gold-clip number on premium-tinted pill */
#pm-topup-overlay .ds-amount-hero {
  padding: 14px 16px;
  background: var(--ds-grad-amount-hero);
  border: 1px solid var(--ds-premium-border);
  border-radius: var(--ds-r-xl);
  display: flex; align-items: center; justify-content: center;
  gap: 10px; margin-bottom: 10px;
}
#pm-topup-overlay .ds-amount-hero__value {
  font-size: 30px; font-weight: 800; letter-spacing: -1px; line-height: 1;
  background: var(--ds-grad-gold);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  /* Was `filter: drop-shadow(0 0 12px var(--ds-gold-glow-strong))`. iOS
     WKWebView (Telegram WebView wrapper especially) fails to invalidate
     the cached drop-shadow region when `-webkit-background-clip:text`
     content changes — a ghost silhouette of the previous amount glows
     behind the new one. text-shadow is rendered per-glyph at paint time
     and doesn't share that broken compositing path. Two stacked stops
     reproduce the same soft halo. Bug caught 2026-05-28 ("5,000 ★"
     ghosting through the new "100 ★" after preset taps). */
  filter: none;
  text-shadow:
    0 0 12px rgba(255, 184, 0, 0.35),
    0 0 6px  rgba(255, 184, 0, 0.20);
  font-variant-numeric: tabular-nums;
}
#pm-topup-overlay .ds-bonus-chip {
  padding: 4px 8px; border-radius: var(--ds-r-pill);
  background: var(--ds-grad-bonus);
  border: 1px solid var(--ds-green-border);
  color: var(--ds-green);
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.3px;
}
#pm-topup-overlay .ds-bonus-chip.hidden { display: none; }

/* YOU PAY / WALLET row — TON only */
#pm-topup-overlay .ds-pay-row {
  padding: 10px 14px; border-radius: var(--ds-r-lg);
  background: var(--ds-bg-card-dark);
  border: 1px solid var(--ds-border);
  margin-bottom: 10px;
  display: flex; align-items: center; gap: 10px;
}
#pm-topup-overlay .ds-pay-row.hidden { display: none; }
#pm-topup-overlay .ds-pay-row__pair { min-width: 0; }
#pm-topup-overlay .ds-pay-row__pair--end { margin-left: auto; text-align: right; }
#pm-topup-overlay .ds-pay-row__label {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.4px;
  color: var(--ds-text-3);
}
#pm-topup-overlay .ds-pay-row__value {
  font-size: 14.5px; font-weight: 800;
  font-variant-numeric: tabular-nums;
}
#pm-topup-overlay .ds-pay-row__wallet {
  font-size: 12px; font-weight: 700;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* Preset strip — 4 amount chips + Custom keypad toggle */
#pm-topup-overlay .ds-presets { display: flex; gap: 6px; margin-bottom: 10px; }
#pm-topup-overlay .ds-preset {
  position: relative; flex: 1; padding: 10px 0 9px;
  border-radius: var(--ds-r-md);
  background: var(--ds-bg-chip);
  border: 1px solid var(--ds-border);
  color: #fff; cursor: pointer; font-family: inherit;
  font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.18s, border-color 0.18s;
}
#pm-topup-overlay .ds-preset[aria-pressed="true"] {
  background: var(--ds-premium-active-bg);
  border: 1.5px solid var(--ds-premium-active-border);
}
#pm-topup-overlay .ds-preset__bonus {
  position: absolute; top: -6px; right: -4px;
  padding: 1px 5px; border-radius: var(--ds-r-pill);
  background: var(--ds-grad-bonus);
  border: 1px solid var(--ds-green-border);
  color: var(--ds-green);
  font-size: 9px; font-weight: 800; letter-spacing: 0.2px;
  line-height: 13px;
  pointer-events: none;
}
#pm-topup-overlay .ds-preset--custom { flex: 0 0 auto; padding: 10px 12px 9px; }
#pm-topup-overlay .ds-preset:active:not([aria-pressed="true"]) { background: rgba(255, 255, 255, 0.07); }

/* Numeric keypad — replaces hint when Custom is open */
#pm-topup-overlay .ds-keypad {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
  align-content: start;
}
#pm-topup-overlay .ds-keypad.hidden { display: none; }
#pm-topup-overlay .ds-keypad__key {
  padding: 6px 0; border-radius: var(--ds-r-sm);
  background: var(--ds-bg-chip);
  border: 1px solid var(--ds-border);
  color: #fff; font-family: inherit;
  font-size: 14px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
#pm-topup-overlay .ds-keypad__key:active { background: rgba(255, 255, 255, 0.07); }

/* Hint footer — dashed grey panel shown when Custom is NOT open */
#pm-topup-overlay .ds-hint {
  flex: 1; padding: 14px;
  border-radius: var(--ds-r-lg);
  background: var(--ds-bg-hint);
  border: 1px dashed rgba(255, 255, 255, 0.10);
  font-size: 12px; font-weight: 500;
  color: var(--ds-text-3); text-align: center;
  display: flex; align-items: center; justify-content: center;
}
#pm-topup-overlay .ds-hint.hidden { display: none; }
#pm-topup-overlay .ds-spacer { flex: 1; }

/* CTAs — gold for Stars / premium-gradient for TON */
#pm-topup-overlay .ds-cta {
  margin-top: 10px;
  padding: 14px 0; border: none; border-radius: var(--ds-r-xl);
  cursor: pointer; font-family: inherit;
  display: flex; width: 100%;
  align-items: center; justify-content: center;
  gap: 8px;
}
#pm-topup-overlay .ds-cta.hidden { display: none; }
#pm-topup-overlay .ds-cta:disabled { cursor: default; }
#pm-topup-overlay .ds-cta:active:not(:disabled) { transform: scale(0.98); transition: transform 0.08s; }
#pm-topup-overlay .ds-cta--gold {
  background: var(--ds-grad-gold);
  color: var(--ds-gold-ink);
  font-size: 15px; font-weight: 800; letter-spacing: 0.2px;
  box-shadow: var(--ds-shadow-gold);
}
#pm-topup-overlay .ds-cta--gold:disabled {
  background: rgba(255, 205, 80, 0.15);
  color: rgba(255, 205, 80, 0.55);
  box-shadow: none;
}
#pm-topup-overlay .ds-cta--premium {
  background: var(--ds-grad-premium);
  background-size: 200% 200%;
  animation: dsPremiumGradient 8s ease infinite;
  color: #fff;
  font-size: 14.5px; font-weight: 800; letter-spacing: 0.15px;
  box-shadow: var(--ds-shadow-prem);
}
#pm-topup-overlay .ds-cta--premium:disabled { opacity: 0.5; box-shadow: none; animation: none; }
#pm-topup-overlay .ds-cta__sep { opacity: 0.7; font-weight: 700; }
#pm-topup-overlay .ds-cta__group { display: inline-flex; align-items: center; gap: 5px; }

/* Gifts — head + scrollable grid + bottom link */
#pm-topup-overlay .ds-gifts-head { margin-bottom: 8px; }
#pm-topup-overlay .ds-gifts-title {
  font-size: 15px; font-weight: 800; margin-bottom: 2px;
  background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
#pm-topup-overlay .ds-gifts-scroll {
  flex: 1; min-height: 0; margin-top: 4px;
  overflow-y: auto;
  padding-right: 4px; margin-right: -4px;
}
#pm-topup-overlay .ds-gifts-scroll::-webkit-scrollbar { width: 4px; }
#pm-topup-overlay .ds-gifts-scroll::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 4px; }
#pm-topup-overlay .ds-gifts-scroll::-webkit-scrollbar-track { background: transparent; }

/* Deposit grid — 3-col vertical cards */
#pm-topup-overlay .ds-gifts-grid--3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
/* Withdraw grid — 2-col horizontal rows */
#pm-topup-overlay .ds-gifts-grid--2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 7px; }

/* Gift card — vertical stack (deposit) */
#pm-topup-overlay .ds-gift {
  padding: 8px 6px 9px;
  border-radius: var(--ds-r-lg);
  background: var(--ds-grad-gift-card);
  border: 1px solid var(--ds-gold-card-edge);
  box-shadow: inset 0 1px 0 rgba(255, 230, 150, 0.06);
  cursor: pointer; font-family: inherit;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
#pm-topup-overlay .ds-gift__thumb {
  position: relative;
  width: 54px; height: 54px;
  border-radius: var(--ds-r-md);
  overflow: hidden;
  background: #0e1a2a;
  display: flex; align-items: center; justify-content: center;
}
#pm-topup-overlay .ds-gift__thumb img { width: 100%; height: 100%; object-fit: cover; }
#pm-topup-overlay .ds-gift__thumb-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; color: var(--ds-text-3);
}
#pm-topup-overlay .ds-gift__qty {
  position: absolute; right: 2px; bottom: 2px;
  padding: 0 4px; border-radius: 4px;
  background: rgba(0, 0, 0, 0.7);
  color: #fff; font-size: 9px; font-weight: 700;
}
#pm-topup-overlay .ds-gift__name {
  font-size: 10.5px; font-weight: 600;
  color: var(--ds-text-2);
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#pm-topup-overlay .ds-gift__value {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11.5px; font-weight: 800;
  color: var(--ds-gold-text);
  font-variant-numeric: tabular-nums;
}

/* Withdraw card — horizontal row */
#pm-topup-overlay .ds-gift--row {
  padding: 9px;
  flex-direction: row; align-items: center;
  gap: 8px; text-align: left;
}
#pm-topup-overlay .ds-gift--row .ds-gift__thumb { width: 40px; height: 40px; border-radius: 8px; flex-shrink: 0; }
#pm-topup-overlay .ds-gift--row .ds-gift__name { font-size: 12px; }
#pm-topup-overlay .ds-gift--row .ds-gift__meta { flex: 1; min-width: 0; overflow: hidden; }
#pm-topup-overlay .ds-gift--row .ds-gift__lock,
#pm-topup-overlay .ds-gift--row .ds-gift__value { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
#pm-topup-overlay .ds-gift--locked { opacity: 0.6; cursor: default; }
#pm-topup-overlay .ds-gift__lock {
  font-size: 10px; color: var(--ds-text-4);
  display: flex; align-items: center; gap: 3px; margin-top: 2px;
}

/* Footer link — deposit ↔ withdraw toggle */
#pm-topup-overlay .ds-gifts-link {
  margin-top: 8px;
  padding: 8px 0;
  background: none; border: none; cursor: pointer; font-family: inherit;
  color: var(--ds-gold-text);
  font-size: 13px; font-weight: 700;
  text-align: center; width: 100%;
}

/* ── Send-a-collectible step — live-status stepper (design: assets/'C _ Live
   status _ tap Open.html'). Storage ready ✓ / Transfer your gift ● / Receive
   your Stars ○ ; poll-driven states flip step 3 to done / shows expired. ───── */
#pm-topup-overlay .ds-send-title { font-size: 17px; font-weight: 800; letter-spacing: -0.3px; color: var(--ds-text); margin-bottom: 3px; }
#pm-topup-overlay .ds-send-sub { font-size: 12px; color: var(--ds-text-3); margin: 0 0 16px; }
#pm-topup-overlay .ds-steps { display: flex; flex-direction: column; }
#pm-topup-overlay .ds-step { display: flex; gap: 12px; padding-bottom: 16px; }
#pm-topup-overlay .ds-step:last-child { padding-bottom: 0; }
#pm-topup-overlay .ds-step__rail { position: relative; flex-shrink: 0; width: 22px; display: flex; justify-content: center; }
/* connector line from this dot down to the next step's dot */
#pm-topup-overlay .ds-step:not(:last-child) .ds-step__rail::after {
  content: ''; position: absolute; left: 50%; transform: translateX(-50%);
  top: 24px; bottom: -16px; width: 2px; border-radius: 2px;
  background: rgba(255, 255, 255, 0.12);
}
#pm-topup-overlay .ds-step--done .ds-step__rail::after { background: rgba(255, 205, 80, 0.5); }
#pm-topup-overlay .ds-step__dot {
  position: relative; z-index: 1; box-sizing: border-box;
  width: 22px; height: 22px; border-radius: 999px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
#pm-topup-overlay .ds-step--pending .ds-step__dot { border: 2px solid rgba(255, 255, 255, 0.18); }
#pm-topup-overlay .ds-step--active .ds-step__dot {
  border: 2px solid var(--ds-gold-2);
  box-shadow: 0 0 0 3px rgba(255, 184, 0, 0.12);
}
#pm-topup-overlay .ds-step--active .ds-step__dot::after {
  content: ''; width: 8px; height: 8px; border-radius: 999px; background: var(--ds-gold-2);
}
#pm-topup-overlay .ds-step--done .ds-step__dot { background: var(--ds-grad-gold); }
#pm-topup-overlay .ds-step__check { display: none; }
#pm-topup-overlay .ds-step--done .ds-step__check { display: block; }
#pm-topup-overlay .ds-step__body { flex: 1; min-width: 0; }
#pm-topup-overlay .ds-step__t { font-size: 13.5px; font-weight: 700; color: var(--ds-text); }
#pm-topup-overlay .ds-step--pending .ds-step__t { color: var(--ds-text-3); }
#pm-topup-overlay .ds-step__d { font-size: 11.5px; line-height: 1.4; color: rgba(255, 255, 255, 0.5); margin-top: 2px; }
/* Dashed gold handle box (copyable @custody) */
#pm-topup-overlay .ds-dep-handle {
  width: 100%; box-sizing: border-box;
  margin: 9px 0; padding: 12px 14px;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px dashed rgba(255, 205, 80, 0.5); border-radius: 12px;
  background: rgba(0, 0, 0, 0.3);
  color: var(--ds-gold-text); font-family: inherit; font-size: 14.5px; font-weight: 800;
  letter-spacing: 0.2px; cursor: pointer;
}
#pm-topup-overlay .ds-dep-handle:active { transform: scale(0.99); transition: transform 0.06s; }
#pm-topup-overlay .ds-dep-copy { font-size: 13px; opacity: 0.7; }
/* Step-3 quote ("Receive ~N ★" when a specific gift is picked) */
#pm-topup-overlay .ds-dep-receive { font-size: 12px; font-weight: 800; color: var(--ds-gold-text); margin-top: 3px; font-variant-numeric: tabular-nums; }
#pm-topup-overlay .ds-dep-receive.hidden { display: none; }
/* Credited / timeout status line (poll-driven) */
#pm-topup-overlay .ds-dep-wait { font-size: 11.5px; font-weight: 600; color: var(--ds-text-3); margin-top: 4px; line-height: 1.4; }
#pm-topup-overlay .ds-dep-wait.hidden { display: none; }
#pm-topup-overlay .ds-dep-wait.pm-deposit-wait--ok { color: var(--ds-green); font-weight: 700; }
/* Expiry countdown (above the CTA) */
#pm-topup-overlay .ds-dep-countdown { font-size: 11px; font-weight: 600; color: var(--ds-text-4); text-align: center; margin: 2px 0 10px; font-variant-numeric: tabular-nums; }
#pm-topup-overlay .ds-dep-countdown::before { content: '⏱ '; }
#pm-topup-overlay .ds-dep-countdown.hidden { display: none; }
/* Premium CTA at the foot */
#pm-topup-overlay .ds-dep-cta { width: 100%; margin-top: auto; }
#pm-topup-overlay .ds-dep-cta::before { content: '→ '; }
#pm-topup-overlay .ds-dep-cta.hidden { display: none; }

/* Gifts empty state — reuses .ds-hint */
#pm-topup-overlay .ds-gifts-scroll .ds-hint { flex: none; min-height: 100px; }

/* Hide the legacy .pm-sheet chrome when V5 sheet is active (the legacy
   .pm-sheet wrapper is removed entirely in the V5 markup — these rules
   are defensive in case predmarket.js races inject something). */
#pm-topup-overlay .pm-sheet { display: none; }


/* ════════════════════════════════════════════════════════════════════════════
   EVENTS TAB — Multi-outcome event cards (Polymarket "election" pattern).
   Spec: miniapp/assets/Option 3 Multi-outcome Event.html + the contract at
   contracts/requests/predmarket_events_tab.md.

   Class namespace: .pm-evt-* (independent from .pm-card / .pm-detail). Tier
   colour set per-card via inline style --tier. Outcome palette below.
   ════════════════════════════════════════════════════════════════════════════ */
:root {
  /* 8 outcome colours — distinguishable at 6px segment width. May (current
     month) gets a darker pre-Jun shade. */
  --pm-evt-c0: #FF4F8C;   /* May — pink (darker, distinguishes from Jun) */
  --pm-evt-c1: #FF6BA8;   /* Jun — pink   */
  --pm-evt-c2: #FF9D6B;   /* Jul — peach  */
  --pm-evt-c3: #FFD166;   /* Aug — gold   */
  --pm-evt-c4: #5fe39a;   /* Sep — mint   */
  --pm-evt-c5: #5ec1ff;   /* Oct — sky    */
  --pm-evt-c6: #9b5bff;   /* Nov — purple */
  --pm-evt-c7: #E46ACE;   /* Dec — magenta*/
  --pm-evt-c8: #708499;   /* Tail — slate */
}

#pm-events { padding: 14px 0 24px; }

.pm-evt-card {
  --tier: #ff6ba8;
  /* Chrome aligned to the single-market .pm-card (same radius + neutral border)
     so events + single + user markets read as ONE design family. The FEATURED
     hero keeps its gold border as the intentional headline exception. */
  position: relative; border-radius: var(--pm-r-lg); overflow: hidden;
  background:
    radial-gradient(ellipse 80% 60% at 100% 0%, color-mix(in oklab, var(--tier) 33%, transparent) 0%, transparent 60%),
    linear-gradient(160deg, #1a2434 0%, #0e1a2a 100%);
  border: 1px solid var(--pm-border-2);
  box-shadow: 0 0 20px color-mix(in oklab, var(--tier) 14%, transparent),
              inset 0 1px 0 rgba(255,255,255,0.05);
  margin-bottom: 12px;
}
/* Entry animation only for freshly-inserted event cards (_pmReconcile adds
   .pm-enter); in-place refreshes never re-animate. */
.pm-evt-card.pm-enter { animation: fadeInUp 0.4s ease-out backwards; }
/* Press feedback on the tap target (the toggle header), not the whole card —
   so pressing a BUY chip in an expanded card doesn't shrink the card. */
.pm-evt-acc-toggle:active { transform: scale(0.99); transition: transform 0.06s ease-out; }
.pm-evt-card-glow {
  position: absolute; right: -40px; top: -30px;
  width: 180px; height: 180px;
  background: radial-gradient(circle at center, color-mix(in oklab, var(--tier) 36%, transparent) 0%, transparent 60%);
  filter: blur(12px); pointer-events: none;
}
.pm-evt-card-inner { position: relative; padding: 14px 14px 12px; }

/* Header band — artwork + chips + question */
.pm-evt-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.pm-evt-art {
  width: 52px; height: 52px; border-radius: 12px; flex-shrink: 0;
  background:
    radial-gradient(circle at center, color-mix(in oklab, var(--tier) 34%, transparent) 0%, transparent 70%),
    #0e1a2a;
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow: 0 4px 14px color-mix(in oklab, var(--tier) 33%, transparent),
              inset 0 1px 0 rgba(255,255,255,0.06);
  display: inline-flex; align-items: center; justify-content: center; overflow: hidden;
}
.pm-evt-art img { width: 92%; height: 92%; object-fit: contain; }
.pm-evt-titlecol { flex: 1; min-width: 0; }
.pm-evt-chiprow {
  display: flex; gap: 6px; align-items: center; margin-bottom: 4px; flex-wrap: wrap;
}
.pm-evt-outcomeschip {
  font-size: 9px; font-weight: 800; letter-spacing: 0.6px;
  padding: 2px 7px; border-radius: 999px;
  background: rgba(151, 111, 255, 0.16);
  border: 1px solid rgba(151, 111, 255, 0.32);
  color: #C4A8FF; text-transform: uppercase;
}
.pm-evt-question {
  font-size: 15.5px; font-weight: 700; color: #FFFFFF;
  letter-spacing: -0.2px; line-height: 1.25;
}
.pm-evt-question .pm-evt-q-gift { color: var(--tier); }

/* Leading-answer band */
.pm-evt-leader { display: flex; align-items: flex-end; gap: 10px; margin-bottom: 8px; }
.pm-evt-leader-eyebrow {
  font-size: 9px; font-weight: 800; letter-spacing: 0.6px;
  text-transform: uppercase; color: #FFCA28;
}
.pm-evt-leader-row { display: flex; align-items: baseline; gap: 6px; margin-top: 2px; }
.pm-evt-leader-label {
  font-size: 26px; font-weight: 900; color: #F5F5F5;
  letter-spacing: -0.8px; line-height: 1;
}
.pm-evt-leader-pct {
  font-size: 22px; font-weight: 900; letter-spacing: -0.6px;
}
.pm-evt-leader-pct sup { font-size: 12px; opacity: 0.6; font-weight: 800; }
.pm-evt-leader-sum {
  margin-left: auto; text-align: right;
}
.pm-evt-leader-sum-eyebrow {
  font-size: 9px; color: #708499; letter-spacing: 0.4px;
  text-transform: uppercase; font-weight: 800;
}
.pm-evt-leader-sum-val {
  font-size: 14px; font-weight: 800; color: #5fe39a;
}
.pm-evt-leader-sum-val sup { font-size: 9px; opacity: 0.55; font-weight: 800; }

/* Stacked rainbow bar — outcome widths from yes_price_norm * 100% */
.pm-evt-stack {
  display: flex; height: 12px; border-radius: 4px; overflow: hidden;
  background: rgba(255,255,255,0.04);
  box-shadow: inset 0 1px 0 rgba(0,0,0,0.20);
}
.pm-evt-stack > span {
  display: block; height: 100%; border-right: 1px solid rgba(0,0,0,0.32);
}
.pm-evt-stack > span:last-child { border-right: 0; }

/* Outcome rows */
.pm-evt-outcomes { margin-top: 10px; display: flex; flex-direction: column; gap: 2px; }
.pm-evt-outcome {
  /* Label is a FIXED column (not 1fr) so the probability bar hugs it and the
     bar fills the remaining space. With a 1fr label the gap between label and
     bar grew with viewport width — fine on a phone, badly stretched on PC
     (bug 2026-05-29). Fixed label keeps every bar left-aligned across rows. */
  display: grid; grid-template-columns: 14px 100px 1fr 44px auto;
  align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 9px;
  border: 1px solid rgba(255,255,255,0.04);
}
.pm-evt-outcome--mode   { background: rgba(255,255,255,0.025); }
.pm-evt-outcome--yours  {
  background: linear-gradient(90deg, rgba(255, 202, 40, 0.14) 0%, rgba(255, 202, 40, 0.02) 100%);
  border-color: rgba(255, 205, 80, 0.40);
}
.pm-evt-outcome-dot {
  width: 10px; height: 10px; border-radius: 3px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.35);
}
.pm-evt-outcome-label {
  font-size: 12.5px; color: #F5F5F5; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: flex; align-items: center; gap: 6px;
}
.pm-evt-outcome-flag {
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.5px;
  padding: 1px 6px; border-radius: 999px; flex-shrink: 0;
}
.pm-evt-outcome-flag--leading {
  color: #FFCA28; background: rgba(255, 202, 40, 0.12);
  border: 1px solid rgba(255, 205, 80, 0.30);
}
.pm-evt-outcome-flag--yours {
  color: #5fe39a; background: rgba(52, 199, 89, 0.12);
  border: 1px solid rgba(52, 199, 89, 0.30);
}
.pm-evt-outcome-bar {
  height: 6px; border-radius: 2px; background: rgba(255,255,255,0.04); overflow: hidden;
}
.pm-evt-outcome-bar > span { display: block; height: 100%; opacity: 0.85; }
.pm-evt-outcome-pct {
  font-size: 13.5px; font-weight: 800; color: #F5F5F5;
  text-align: right; font-variant-numeric: tabular-nums;
}
.pm-evt-outcome-pct sup { font-size: 9px; opacity: 0.55; font-weight: 800; }

.pm-evt-buy-btn {
  padding: 4px 10px; border-radius: 6px;
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.4px;
  color: #1a1205;
  background: linear-gradient(180deg, #FFE38A 0%, #FFCA28 50%, #E5A100 100%);
  border: none; cursor: pointer; font-family: inherit;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45);
}
.pm-evt-buy-btn:active { transform: scale(0.96); }
/* A passed / resolved month: dim the row and swap BUY for a muted status chip
   (no dead BUY on a market that's already decided server-side). */
.pm-evt-outcome--resolved { opacity: 0.55; }
.pm-evt-outcome-status {
  white-space: nowrap; text-align: center;
  padding: 4px 9px; border-radius: 6px;
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase;
  color: #aab2bd; background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.09);
}

/* Footer band */
.pm-evt-foot {
  margin-top: 10px; padding-top: 8px;
  border-top: 1px solid rgba(255,255,255,0.06);
  display: flex; align-items: center; gap: 10px;
  font-size: 11px; color: #708499;
}
.pm-evt-foot-stat { display: inline-flex; align-items: center; gap: 3px; }

/* ── Accordion (collapsed event card in the Markets tab) ─────────────────────
   Collapsed by default: head + a compact summary band (mini distribution bar +
   leading answer + pool/traders) show; the leading band, full stack, and the
   8-9 outcome rows live in .pm-evt-acc-body and reveal on .pm-evt-card--expanded.
   BUY chips sit inside the body (outside .pm-evt-acc-toggle) so a BUY tap never
   toggles the accordion. */
.pm-evt-acc-toggle { cursor: pointer; -webkit-tap-highlight-color: transparent; outline: none; }
.pm-evt-acc .pm-evt-head { margin-bottom: 0; }
.pm-evt-chevron {
  margin-left: auto; align-self: center; flex-shrink: 0; color: #708499;
  display: inline-flex; align-items: center;
  transition: transform 0.26s cubic-bezier(0.4,0,0.2,1), color 0.2s ease;
}
.pm-evt-card--expanded .pm-evt-chevron { transform: rotate(180deg); color: var(--tier); }

.pm-evt-acc-collapsed { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.pm-evt-card--expanded .pm-evt-acc-collapsed { display: none; }
.pm-evt-ministack {
  display: flex; height: 7px; border-radius: 4px; overflow: hidden;
  background: rgba(255,255,255,0.05);
}
.pm-evt-ministack > span { display: block; height: 100%; transition: width 0.5s cubic-bezier(0.2,0.8,0.3,1); }
.pm-evt-minirow {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 11px; color: #8395a9;
}
.pm-evt-minilead {
  font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: #77899d;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.pm-evt-minilead b { font-size: 12px; letter-spacing: 0; text-transform: none; margin-left: 3px; }
.pm-evt-minifoot { display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; }

/* Robust accordion via CSS grid 0fr→1fr (no max-height-to-content guesswork:
   the row track interpolates to the inner's natural height, then back to 0).
   The inner wrapper carries overflow:hidden + min-height:0 so the clip works. */
/* Smooth open: JS animates an explicit measured height (pmEvtToggle) — the
   inner lays out once and the box clips as height interpolates (cheap + smooth
   on iOS WebKit, unlike the old grid-template-rows track animation, which
   relayed out every frame and snapped). Inner rises (translateY+opacity). */
.pm-evt-acc-body {
  overflow: hidden; height: 0; opacity: 0;
  transition: height 0.3s cubic-bezier(0.22,0.61,0.36,1), opacity 0.2s ease;
  /* Bound the per-frame relayout of the height animation to this subtree so a
     long 9-outcome body can't thrash the whole list. will-change is toggled in
     JS (pmEvtToggle) only while animating, not left on permanently. */
  contain: layout paint;
}
.pm-evt-acc-inner {
  overflow: hidden; min-height: 0; padding-top: 12px;
  transform: translateY(-8px);
  transition: transform 0.3s cubic-bezier(0.22,0.61,0.36,1);
}
.pm-evt-card--expanded .pm-evt-acc-body { opacity: 1; }
.pm-evt-card--expanded .pm-evt-acc-inner { transform: translateY(0); }
.pm-evt-acc-body .pm-evt-leader { margin-top: 0; }

/* Cumulative "by Dec" year gauge (collapsed summary) + headline (expanded). */
.pm-evt-yearbar {
  height: 7px; border-radius: 4px; overflow: hidden;
  background: rgba(255,255,255,0.06);
}
.pm-evt-yearbar > span { display: block; height: 100%; border-radius: 4px; opacity: 0.92; }
.pm-evt-eoy {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.pm-evt-eoy-eyebrow {
  font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase;
  color: #708499; font-weight: 700;
}
.pm-evt-eoy-pct { font-size: 26px; font-weight: 800; line-height: 1; }
.pm-evt-eoy-pct sup { font-size: 13px; opacity: 0.6; font-weight: 800; }

/* FEATURED hero variant — elevated top-of-list event card. */
.pm-evt-card--featured {
  border-color: rgba(255, 205, 80, 0.5);
  box-shadow: 0 0 26px color-mix(in oklab, var(--tier) 22%, transparent),
              0 6px 22px rgba(0,0,0,0.35),
              inset 0 1px 0 rgba(255,255,255,0.07);
}
.pm-evt-badge {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.04em;
  padding: 3px 7px; border-radius: 7px; line-height: 1;
}
.pm-evt-badge--featured {
  color: #1a1205;
  background: linear-gradient(180deg, #ffe38a 0%, #e5a100 100%);
  box-shadow: 0 1px 4px rgba(255, 184, 0, 0.3);
}
.pm-evt-badge--hot {
  color: #ff8a5c; background: rgba(255, 99, 71, 0.14);
  border: 1px solid rgba(255, 99, 71, 0.32);
}

/* ── Compact collapsed event cards (denser Markets list) ─────────────────────
   Operator wants the per-gift cards back to a tight, scannable size. Only the
   always-visible head + collapsed summary shrink; the expanded body keeps its
   richer spacing. */
.pm-evt-card { margin-bottom: 8px; }
.pm-evt-card-inner { padding: 9px 12px; }
.pm-evt-acc .pm-evt-art { width: 40px; height: 40px; border-radius: 10px; }
.pm-evt-acc .pm-evt-head { gap: 9px; }
.pm-evt-acc .pm-evt-chiprow { margin-bottom: 2px; gap: 5px; }
.pm-evt-acc .pm-evt-outcomeschip { font-size: 9px; padding: 1px 6px; }
.pm-evt-acc .pm-evt-question {
  font-size: 13px; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pm-evt-acc-collapsed { margin-top: 6px; gap: 4px; }
.pm-evt-yearbar { height: 5px; }
.pm-evt-minirow { font-size: 10.5px; }
/* Featured hero stays a touch larger to read as the headline card. */
.pm-evt-card--featured .pm-evt-art { width: 46px; height: 46px; }
.pm-evt-card--featured .pm-evt-question { font-size: 14px; }

/* Operator: drop the purple light on the right of Markets cards. Removes the
   blurred corner glow blob, the tier-tinted top-right background radial, and
   the tier-coloured box-shadow halo — leaving a clean dark card (the rainbow
   distribution bar + % colours still carry the colour). Border kept for edge
   definition. */
.pm-evt-card-glow { display: none; }
.pm-evt-card {
  background: linear-gradient(160deg, #1a2434 0%, #0e1a2a 100%);
  box-shadow: 0 1px 4px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.04);
}
.pm-evt-card--featured {
  box-shadow: 0 2px 12px rgba(0,0,0,0.34), inset 0 1px 0 rgba(255,255,255,0.06);
}

/* Skeleton during cold load — reuse .pm-skel timing via .pm-evt-skel */
.pm-evt-skel {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: var(--pm-r-xl, 18px); height: 320px;
  margin-bottom: 12px;
  animation: pm-evt-skel-pulse 1.4s ease-in-out infinite;
}
@keyframes pm-evt-skel-pulse {
  0%,100% { opacity: 0.55; } 50% { opacity: 0.85; }
}

/* ═══ User-created markets (beta; dark behind user_markets_enabled) ═══════════
   Create chip in the seg-tab row + create/my-markets/report sheets + combined
   creator+referral earnings card. Reuses the .pm-sheet shell + theme tokens. */

/* Tab strip + Create chip share ONE row. The seg flexes (labels ellipsize) so
   the row never overflows on narrow phones; the gold chip stays compact and
   matches the seg's height + gold accent. */
.pm-seg-row { display: flex; align-items: stretch; gap: 8px; margin-top: 14px; }
.pm-seg-row .pm-seg { flex: 1; min-width: 0; margin-top: 0; }
.pm-seg-row .pm-seg-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.pm-create-chip {
  /* V6 premium gradient (design: Create market page.html) — blue→purple→pink. */
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 5px;
  padding: 0 13px; border-radius: var(--pm-r-md); cursor: pointer; font-family: inherit;
  font-size: 12.5px; font-weight: 800; letter-spacing: 0.2px; color: #fff; border: none;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  background-size: 200% 200%; animation: pr-shimmer 8s ease infinite;
  box-shadow: 0 2px 12px rgba(151, 111, 255, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition: transform .12s ease, opacity .15s ease;
}
.pm-create-chip.hidden { display: none; }
.pm-create-chip:active { transform: scale(0.97); }
.pm-create-chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Compact "My markets" chip (list icon) — neutral, sits left of Create. */
.pm-mine-chip {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; padding: 0; border-radius: var(--pm-r-md); cursor: pointer;
  border: 1px solid var(--tg-separator); background: var(--tg-bg-input);
  color: var(--tg-text); transition: transform .12s ease;
}
.pm-mine-chip.hidden { display: none; }
.pm-mine-chip:active { transform: scale(0.96); }
@keyframes pr-shimmer { 0%,100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }

/* "My markets ›" secondary link at the foot of the Create sheet. */
.pm-um-mine-link {
  display: block; width: 100%; margin-top: 10px; padding: 10px;
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: 13.5px; font-weight: 700; color: var(--pm-gold-warm, #ffcd50);
}
.pm-um-mine-link:active { opacity: 0.7; }

/* Form fields (create + report sheets) */
.pm-um-field { margin: 0 0 14px; }
.pm-um-flabel {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 12.5px; font-weight: 700; color: var(--tg-hint);
  text-transform: uppercase; letter-spacing: .03em; margin: 0 0 6px;
}
.pm-um-count { font-weight: 600; color: var(--tg-hint); letter-spacing: 0; text-transform: none; }
.pm-um-count--warn { color: var(--pm-no, #ff8085); }
.pm-um-input {
  width: 100%; box-sizing: border-box;
  background: var(--tg-bg-input); border: 1px solid var(--tg-separator);
  border-radius: 12px; padding: 13px 14px; color: var(--tg-text);
  font-size: 15px; outline: none; font-family: inherit;
}
.pm-um-input:focus { border-color: var(--tg-accent); }
.pm-um-textarea { resize: vertical; min-height: 64px; line-height: 1.4; }
.pm-um-input--err { border-color: var(--pm-no, #ff8085); }
.pm-um-ferr { display: none; color: var(--pm-no, #ff8085); font-size: 12.5px; margin-top: 6px; line-height: 1.4; }
.pm-um-ferr--on { display: block; }
.pm-um-cta { width: 100%; margin-top: 4px; }

/* My-markets list */
.pm-um-mine-list { margin-top: 4px; }
.pm-um-loading, .pm-um-empty { text-align: center; color: var(--tg-hint); font-size: 13px; padding: 22px 12px; }
.pm-um-row {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 0; border-bottom: 1px solid var(--tg-separator);
}
.pm-um-row:last-child { border-bottom: none; }
.pm-um-row-main { flex: 1; min-width: 0; }
.pm-um-row-title {
  font-size: 14px; font-weight: 700; color: var(--tg-text); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.pm-um-row-meta { font-size: 12px; color: var(--tg-hint); margin-top: 3px; }
.pm-um-state { font-weight: 700; }
.pm-um-state--open { color: var(--pm-yes, #5fe39a); }
.pm-um-state--closed { color: #ffca28; }
.pm-um-state--settled, .pm-um-state--void { color: var(--tg-hint); }
.pm-um-row-action { flex-shrink: 0; }
.pm-um-propose-row { display: flex; gap: 6px; }
.pm-um-propose-btn {
  border: 1px solid var(--tg-separator); background: var(--tg-bg-input);
  border-radius: 10px; padding: 8px 10px; font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.pm-um-propose-btn:active { transform: scale(0.97); }
.pm-um-propose-btn--yes { color: var(--pm-yes, #5fe39a); border-color: rgba(95,227,154,.4); }
.pm-um-propose-btn--no { color: var(--pm-no, #ff8085); border-color: rgba(255,128,133,.4); }
.pm-um-pending, .pm-um-settled, .pm-um-open-meta { font-size: 12px; color: var(--tg-hint); font-weight: 600; }

/* Combined earnings card */
.pm-um-earn {
  background: linear-gradient(160deg, rgba(95,150,255,.10), rgba(170,120,255,.08));
  border: 1px solid var(--tg-separator); border-radius: 16px;
  padding: 14px 16px; margin: 0 0 16px;
}
.pm-um-earn-none { text-align: center; color: var(--tg-hint); font-size: 13px; padding: 6px 4px; }
.pm-um-earn-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pm-um-earn-title { font-size: 13px; font-weight: 800; color: var(--tg-text); }
.pm-um-earn-sub { font-size: 11.5px; color: var(--tg-hint); }
.pm-um-earn-big { font-size: 30px; font-weight: 800; color: var(--tg-text); margin: 6px 0 8px; }
.pm-um-earn-split { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.pm-um-earn-chip { font-size: 12px; color: var(--tg-hint); background: var(--tg-bg-input); border-radius: 8px; padding: 5px 9px; }
.pm-um-earn-chip b { color: var(--tg-text); }
.pm-um-claim-btn { width: 100%; }
.pm-um-earn-hint { text-align: center; font-size: 11.5px; color: var(--tg-hint); margin-top: 8px; }

/* Report reason chips */
.pm-um-reasons { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 16px; }
.pm-um-reason {
  border: 1px solid var(--tg-separator); background: var(--tg-bg-input);
  border-radius: 10px; padding: 10px 14px; font-size: 13.5px; font-weight: 600;
  color: var(--tg-text); cursor: pointer;
}
.pm-um-reason:active { transform: scale(0.97); }
.pm-um-reason--on { border-color: var(--tg-accent); background: var(--tg-bg-secondary); color: var(--tg-accent); }

/* Detail-page report button + user-market rules description */
.pm-um-detail-actions { display: flex; justify-content: center; margin: 14px 0 4px; }
.pm-um-report-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; color: var(--tg-hint);
  font-size: 12.5px; font-weight: 600; cursor: pointer; padding: 6px 10px;
}
.pm-um-report-btn:active { opacity: .7; }
.pm-um-report-btn--done { color: var(--pm-no, #ff8085); cursor: default; }
.pm-um-rules-desc { color: var(--tg-text); margin-bottom: 6px; line-height: 1.45; }



/* ═══ V6 Game-wizard create-market (design: assets/Create market page.html) ═══
   Premium gradient wizard: 3 steps + month calendar + confetti success. The
   .v6-screen fills #pm-create-overlay (full-screen flow, not a bottom sheet). */
/* ═══════════════════════════════════════════════════════════════
   V6 — GAME WIZARD (Premium gradient, no gold)
   ═══════════════════════════════════════════════════════════════ */
.v6-screen {
  position: absolute; inset: 0;
  top: 0;
  display: flex; flex-direction: column;
  padding: max(14px, env(safe-area-inset-top)) 18px 0;
  box-sizing: border-box;
  background:
    radial-gradient(ellipse 120% 60% at 50% -10%, rgba(151,111,255,0.18) 0%, transparent 55%),
    radial-gradient(ellipse 90% 50% at 100% 110%, rgba(228,106,206,0.12) 0%, transparent 55%),
    linear-gradient(180deg, #0c1322 0%, #0a0f1c 100%);
  color: #F5F5F5;
}

/* Header */
.v6-hdr {
  display: flex; align-items: center; gap: 14px;
  padding: 4px 0 22px;
}

.v6-icon-btn {
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: 11px; border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.04);
  color: rgba(255,255,255,0.7);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; transition: transform 0.12s, background 0.15s;
}

.v6-icon-btn:active { transform: scale(0.92); background: rgba(255,255,255,0.08); }

/* Progress: filling track + 3 numbered nodes */
.v6-progress {
  flex: 1; position: relative;
  height: 34px;
  display: flex; align-items: center;
}

.v6-track {
  position: absolute; left: 16px; right: 16px; top: 50%;
  height: 5px; transform: translateY(-50%);
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  overflow: hidden;
}

.v6-track-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  box-shadow: 0 0 12px rgba(151,111,255,0.55);
  transition: width 0.45s cubic-bezier(0.2, 0.8, 0.3, 1);
}

.v6-nodes {
  position: relative; z-index: 1;
  flex: 1; display: flex; justify-content: space-between;
}

.v6-node {
  width: 30px; height: 30px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  transition: transform 0.25s, background 0.25s, color 0.25s, box-shadow 0.25s;
}

.v6-node--todo {
  background: #1a2030;
  color: rgba(255,255,255,0.40);
  box-shadow: inset 0 0 0 1.5px rgba(255,255,255,0.10);
}

.v6-node--active {
  background: linear-gradient(135deg, #6B93FF, #976FFF);
  color: #fff;
  transform: scale(1.16);
  box-shadow: 0 0 0 4px rgba(151,111,255,0.18), 0 4px 14px rgba(99,102,241,0.5);
}

.v6-node--done {
  background: linear-gradient(135deg, #976FFF, #E46ACE);
  color: #fff;
  box-shadow: 0 2px 10px rgba(228,106,206,0.4);
}

/* Body + step transition (pop + slide) */
.v6-body { flex: 1; min-height: 0; position: relative; overflow-y: auto; scrollbar-width: none; }
.v6-body::-webkit-scrollbar { display: none; }

.v6-step {
  animation: v6-in 0.4s cubic-bezier(0.16, 0.84, 0.36, 1) backwards;
}

.v6-step[data-dir="-1"] { animation-name: v6-in-back; }

@keyframes v6-in {
  from { opacity: 0; transform: translateX(28px) scale(0.98); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}

@keyframes v6-in-back {
  from { opacity: 0; transform: translateX(-28px) scale(0.98); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}

.v6-step-inner { display: flex; flex-direction: column; }

.v6-kicker {
  font-size: 11px; font-weight: 800; letter-spacing: 2px; text-transform: uppercase;
  background: linear-gradient(90deg, #6B93FF, #976FFF, #E46ACE);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  margin-bottom: 10px;
}

.v6-title {
  font-size: 28px; font-weight: 800; letter-spacing: -0.7px; line-height: 1.1;
  color: #fff;
  margin-bottom: 6px;
  text-wrap: balance;
}

.v6-subtitle {
  font-size: 14px; font-weight: 500;
  color: rgba(255,255,255,0.5);
  margin-bottom: 6px;
}

/* Big input */
.v6-input-wrap { position: relative; margin-top: 18px; }

.v6-input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 2px solid rgba(255,255,255,0.10);
  border-radius: 16px;
  padding: 16px 16px 30px;
  font-family: inherit;
  font-size: 18px; font-weight: 700; line-height: 1.35;
  color: #fff;
  resize: none;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}

.v6-input::placeholder { color: rgba(255,255,255,0.26); font-weight: 600; }

.v6-input:focus {
  outline: none;
  border-color: #976FFF;
  background: rgba(151,111,255,0.06);
  box-shadow: 0 0 0 4px rgba(151,111,255,0.14), 0 0 28px rgba(151,111,255,0.14);
}

.v6-input--ok { border-color: rgba(151,111,255,0.4); }

.v6-input--error {
  border-color: #ff7a7a !important;
  box-shadow: 0 0 0 4px rgba(255,122,122,0.12) !important;
}

.v6-counter {
  position: absolute; right: 14px; bottom: 12px;
  font-size: 11px; font-weight: 700;
  color: rgba(255,255,255,0.35);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}

.v6-counter.hot { color: #ff9d7a; }

.v6-error {
  display: flex; align-items: center; gap: 7px;
  margin-top: 12px;
  font-size: 13px; font-weight: 600;
  color: #ff8a8a;
  animation: v6-err 0.25s ease-out;
}

.v6-error::before {
  content: '!'; width: 18px; height: 18px; flex-shrink: 0;
  border-radius: 999px; background: rgba(255,122,122,0.16); color: #ff8a8a;
  font-size: 11px; font-weight: 900;
  display: inline-flex; align-items: center; justify-content: center;
}

@keyframes v6-err { from { opacity: 0; transform: translateX(-4px);} to {opacity:1; transform: translateX(0);} }

/* Overflow-fee UI (25⭐ beyond the free open-market cap) — soft gold hint on
 * step 3, a Top-up CTA on the 402 inline state, and a fee note on success. */
.v6-fee-hint {
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: 12px;
  font-size: 12.5px; font-weight: 700;
  color: #FFE08A;
  background: rgba(255, 200, 60, 0.10);
  border: 1px solid rgba(255, 200, 60, 0.30);
}
.v6-fee-hint b { font-weight: 900; color: #FFCE48; }
.v6-fee-note {
  margin: 6px auto 0;
  font-size: 12.5px; font-weight: 800;
  color: #FFCE48;
}
.v6-topup-cta {
  display: block; width: 100%;
  margin-top: 12px;
  padding: 13px;
  border-radius: 14px;
  border: none;
  font-size: 15px; font-weight: 800;
  color: #0e1626;
  background: linear-gradient(180deg, #FFD86B, #FFB800);
  cursor: pointer;
}
.v6-topup-cta:active { transform: scale(0.98); }

/* Multi-outcome ("N-way") builder — Step-3 toggle + outcomes list. Dark until
 * user_markets_multi_enabled; matches the v6 wizard palette. */
.v6-multi-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  margin-top: 12px; padding: 11px 13px;
  border-radius: 13px; border: 1.5px solid rgba(255,255,255,0.10);
  background: rgba(255,255,255,0.03); cursor: pointer; font-family: inherit;
  transition: border-color 0.2s, background 0.2s;
}
.v6-multi-toggle.on { border-color: rgba(151,111,255,0.45); background: rgba(151,111,255,0.08); }
.v6-multi-box {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 7px;
  border: 1.5px solid rgba(255,255,255,0.25);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.2s, border-color 0.2s;
}
.v6-multi-toggle.on .v6-multi-box { border-color: transparent; background: linear-gradient(135deg, #6B93FF, #976FFF); }
.v6-multi-label { font-size: 14.5px; font-weight: 800; color: rgba(255,255,255,0.9); }
.v6-multi-hint { margin-left: auto; font-size: 11.5px; font-weight: 700; color: rgba(255,255,255,0.4); }
.v6-outcomes { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.v6-outcomes-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11.5px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase;
  color: rgba(255,255,255,0.42);
}
.v6-oc-count { font-variant-numeric: tabular-nums; color: rgba(255,255,255,0.55); }
.v6-outcome-row { display: flex; align-items: center; gap: 8px; }
.v6-outcome-input {
  flex: 1; min-width: 0; padding: 11px 13px; border-radius: 11px;
  border: 1.5px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.04);
  color: #fff; font-family: inherit; font-size: 14px; font-weight: 600;
  outline: none; transition: border-color 0.2s, background 0.2s;
}
.v6-outcome-input:focus { border-color: rgba(151,111,255,0.5); background: rgba(151,111,255,0.06); }
.v6-outcome-input::placeholder { color: rgba(255,255,255,0.3); }
.v6-outcome-rm {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 10px;
  border: 1.5px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  color: rgba(255,255,255,0.45); font-size: 14px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.2s, border-color 0.2s;
}
.v6-outcome-rm:active { transform: scale(0.92); }
.v6-add-outcome {
  margin-top: 2px; padding: 10px; width: 100%;
  border-radius: 11px; border: 1.5px dashed rgba(151,111,255,0.4);
  background: transparent; color: #B79CFF;
  font-family: inherit; font-size: 13.5px; font-weight: 800; cursor: pointer;
  transition: transform 0.14s, background 0.2s;
}
.v6-add-outcome:active { transform: scale(0.99); }
/* By-month mode note (auto "when?" outcomes) */
.v6-bymonth-note {
  margin-top: 4px; padding: 11px 13px; border-radius: 12px;
  font-size: 12.5px; font-weight: 600; line-height: 1.45;
  color: rgba(255,255,255,0.72);
  background: rgba(151,111,255,0.08); border: 1px solid rgba(151,111,255,0.25);
}
.v6-bymonth-note b { color: #C4A8FF; font-weight: 800; }

/* ── Progressive close-date picker (field + month→day→hour sheet) ──────────────
   Design: miniapp/assets/Data System.html (Date Picker Stages / v6-datesheet.jsx).
   Copied from the design bundle; .v6ds-sheet gets a max-width so it centres on
   the 480px PC wizard column (mobile stays full-width). */
.v6ds-field {
  width: 100%; box-sizing: border-box; margin-top: 18px;
  display: flex; align-items: center; gap: 13px;
  padding: 15px 16px; border-radius: 16px;
  border: 2px solid rgba(255,255,255,0.10);
  background: rgba(255,255,255,0.04);
  font-family: inherit; cursor: pointer; text-align: left;
  transition: border-color 0.2s, background 0.2s, transform 0.14s, box-shadow 0.2s;
}
.v6ds-field:active { transform: scale(0.985); }
.v6ds-field:hover { border-color: rgba(151,111,255,0.35); }
.v6ds-field.filled {
  border-color: rgba(151,111,255,0.42);
  background: rgba(151,111,255,0.07);
  box-shadow: 0 0 0 4px rgba(151,111,255,0.07);
}
.v6ds-field-ic {
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  background: linear-gradient(135deg, #6B93FF, #976FFF 55%, #E46ACE);
  box-shadow: 0 4px 14px rgba(151,111,255,0.42), inset 0 1px 0 rgba(255,255,255,0.28);
}
.v6ds-field-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.v6ds-field-lbl {
  font-size: 10.5px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase;
  color: rgba(255,255,255,0.5);
}
.v6ds-field-val {
  font-size: 17px; font-weight: 800; letter-spacing: -0.3px; color: #fff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.v6ds-field:not(.filled) .v6ds-field-val { color: rgba(255,255,255,0.42); font-weight: 700; }
.v6ds-field-chev { flex-shrink: 0; color: rgba(255,255,255,0.4); }
.v6ds-dim {
  position: absolute; inset: 0; z-index: 20;
  background: rgba(4,8,16,0.62); backdrop-filter: blur(3px);
  animation: v6m-fade 0.22s ease-out;
}
.v6ds-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 21;
  max-width: 480px; margin-left: auto; margin-right: auto;
  box-sizing: border-box;
  /* Flex column capped to the overlay (= viewport) height: the crumbs (top) and
     the confirm button (bottom) stay pinned/visible and only the body flexes, so
     the sheet can never grow past the screen (was: uncapped → top unreachable). */
  display: flex; flex-direction: column; max-height: calc(100% - 8px);
  padding: 8px 18px max(20px, env(safe-area-inset-bottom));
  border-radius: 26px 26px 0 0;
  background:
    radial-gradient(ellipse 120% 60% at 50% 0%, rgba(151,111,255,0.20) 0%, transparent 58%),
    linear-gradient(180deg, #141d2e 0%, #0b1120 100%);
  border-top: 1px solid rgba(151,111,255,0.30);
  box-shadow: 0 -18px 50px rgba(0,0,0,0.55);
  animation: v6m-rise 0.36s cubic-bezier(0.16,0.84,0.36,1);
}
.v6ds-handle { width: 38px; height: 4px; border-radius: 2px; background: rgba(255,255,255,0.2); margin: 4px auto 14px; }
.v6ds-crumbs { display: flex; align-items: center; gap: 5px; }
.v6ds-crumb {
  display: inline-flex; align-items: baseline; gap: 5px;
  border: 0; cursor: pointer; font-family: inherit;
  padding: 6px 11px; border-radius: 999px;
  font-size: 12.5px; font-weight: 800; letter-spacing: 0.1px;
  background: rgba(255,255,255,0.05); color: rgba(255,255,255,0.4);
  font-variant-numeric: tabular-nums;
  transition: background 0.2s, color 0.2s, transform 0.12s;
}
.v6ds-crumb:disabled { cursor: default; }
.v6ds-crumb:not(:disabled):active { transform: scale(0.95); }
.v6ds-crumb-n { font-size: 9.5px; font-weight: 800; opacity: 0.65; }
.v6ds-crumb.done { color: rgba(255,255,255,0.88); background: rgba(151,111,255,0.16); }
.v6ds-crumb.active { color: #fff; background: linear-gradient(135deg, #6B93FF, #976FFF); box-shadow: 0 2px 10px rgba(99,102,241,0.4); }
.v6ds-crumb-sep { color: rgba(255,255,255,0.2); font-weight: 800; }
.v6ds-title { font-size: 20px; font-weight: 800; letter-spacing: -0.4px; color: #fff; margin: 12px 2px 12px; }
.v6ds-title b { background: linear-gradient(90deg, #8FB0FF, #B79CFF, #F08BDC); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.v6ds-handle, .v6ds-crumbs, .v6ds-summary, .v6ds-confirm { flex: 0 0 auto; }   /* pinned chrome */
/* One fixed body height for every stage → the sheet is the SAME size on month /
   day / hour (no jump). Flex-shrinks (then scrolls) only if the viewport is too
   short to fit it. */
.v6ds-body { flex: 0 1 auto; min-height: 0; height: 350px; overflow-y: auto; scrollbar-width: none; }
.v6ds-body::-webkit-scrollbar { width: 0; }
.v6ds-stage { animation: v6-in 0.34s cubic-bezier(0.16,0.84,0.36,1) backwards; }
.v6ds-stage[data-dir="-1"] { animation-name: v6-in-back; }
.v6ds-dow { display: grid; grid-template-columns: repeat(7,1fr); gap: 5px; margin-bottom: 6px; }
.v6ds-dow span { text-align: center; font-size: 10px; font-weight: 800; letter-spacing: 0.4px; color: rgba(255,255,255,0.32); text-transform: uppercase; }
.v6ds-days { display: grid; grid-template-columns: repeat(7,1fr); gap: 5px; }
.v6ds-day {
  height: 38px; display: flex; align-items: center; justify-content: center;
  border-radius: 11px; border: 1.5px solid rgba(255,255,255,0.07); background: rgba(255,255,255,0.03);
  font-family: inherit; font-size: 14.5px; font-weight: 800; color: rgba(255,255,255,0.82);
  font-variant-numeric: tabular-nums; cursor: pointer;
  transition: transform 0.12s, border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.v6ds-day.blank { border: 0; background: transparent; cursor: default; }
.v6ds-day:not(.disabled):not(.blank):active { transform: scale(0.9); }
.v6ds-day:not(.disabled):not(.blank):not(.selected):hover { border-color: rgba(151,111,255,0.35); background: rgba(151,111,255,0.06); }
.v6ds-day.disabled { opacity: 0.24; cursor: default; }
.v6ds-day.today:not(.selected) { border-color: rgba(151,111,255,0.4); color: #C4A8FF; }
.v6ds-day.selected { border-color: transparent; color: #fff; background: linear-gradient(135deg, #6B93FF, #976FFF 50%, #E46ACE); box-shadow: 0 5px 16px rgba(151,111,255,0.5), inset 0 1px 0 rgba(255,255,255,0.25); transform: scale(1.06); }
.v6ds-hours { display: grid; grid-template-columns: repeat(4,1fr); gap: 7px; }
.v6ds-hour {
  padding: 9px 0; border-radius: 12px; border: 1.5px solid rgba(255,255,255,0.07); background: rgba(255,255,255,0.03);
  font-family: inherit; font-size: 14.5px; font-weight: 800; color: rgba(255,255,255,0.82);
  font-variant-numeric: tabular-nums; cursor: pointer; text-align: center;
  transition: transform 0.12s, border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.v6ds-hour:not(.disabled):active { transform: scale(0.92); }
.v6ds-hour:not(.disabled):not(.selected):hover { border-color: rgba(151,111,255,0.35); background: rgba(151,111,255,0.06); }
.v6ds-hour.disabled { opacity: 0.22; cursor: default; }
.v6ds-hour.selected { border-color: transparent; color: #fff; background: linear-gradient(135deg, #6B93FF, #976FFF 50%, #E46ACE); box-shadow: 0 5px 16px rgba(151,111,255,0.5), inset 0 1px 0 rgba(255,255,255,0.25); transform: scale(1.04); }
.v6ds-hours-note { font-size: 11.5px; font-weight: 600; color: rgba(255,255,255,0.4); margin: 8px 2px 0; text-align: center; }
.v6ds-summary {
  margin-top: 10px; padding: 11px 14px; border-radius: 13px;
  border: 1.5px dashed rgba(255,255,255,0.12);
  font-size: 13px; font-weight: 600; text-align: center;
  color: rgba(255,255,255,0.42); font-variant-numeric: tabular-nums; transition: background-color 0.25s, border-color 0.25s, color 0.25s, box-shadow 0.25s, transform 0.25s, opacity 0.25s;
}
.v6ds-summary.ready { border-style: solid; border-color: rgba(151,111,255,0.35); background: rgba(151,111,255,0.08); color: rgba(255,255,255,0.85); }
.v6ds-summary b { background: linear-gradient(90deg, #8FB0FF, #B79CFF, #F08BDC); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; font-weight: 800; }
.v6ds-confirm { margin-top: 10px; }

/* ── Creator market settings sheet (reuses the v6 chassis: .v6-screen/.v6-hdr/
   .v6-body/.v6-foot/.v6-input/.v6-counter/.v6-cta). Edit name/desc + delete. ── */
.v6-hdr-title { flex: 1; text-align: center; font-size: 15px; font-weight: 800; color: var(--pm-fg, #e7eef6); letter-spacing: -0.2px; }
.v6-set-label { font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: rgba(255,255,255,0.5); margin: 18px 2px 8px; }
.v6-set-label:first-child { margin-top: 4px; }
.v6-set-opt { font-weight: 600; text-transform: none; letter-spacing: 0; color: rgba(255,255,255,0.3); }
.v6-set-locked {
  margin: 2px 0 6px; padding: 11px 13px; border-radius: 12px;
  font-size: 12.5px; font-weight: 700; line-height: 1.4;
  color: #FFE08A; background: rgba(255,200,60,0.10); border: 1px solid rgba(255,200,60,0.30);
}
.v6-set-view {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  margin-top: 18px; padding: 14px 15px; border-radius: 14px;
  border: 1.5px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.03);
  color: rgba(255,255,255,0.88); font-family: inherit; font-size: 14px; font-weight: 700;
  cursor: pointer; transition: border-color 0.2s, background 0.2s, transform 0.14s;
}
.v6-set-view:hover { border-color: rgba(151,111,255,0.35); }
.v6-set-view:active { transform: scale(0.99); }
.v6-set-view span { color: rgba(255,255,255,0.4); font-size: 17px; }
.v6-set-delete {
  display: block; width: 100%; margin-top: 10px; padding: 14px; border-radius: 14px;
  border: 1.5px solid rgba(255,80,80,0.40); background: rgba(255,80,80,0.08); color: #ff8a8a;
  font-family: inherit; font-size: 15px; font-weight: 800; cursor: pointer;
  transition: background 0.2s, transform 0.14s;
}
.v6-set-delete:active { transform: scale(0.98); }

/* Year segmented toggle */
.v6-year-seg {
  display: inline-flex; align-self: flex-start; gap: 4px;
  padding: 4px; margin: 12px 0 10px;
  background: rgba(255,255,255,0.04);
  border-radius: 12px;
}

.v6-year-btn {
  border: 0; cursor: pointer;
  padding: 8px 20px; border-radius: 9px;
  font-family: inherit; font-size: 14px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,0.45);
  background: transparent;
  transition: color 0.2s, background 0.2s;
}

.v6-year-btn.active {
  color: #fff;
  background: linear-gradient(135deg, #6B93FF, #976FFF);
  box-shadow: 0 2px 10px rgba(99,102,241,0.4);
}

/* Calendar — 3 cols, big punchy cells */
.v6-cal {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px;
}

.v6-cell {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px;
  padding: 9px 0;
  border-radius: 13px;
  border: 1.5px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.03);
  font-family: inherit; cursor: pointer;
  transition: transform 0.14s, border-color 0.2s, background 0.2s, box-shadow 0.2s;
}

.v6-cell:not(.disabled):active { transform: scale(0.93); }

.v6-cell:not(.disabled):not(.selected):hover {
  border-color: rgba(151,111,255,0.35);
  background: rgba(151,111,255,0.06);
}

.v6-cell-m { font-size: 14px; font-weight: 800; color: rgba(255,255,255,0.85); letter-spacing: -0.2px; }

.v6-cell-d { font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.34); font-variant-numeric: tabular-nums; }

.v6-cell.disabled { opacity: 0.26; cursor: default; }

.v6-cell.selected {
  border-color: transparent;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  box-shadow: 0 6px 20px rgba(151,111,255,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
  transform: scale(1.04);
}

.v6-cell.selected .v6-cell-m { color: #fff; }

.v6-cell.selected .v6-cell-d { color: rgba(255,255,255,0.8); }

.v6-date-tag {
  margin-top: 10px; padding: 10px 14px;
  border-radius: 13px;
  border: 1.5px dashed rgba(255,255,255,0.12);
  font-size: 13.5px; font-weight: 600;
  color: rgba(255,255,255,0.42);
  text-align: center;
  font-variant-numeric: tabular-nums;
  transition: background-color 0.25s, border-color 0.25s, color 0.25s, box-shadow 0.25s, transform 0.25s, opacity 0.25s;
}

.v6-date-tag.filled {
  border-style: solid;
  border-color: rgba(151,111,255,0.35);
  background: rgba(151,111,255,0.08);
  color: rgba(255,255,255,0.8);
}

.v6-date-tag.filled b {
  background: linear-gradient(90deg, #8FB0FF, #B79CFF, #F08BDC);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  font-weight: 800;
}

/* Footer CTA */
.v6-foot {
  padding: 16px 0 max(18px, env(safe-area-inset-bottom));
}

.v6-cta {
  width: 100%; box-sizing: border-box;
  padding: 17px 18px; border: none; border-radius: 16px;
  font-family: inherit; font-size: 16px; font-weight: 800; letter-spacing: 0.2px;
  color: #fff; cursor: pointer;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  background-size: 200% 200%;
  animation: pr-shimmer 8s ease infinite;
  box-shadow: 0 6px 22px rgba(99,102,241,0.45), inset 0 1px 0 rgba(255,255,255,0.22);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: transform 0.14s, box-shadow 0.2s;
}

.v6-cta:active { transform: scale(0.97); }

.v6-cta--off {
  background: rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.3);
  box-shadow: none; animation: none;
  cursor: not-allowed;
}

.v6-cta-ghost {
  width: 100%; box-sizing: border-box;
  margin-top: 10px;
  padding: 15px 18px; border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.10);
  background: transparent;
  font-family: inherit; font-size: 15px; font-weight: 700;
  color: rgba(255,255,255,0.6); cursor: pointer;
  transition: background 0.15s;
}

.v6-cta-ghost:active { background: rgba(255,255,255,0.05); }

/* Success */
.v6-success {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding-top: 24px;
  animation: v6-in 0.4s cubic-bezier(0.16,0.84,0.36,1) backwards;
}

.v6-burst {
  width: 80px; height: 80px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  box-shadow: 0 10px 36px rgba(151,111,255,0.6), inset 0 2px 0 rgba(255,255,255,0.3);
  margin-bottom: 18px;
  animation: v6-pop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) backwards;
}

@keyframes v6-pop {
  0% { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.12); }
  100% { transform: scale(1); opacity: 1; }
}

.v6-success-title {
  font-size: 30px; font-weight: 800; letter-spacing: -0.6px;
  color: #fff; margin-bottom: 6px; text-align: center;
}

.v6-success-sub {
  font-size: 14px; font-weight: 500; color: rgba(255,255,255,0.5);
  text-align: center; margin-bottom: 18px;
}

.v6-success-card {
  width: 100%; box-sizing: border-box;
  padding: 14px 16px; border-radius: 16px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(151,111,255,0.22);
  margin-bottom: 14px;
}

.v6-success-q { font-size: 16px; font-weight: 700; color: #fff; line-height: 1.35; text-wrap: pretty; }

.v6-success-meta {
  font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,0.5);
  margin-top: 8px; font-variant-numeric: tabular-nums;
}

.v6-success .v6-cta, .v6-success .v6-cta-ghost { margin-top: 0; }

.v6-success .v6-cta-ghost { margin-top: 10px; }

/* Referral share block */
.v6-ref {
  width: 100%; box-sizing: border-box;
  padding: 14px;
  border-radius: 16px;
  background:
    linear-gradient(135deg, rgba(107,147,255,0.12), rgba(151,111,255,0.10), rgba(228,106,206,0.08));
  border: 1px solid rgba(151,111,255,0.28);
  margin-bottom: 16px;
}

.v6-ref-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 9px;
}

.v6-ref-label {
  font-size: 10.5px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase;
  color: rgba(255,255,255,0.55);
}

.v6-ref-badge {
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.2px;
  padding: 3px 9px; border-radius: 999px;
  background: linear-gradient(135deg, #6B93FF, #976FFF, #E46ACE);
  color: #fff;
  box-shadow: 0 2px 8px rgba(151,111,255,0.4);
}

.v6-ref-row {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 6px 6px 13px;
  border-radius: 12px;
  background: rgba(0,0,0,0.28);
  border: 1px solid rgba(255,255,255,0.08);
}

.v6-ref-url {
  flex: 1; min-width: 0;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 12.5px; font-weight: 600;
  color: rgba(255,255,255,0.78);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.v6-ref-copy {
  flex-shrink: 0;
  border: 0; cursor: pointer;
  padding: 8px 14px; border-radius: 9px;
  font-family: inherit; font-size: 12.5px; font-weight: 800; letter-spacing: 0.2px;
  color: #fff;
  background: linear-gradient(135deg, #6B93FF, #976FFF);
  box-shadow: 0 2px 8px rgba(99,102,241,0.4);
  display: inline-flex; align-items: center; gap: 5px;
  transition: transform 0.12s, background 0.2s;
}

.v6-ref-copy:active { transform: scale(0.94); }

.v6-ref-copy.copied {
  background: linear-gradient(135deg, #3fae6f, #5fe39a);
  box-shadow: 0 2px 8px rgba(95,227,154,0.4);
}

@keyframes v6m-fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes v6m-rise { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* Confetti */
.v6-confetti {
  position: absolute; top: 30px; left: 50%;
  width: 0; height: 0; pointer-events: none; z-index: 0;
}

.v6-confetti-bit {
  position: absolute; width: 8px; height: 8px; border-radius: 2px;
  opacity: 0;
  animation: v6-confetti 1.1s ease-out forwards;
}

.v6-cb-0  { background: #6B93FF; animation-delay: .02s; --tx: -90px;  --ty: -10px; --r: 220deg; }

.v6-cb-1  { background: #976FFF; animation-delay: .05s; --tx: 80px;   --ty: -30px; --r: -180deg; }

.v6-cb-2  { background: #E46ACE; animation-delay: .00s; --tx: -50px;  --ty: -70px; --r: 140deg; }

.v6-cb-3  { background: #FFCA28; animation-delay: .08s; --tx: 110px;  --ty: 20px;  --r: -120deg; }

.v6-cb-4  { background: #6B93FF; animation-delay: .03s; --tx: 40px;   --ty: -80px; --r: 300deg; }

.v6-cb-5  { background: #E46ACE; animation-delay: .06s; --tx: -110px; --ty: 30px;  --r: -240deg; }

.v6-cb-6  { background: #976FFF; animation-delay: .01s; --tx: 20px;   --ty: -100px;--r: 90deg; }

.v6-cb-7  { background: #5fe39a; animation-delay: .09s; --tx: -30px;  --ty: 40px;  --r: -90deg; }

.v6-cb-8  { background: #FFCA28; animation-delay: .04s; --tx: 130px;  --ty: -40px; --r: 200deg; }

.v6-cb-9  { background: #6B93FF; animation-delay: .07s; --tx: -130px; --ty: -30px; --r: -160deg; }

.v6-cb-10 { background: #E46ACE; animation-delay: .02s; --tx: 60px;   --ty: 60px;  --r: 260deg; }

.v6-cb-11 { background: #976FFF; animation-delay: .05s; --tx: -70px;  --ty: 70px;  --r: -200deg; }

.v6-cb-12 { background: #5fe39a; animation-delay: .03s; --tx: 90px;   --ty: -90px; --r: 120deg; }

.v6-cb-13 { background: #FFCA28; animation-delay: .08s; --tx: -100px; --ty: -60px; --r: -300deg; }

@keyframes v6-confetti {
  0%   { opacity: 1; transform: translate(0,0) rotate(0); }
  100% { opacity: 0; transform: translate(var(--tx), var(--ty)) rotate(var(--r)); }
}/* Create wizard overlay fills the screen (the abs-inset:0 .v6-screen child covers it). */
.pm-create-overlay { align-items: stretch; }
.pm-create-overlay > .v6-screen { animation: pmSheetUp 0.32s cubic-bezier(0.16,0.84,0.36,1); }
/* Mobile-first: keep the wizard a centred phone-width column on wide PC
   (scoped to the wizard overlay — never touches the Markets list). */
.v6-screen { align-items: center; }
.v6-hdr, .v6-body, .v6-foot { width: 100%; max-width: 480px; }

/* ═══════════════════════════════════════════════════════════════
   V6 — "MY MARKETS" page (game style; design: v6-markets.jsx).
   Adapted to real yes/no user markets: 2-segment YES/NO bar, real
   earnings hero (variant A), state-mapped filter chips, propose sheet.
   ═══════════════════════════════════════════════════════════════ */
.v6m-screen {
  position: absolute; inset: 0; top: 0;
  display: flex; flex-direction: column; box-sizing: border-box;
  background:
    radial-gradient(ellipse 120% 50% at 50% -8%, rgba(151,111,255,0.16) 0%, transparent 55%),
    radial-gradient(ellipse 90% 50% at 100% 110%, rgba(228,106,206,0.10) 0%, transparent 55%),
    linear-gradient(180deg, #0c1322 0%, #0a0f1c 100%);
  color: #F5F5F5;
}.v6m-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0 18px 24px; scrollbar-width: none; }
.v6m-scroll::-webkit-scrollbar { width: 0; }

/* Lifetime earnings hero (variant A) */
.v6e { margin-bottom: 16px; }
.v6e-lbl { font-size: 10px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase; color: rgba(255,255,255,0.5); }
.v6e-stars { font-size: 0.62em; }
.v6e-a { padding: 14px; border-radius: 18px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); }
.v6e-a-top { display: flex; align-items: center; gap: 12px; }
.v6e-a-coin {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: 14px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #6B93FF, #976FFF 55%, #E46ACE);
  box-shadow: 0 4px 14px rgba(151,111,255,0.45), inset 0 1px 0 rgba(255,255,255,0.3);
}
.v6e-a-main { flex: 1; min-width: 0; }
.v6e-a-num { font-size: 28px; font-weight: 800; letter-spacing: -0.6px; line-height: 1; margin-top: 4px; color: #fff; font-variant-numeric: tabular-nums; }
.v6e-a-delta { flex-shrink: 0; align-self: flex-start; font-size: 11px; font-weight: 800; color: #5fe39a; background: rgba(95,227,154,0.12); padding: 4px 9px; border-radius: 999px; font-variant-numeric: tabular-nums; }
.v6e-a-claim {
  width: 100%; margin-top: 14px; border: 0; cursor: pointer; padding: 13px; border-radius: 13px;
  font-family: inherit; font-size: 14.5px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  background-size: 200% 200%; animation: pr-shimmer 8s ease infinite;
  box-shadow: 0 4px 16px rgba(99,102,241,0.42), inset 0 1px 0 rgba(255,255,255,0.22);
  display: inline-flex; align-items: center; justify-content: center; gap: 7px; transition: transform 0.14s;
}
.v6e-a-claim:active { transform: scale(0.98); }
.v6e-a-claim:disabled { opacity: 0.55; filter: grayscale(0.3); cursor: default; animation: none; }.v6m-chip {
  flex-shrink: 0; border: 1px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.04);
  color: rgba(255,255,255,0.62); padding: 8px 13px; border-radius: 999px;
  font-family: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; transition: color 0.2s, background 0.2s, border-color 0.2s;
}
.v6m-chip-c { font-size: 11px; font-weight: 800; color: rgba(255,255,255,0.42); font-variant-numeric: tabular-nums; }
.v6m-chip.active { color: #fff; border-color: transparent; background: linear-gradient(135deg, #6B93FF, #976FFF); box-shadow: 0 2px 10px rgba(99,102,241,0.4); }
.v6m-chip.active .v6m-chip-c { color: rgba(255,255,255,0.85); }
.v6m-chip.urgent:not(.active) { border-color: rgba(255, 202, 40, 0.35); color: #FFCA28; }
.v6m-chip.urgent:not(.active) .v6m-chip-c { color: rgba(255, 202, 40, 0.6); }.v6m-card-art .pm-card-mono { font-size: 22px; font-weight: 800; color: #fff; }.v6m-chip-out { font-size: 9px; font-weight: 800; letter-spacing: 0.6px; padding: 2px 7px; border-radius: 999px; background: rgba(151,111,255,0.16); border: 1px solid rgba(151,111,255,0.32); color: #C4A8FF; }.v6m-stack { display: flex; height: 11px; border-radius: 4px; overflow: hidden; background: rgba(255,255,255,0.04); box-shadow: inset 0 1px 0 rgba(0,0,0,0.20); }
.v6m-stack > span { display: block; height: 100%; border-right: 1px solid rgba(0,0,0,0.32); }
.v6m-stack > span:last-child { border-right: 0; }
.v6m-stack--dim { filter: saturate(0.5) opacity(0.7); }.v6m-foot-pct { font-size: 17px; font-weight: 800; letter-spacing: -0.5px; font-variant-numeric: tabular-nums; }
.v6m-foot-by { font-size: 10.5px; font-weight: 800; letter-spacing: 0.6px; color: rgba(255,255,255,0.40); text-transform: uppercase; }
.v6m-foot-stats { margin-left: auto; font-size: 11.5px; font-weight: 600; color: rgba(255,255,255,0.5); font-variant-numeric: tabular-nums; }
.v6m-badge { flex-shrink: 0; font-size: 9px; font-weight: 800; letter-spacing: 0.6px; padding: 2px 7px; border-radius: 999px; white-space: nowrap; text-transform: uppercase; }
.v6m-badge--open { background: rgba(95,227,154,0.14); color: #5fe39a; }
.v6m-badge--await { background: rgba(255,202,40,0.16); color: #FFCA28; }
.v6m-badge--win { background: rgba(151,111,255,0.18); color: #C4A8FF; }
.v6m-await { display: flex; align-items: center; gap: 10px; margin-top: 11px; padding: 10px 12px; border-radius: 12px; background: rgba(255,202,40,0.10); border: 1px solid rgba(255,202,40,0.30); }
.v6m-await-txt { flex: 1; font-size: 12.5px; font-weight: 600; color: rgba(255,229,168,0.92); }
.v6m-await-btn { flex-shrink: 0; border: 0; cursor: pointer; padding: 8px 13px; border-radius: 10px; font-family: inherit; font-size: 12px; font-weight: 800; color: #fff; background: linear-gradient(135deg, #6B93FF, #976FFF); box-shadow: 0 2px 8px rgba(99,102,241,0.4); transition: transform 0.12s; }
.v6m-await-btn:active { transform: scale(0.94); }
.v6m-earned { display: flex; align-items: center; margin-top: 10px; padding: 9px 13px; border-radius: 12px; background: rgba(151,111,255,0.10); border: 1px solid rgba(151,111,255,0.22); font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,0.6); }
.v6m-earned-v { margin-left: auto; font-size: 14px; font-weight: 800; background: linear-gradient(90deg, #8FB0FF, #C4A8FF, #F08BDC); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
/* Empty state */
.v6m-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px 32px 60px; text-align: center; }
.v6m-empty-orb { width: 80px; height: 80px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%); box-shadow: 0 10px 32px rgba(151,111,255,0.55), inset 0 2px 0 rgba(255,255,255,0.28); margin-bottom: 22px; animation: v6-pop 0.5s cubic-bezier(0.2,1.4,0.4,1) backwards; }
.v6m-empty-title { font-size: 24px; font-weight: 800; letter-spacing: -0.5px; color: #fff; margin-bottom: 8px; }
.v6m-empty-sub { font-size: 14px; font-weight: 500; line-height: 1.55; color: rgba(255,255,255,0.52); margin-bottom: 24px; }

/* Propose sheet */
.v6m-sheet-dim { position: fixed; inset: 0; background: rgba(0,0,0,0.5); backdrop-filter: blur(2px); z-index: 2050; animation: v6m-fade 0.2s ease-out; }
@keyframes v6m-fade { from { opacity: 0; } to { opacity: 1; } }
.v6m-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 2051;
  padding: 8px 18px max(24px, env(safe-area-inset-bottom)); border-radius: 24px 24px 0 0;
  background: radial-gradient(ellipse 120% 60% at 50% 0%, rgba(151,111,255,0.18) 0%, transparent 60%), linear-gradient(180deg, #161f30 0%, #0e1626 100%);
  border-top: 1px solid rgba(151,111,255,0.30); box-shadow: 0 -16px 44px rgba(0,0,0,0.5);
  animation: v6m-rise 0.34s cubic-bezier(0.16,0.84,0.36,1);
}
@keyframes v6m-rise { from { transform: translateY(100%); } to { transform: translateY(0); } }
.v6m-sheet-handle { width: 38px; height: 4px; border-radius: 2px; background: rgba(255,255,255,0.2); margin: 4px auto 14px; }
.v6m-sheet-hd { display: flex; align-items: center; justify-content: space-between; font-size: 19px; font-weight: 800; letter-spacing: -0.3px; color: #fff; margin-bottom: 12px; }
.v6m-sheet-q { font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.6); padding: 10px 12px; border-radius: 12px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.07); margin-bottom: 16px; line-height: 1.4; }
.v6m-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.v6m-opt { border: 1.5px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.03); border-radius: 14px; padding: 14px 6px; font-family: inherit; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 5px; transition: transform 0.12s, border-color 0.2s, background 0.2s, box-shadow 0.2s; }
.v6m-opt:active { transform: scale(0.95); }
.v6m-opt-glyph { width: 36px; height: 36px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 900; }
.v6m-opt-label { font-size: 13px; font-weight: 800; letter-spacing: 0.4px; }
.v6m-opt-sub { font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.42); font-variant-numeric: tabular-nums; }
.v6m-opt--yes .v6m-opt-glyph { background: rgba(95,227,154,0.16); color: #5fe39a; }
.v6m-opt--no  .v6m-opt-glyph { background: rgba(255,138,138,0.16); color: #ff8a8a; }
.v6m-opt--yes .v6m-opt-label { color: #9DEFC0; }
.v6m-opt--no  .v6m-opt-label { color: #FFB5B5; }
.v6m-opt.selected.v6m-opt--yes { border-color: rgba(95,227,154,0.6); background: rgba(95,227,154,0.12); box-shadow: 0 0 0 3px rgba(95,227,154,0.10); }
.v6m-opt.selected.v6m-opt--no { border-color: rgba(255,138,138,0.6); background: rgba(255,138,138,0.12); box-shadow: 0 0 0 3px rgba(255,138,138,0.10); }
.v6m-warn { margin-top: 12px; padding: 10px 12px; border-radius: 12px; background: rgba(255,107,53,0.07); border: 1px solid rgba(255,107,53,0.20); font-size: 11.5px; font-weight: 600; line-height: 1.45; color: rgba(255,200,165,0.88); }

/* My-markets overlay fills the screen; cap content to a centred phone-width
   column on wide PC (scoped to this overlay — never touches the Markets list). */
.pm-mm-overlay { align-items: stretch; }
.pm-mm-overlay > .v6m-screen { animation: pmSheetUp 0.32s cubic-bezier(0.16,0.84,0.36,1); }.v6m-sheet { max-width: 480px; margin-left: auto; margin-right: auto; }

/* ── V6 populated My-markets: card wrapper, state strips, badge, chevron ───── */
/* The card body is the shared Markets card (renderMarketCard — keeps the
   identical body + big right-side %/side). This wrapper adds the tier glow +
   bordered frame so the per-state strip reads as one attached block. The inner
   .pm-card is neutralised (no own border/bg/margin/animation). */
.pm-mm-card {
  position: relative; border-radius: var(--pm-r-lg, 16px); overflow: hidden;
  background: var(--pm-card); border: 1px solid var(--pm-border-2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04); margin-bottom: 10px;
  animation: fadeInUp 0.35s ease-out backwards;
}
.pm-mm-card--await { border-color: rgba(255,202,40,0.32); }
.pm-mm-card--disputed { border-color: rgba(255,107,53,0.34); }
.pm-mm-card--resolved { opacity: 0.82; }
.pm-mm-glow {
  position: absolute; top: -52%; right: -12%; width: 150px; height: 150px;
  border-radius: 999px; pointer-events: none;
  background: radial-gradient(circle, color-mix(in oklab, var(--tier, #5fe39a) 26%, transparent) 0%, transparent 68%);
}
.pm-mm-card > .pm-card {
  position: relative; z-index: 1;
  background: transparent; border: 0; box-shadow: none; margin: 0; border-radius: 0; animation: none;
}
/* Gift thumbnail gets the V6 tier drop-shadow inside My-markets. */
.pm-mm-card .pm-card-art img { filter: drop-shadow(0 2px 6px color-mix(in oklab, var(--tier, #5fe39a) 40%, transparent)); }
/* Chevron affordance at the row's right edge (tap bubbles up → opens detail). */
.pm-card-chev {
  flex-shrink: 0; align-self: center; width: 26px; height: 26px; margin-left: 2px; padding: 0;
  border: 0; background: transparent; color: rgba(255,255,255,0.34);
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; cursor: pointer;
}
.pm-card-chev:active { background: rgba(255,255,255,0.06); }

/* Lifecycle badge: orange disputed variant (open/await/win already defined). */
.v6m-badge--disputed { background: rgba(255,107,53,0.16); color: #FFB077; }

/* State strips sit inside .pm-mm-card as a sibling of .pm-card; align with the
   card body and clear the row above. */
.pm-mm-card .v6m-await,
.pm-mm-card .v6m-earned,
.pm-mm-card .v6m-disputed { position: relative; z-index: 1; margin: 0 14px 13px; }
.v6m-await-txt b { color: #FFCA28; font-weight: 800; }
.v6m-earned-v--na { -webkit-text-fill-color: rgba(255,255,255,0.4); color: rgba(255,255,255,0.4); background: none; }
/* Disputed strip (was missing from the bundle). */
.v6m-disputed {
  padding: 10px 12px; border-radius: 12px;
  background: rgba(255,107,53,0.10); border: 1px solid rgba(255,107,53,0.28);
  font-size: 12px; font-weight: 600; line-height: 1.4; color: rgba(255,200,165,0.92);
}

/* Propose sheet: 3-up grid + Invalid option (was YES/NO only). */
.v6m-opts--3 { grid-template-columns: 1fr 1fr 1fr; }
.v6m-opt--inv .v6m-opt-glyph { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.6); }
.v6m-opt--inv .v6m-opt-label { color: rgba(255,255,255,0.72); }
.v6m-opt.selected.v6m-opt--inv { border-color: rgba(255,255,255,0.35); background: rgba(255,255,255,0.08); }

/* Amber "Needs result" filter chip (urgent), matching the V6 design. */
.pm-chip--await:not(.active) { border-color: rgba(255,202,40,0.35); color: #FFCA28; }
.pm-chip--await:not(.active) .pm-chip-count { color: rgba(255,202,40,0.6); }

/* My-markets has 5 variable-width filter chips (incl. the long "Needs result").
   The Markets tab's equal-width `flex:1 1 0` is wrong here (it stretches them to
   giant pills on wide PC and clips the long chip + count on the narrow TG
   webview). Size them to content and keep all 5 on a SINGLE row — shrunk
   (tighter padding, smaller label + count) so the full set fits; if a very
   narrow viewport still can't, the row scrolls horizontally (never a 2nd row).
   Disputed is left as-is — only the surrounding chips shrink. */
#pm-um-filters { flex-wrap: nowrap; overflow-x: auto; gap: 6px; scrollbar-width: none; -ms-overflow-style: none; }
#pm-um-filters::-webkit-scrollbar { display: none; }
#pm-um-filters .pm-chip { flex: 0 0 auto; padding: 6px 9px; font-size: 11px; }
#pm-um-filters .pm-chip-count { font-size: 9px; padding: 1px 4px; }

/* ── History page: "My bets" + "My markets" switcher (reuses .pm-seg) ──────── */
/* This switcher is SECONDARY to the main Markets/History tab bar, so render it
   visibly smaller (shorter tabs, smaller label + count, lighter frame) — at the
   shared .pm-seg size it read as a peer of the main buttons, which looked off. */
.pm-hist-seg { margin-top: 14px; margin-bottom: 14px; border-color: rgba(255,205,80,0.10); }
.pm-hist-seg .pm-seg-tab { padding: 5px 10px; font-size: 12px; letter-spacing: 0.1px; }
.pm-hist-seg .pm-seg-count { font-size: 9.5px; padding: 1px 5px; }
/* Keep the gap below the main tab bar identical across tabs. The Markets list
   stacks #pm-list padding-top (14) + .pm-chips margin-top (10) = 24px, but the
   History switcher sits 14px under the bar. Drop the chips' extra top margin so
   both views start at the same 14px (no vertical jump when switching tabs). */
#pm-list .pm-chips { margin-top: 0; }#pm-hist-markets { padding-top: 2px; }

/* ══ Server Status sheet (Settings → Server Status) ═══════════════════════════
   Restored 2026-05-30 (was collateral of the Top-page V3 redesign + dead-CSS
   sweep). Sits on the existing .pm-sheet overlay frame. */
.status-sheet-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.status-sheet-head-icon { width: 22px; height: 22px; color: var(--tg-text); flex-shrink: 0; }
.status-pill {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px; border-radius: 12px;
  font-size: 14px; font-weight: 600;
  margin-bottom: 10px;
}
.status-pill-dot  { font-size: 14px; line-height: 1; }
.status-pill-text { flex: 1; min-width: 0; }
.status-pill--operational { background: rgba(60, 200, 120, 0.14); color: #3ECF80; }
.status-pill--degraded    { background: rgba(240, 170, 50, 0.16); color: #F0AA32; }
.status-pill--outage      { background: rgba(230, 80, 90, 0.16); color: #E6505A; }
.status-pill--unknown     { background: var(--tg-bg-input); color: var(--tg-hint); }
.status-recheck {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--tg-bg-input); color: var(--tg-hint);
  border: none; border-radius: 999px;
  padding: 6px 12px; font-size: 12px; font-weight: 600;
  cursor: pointer; margin-bottom: 14px; font-family: inherit;
}
.status-recheck:active { opacity: 0.7; }
.status-recheck.is-fetching .status-recheck-spinner { animation: statusSpin 1s linear infinite; display: inline-block; }
@keyframes statusSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
.status-banner {
  background: rgba(230, 80, 90, 0.12); color: #E6505A;
  padding: 10px 12px; border-radius: 10px; font-size: 13px;
  margin-bottom: 12px;
}
.status-banner.hidden { display: none; }
.status-section-label {
  font-size: 12px; font-weight: 600; color: var(--tg-hint);
  margin: 16px 0 8px;
}
.status-section-label.hidden { display: none; }
.status-safe-card {
  background: var(--tg-bg-input);
  border-radius: 14px;
  padding: 14px;
  display: flex; flex-direction: column; gap: 12px;
}
.status-safe-row { display: flex; align-items: flex-start; gap: 12px; }
.status-safe-icon {
  font-size: 16px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.status-safe-text  { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.status-safe-title { font-size: 14px; font-weight: 600; color: var(--tg-text); }
.status-safe-sub   { font-size: 13px; color: var(--tg-hint); line-height: 1.4; }
.status-comp-list {
  background: var(--tg-bg-input);
  border-radius: 14px;
  overflow: hidden;
}
.status-comp {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--tg-separator);
  font-size: 14px;
}
.status-comp:last-child { border-bottom: none; }
.status-comp-icon   { width: 20px; text-align: center; flex-shrink: 0; }
.status-comp-label  { color: var(--tg-text); font-weight: 500; flex: 1; min-width: 0; }
.status-comp-detail { color: var(--tg-hint); font-size: 12px; flex-shrink: 0; }
.status-limited-list {
  background: rgba(240, 170, 50, 0.10);
  border-radius: 14px;
  overflow: hidden;
}
.status-limited-list.hidden { display: none; }
.status-limited-item {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(240, 170, 50, 0.15);
  font-size: 14px; color: var(--tg-text);
}
.status-limited-item:last-child { border-bottom: none; }
/* Avatar amber dot when overall !== 'operational'. */
.user-avatar-status {
  position: absolute; left: -4px; top: -4px;
  width: 12px; height: 12px; border-radius: 50%;
  background: #F0AA32; border: 2px solid var(--tg-bg);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
.user-avatar-status.hidden { display: none; }

/* ── In-app confirm modal (centered card, v6 styling) ──────────────────────
   Replaces native tg.showPopup for create/settings confirms. Markup injected
   by pmConfirm() in predmarket.*.js. Sits above the create overlay (z 1000)
   and the date sheet, so the fee gate reads on top of the wizard. */
.pm-confirm-overlay {
  position: fixed; inset: 0; z-index: 2200;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(6, 10, 20, 0.62); backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  overscroll-behavior: contain; touch-action: none;
  animation: pmCfFade 0.18s ease-out;
}
.pm-confirm-overlay > * { touch-action: auto; }
.pm-confirm-overlay.hidden { display: none; }
@keyframes pmCfFade { from { opacity: 0; } to { opacity: 1; } }

.pm-confirm-card {
  width: 100%; max-width: 340px; box-sizing: border-box;
  padding: 26px 22px 20px; border-radius: 24px;
  text-align: center;
  background: radial-gradient(ellipse 120% 70% at 50% 0%, rgba(151,111,255,0.20) 0%, transparent 62%), linear-gradient(180deg, #182133 0%, #0e1626 100%);
  border: 1px solid rgba(151,111,255,0.30);
  box-shadow: 0 24px 60px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.06);
  animation: pmCfPop 0.34s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
}
.pm-confirm-card--danger { border-color: rgba(255,107,107,0.34); }
@keyframes pmCfPop {
  0% { opacity: 0; transform: scale(0.9) translateY(8px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

.pm-cf-ic {
  width: 58px; height: 58px; margin: 0 auto 14px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  box-shadow: 0 10px 30px rgba(151,111,255,0.5), inset 0 2px 0 rgba(255,255,255,0.28);
  animation: v6-pop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) backwards;
}
.pm-cf-ic--danger {
  background: linear-gradient(135deg, #ff7a7a 0%, #ff5470 100%);
  box-shadow: 0 10px 30px rgba(255,84,112,0.5), inset 0 2px 0 rgba(255,255,255,0.28);
}

.pm-cf-title {
  font-size: 21px; font-weight: 800; letter-spacing: -0.4px;
  color: #fff; margin-bottom: 7px; text-wrap: balance;
}
.pm-cf-msg {
  font-size: 14px; font-weight: 500; line-height: 1.5;
  color: rgba(255,255,255,0.62); text-wrap: pretty;
}
.pm-cf-msg b { color: #fff; font-weight: 800; }

.pm-cf-chip {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: 13px; padding: 7px 14px; border-radius: 999px;
  background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.10);
  font-size: 12.5px; font-weight: 700; color: rgba(255,255,255,0.82);
  font-variant-numeric: tabular-nums;
}

.pm-cf-btns { margin-top: 22px; display: flex; flex-direction: column; gap: 10px; }

.pm-cf-btn {
  width: 100%; box-sizing: border-box;
  padding: 15px 18px; border: none; border-radius: 15px;
  font-family: inherit; font-size: 15.5px; font-weight: 800; letter-spacing: 0.2px;
  color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: transform 0.14s, background 0.18s;
}
.pm-cf-btn:active { transform: scale(0.97); }

.pm-cf-btn--primary {
  background: linear-gradient(135deg, #6B93FF 0%, #976FFF 50%, #E46ACE 100%);
  background-size: 200% 200%;
  animation: pr-shimmer 8s ease infinite;
  box-shadow: 0 6px 22px rgba(99,102,241,0.45), inset 0 1px 0 rgba(255,255,255,0.22);
}
.pm-cf-btn--secondary {
  background: rgba(151,111,255,0.16);
  border: 1px solid rgba(151,111,255,0.34);
  color: #cbb8ff;
}
.pm-cf-btn--danger {
  background: linear-gradient(135deg, #ff7a7a 0%, #ff5470 100%);
  box-shadow: 0 6px 22px rgba(255,84,112,0.42), inset 0 1px 0 rgba(255,255,255,0.20);
}
.pm-cf-btn--ghost {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.10);
  color: rgba(255,255,255,0.6); font-weight: 700;
}
.pm-cf-btn--ghost:active { background: rgba(255,255,255,0.05); }

/* ════════════════════════════════════════════════════════════════════
   RTL — Arabic. <html dir="rtl"> is set by app.js _applyDir() when lang=ar.
   dir="rtl" already mirrors flex-row order, inline flow and start/end text
   alignment, so the flex layouts (bottom-nav, list rows, settings rows, sort
   row, stat tiles, predict cards) flip for free. These rules cover the spots
   that pin to PHYSICAL left/right or force an explicit text-align. Everything
   is scoped under [dir="rtl"] so LTR languages are byte-for-byte unaffected.
   ════════════════════════════════════════════════════════════════════ */
[dir="rtl"] body { text-align: right; }

/* Headings / labels / sheet text that were explicitly left-aligned in LTR. */
[dir="rtl"] .page-title,
[dir="rtl"] .page-subtitle,
[dir="rtl"] .totals-title,
[dir="rtl"] .ccy-picker-title,
[dir="rtl"] .pf-sheet-lbl,
[dir="rtl"] .pm-sheet-head-title,
[dir="rtl"] .v6-hint-note,
[dir="rtl"] .settings-section-title { text-align: right; }

/* Home hero: the ★/▽/$ switcher is a VERTICAL pill pinned RIGHT-CENTRE in LTR → mirror
   to LEFT-CENTRE. (Title + value are centred, P&L is centred, so they need no flip; the
   top:50% + translateY(-50%) vertical centring carries over from the base rule.) */
[dir="rtl"] #page-home.hm-v8 .hmv8-cur { right: auto; left: 12px; }

/* Directional chevrons / carets point the wrong way in RTL → mirror the glyph
   (only the standalone arrow spans, never text-bearing elements). */
[dir="rtl"] .totals-title-arrow,
[dir="rtl"] .sort-caret { display: inline-block; transform: scaleX(-1); }

/* Search inputs hard-code text-align:left → align to the right under RTL. */
[dir="rtl"] .search-input,
[dir="rtl"] #page-leaderboard.lb-v3 .vk-search input.search-input,
[dir="rtl"] #page-leaderboard.lb-v3 .vk-search input { text-align: right; }

/* Numbers, prices and currency spans always read left-to-right (digits + the
   $/⭐/TON glyph). Force LTR on them so "$442 414" never visually reverses,
   even inside an RTL paragraph. */
[dir="rtl"] .hmv8-numtext,
[dir="rtl"] .totals-primary,
[dir="rtl"] .totals-secondary,
[dir="rtl"] .hmv8-pnl,
[dir="rtl"] [data-stars-value] { direction: ltr; }

/* Sub-line under the hint note / any list using physical left padding for an
   icon gutter — let dir handle the gutter side. */
[dir="rtl"] .ccy-picker-opts .ccy-opt { text-align: right; }

/* ── TON Connect modal stacking ──────────────────────────────────────────────
   The @tonconnect/ui SDK injects its wallet-connect modal (z-index:1000) at <body>.
   The deposit sheet #pm-topup-overlay is z-index:1100, so tapping "Connect wallet to
   deposit TON" opened the wallet modal BEHIND the sheet — invisible, so connect looked
   dead. (Settings connect worked only because Settings is a plain page, not a z:1100
   overlay.) Lift the SDK's injected roots into a top stacking context so the modal
   always wins. Harmless when closed (the roots are empty). Verified: with the deposit
   overlay open at z:1100, the modal now renders on top. */
tc-root,
#tc-widget-root { position: relative; z-index: 2147483000; }
