/* 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;
}
/* Bingo's card(s) can grow taller than the lottery content this shell was
   built for (`.live-body`'s default centering + `safe` fallback isn't
   reliably enough clearance in every WebView) — pin it to the top instead
   of centering, so a big "inspecting" card never crowds the ball-strip
   (recent calls) above it regardless of viewport height. */
.live-body--bingo {
  justify-content: flex-start;
  padding-top: 14px;
}

.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 {
  /* Without this, a flex item shrinks by default — once the bingo screen's
     cards (`.bingo-cards`, `flex: none`, so it never shrinks) grow tall
     enough that everything no longer fits `.live-body`'s height, flexbox
     squeezes whichever siblings *aren't* protected instead of just letting
     `.live-body`'s own `overflow-y: auto` scroll — clipping this and the
     ball-strip/info-row below to near-nothing rather than shrinking the
     cards. */
  flex: none;
  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;
}

/* A small thumbnail, the title, and the countdown chip in one compact row
   — see the comment in `draw_card.rs` (and `tickets.rs`, which shares this
   layout) on why the image isn't a whole row of its own any more: on a
   phone-width list, that extra row per card added up fast. */
.draw-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 0;
}

.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;
}
.pay-holder {
  margin-top: 4px;
  font-size: 12px;
  color: var(--ink-mute);
}

.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: 38px;
  height: 38px;
  border-radius: 8px;
  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: 16px;
}

.draw-info { padding: 6px 12px 10px; }

/* Shared base for both this list card and `draw_detail.rs`'s hero overlay
   (`.ticket-hero-overlay .draw-prize`/`.draw-name`, which uses these as-is:
   prize prominent, name a small muted caption below it — don't restyle
   these bare classes for the list card's own, different hierarchy below;
   scope to `.draw-head`/`.draw-info` instead so the detail screen doesn't
   silently inherit it too). */
.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;
}

/* The list card's title, in `.draw-head` — full card width (minus the
   small thumbnail and timer chip either side of it), not squeezed the way
   it used to be alongside a much bigger image, so a title long enough to
   need 2 lines actually gets them instead of an ellipsis moved down a
   line. Promoted to the real headline here (`.draw-info .draw-prize` below
   becomes the supporting line, unlike the shared base above). */
.draw-head .draw-name {
  flex: 1;
  min-width: 0;
  margin-top: 0;
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.25;
  text-transform: none;
  color: var(--ink);
  white-space: normal;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

/* Demoted to a supporting line under the title above it (see `.draw-head
   .draw-name`) — often a full marketing sentence (e.g. "Buy a ticket for a
   chance to win an iPhone"), so it keeps the shared base's single-line
   truncation rather than fighting for the height a 2-line clamp would cost. */
.draw-info .draw-prize {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--gold-bright);
}

.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 — the back arrow, prize/timer/watch-live all live on top of
   the hero image (a compact scrim overlay) instead of their own rows, so
   only the fixed strip below it (description/your-numbers/sold-count) and
   then the ticket-number grid share the rest of the screen. Only the grid
   area (`.ticket-detail-scroll`) scrolls — everything above it is pinned,
   so picking numbers never loses the header off the top of a short phone
   screen. */
.ticket-detail-page {
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0;
}

.ticket-detail {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  animation: fade-up 0.24s ease both;
}

.ticket-hero-wrap {
  position: relative;
  flex: none;
  /* `.ticket-detail-page` zeroes out `.page`'s side padding for this whole
     screen (so this bleeds edge-to-edge); `.ticket-detail-fixed`/
     `.ticket-detail-scroll` add their own 16px side padding back for
     everything below the image. */
}
.ticket-hero-wrap .ticket-hero {
  width: 100%;
  height: 190px;
  object-fit: cover;
  padding: 0;
  border: none;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  /* Fallback fill behind a slow-loading or transparent image — without
     this the hero is just page-colored blank space until the image
     paints, which reads as broken rather than loading. */
  background: linear-gradient(160deg, #241f0e 0%, #15140f 70%);
}
.ticket-hero-wrap .ticket-hero.is-empty {
  height: 190px;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  display: grid;
  place-items: center;
  font-size: 46px;
  color: var(--gold-bright);
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(245, 197, 66, 0.18), transparent 60%),
    linear-gradient(160deg, #241f0e 0%, #15140f 70%);
}

.back.ticket-hero-back {
  position: absolute;
  top: calc(10px + env(safe-area-inset-top));
  left: 12px;
  z-index: 2;
  background: rgba(10, 9, 6, 0.55);
  border-color: rgba(245, 197, 66, 0.3);
  backdrop-filter: blur(6px);
}

.ticket-hero-overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 30px 14px 10px;
  background: linear-gradient(to top, rgba(6, 5, 3, 0.94), rgba(6, 5, 3, 0.6) 65%, transparent);
}
.ticket-hero-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ticket-hero-overlay .draw-prize { font-size: 16px; }
.ticket-hero-overlay .draw-name { margin-top: 2px; }

