/* edilbot mini app — visual system.
   Theme: golden yellow on deep black. Deliberately brand-consistent, so it
   does NOT inherit Telegram's per-user theme variables — the app looks the
   same in every client. */

/* Nexa — self-hosted in fonts/ (see fonts/README.md). Missing files just
   fall through to Jost, then the platform sans. */
@font-face {
  font-family: "Nexa";
  src: url("/fonts/NexaRegular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Nexa";
  src: url("/fonts/NexaBold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Nexa";
  src: url("/fonts/NexaHeavy.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
}

:root {
  --bg:          #0a0a0c;
  --bg-2:        #0f0f12;
  --surface:     #16161a;
  --surface-hi:  #1e1e24;
  --line:        rgba(255, 255, 255, 0.08);
  --line-gold:   rgba(245, 197, 66, 0.22);

  --gold:        #f5c542;
  --gold-bright: #ffd866;
  --gold-deep:   #c99a24;
  --gold-grad:   linear-gradient(135deg, #ffe08a 0%, #f5c542 42%, #d7a52c 100%);

  --ink:         #f6f5f2;
  --ink-dim:     #a3a3ab;
  --ink-mute:    #6e6e77;
  --good:        #4ade80;
  --bad:         #ff6b6b;

  --r-lg: 18px;
  --r-md: 13px;
  --r-sm: 9px;

  --shadow: 0 12px 34px rgba(0, 0, 0, 0.5);
  --tabbar-h: 62px;
  --topbar-h: 52px;

  /* Nexa throughout, Jost (web) then platform sans as fallbacks.
     `--font-display` stays as a separate name for the "value" moments
     (wordmark, prize, totals, timers) even though it resolves the same. */
  --font-ui: "Nexa", "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Nexa", "Jost", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
}

body {
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
}

button { font-family: inherit; }

::selection { background: var(--gold); color: #000; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- shell ---------- */

.app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  background:
    radial-gradient(120% 240px at 50% -40px, rgba(245, 197, 66, 0.10), transparent 70%),
    var(--bg);
  position: relative;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  min-height: calc(var(--topbar-h) + env(safe-area-inset-top));
  padding: calc(11px + env(safe-area-inset-top)) 18px 10px;
  background: linear-gradient(var(--bg) 68%, transparent);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Wallet balance — a pill on the right of the app bar; taps through to
   /deposit. Amount in white, a gold "+" segment as the deposit affordance. */
.balance {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 5px 5px 5px 13px;
  border-radius: 999px;
  background: var(--surface-hi);
  border: 1px solid var(--line);
  text-decoration: none;
  transition: transform 0.08s ease, border-color 0.15s ease;
}
.balance:active { transform: scale(0.96); }
.balance:hover { border-color: var(--line-gold); }

.balance-val {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.balance-add {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--gold-grad);
  color: #1a1400;
  font-size: 15px;
  font-weight: 800;
  line-height: 1;
}

.brand {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.brand-mark {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--gold);
}

.brand-mark b { color: var(--ink); font-weight: 800; }

.brand-sub {
  margin-top: 1px;
  font-size: 11px;
  color: var(--ink-mute);
  letter-spacing: 0.01em;
}

@media (max-width: 360px) {
  .brand-sub { display: none; }
}

/* ---------- live draw (full-screen takeover) ---------- */

.live {
  position: fixed;
  inset: 0;
  margin: 0 auto; /* centre within max-width — NOT transform: the fade-up
                     animation below sets `transform` and would clobber it */
  max-width: 480px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(88% 50% at 50% 20%, rgba(245, 197, 66, 0.13), transparent 70%),
    var(--bg);
  animation: fade-up 0.24s ease both;
}

.live-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(14px + env(safe-area-inset-top)) 18px 10px;
}

.live-tag {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.live-close {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-dim);
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.08s ease;
}
.live-close:active { transform: scale(0.92); }

.live-top-l {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.live-viewers {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-dim);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px 9px;
  font-variant-numeric: tabular-nums;
  animation: fade-up 0.2s ease both;
}
.live-viewers-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #35c26b;
  box-shadow: 0 0 0 3px rgba(53, 194, 107, 0.18);
  animation: live-pulse 1.8s ease-in-out infinite;
}
@keyframes live-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.live-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Plain `center` clips symmetrically once content overflows (you'd land
     scrolled to the middle, needing to scroll *up* to see the first card) —
     `safe` falls back to start-alignment instead, so overflow always scrolls
     naturally from the top. Only matters once bingo can show several full
     cartela cards, taller than one screen; the lottery countdown/reveal this
     screen was built for never overflowed. */
  justify-content: safe center;
  text-align: center;
  gap: 16px;
  padding: 0 32px calc(48px + env(safe-area-inset-bottom));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.live-ring {
  position: relative;
  width: 152px;
  height: 152px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: none;
}
/* Bingo's calling header needs to stay small and stable above a scrollable
   card list, unlike the lottery reveal this ring was built for (which is
   the only thing on screen) — same ring, smaller footprint. */
.live-ring.is-compact {
  width: 100px;
  height: 100px;
}
.live-ring.is-compact .live-ring-num { font-size: 20px; }
.live-ring::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 6%, var(--gold-bright) 40%, var(--gold) 54%, transparent 76% 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
}
.live-ring.is-idle::before {
  background: conic-gradient(from 0deg, rgba(245, 197, 66, 0.20), rgba(245, 197, 66, 0.05));
}
.live-ring.is-spinning::before { animation: spin 0.9s linear infinite; }
.live-ring.is-done::before {
  background: var(--gold);
  box-shadow: 0 0 34px rgba(245, 197, 66, 0.35);
}

.live-ring-num {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.is-spinning .live-ring-num { animation: flicker 0.5s ease-in-out infinite alternate; }
.is-done .live-ring-num {
  color: var(--ink);
  font-size: 34px;
  animation: reveal 0.35s ease both;
}

.live-emoji { font-size: 44px; }

.live-headline {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}
.live-headline.gold {
  color: var(--gold);
  text-shadow: 0 0 26px rgba(245, 197, 66, 0.3);
}

.live-sub {
  font-size: 14px;
  color: var(--ink-dim);
  max-width: 32ch;
}

.live-body .btn { width: auto; margin-top: 6px; padding: 12px 22px; }

/* Final winner(s) shown when the live link is opened after the draw ran. */
.live-final-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 320px;
  margin-top: 4px;
}
.live-final-row {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
}
.live-final-medal { font-size: 22px; line-height: 1; flex: none; }

/* Bingo's winner reveal only — the lottery's own `.live-final-row` (medal +
   text, side by side) is untouched; `:has()` scopes this to rows that also
   contain a mini cartela card, stacking them instead of squeezing the card
   next to the text. */
.live-final-row:has(.bingo-card) {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}
.live-final-row .bingo-card {
  max-width: 200px;
  margin: 0 auto;
}
.live-final-row .bingo-cell {
  font-size: 14px;
}
.live-final-row .bingo-cell.is-free {
  font-size: 16px;
}

.bingo-cell.is-winning-line {
  background: var(--gold-grad);
  border-color: var(--gold);
  color: #1a1400;
  box-shadow: 0 0 0 2px rgba(245, 197, 66, 0.5), 0 0 14px rgba(245, 197, 66, 0.55);
  animation: winning-cell-pulse 1s ease-in-out infinite;
}
@keyframes winning-cell-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}
.live-final-text { min-width: 0; }
.live-final-who {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-final-prize {
  font-size: 13px;
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- screens ---------- */

.screen {
  padding: 16px 16px calc(var(--tabbar-h) + 28px + env(safe-area-inset-bottom));
  /* No transform/animation here: it would become the containing block for
     the `position: fixed` live-draw screen and pull it off the viewport.
     Cards fade themselves in instead. */
}

/* Standalone screens (`/draws`, `/live/:id`) that render without the Shell. */
.page {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  background:
    radial-gradient(120% 200px at 50% -40px, rgba(245, 197, 66, 0.08), transparent 70%),
    var(--bg);
  padding: calc(16px + env(safe-area-inset-top)) 16px
    calc(28px + env(safe-area-inset-bottom));
}

.section-head {
  margin: 6px 4px 12px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.section-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 6px 2px 12px;
}
.section-row .section-head { margin: 0; }

.soon {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-bright);
  background: rgba(245, 197, 66, 0.12);
  border: 1px solid var(--line-gold);
  padding: 3px 7px;
  border-radius: 999px;
}

/* ---------- cards ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
}

/* ---------- draw card ---------- */

.draw {
  position: relative;
  margin-bottom: 10px;
  background: linear-gradient(180deg, var(--surface-hi), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  animation: fade-up 0.25s ease both;
}

.draw-bar {
  position: absolute;
  left: 0;
  top: 0;
  height: 2px;
  z-index: 1;
  background: var(--gold-grad);
  transition: width 0.5s ease;
}

.draw-body {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px 10px;
}

.draw-cta {
  display: flex;
  gap: 8px;
  padding: 0 12px 12px;
}
.draw-cta .btn { flex: 1; width: auto; }

/* Text/number field, used by the deposit screen. */
.input {
  display: block;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink);
  -webkit-text-fill-color: var(--ink); /* webkit ignores `color` on inputs otherwise */
  caret-color: var(--gold);
  font-family: inherit;
  font-size: 16px; /* >=16px stops iOS zooming in on focus */
  line-height: 1.2;
}
.input::placeholder { color: var(--ink-mute); -webkit-text-fill-color: var(--ink-mute); }
.input:focus { outline: none; border-color: var(--line-gold); }
.input--area { resize: vertical; min-height: 64px; line-height: 1.4; }

/* ---------- deposit screen ---------- */

.field-label {
  display: block;
  margin: 0 2px 7px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.field-hint {
  margin: 6px 2px 0;
  font-size: 11.5px;
  color: var(--ink-mute);
}

.amount-field { position: relative; }
.amount-input {
  padding-right: 52px;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.amount-cur {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-mute);
}

.chips-row { display: flex; gap: 8px; margin-top: 10px; }
.chip--tap {
  flex: 1;
  appearance: none;
  cursor: pointer;
  padding: 9px 0;
  border-radius: 8px;
  background: var(--surface-hi);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-family: inherit;
  font-weight: 700;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  transition: transform 0.08s ease, border-color 0.15s ease, color 0.15s ease;
}
.chip--tap:active {
  transform: scale(0.95);
  border-color: var(--line-gold);
  color: var(--gold-bright);
}

.seg {
  display: flex;
  gap: 4px;
  margin-bottom: 10px;
  padding: 4px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border: 1px solid var(--line);
}
.seg-btn {
  flex: 1;
  appearance: none;
  cursor: pointer;
  padding: 9px 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ink-mute);
  font-family: inherit;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
  transition: background 0.15s ease, color 0.15s ease;
}
.seg-btn.active { background: var(--surface-hi); color: var(--gold-bright); }
/* Bingo's stake picker only — a bolder, filled active state (matching the
   primary button treatment) rather than the plain highlight the shared
   `.seg-btn` uses for the profile/deposit/withdraw toggles. */
.stake-tabs .seg-btn.active {
  background: var(--gold-grad);
  color: #1a1400;
  box-shadow: 0 4px 14px rgba(245, 197, 66, 0.25);
}

.pay-card { padding: 4px 14px; }
.pay-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
}
.pay-row + .pay-row { border-top: 1px solid var(--line); }
.pay-text { min-width: 0; }
.pay-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.pay-value {
  margin-top: 2px;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
}

.form-error {
  margin: 12px 2px 0;
  font-size: 13px;
  color: var(--bad);
}
.submit-hint {
  margin: 8px 2px 0;
  font-size: 12px;
  color: var(--ink-mute);
  text-align: center;
}

.draw-img {
  flex: none;
  width: 66px;
  height: 66px;
  border-radius: 10px;
  object-fit: cover;
  background: linear-gradient(135deg, #2a2411, #15140f);
  border: 1px solid var(--line-gold);
}
.draw-img.is-empty {
  display: grid;
  place-items: center;
  font-size: 26px;
}

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

.draw-prize {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--gold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.draw-name {
  margin-top: 1px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.draw-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }

/* Ranked-prize tiers get their own full-width strip under the card body, so
   all three medals are visible at once — the info column above is too narrow
   to hold them without a hidden sideways scroll. Wraps to a second line only
   for very large amounts. */
.draw-ranks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: -1px;
  padding: 0 12px 11px;
}
.chip--rank {
  background: rgba(245, 197, 66, 0.08);
  border-color: var(--line-gold);
  color: var(--gold-bright);
}

.chip {
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.draw-timer {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 7px 9px;
  border-radius: 8px;
  background: var(--bg-2);
  border: 1px solid var(--line);
}
.draw-timer-val {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.draw-timer-lbl {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.see-all {
  flex: none;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--gold-bright);
  text-decoration: none;
  white-space: nowrap;
}
.see-all:active { opacity: 0.6; }

/* ---------- buy button spinner ---------- */

.spinner {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-right: 7px;
  vertical-align: -2px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

/* ---------- my tickets ---------- */

/* Row reuses the `.draw` shell but is a whole-card link. */
a.ticket-row {
  display: block;
  color: inherit;
  text-decoration: none;
}
a.ticket-row:active { transform: scale(0.985); }

/* The tappable body of a draw card (Play / Draws) — opens `/draws/:id`.
   The Buy / Watch-live row sits outside this link. */
.draw-tap {
  display: block;
  color: inherit;
  text-decoration: none;
}
.draw-tap:active { opacity: 0.82; }

.ticket-desc {
  margin: 12px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-dim);
}

.status-pill {
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
  border: 1px solid var(--line);
  color: var(--ink-dim);
  background: var(--bg-2);
}
.status-pill.is-open {
  color: var(--gold-bright);
  border-color: var(--line-gold);
  background: rgba(245, 197, 66, 0.08);
}
.status-pill.is-drawing {
  color: var(--gold-bright);
  border-color: var(--line-gold);
  background: rgba(245, 197, 66, 0.08);
  animation: pulse 1.4s ease-in-out infinite;
}
.status-pill.is-won {
  color: #7ee2a8;
  border-color: rgba(126, 226, 168, 0.3);
  background: rgba(126, 226, 168, 0.1);
}
.status-pill.is-muted { color: var(--ink-mute); }

/* Detail screen */
.ticket-detail { animation: fade-up 0.24s ease both; }

.ticket-hero {
  width: 100%;
  height: 200px;
  /* Show the whole prize image, not a cropped slice — letterbox against
     the gradient rather than filling the box. */
  object-fit: contain;
  padding: 6px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-gold);
  background: linear-gradient(135deg, #2a2411, #15140f);
}
.ticket-hero.is-empty {
  display: grid;
  place-items: center;
  font-size: 44px;
}

.ticket-detail-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  margin-top: 14px;
}
.ticket-detail-head .draw-prize { font-size: 18px; white-space: normal; }
.ticket-detail-head .status-pill { margin-top: 6px; }

.ticket-detail-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-top: 16px;
  padding: 14px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
}
.ticket-detail-grid .pstat-num { font-size: 15px; }

.ticket-numbers { flex-wrap: wrap; margin-top: 10px; }

.ticket-sub {
  margin-top: 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}

.ticket-actions {
  display: flex;
  gap: 8px;
  margin-top: 20px;
}
.ticket-actions > * { flex: 1; width: auto; }
.ticket-actions .btn {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------- pick-your-own number board ---------- */

.num-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
  gap: 6px;
}
.num-grid.is-loading { display: none; }

/* Bingo's card-picker board only — the lottery's own use of `.num-grid`
   (`components/number_board.rs`) doesn't wrap it in this, so that board's
   scroll behavior is unchanged. Caps the grid to its own scroll region so
   the stake tabs/countdown above and the buy footer below stay in place
   instead of scrolling away with a long card list. */
.card-grid-scroll {
  max-height: 46vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 -2px;
  padding: 2px;
}
/* `repeat(auto-fill, minmax(38px, 1fr))` needs a definite container width to
   compute a stable column count — inside this scrollable wrapper that came
   out ambiguous and collapsed to very few columns, which then stretched to
   fill the row. A fixed column count sidesteps that regardless of cause. */
.card-grid-scroll .num-grid {
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
}

/* Bingo's card-picker cells only — round, with real depth (gradient +
   shadow), echoing the "ball" chips on the calling screen instead of the
   flat bordered squares the lottery's number board uses. */
.card-grid-scroll .num-cell {
  /* Fixed, capped size instead of stretching to fill its `1fr` grid
     column — centered within the column so 5 columns still lay out evenly,
     just without each ball ballooning to the column's full width. */
  width: 100%;
  max-width: 46px;
  margin: 0 auto;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--surface-hi), var(--bg-2));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 3px 8px rgba(0, 0, 0, 0.3);
  font-size: 13px;
}
.card-grid-scroll .num-cell.is-selected {
  background: var(--gold-grad);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 4px 16px rgba(245, 197, 66, 0.35);
}
.card-grid-scroll .num-cell.is-mine {
  background: rgba(245, 197, 66, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.num-cell {
  appearance: none;
  aspect-ratio: 1;
  min-width: 0;
  padding: 0;
  border-radius: 8px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-family: inherit;
  font-weight: 700;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: transform 0.06s, background 0.12s, border-color 0.12s;
}
.num-cell:active { transform: scale(0.9); }

.num-cell.is-selected {
  background: var(--gold-grad);
  border-color: var(--gold);
  color: #1a1400;
}
.num-cell.is-taken {
  border-color: transparent;
  color: var(--ink);
  font-weight: 800;
  cursor: not-allowed;
}
/* A small palette taken cells cycle through by card number, so a filling
   board reads as colorful and lively rather than a wall of greyed-out
   cells. */
.num-cell.is-taken.c0 { background: rgba(255, 107, 107, 0.26); box-shadow: inset 0 0 0 1px rgba(255, 107, 107, 0.45); }
.num-cell.is-taken.c1 { background: rgba(34, 211, 238, 0.24); box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.45); }
.num-cell.is-taken.c2 { background: rgba(167, 139, 250, 0.26); box-shadow: inset 0 0 0 1px rgba(167, 139, 250, 0.45); }
.num-cell.is-taken.c3 { background: rgba(74, 222, 128, 0.24); box-shadow: inset 0 0 0 1px rgba(74, 222, 128, 0.45); }
.num-cell.is-taken.c4 { background: rgba(244, 114, 182, 0.26); box-shadow: inset 0 0 0 1px rgba(244, 114, 182, 0.45); }
.num-cell.is-mine {
  background: rgba(245, 197, 66, 0.12);
  border-color: var(--line-gold);
  color: var(--gold-bright);
  cursor: default;
}

.num-foot {
  position: sticky;
  bottom: 0;
  display: flex;
  gap: 8px;
  margin-top: 14px;
  padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--bg) 72%, transparent);
}
.num-foot .btn { display: flex; align-items: center; justify-content: center; }

