/* =============================================================================
   Voxbet mini-app design tokens — ONE source of truth for all ten surfaces.
   Loaded before every page's own stylesheet, which keeps its layout rules and
   drops its `:root` block.
   =============================================================================

   Why this file exists
   --------------------
   Each mini-app used to declare its own palette: ten `:root` blocks, six
   dark-first and four light-first, so the suite was visibly two products — a
   punter going sportsbook (light) → slip (light) → race card (dark) watched the
   app change identity mid-flow. Nine copies of `applyTheme` themed either five
   or six tokens, and NONE of them themed `--line`, so a dark Telegram theme drew
   every border in near-white.

   The two rules that stop it recurring
   ------------------------------------
   1. JavaScript owns as little as possible. `theme.js` sets FOUR substrate
      tokens (bg / card / text / muted) from Telegram. Everything else is
      derived from those in CSS, so a token can never be "the one somebody forgot
      to theme".
   2. Anything structural is a mix of the text colour, never a fixed grey. A
      border derived from `--text` follows the theme for free.

   ACCENT vs LINK — the distinction that was getting things wrong
   --------------------------------------------------------------
   `--accent` is a FILL. It is the colour you put BEHIND something, with
   `--accent-text` on top: a primary button, the picked selection, the active
   tab's underline. It is Voxbet blue and it is deliberately NOT taken from the
   user's Telegram theme — it is the one thing that makes every surface
   recognisably the same product. That is what "branded" buys you.

   `--link` is TEXT. It is the accent used as ink — a "See all ›" link, a Back
   button's label. You cannot use `--accent` for this: a fill colour has no
   guarantee of contrasting with the page background (Telegram's `button_color`
   is defined only against `button_text_color`), which is how `.back` and `.more`
   ended up at 2.4:1 against a 4.5:1 requirement. `--link` mixes the brand hue
   with the CURRENT text colour, so it darkens on a light theme and lightens on a
   dark one, automatically, and keeps the brand hue dominant either way.

   Rule of thumb: background → `--accent`. Letters → `--link`.

   Changing the brand colour: edit `--accent` below and nothing else. Keep
   white-on-accent at or above 4.5:1 (the current value measures 4.55:1).
*/

:root {
  /* ---- Brand. Fixed across every theme — this is the identity. ---- */
  --accent: #2f6fed;
  --accent-text: #ffffff;
  /* The accent as INK. Mixed with --text so it tracks the theme's polarity.
     Measures 7.09:1 on the light fallback and 6.28:1 on the dark one. */
  --link: color-mix(in srgb, var(--accent) 70%, var(--text) 30%);

  /* ---- Substrate. These four are what theme.js overwrites from Telegram. ---- */
  --bg: #ffffff;
  --card: #f4f5f7;
  --text: #12161c;
  --muted: #5f6773; /* 5.24:1 on --card (the old #8a8f98 measured 2.98:1) */

  /* ---- Derived. Never set these directly; they follow the substrate. ---- */
  --card-2: color-mix(in srgb, var(--text) 7%, var(--card));
  --line: color-mix(in srgb, var(--text) 14%, transparent);
  --line-strong: color-mix(in srgb, var(--text) 26%, transparent);
  --tint: color-mix(in srgb, var(--accent) 14%, transparent);

  /* ---- Semantic. Meaning, not brand — these do flip with polarity. ---- */
  --pos: #157f43;
  --neg: #c0293c;
  --warn: #8a5a00;
  --hot: #9a5b0a;

  /* ---- Compatibility aliases for names the pages already use. ---- */
  --panel: var(--card);
  --panel-2: var(--card-2);
  --accent-2: var(--pos);
  --ok: var(--pos);
  --bad: var(--neg);
  --danger: var(--neg);
  --border: var(--line);

  color-scheme: light dark;
}