.ticket-hero-stats {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
}
.ticket-hero-stat {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-variant-numeric: tabular-nums;
}
.ticket-hero-stat b { font-size: 13px; font-weight: 800; line-height: 1.1; color: var(--ink); }
.ticket-hero-stat small {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.ticket-hero-stats .btn { margin-left: auto; }

/* Bottom safe-area padding here (not on `.ticket-detail-page`, which is
   zeroed for the hero's edge-to-edge bleed) covers the uncapped-draw case,
   where this is the last thing on screen — a numbered draw's own bottom
   inset comes from `.num-foot` inside the scroll area instead. */
.ticket-detail-fixed { flex: none; padding: 12px 16px calc(10px + env(safe-area-inset-bottom)); }

.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;
}

/* Only this area scrolls (the pick-your-own grid, when the draw has one) —
   everything in `.ticket-hero-wrap`/`.ticket-detail-fixed` above stays put. */
.ticket-detail-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 16px;
}

/* ---------- 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: 0;
  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 {
  /* An equal, stable share of `.table-status-stats`'s width — not sized off
     its own content, so the winning stack's text growing as the pot does
     (e.g. "0.00 ETB" -> "5000.00 ETB") never reflows/resizes this box or
     anything sharing the row (which under bingo's rapid buy-in pace read as
     the stat "shaking" rather than a smooth count-up). A fixed pixel width
     did this too but had to be guessed against a screen width, which is how
     this used to overflow the card on narrower phones — `flex: 1` derives
     it from the actual available space instead. */
  flex: 1;
  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;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
}
/* The "ETB" next to the winning-stack figure — same idea as a currency
   symbol riding smaller/dimmer beside the number rather than spelled out at
   full size, so a long amount stays readable without the unit crowding it. */
.table-stat-unit {
  margin-left: 2px;
  font-size: 10px;
  font-weight: 700;
  color: var(--ink-mute);
}
.table-stat-lbl {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  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 {
  flex: none; /* see `.live-headline`'s comment — don't let this get squeezed */
  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;
}
/* An iOS-style toggle switch (label + sliding track/knob) rather than a
   text button — used for bingo's auto-daub preference, both here and on the
   lobby's "Your cards" row. */
.switch {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}
.switch-label {
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color 0.12s ease;
}
.switch.is-on .switch-label { color: var(--gold-bright); }
.switch-track {
  flex: none;
  position: relative;
  width: 32px;
  height: 19px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.switch.is-on .switch-track {
  background: var(--gold-grad);
  border-color: var(--gold);
}
.switch-knob {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--ink-dim);
  transition: transform 0.15s ease, background 0.15s ease;
}
.switch.is-on .switch-knob {
  transform: translateX(13px);
  background: #1a1400;
}
.switch:active .switch-knob { transform: scale(0.9); }
.switch.is-on:active .switch-knob { transform: translateX(13px) scale(0.9); }

/* ---------- 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.
     `flex: none` for the same reason `.live-headline` has it — otherwise
     this is what gets vertically squeezed down to a sliver (clipping the
     ball circles) once a big card below it needs more room than fits. */
  flex: none;
  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);
}

/* Fewer cards held means more room per card — a lone card gets a big,
   easy-to-read layout; a full 5-card hand keeps the original compact size
   (the un-modified `.bingo-card` rule above, no size-5plus override
   needed). */