/* ---------- bingo: lobby table-status panel ---------- */

.table-status {
  /* `.page` is plain block flow, so this gets full width for free — no
     max-width cap here, unlike the game screen's elements below (which sit
     inside `.live-body`'s narrower, padded flex column and genuinely need
     one to avoid overflowing it). */
  width: 100%;
  box-sizing: border-box;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
  padding: 14px 16px;
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(245, 197, 66, 0.10), transparent 60%),
    linear-gradient(180deg, var(--surface-hi), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.table-status-timer {
  /* Was `flex: none` with a `nowrap` label — the label's full text forced
     this column wider than it needed to be, pushing the row past the
     screen edge with nothing able to shrink to compensate. Letting the
     label wrap removes that forced minimum. */
  flex: none;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding-right: 14px;
  border-right: 1px solid var(--line);
}
.table-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 0 3px rgba(245, 197, 66, 0.18);
  animation: live-pulse 1.8s ease-in-out infinite;
}
.table-status-timer-val {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.table-status-timer-lbl {
  max-width: 72px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-mute);
}

.table-status-stats {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  gap: 8px;
}

.table-stat {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}
.table-stat-val {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.table-stat-lbl {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.table-stat-divider {
  width: 1px;
  align-self: stretch;
  background: var(--line);
}

/* ---------- bingo: game screen info row ---------- */
/* Plain, no card/border — just the prize pool on the left and the
   auto-daub reminder on the right, flanking the calling ring above. */
.game-info-row {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.game-info-money {
  min-width: 0;
  font-weight: 800;
  font-size: 14px;
  color: var(--gold-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.game-info-auto {
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- bingo: ball history + cartela card ---------- */

.ball-strip {
  /* `.live-body` is a flex column with `align-items: center`, so without an
     explicit width this (and every other bingo element below) would
     shrink-wrap to its own content instead of using the available screen
     width — the root cause of the cartela grid looking cramped/misaligned. */
  width: 100%;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 4px 2px 12px;
  scrollbar-width: none;
}
.ball-strip::-webkit-scrollbar { display: none; }

.ball {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink-dim);
}
.ball.is-latest {
  background: var(--gold-grad);
  border-color: var(--gold);
  color: #1a1400;
  box-shadow: 0 0 0 3px rgba(245, 197, 66, 0.15);
}

/* A player's cartela cards: 3 per row (a leftover 1 or 2 center themselves
   alone on the last row via `justify-content: center` on a wrapping flex
   container), each a small self-contained card with its own label. */
.bingo-cards {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  flex: none;
  justify-content: center;
  align-content: flex-start;
  gap: 8px;
  margin-top: 4px;
  /* Its own scroll region, capped well short of the viewport, so the
     calling header above (ring + ball history) always stays put instead of
     the whole screen scrolling past it to reach the cards. */
  max-height: 38vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 6px;
}

.bingo-card {
  flex: 0 1 112px;
  max-width: 112px;
  padding: 7px;
  background: linear-gradient(180deg, var(--surface-hi), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}

/* A made-up card shown to a viewer who didn't buy one this round, so they
   have something to follow along with instead of an empty area. */
.bingo-card.is-inspecting {
  border-style: dashed;
  opacity: 0.72;
}

.bingo-card-label {
  margin: 0 0 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-mute);
}

.bingo-head {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;
  margin-bottom: 3px;
}
.bingo-head span {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 8px;
  letter-spacing: 0.03em;
  color: var(--gold-bright);
}

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

.bingo-cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-weight: 700;
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.bingo-cell.is-free {
  color: var(--gold-bright);
  border-color: var(--line-gold);
  font-size: 11px;
}
.bingo-cell.is-marked {
  background: var(--gold-grad);
  border-color: var(--gold);
  color: #1a1400;
  transform: scale(1.04);
}

/* ---------- game placeholders ---------- */

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

.game {
  display: block;
  padding: 15px 14px 16px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  opacity: 0.82;
  transition: transform 0.08s ease, opacity 0.15s ease, border-color 0.15s ease;
}
.game:active { transform: scale(0.97); }
.game:hover { opacity: 1; border-color: var(--line-gold); }
.game-emoji { font-size: 23px; filter: grayscale(0.4); }
.game-name {
  font-family: var(--font-display);
  margin-top: 8px;
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
}
.game-soon {
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* ---------- sub-page header ---------- */

.screen-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 2px 2px 14px;
}
.screen-head span {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.back {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--gold-bright);
  font-size: 17px;
  line-height: 1;
  text-decoration: none;
}
.back:active { transform: scale(0.92); }

/* ---------- buttons ---------- */

.btn {
  appearance: none;
  display: block;
  border: 0;
  border-radius: var(--r-md);
  padding: 13px 16px;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease, opacity 0.15s ease;
  width: 100%;
}

.btn:active { transform: scale(0.978); }
.btn:disabled { opacity: 0.55; cursor: default; }

.btn--primary {
  background: var(--gold-grad);
  color: #1a1400;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 8px 20px rgba(245, 197, 66, 0.18);
}
.btn--primary:active { filter: brightness(0.96); }

.btn--ghost {
  background: transparent;
  color: var(--gold-bright);
  border: 1px solid var(--line-gold);
}
.btn--ghost:active { background: rgba(245, 197, 66, 0.08); }

.btn--sm { padding: 10px 12px; font-size: 13px; }

/* ---------- empty / skeleton ---------- */

.empty {
  text-align: center;
  padding: 56px 24px;
  animation: fade-up 0.3s ease both;
}
.empty-emoji { font-size: 34px; }
.empty-title {
  font-family: var(--font-display);
  margin-top: 10px;
  font-weight: 700;
  font-size: 16px;
  color: var(--ink);
  text-wrap: balance;
}
.empty-badge { margin-top: 10px; }
.empty-sub { margin-top: 10px; font-size: 13.5px; color: var(--ink-mute); }

/* ---------- open-in-Telegram gate (shown outside Telegram) ---------- */

.tg-gate {
  min-height: 100vh;
  max-width: 480px;
  margin: 0 auto;
  padding: 40px 32px calc(40px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background:
    radial-gradient(120% 260px at 50% -20px, rgba(245, 197, 66, 0.12), transparent 70%),
    var(--bg);
  animation: fade-in 0.3s ease both;
}
.tg-gate-mark {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 12px;
  color: var(--gold);
  margin-bottom: 26px;
}
.tg-gate-emoji { font-size: 42px; }
.tg-gate-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 21px;
  color: var(--ink);
  margin: 16px 0 10px;
  text-wrap: balance;
}
.tg-gate-sub {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--ink-dim);
  max-width: 32ch;
}

.sk-card {
  height: 190px;
  border-radius: var(--r-lg);
  margin-bottom: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}
.sk-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.05) 45%, transparent 70%);
  animation: shimmer 1.4s infinite;
}

/* ---------- toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 40;
  max-width: 420px;
  width: calc(100% - 40px);
  padding: 12px 16px;
  border-radius: var(--r-md);
  background: var(--surface-hi);
  border: 1px solid var(--line-gold);
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  text-align: center;
  box-shadow: var(--shadow);
  animation: pop 0.24s ease both;
}

/* ---------- winners ---------- */

.winner {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 11px 12px;
  margin-bottom: 8px;
  animation: fade-up 0.3s ease both;
}

.winner-trust {
  margin: -2px 4px 14px;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-dim);
  background: var(--surface);
  border: 1px solid var(--line-gold);
  border-radius: var(--r-md);
}
.winner-trust b { color: var(--ink); font-weight: 600; }