/* Dark substrate + semantics.
   Declared twice on purpose: `prefers-color-scheme` covers a webview that
   forwards the system scheme, and `[data-theme]` covers the case it doesn't —
   theme.js stamps that attribute after measuring Telegram's actual background,
   which is the only thing guaranteed to be right. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0f1216;
    --card: #171b21;
    --text: #e8eaed;
    --muted: #8b93a1; /* 5.58:1 on --card */
    --pos: #4ade80;
    --neg: #ff7583;
    --warn: #f0b429;
    --hot: #f59e0b;
  }
}
:root[data-theme="dark"] {
  --bg: #0f1216;
  --card: #171b21;
  --text: #e8eaed;
  --muted: #8b93a1;
  --pos: #4ade80;
  --neg: #ff7583;
  --warn: #f0b429;
  --hot: #f59e0b;
}

/* ---- Shared primitives, so ten pages stop re-deriving them ---- */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font:
    15px / 1.45 -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    sans-serif;
}

/* ≥16px on any focusable text field stops iOS zooming the whole page on focus.
   Applied to every input, not just the ones somebody remembered — `select` does
   it too, which is how the admin console's heat picker slipped through. */
input,
select,
textarea,
button {
  font-family: inherit;
}
@media (max-width: 900px) {
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  textarea {
    font-size: 16px;
  }
}

.muted {
  color: var(--muted);
}

/* =============================================================================
   `hidden` MUST ACTUALLY HIDE.

   The `hidden` attribute is styled only by the UA stylesheet's
   `[hidden] { display: none }`, and EVERY author rule beats a UA rule regardless
   of specificity. So any element carrying both `hidden` and a class that sets
   `display` is permanently visible, and the JavaScript that sets `el.hidden` is
   silently doing nothing.

   Live on 2026-08-25: the FPL card's `.badge { display: inline-block }` meant the
   red LIVE badge showed on a gameweek where every match had finished — while the
   panel directly beneath it correctly said "your players' matches are all
   finished". The api was right, `isInPlay` was right, and the page overrode both.
   `styles.css` already carried a one-off `.help-overlay[hidden]` patch for the
   same collision, which is the tell that this is a class rather than an incident.

   One rule, loaded before every page's own stylesheet, so it cannot be fixed for
   one element and left broken for the next. `!important` is deliberate: `hidden`
   means "not applicable", and no layout rule should be able to outvote it.
   ========================================================================== */
[hidden] {
  /* biome-ignore lint/complexity/noImportantStyles: the whole point. Without the
     flag this loses the tie to any later `display` and the attribute goes back to
     doing nothing — which is the bug being fixed, not a style preference. */
  display: none !important;
}

/* THE PRICE IS THE BUTTON — see `priceTap` in `ui.js`.
   Here rather than in one page's sheet because the renderer is shared: the next
   surface to offer a selection gets the affordance without restating it, which
   is the whole point of there being one.

   `.px-off` is a price that CANNOT be backed, and it is a `<span>` — not a
   disabled button. It keeps full contrast deliberately: finding the odds is not
   betting, and a greyed price reads as a fault where a plain one reads as a
   book that is shut. */
.px {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--text);
}
button.px {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  padding: 4px 10px;
  font-size: inherit;
  font-family: inherit;
  line-height: 1.3;
  cursor: pointer;
}
button.px:hover {
  border-color: var(--accent);
}
/* Added. Same fill the board's picked selection uses, so one action looks the
   same wherever it is taken. */
button.px.picked {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}

/*
  THE UNLINKED CARD'S HEADER — the case for linking a team.

  Tinted rather than boxed in a colour of its own: `--tint` is already the
  accent at low strength and follows a theme change with everything else, so
  this cannot become the one panel that is unreadable in dark mode. It reads as
  part of the card it sits above, which is the point — it is an argument about
  the bets underneath it, not a notice interrupting them.
*/
.joinup {
  background: var(--tint);
  border-left: 3px solid var(--accent);
}
.joinup .lede {
  margin: 0 0 0.35rem;
}
.joinup .hint {
  margin: 0 0 0.75rem;
}