.bingo-cards.size-2 .bingo-card { flex-basis: 168px; max-width: 168px; padding: 10px; }
.bingo-cards.size-2 .bingo-card-label { font-size: 11px; }
.bingo-cards.size-2 .bingo-head span { font-size: 10px; }
.bingo-cards.size-2 .bingo-cell { font-size: 13px; }

.bingo-cards.size-3-4 .bingo-card { flex-basis: 128px; max-width: 128px; padding: 8px; }
.bingo-cards.size-3-4 .bingo-cell { font-size: 10px; }

/* The large single-card layout needs more clearance from the ball-strip
   (recent calls) above it than the default `.bingo-cards` margin-top gives
   — otherwise a big card visually crowds/covers the row of called numbers
   right above it. */
.bingo-cards.size-1 { margin-top: 22px; }
.bingo-cards.size-1 .bingo-card { flex-basis: 240px; max-width: 240px; padding: 14px; }
.bingo-cards.size-1 .bingo-card-label { font-size: 13px; margin-bottom: 8px; }
.bingo-cards.size-1 .bingo-head span { font-size: 13px; }
.bingo-cards.size-1 .bingo-grid { gap: 4px; }
.bingo-cards.size-1 .bingo-cell { font-size: 20px; border-radius: 6px; }

/* ---------- bingo lobby: "your cards" preview strip ---------- */

/* Same horizontal-scroll recipe as `.ball-strip` (recent calls, on the live
   game screen) — a row of fixed-size items that scrolls instead of wrapping,
   scrollbar hidden since the row itself is the affordance. */
.my-cards-strip {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  overflow-x: auto;
  padding: 2px 2px 6px;
  scrollbar-width: none;
}
.my-cards-strip::-webkit-scrollbar { display: none; }
.my-cards-strip .bingo-card { flex: none; width: 72px; max-width: none; padding: 5px; }
.my-cards-strip .bingo-card-label { font-size: 8px; margin-bottom: 2px; }
.my-cards-strip .bingo-head { gap: 1px; margin-bottom: 2px; }
.my-cards-strip .bingo-head span { font-size: 6px; }
.my-cards-strip .bingo-grid { gap: 1px; }
.my-cards-strip .bingo-cell { font-size: 8px; border-radius: 3px; }

/* A viewer with no cartela this round gets this instead of a fake card to
   follow along with (see `bingo_game.rs`'s comment on why one isn't shown)
   — a dashed placeholder-style card of its own, the same "not the real
   thing" cue the removed fake card used to carry with its dashed border. */
.inspecting-state {
  width: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 22px;
  padding: 26px 20px;
  border: 1px dashed var(--line-gold);
  border-radius: var(--r-lg);
  background: radial-gradient(120% 140% at 50% 0%, rgba(245, 197, 66, 0.08), transparent 65%);
  animation: fade-up 0.24s ease both;
}
.inspecting-emoji {
  font-size: 34px;
  animation: inspecting-peek 2.4s ease-in-out infinite;
}
@keyframes inspecting-peek {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-4px) rotate(-6deg); }
}
.inspecting-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 800;
  color: var(--gold-bright);
}
.inspecting-note {
  width: 100%;
  max-width: 30ch;
  text-align: center;
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-dim);
}

.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 {
  /* Reset for the live grid's cells, which are `<button>`s (so a manual
     daub tap — auto-daub off — has something to click); the post-game
     winner reveal's cells reuse this same class on plain `<span>`s, where
     these just have no effect. */
  appearance: none;
  font-family: inherit;
  margin: 0;
  padding: 0;
  cursor: default;
  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;
}
button.bingo-cell:not(:disabled) {
  cursor: pointer;
}
button.bingo-cell:not(:disabled):active {
  transform: scale(0.92);
}
.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;
}
/* The bingo lobby's stake picker rides this row instead of a full-width
   segmented bar below it — a few short tabs don't need their own row. */
.screen-head .stake-tabs {
  margin-left: auto;
  margin-bottom: 0;
  padding: 3px;
}
.screen-head .stake-tabs .seg-btn {
  flex: none;
  padding: 6px 10px;
  font-size: 11px;
}
.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; }
.btn--xs {
  display: inline-flex;
  align-items: center;
  width: auto;
  padding: 6px 10px;
  font-size: 11px;
  border-radius: 8px;
}

/* ---------- 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; }
}