.winner-media {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: var(--surface-hi);
  border: 1px solid var(--line-gold);
}
.winner-media.is-placeholder {
  display: grid;
  place-items: center;
  font-size: 20px;
}

.winner-text { flex: 1; min-width: 0; }

.winner-proof-btn {
  flex: none;
  width: auto;
  padding: 8px 12px;
  font-size: 12px;
}

.winner-name {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--gold);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.winner-prize {
  font-size: 13px;
  color: var(--ink-dim);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.winner-meta {
  font-size: 11.5px;
  color: var(--ink-mute);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
}

/* ---------- proof bottom sheet ---------- */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(2px);
  animation: fade-in 0.2s ease both;
}

.sheet {
  width: 100%;
  max-width: 480px;
  max-height: 78vh;
  overflow-y: auto;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -20px 50px rgba(0, 0, 0, 0.5);
  padding-bottom: env(safe-area-inset-bottom);
  animation: sheet-up 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.sheet-handle {
  width: 36px;
  height: 4px;
  margin: 10px auto 4px;
  border-radius: 999px;
  background: var(--line);
}

.sheet-img {
  display: block;
  width: calc(100% - 32px);
  height: 220px; /* fixed frame — the photo is letterboxed, sheet stays compact */
  margin: 8px 16px 0;
  border-radius: var(--r-md);
  border: 1px solid var(--line-gold);
  object-fit: contain;
  background: #000;
}

.sheet-body { padding: 14px 16px 10px; }
.sheet-name {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.sheet-prize {
  margin-top: 3px;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--gold);
}
.sheet-meta {
  margin-top: 6px;
  font-size: 12px;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}
.sheet-close { width: auto; margin: 2px 16px 16px; }

/* ---------- profile ---------- */

.profile-id-row { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.profile-avatar {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--gold-grad);
  color: #1a1400;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 19px;
}
.profile-id { min-width: 0; }
.profile-name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.profile-handle { margin-top: 1px; font-size: 12.5px; color: var(--ink-dim); }

/* wallet block — the one focal point */
.wallet { padding: 18px; }
.wallet-lbl {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.wallet-bal {
  margin-top: 4px;
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.wallet-bonus {
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}
.wallet-actions {
  display: flex;
  gap: 8px;
  margin-top: 16px;
}
.wallet-actions .btn { flex: 1; width: auto; }

/* ---------- transaction rows ---------- */

.muted-line { margin: 2px 2px 0; font-size: 12.5px; color: var(--ink-mute); }

.tx-list { padding: 4px 14px; }

.tx-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
}
.tx-row + .tx-row { border-top: 1px solid var(--line); }

.tx-icon {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--surface-hi);
  font-size: 15px;
}
.tx-main { flex: 1; min-width: 0; }
.tx-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}
.tx-tag {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-mute);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 1px 5px;
}
.tx-time { margin-top: 2px; font-size: 11.5px; color: var(--ink-mute); }
.tx-amt {
  flex: none;
  font-size: 13.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
}
.tx-amt.is-in { color: var(--good); }
.tx-amt.is-out { color: var(--ink-dim); }

/* ---------- invite ---------- */

.invite { padding: 18px; }

.invite-lead { font-size: 13.5px; color: var(--ink-dim); margin: 0 0 14px; }

.ref-row { display: flex; gap: 8px; }

.ref-row input {
  flex: 1;
  min-width: 0;
  padding: 11px 12px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 13px;
}

.ref-row .btn { width: auto; padding: 11px 18px; }

.earned {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: rgba(245, 197, 66, 0.10);
  border: 1px solid var(--line-gold);
}
.earned-num {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.earned-lbl {
  margin-top: 1px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.promos { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.promos li {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border-left: 3px solid var(--gold);
  font-size: 13px;
  color: var(--ink-dim);
}

/* ---------- tab bar ---------- */

.tabbar {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  z-index: 30;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: rgba(12, 12, 15, 0.9);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}

.tabbar a {
  color: var(--ink-mute);
  height: var(--tabbar-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: color 0.15s ease;
  position: relative;
}

/* Line icons (inline SVG, `stroke: currentColor`) — they take the tab's
   colour, so muted grey when inactive and gold when active, on theme. */
.tabbar a .ico { display: flex; }
.tabbar a .ico svg {
  width: 22px;
  height: 22px;
  display: block;
}

.tabbar a.active { color: var(--gold); }
.tabbar a.active::before {
  content: "";
  position: absolute;
  top: 0;
  width: 24px;
  height: 2px;
  border-radius: 0 0 3px 3px;
  background: var(--gold);
}

/* ---------- keyframes ---------- */

@keyframes fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes pop {
  from { opacity: 0; transform: translate(-50%, 8px) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
@keyframes shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(245, 197, 66, 0.55); }
  70%  { box-shadow: 0 0 0 9px rgba(245, 197, 66, 0); }
  100% { box-shadow: 0 0 0 0 rgba(245, 197, 66, 0); }
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes flicker { from { opacity: 0.35; } to { opacity: 1; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes reveal {
  from { opacity: 0; transform: scale(0.7); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
