/* ===================================================================
   AcquiCup — design system
   Brand: Acquisit (navy #0F2D52, electric blue #41A4FF, yellow #FFDD65)
   Fonts: Hanken Grotesk (UI) · Geist Mono (scores, odds, tabular nums)
   Themes via [data-theme] on the app root: boardroom | stadium | editorial
   =================================================================== */

:root {
  /* fixed brand anchors (don't change per theme) */
  --brand-navy: #0F2D52;
  --brand-blue: #41A4FF;
  --brand-yellow: #FFDD65;
  --brand-light-blue: #D2EBF3;

  /* semantic status (stable across themes) */
  --pos-bg: #DDF3E9; --pos-tx: #2D7A4F;
  --neg-bg: #FFD4CB; --neg-tx: #B84040;
  --live-tx: #C46A05;   /* in-play provisional points / live indicators */

  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 22px; --r-pill: 999px;
  --ff: "Hanken Grotesk", system-ui, sans-serif;
  --fm: "Geist Mono", ui-monospace, "SF Mono", monospace;

  --shadow-card: 0 1px 2px rgba(15,45,82,.04), 0 6px 18px rgba(15,45,82,.06);
  --shadow-pop: 0 10px 40px rgba(15,45,82,.16);
}

/* ---------- THEME: BOARDROOM (default, light corporate) ---------- */
[data-theme="boardroom"] {
  --bg:        #F6F7F9;
  --surface:   #FFFFFF;
  --surface-2: #F6F8FB;
  --surface-3: #EEF2F7;
  --ink:       #0F2D52;
  --ink-2:     #38506E;
  --ink-soft:  #7B8AA0;
  --line:      #E4E8EF;
  --line-2:    #EDF0F5;
  --accent:    #1E72D6;       /* slightly deeper blue for text/buttons on white */
  --accent-soft:#E8F1FC;
  --accent-ink:#FFFFFF;
  --hero-bg:   #0F2D52;       /* navy hero panels */
  --hero-ink:  #FFFFFF;
  --chip-bg:   #F0F3F8;
  --gold:      #C99A2E;
  --logo-filter: none;        /* uses navy logo */
}

/* ---------- THEME: STADIUM (dark, scoreboard energy) ---------- */
[data-theme="stadium"] {
  --bg:        #0A1E38;
  --surface:   #102945;
  --surface-2: #15314F;
  --surface-3: #1B3A5C;
  --ink:       #EAF2FB;
  --ink-2:     #B7C9DE;
  --ink-soft:  #7C93AE;
  --line:      #203F60;
  --line-2:    #1A3556;
  --accent:    #41A4FF;
  --accent-soft:#15314F;
  --accent-ink:#04203F;
  --hero-bg:   #081A30;
  --hero-ink:  #EAF2FB;
  --chip-bg:   #15314F;
  --gold:      #FFDD65;
  --logo-filter: brightness(0) invert(1);
}

/* ---------- THEME: EDITORIAL (paper, bold, yellow accent) ---------- */
[data-theme="editorial"] {
  --bg:        #ECEAE3;
  --surface:   #FBFAF6;
  --surface-2: #F3F1E9;
  --surface-3: #E9E6DB;
  --ink:       #141414;
  --ink-2:     #3A3A38;
  --ink-soft:  #807C72;
  --line:      #DAD6C8;
  --line-2:    #E4E0D3;
  --accent:    #0F2D52;
  --accent-soft:#E5E9F0;
  --accent-ink:#FFFFFF;
  --hero-bg:   #141414;
  --hero-ink:  #FBFAF6;
  --chip-bg:   #ECE9DE;
  --gold:      #B8902B;
  --logo-filter: none;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--ff);
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.acq-root { background: var(--bg); color: var(--ink); min-height: 100%; }

/* ---------------- typography helpers ---------------- */
.mono { font-family: var(--fm); font-feature-settings: "tnum" 1; letter-spacing: -.01em; }
/* "N of M" count labels under accuracy bars — tighten the wide mono spaces */
.of-cnt { word-spacing: -.28em; }
.eyebrow {
  font-family: var(--fm); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft);
}
h1,h2,h3,h4 { margin: 0; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; }
.h-xl { font-size: 30px; font-weight: 800; letter-spacing: -.03em; }
.muted { color: var(--ink-soft); }
.soft  { color: var(--ink-2); }

/* ---------------- layout primitives ---------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}
.card-pad { padding: 18px 20px; }
.row { display: flex; align-items: center; }
.col { display: flex; flex-direction: column; }
.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}
.gap-16{gap:16px}.gap-20{gap:20px}.gap-24{gap:24px}
.between { justify-content: space-between; }
.center { align-items: center; justify-content: center; }
.wrap { flex-wrap: wrap; }
.grow { flex: 1; }

/* ---------------- badges / chips ---------------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--chip-bg); color: var(--ink-2); white-space: nowrap;
}
.badge.pos { background: var(--pos-bg); color: var(--pos-tx); }
.badge.neg { background: var(--neg-bg); color: var(--neg-tx); }
.badge.blue{ background: var(--accent-soft); color: var(--accent); }
.badge.gold{ background: color-mix(in srgb, var(--brand-yellow) 35%, transparent); color: var(--gold); }
.badge.done{ background: var(--pos-bg); color: var(--pos-tx); }
.badge.amber{ background: color-mix(in srgb, var(--brand-yellow) 32%, transparent); color: var(--gold); }
.badge.navy{ background: var(--brand-navy); color: #fff; }
[data-theme="stadium"] .badge.navy{ box-shadow: inset 0 0 0 1px rgba(255,255,255,.22); }
.badge.live{ background: #FDEBD3; color: var(--live-tx); }
[data-theme="stadium"] .badge.live{ background: rgba(242,130,12,.20); }
[data-theme="stadium"] { --live-tx: #FFB266; }

/* ---- match cards: color-coded by status so state reads at a glance ---- */
/* A left accent stripe (inset shadow, respects the rounded corners) + a faint
   header tint differentiate live / finished / locked / upcoming / tbd. */
.match-card { --mc-accent: var(--line); position: relative; }
.match-card { box-shadow: var(--shadow-card), inset 4px 0 0 0 var(--mc-accent); }
.match-card .match-card-head { background: color-mix(in srgb, var(--mc-accent) 6%, transparent); }
.match-card.mc-live      { --mc-accent: #F2820C; }   /* live → orange */
.match-card.mc-finished  { --mc-accent: var(--pos-tx); }   /* finished → green */
.match-card.mc-locked    { --mc-accent: var(--gold); }
.match-card.mc-needspick { --mc-accent: var(--neg-tx); }   /* missing prediction → red */
.match-card.mc-upcoming  { --mc-accent: var(--accent); }   /* upcoming → blue */
.match-card.mc-tbd       { --mc-accent: var(--line); }
/* Live cards earn a touch more presence — a hairline glow on the accent edge. */
.match-card.mc-live { box-shadow: var(--shadow-card), inset 4px 0 0 0 var(--mc-accent), 0 0 0 1px color-mix(in srgb, #F2820C 22%, transparent); }
.match-card.mc-live .match-card-head { background: color-mix(in srgb, #F2820C 8%, transparent); }
/* Un-predicted upcoming cards: a faint red header tint reinforces the red accent. */
.match-card.mc-needspick .match-card-head { background: color-mix(in srgb, var(--neg-tx) 7%, transparent); }
/* On phones the kickoff date and time+timezone stack onto two lines instead of
   sharing one with a " · " separator (which gets cramped beside the stage badge). */
@media (max-width: 640px) {
  .match-card-when { display: inline-flex; flex-direction: column; align-items: center; text-align: center; line-height: 1.3; }
  .match-card-when .mc-sep { display: none; }
}
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: #F2820C; box-shadow: 0 0 0 0 rgba(242,130,12,.6); animation: pulse 1.4s infinite; }
@keyframes pulse { 0%{box-shadow:0 0 0 0 rgba(242,130,12,.5)} 70%{box-shadow:0 0 0 7px rgba(242,130,12,0)} 100%{box-shadow:0 0 0 0 rgba(242,130,12,0)} }

/* ---------------- team flag ---------------- */
.team-flag {
  flex: none;
  object-fit: cover;
  display: inline-block;
  box-shadow: 0 0 0 1px rgba(15,45,82,.12), 0 1px 2px rgba(0,0,0,.14);
}
[data-theme="stadium"] .team-flag { box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.3); }
.team-flag.fallback {
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-family: var(--fm); font-weight: 600; letter-spacing: -.02em;
}

/* ---------------- team badge (legacy) ---------------- */
.team-badge {
  --tc: #888;
  width: 38px; height: 38px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--fm); font-size: 12px; font-weight: 600;
  color: #fff; background: var(--tc); position: relative; flex: none;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.12);
}
.team-badge.sm { width: 28px; height: 28px; font-size: 10px; }
.team-badge.lg { width: 56px; height: 56px; font-size: 17px; }

/* ---------------- buttons ---------------- */
.btn {
  font-family: var(--ff); font-size: 14px; font-weight: 600;
  border: 1px solid transparent; border-radius: var(--r-pill);
  padding: 10px 18px; cursor: pointer; display: inline-flex; align-items: center;
  gap: 8px; transition: transform .08s ease, background .15s ease, box-shadow .15s; white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 40%, transparent); }
.btn-navy { background: var(--brand-navy); color: #fff; }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { background: var(--surface-2); }
/* ghost buttons placed on a dark hero panel — keep icons/borders legible */
.btn-ghost.on-hero { color: var(--hero-ink); border-color: color-mix(in srgb, var(--hero-ink) 28%, transparent); }
.btn-ghost.on-hero:hover { background: color-mix(in srgb, var(--hero-ink) 12%, transparent); }
.btn-soft { background: var(--accent-soft); color: var(--accent); }
.btn-danger { background: var(--neg-tx); color: #fff; }
.btn-danger:hover { box-shadow: 0 4px 14px color-mix(in srgb, var(--neg-tx) 38%, transparent); }
.btn-sm { padding: 7px 13px; font-size: 13px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* keyboard focus ring (only on keyboard nav, not mouse click) — theme-aware */
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------------- progress / meters ---------------- */
.meter { height: 7px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }

/* ---------------- table ---------------- */
.lb { width: 100%; border-collapse: collapse; }
.lb thead th {
  text-align: left; font-family: var(--fm); font-size: 10px; font-weight: 500;
  letter-spacing: .05em; text-transform: uppercase; color: var(--ink-soft);
  background: var(--surface-2); padding: 14px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
.lb thead th:first-child { padding-left: 18px; }
.lb thead th:last-child { padding-right: 18px; }
.lb td { padding: 13px 12px; border-bottom: 1px solid var(--line-2); font-size: 14px; vertical-align: middle; }
.lb td:first-child { padding-left: 18px; }
.lb td:last-child { padding-right: 18px; }
.lb tr:last-child td { border-bottom: none; }
.lb tr.me-row td { background: var(--accent-soft); }
.lb tr.hov:hover td { background: var(--surface-2); }
/* Sortable column header — clickable, subtly highlights on hover. */
.lb thead th.hov { cursor: pointer; }
.lb thead th.hov:hover { color: var(--ink); background: var(--line-2); }
.rank-num { font-family: var(--fm); font-weight: 600; font-size: 15px; }
/* Center variant — header + content (AcquiBoard Individual table). Scoped so the other
   .lb leaderboards keep their left/right alignment. */
.lb.lb-center thead th, .lb.lb-center td { text-align: center; }

/* movement arrows */
.mv { font-family: var(--fm); font-size: 12px; display: inline-flex; align-items: center; gap: 2px; }
.mv.up { color: var(--pos-tx); } .mv.dn { color: var(--neg-tx); } .mv.flat { color: var(--ink-soft); }

/* scoreboard */
.score-num { font-family: var(--fm); font-weight: 600; font-variant-numeric: tabular-nums; }

/* segmented control / tabs */
.tabs { display: flex; gap: 2px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-pill); padding: 3px; }
.tabs button {
  font-family: var(--ff); font-size: 13px; font-weight: 600; color: var(--ink-soft);
  background: transparent; border: none; padding: 7px 14px; border-radius: var(--r-pill); cursor: pointer; white-space: nowrap;
}
.tabs button.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card); }
/* full-width segmented control: each tab shares the row equally (binary toggles) */
.tabs.tabs-full { width: 100%; }
.tabs.tabs-full button { flex: 1 1 0; text-align: center; }

/* inputs */
.field {
  font-family: var(--ff); font-size: 14px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 11px 13px; width: 100%; outline: none;
}
.field:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
label.lbl { font-size: 12.5px; font-weight: 600; color: var(--ink-2); display: block; margin-bottom: 6px; }

/* divider */
.hr { height: 1px; background: var(--line); border: none; margin: 0; }

/* small line separator under a page sub-header (PageHead) */
.pagehead-sep { width: 120px; height: 3px; border: none; border-radius: 3px; margin: 10px 0 0; background: var(--line); }

/* scroller hide */
.noscroll::-webkit-scrollbar { width: 8px; height: 8px; }
.noscroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 99px; }

/* ---------------- tournament: group tables + knockout bracket ---------------- */
/* compact league table inside group cards */
.gtbl td, .gtbl th { padding-top: 9px; padding-bottom: 9px; }
.gtbl th.num, .gtbl td.num { text-align: center; padding-left: 7px; padding-right: 7px; width: 34px; }
.gtbl th:last-child, .gtbl td:last-child { padding-right: 16px; }
.gtbl tr.qrow td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* match card (shared by the desktop tree, mobile rounds, 3rd-place card) */
.ko-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 10px 12px; box-shadow: var(--shadow-card);
  transition: border-color .12s, transform .08s;
}
.ko-card.pointer:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.ko-card.pointer:active { transform: translateY(1px); }
.ko-team { display: flex; align-items: center; gap: 9px; }
.ko-team .nm { font-weight: 600; font-size: 13px; }
.ko-team.ko-win .nm { font-weight: 800; }
.ko-team.ko-lose { opacity: .48; }
/* fixed-width winner mark (left) + fixed-width score column (right): keeps the two
   team rows' ticks and scores vertically aligned regardless of name length */
.ko-mark { flex: none; width: 14px; display: inline-flex; align-items: center; justify-content: center; }
.ko-score { flex: none; width: 18px; text-align: center; font-size: 14px; }

/* tentative entrant — the team currently holding a "1st/2nd Group X" slot, shown
   italic with a dashed flag + an accent slot chip (e.g. "1C") and a "Tentative" pill
   in the card meta row; the unresolved placeholder slot (a "Winner Match 73" /
   "3rd Group …" label) is shown in muted, smaller text. */
.ko-team.ko-tentative .nm { font-style: italic; font-weight: 600; color: var(--ink-soft); }
.ko-team.ko-tentative .team-flag { border: 1.5px dashed color-mix(in srgb, var(--accent) 55%, var(--line)); }
.ko-team.ko-placeholder .nm { font-size: 12px; }
.ko-slot-tag {
  flex: none; font: 800 9.5px/1 var(--fm); letter-spacing: .04em;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 38%, var(--line)); border-radius: 4px; padding: 2px 4px;
}
/* the prominent "Tentative" label in the card meta row */
.ko-tentative-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font: 800 9.5px/1 var(--fm); letter-spacing: .06em; text-transform: uppercase;
  color: var(--gold); background: color-mix(in srgb, var(--brand-yellow) 22%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--line)); border-radius: 999px; padding: 2px 8px;
}
.ko-tentative-tag .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--gold); }

/* ---- knockout bracket: connected tree with SVG path connectors ---- */
/* the host .card keeps overflow:hidden; this inner wrapper is the only scroller */
.kob-scroll { overflow-x: auto; overflow-y: hidden; padding-bottom: 8px; }
.kob-inner { position: relative; }
.kob-headers { position: relative; }
.kob-headers .kob-h { position: absolute; top: 0; text-align: center; }
.kob-stage { position: relative; }
/* SVG sized to the stage; sits under the cards and passes clicks through */
.kob-links { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 0; overflow: visible; }
.kob-links path { fill: none; stroke: var(--line-2); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* tree cards are absolutely placed by JS geometry; height is the geometry source of truth */
.kob-card { position: absolute; z-index: 1; box-sizing: border-box; padding: 9px 11px; overflow: hidden; }
/* legend chip + the mobile round connector chevron */
.kob-legend { display: inline-flex; align-items: center; gap: 8px; font: 500 11px/1.4 var(--fm); color: var(--ink-soft); }
.kob-legend .dot { flex: none; width: 9px; height: 9px; border-radius: 3px; border: 1px solid var(--line); background: var(--surface-2); }
.kob-mchev { display: flex; justify-content: center; color: color-mix(in srgb, var(--ink-soft) 80%, transparent); margin: -2px 0; }

/* utility */
.pointer { cursor: pointer; }
.full { width: 100%; }
.nowrap { white-space: nowrap; }
a { color: inherit; text-decoration: none; }

/* ===================================================================
   RESPONSIVE LAYER
   Tiers: mobile ≤640 · tablet 641–1023 · desktop ≥1024.
   The shell swaps top-nav↔bottom-nav in JS at 820 (useNarrow): ≥820 renders the
   sticky desktop top bar, <820 the mobile top bar + bottom tabs. These
   rules add the CSS reflow/scaling that was missing (styles.css had zero
   @media queries). Inline styles in the JSX win the cascade, so overrides of
   inline grid/padding/font/width use !important — each tightly scoped to a
   media query + class hook so nothing leaks to desktop. All colors use theme
   vars so the three [data-theme]s stay correct.
   =================================================================== */

/* let flex children shrink (ellipsis) instead of forcing overflow */
.col, .grow { min-width: 0; }
img { max-width: 100%; height: auto; }

/* Forced line break shown only on the desktop top-bar tier (≥820); below that the
   text flows/wraps naturally. Used to split a two-sentence sub-header one per line. */
.desk-br { display: none; }
@media (min-width: 820px) { .desk-br { display: inline; } }

/* The dashboard & beat-acquisit two-column grids carry .dash-grid as a reflow
   hook but no CSS ever targeted it — collapse them to one column below 900. */
@media (max-width: 900px) {
  .dash-grid { grid-template-columns: 1fr !important; }
}

/* On phones the headline stats stop auto-fitting (which would stack all three);
   instead Total points spans the full width and the two ranking tiles share one
   row below it. */
@media (max-width: 640px) {
  .dash-stats { grid-template-columns: 1fr 1fr !important; }
  .dash-stats > :first-child { grid-column: 1 / -1; }
  /* Even tile counts (company profile's 4 KPIs) keep a clean 2×2 — no hero tile. */
  .dash-stats.dash-stats-even > :first-child { grid-column: auto; }
}

/* ---- TABLET (821–1023): trim content side padding so it keeps room ---- */
@media (min-width: 821px) and (max-width: 1023px) {
  main.noscroll > div { padding-left: 22px !important; padding-right: 22px !important; }
}

/* ---- DESKTOP TOP NAV (replaces the old left sidebar; shell renders it ≥820) ----
   Hover state for non-active items: the JSX sets the active pill via an inline
   background, so scope the hover to :not(.on) and use !important to beat the
   inline `transparent` on the inactive items. */
.topnav-item:not(.on):hover { background: var(--surface-2) !important; color: var(--ink) !important; }
/* keyboard focus ring for the nav links + brand (mouse clicks stay ring-free) */
.topnav-item:focus-visible, .topnav-brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 10px; }
/* the nav can scroll horizontally as a safety valve on cramped widths — hide the bar */
.topnav-nav { scrollbar-width: none; }
.topnav-nav::-webkit-scrollbar { display: none; }
/* Progressive compaction so the bar never overflows as the viewport narrows:
   ≤1140 drop the name/rank text (avatar + Sign out stay); ≤900 drop the nav
   labels (icon-only — the title attr supplies a hover tooltip). Both classes
   only exist in the desktop shell, so these are inert in the mobile shell. */
@media (max-width: 1140px) { .topnav-name { display: none; } }
@media (max-width: 900px) { .topnav-label { display: none; } }

/* ---- TABLET TOP NAV (820–1023) ----
   On a tablet the five icon-only items clumped in the middle with a big empty
   gap on either side. The fix is to bring the labels back down to 901px so the
   centred nav fills the bar like it does on desktop — the wider labelled items
   leave no awkward side gaps. The items + bar chrome are tightened so all five
   labelled items still fit the centre band; only the narrowest tablets (≤900)
   fall back to icon-only. Inline styles in the JSX win the cascade, hence the
   !important on the tightening. */
@media (min-width: 820px) and (max-width: 1023px) {
  .topnav-inner { gap: 12px !important; padding-left: 18px !important; padding-right: 18px !important; }
  .topnav-nav   { gap: 2px !important; }
  .topnav-right { gap: 9px !important; }
  .topnav-item  { padding: 8px 9px !important; gap: 6px !important; font-size: 13px !important; }
}

/* ---- AUTH: the 2-panel split stacks, then drops the brand panel on phones ----
   Scoped to the auth-only .auth-split hook so the rule can't leak to other
   layouts. (The authed shell is a separate column layout — header + main — and
   carries no .auth-split, so it's untouched here.) */
/* mobile-only login logo: hidden until the brand panel drops out (≤640px below) */
.auth-mobile-brand { display: none; }
@media (max-width: 820px) {
  .auth-split { flex-direction: column !important; }
  .auth-brand { padding: 32px 24px !important; }
}
@media (max-width: 640px) {
  .auth-brand { display: none !important; }
  /* the brand panel is gone on phones, so surface the logo atop the form instead */
  .auth-mobile-brand { display: block !important; }
  /* stack the First/Last name fields (min-width:0 would otherwise keep them side-by-side) */
  .auth-names { flex-direction: column; align-items: stretch; }
}

/* ---- bottom tab bar: real touch targets (only exists while shell is mobile, <820) ---- */
@media (max-width: 819px) {
  .bottom-tab { min-height: 46px; min-width: 54px; justify-content: center; }
}

/* ---- mobile slide-out drawer ("top menu", opened by the header hamburger) ----
   Mount-time entrance animations only (no exit anim — the node unmounts on close,
   matching the conditionally-rendered Modal). Slides in from the right edge. */
@keyframes drawer-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes drawer-fade { from { opacity: 0; } to { opacity: 1; } }
.mobile-drawer { animation: drawer-in .22s cubic-bezier(.2,.8,.2,1); }
.mobile-drawer-backdrop { animation: drawer-fade .2s ease; }
@media (prefers-reduced-motion: reduce) {
  .mobile-drawer, .mobile-drawer-backdrop { animation: none; }
}

/* ---- MOBILE (≤640): scale the frozen desktop type / padding / tap targets ---- */
@media (max-width: 640px) {
  .h-xl { font-size: 23px; }
  .card-pad { padding: 14px 15px; }
  /* 16px input text stops iOS Safari auto-zooming on focus */
  .field { font-size: 16px; padding: 12px 13px; }
  .tabs button { padding: 10px 15px; }
  .btn { padding: 11px 16px; }
  .btn-sm { padding: 9px 14px; }
  .team-badge.lg { width: 46px; height: 46px; font-size: 15px; }
  /* tables reclaim horizontal room (leaderboards + admin) */
  .lb thead th, .lb td { padding: 11px 8px; }
  .lb thead th:first-child, .lb td:first-child { padding-left: 13px; }
  .lb thead th:last-child, .lb td:last-child { padding-right: 13px; }
  /* keep inline table inputs/buttons touch-sized without enlarging their text */
  .lb .field { min-height: 38px; }
  .lb .btn-sm { min-height: 36px; }
  /* Dashboard "Recent points" (and the profile Predictions table reusing the class):
     drop the trailing Kick-off + Phase metadata columns on a phone — the remaining
     four (match · prediction · score · points) fit without horizontal scroll, so no
     min-width/overflow workaround is needed. */
  .dash-recent-table th:nth-child(5), .dash-recent-table td:nth-child(5),
  .dash-recent-table th:nth-child(6), .dash-recent-table td:nth-child(6) { display: none; }
  /* Dashboard KPIs: force two tiles per row on mobile (auto-fit at minmax(180px,…)
     collapses to one column on a ~360px phone). Inline grid-template wins the
     cascade, hence !important. */
  .dash-kpis { grid-template-columns: 1fr 1fr !important; gap: 12px !important; }
  /* In a half-width tile the 30px value (e.g. "0/2 used") would wrap; trim it. */
  .dash-kpis .card-pad { padding: 14px 14px !important; }
  .dash-kpis .mono { font-size: 24px !important; }
}

/* ---- Admin Users: stacked cards replace the table below the table's 820px min-width ----
   The fixed-layout users table can't fit a phone — it side-scrolls and ellipsizes the
   email. Under 820px the table hides and the same rows render as .admin-user-card
   stacks (full, wrapping email; no horizontal scroll). Both layouts are always in the
   DOM; this swap is the only thing that decides which one shows. */
.admin-users-cards { display: none; }
@media (max-width: 819px) {
  .admin-users-table { display: none; }
  .admin-users-cards { display: block; }
  /* toolbar: count / search / bulk buttons can't share one 360px line — the count keeps
     line 1, the controls span drops to its own full-width line and wraps, with the
     search flexing over whatever its line has left (!important beats its inline minWidth) */
  .admin-users-toolbar { flex-wrap: wrap; row-gap: 10px; }
  .admin-users-toolbar > span:last-child { flex: 1 1 100%; flex-wrap: wrap; row-gap: 8px; }
  .admin-users-toolbar input[type="search"] { flex: 1 1 auto; min-width: 0 !important; }
}
.admin-user-card { padding: 12px 14px; border-bottom: 1px solid var(--line-2); }
.admin-user-card:last-child { border-bottom: none; }
/* the whole point of the card layout: the email never truncates */
.admin-user-email { font-size: 12.5px; overflow-wrap: anywhere; word-break: break-all; }

/* ---- dashboard / beat-acquisit hero blocks ---- */
@media (max-width: 640px) {
  .hero-card .card-pad { padding: 20px 18px !important; }
  .hero-card h1 { font-size: 22px !important; }
  .hero-card .mono { font-size: 26px !important; }
  /* …but not the countdown digits inside the hero pill — they inherit the pill's
     13px (must stay after the .mono rule: same specificity, later wins). */
  .hero-card .pill-mono { font-size: inherit !important; }
  /* Countdown pill + next-match pill + CTA buttons: the stretch column is 240px on
     desktop (an aside next to the welcome text); once it wraps below the text on
     phones, let it span the full card width. */
  .hero-actions { width: 100% !important; }
}

/* My-stats / Prediction-strategy legend labels: the legend columns are sized to
   their bar segment, so the long labels ellipsis on narrow phones. Swap to the
   short variant (Exact / Good / Wrong) at the mobile breakpoint. */
.dash-lbl-short { display: none; }
@media (max-width: 640px) {
  .dash-lbl-full { display: none; }
  .dash-lbl-short { display: inline; }
}

/* ---- Player / Company profile (screens-user) mobile tweaks ---- */
@media (max-width: 640px) {
  /* The hero banner repeats the player's points + rank, but the stat tiles right
     below show the same — drop the duplicate aside on phones. With the aside gone
     the identity block spans the full width; top-align the logo (instead of the
     desktop vertical-center) so it lines up with the eyebrow/name rather than
     floating against a taller text column (company hero with a domain link). */
  .profile-hero-aside { display: none !important; }
  .profile-hero-id { align-items: flex-start !important; }
  /* Both points donuts go full-width (one per row) so each keeps its legend on the
     right instead of wrapping it below. */
  .profile-donuts { grid-template-columns: 1fr !important; gap: 16px !important; }
  /* Keep the legend BESIDE the (shrunk) ring: no wrap, tighter gap, and a flexible
     label that wraps its text rather than pushing the whole legend onto its own row. */
  .donut-chart { flex-wrap: nowrap !important; gap: 14px !important; }
  .donut-chart .donut-legend { flex: 1 1 auto !important; min-width: 0; }
  .donut-chart .donut-legend-label { flex: 1 1 auto !important; width: auto !important; min-width: 0; white-space: normal !important; }
}

/* ---- My-stats bar hover tooltip (Accuracy rate / Risk rate) ----
   A centered popover lifted above the bar; its caret tracks the hovered segment.
   Lists every bucket's share %, count and points, with the hovered one emphasised. */
.statbar-tip {
  position: absolute; bottom: 100%; transform: translate(-50%, -10px);
  z-index: 30; width: max-content; max-width: min(320px, 92%);
  padding: 11px 13px 12px; border-radius: 12px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-pop);
  pointer-events: none; /* never steal the hover from the bar/legend below */
  animation: statbar-tip-in .12s ease-out;
}
/* slide only — no opacity fade, so the popover is fully solid the instant it appears */
@keyframes statbar-tip-in {
  from { transform: translate(-50%, -4px); }
  to   { transform: translate(-50%, -10px); }
}
.statbar-tip-head { display: flex; align-items: center; gap: 8px; padding-bottom: 9px; margin-bottom: 8px; border-bottom: 1px solid var(--line-2); }
.statbar-tip-title { font-weight: 700; font-size: 13px; color: var(--ink); }
.statbar-tip-pct { margin-left: auto; font-weight: 800; font-size: 16px; letter-spacing: -.01em; }
.statbar-tip-dot { width: 11px; height: 11px; border-radius: 4px; flex: none; }
.statbar-tip-dot.sm { width: 9px; height: 9px; border-radius: 3px; }
.statbar-tip-rows { display: flex; flex-direction: column; gap: 1px; }
.statbar-tip-row {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; margin: 0 -6px; border-radius: 7px;
  font-size: 12px; color: var(--ink-soft); transition: background .1s;
}
.statbar-tip-row.on { background: var(--surface-2); color: var(--ink); }
.statbar-tip-row.total { margin-top: 4px; padding-top: 7px; border-top: 1px solid var(--line-2); border-radius: 0; }
.statbar-tip-lbl { flex: 1; min-width: 0; white-space: nowrap; font-weight: 600; }
.statbar-tip-row.on .statbar-tip-lbl { font-weight: 700; }
.statbar-tip-val { flex: none; font-weight: 700; color: var(--ink); }
.statbar-tip-of { color: var(--ink-soft); font-weight: 600; }
.statbar-tip-pts { flex: none; min-width: 48px; text-align: right; font-weight: 600; color: var(--ink-soft); }
.statbar-tip-share { flex: none; min-width: 36px; text-align: right; font-weight: 800; color: var(--ink); }
.statbar-tip-caret {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent;
  border-top: 7px solid var(--surface);
  filter: drop-shadow(0 1px 0 var(--line));
}

/* Portal variant (leaderboard/acquiboard table bars): fixed-positioned so the table's
   horizontal-scroll wrapper can't clip it; left/top come from inline styles. Header pct
   defaults to ink (the Dashboard sets a per-segment colour inline). A footer meta line
   carries the denominator / risk index. Fade-only animation so the inline transform that
   positions the popover isn't overridden by a keyframe. */
.statbar-tip-pct { color: var(--ink); }
.statbar-tip-foot { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line-2); font-size: 11px; color: var(--ink-soft); }
.statbar-tip.is-fixed { position: fixed; bottom: auto; animation: none; }
/* flipped (rendered below the bar) → caret on top edge, pointing up */
.statbar-tip.flip .statbar-tip-caret {
  top: auto; bottom: 100%;
  border-top: 0; border-bottom: 7px solid var(--surface);
  filter: drop-shadow(0 -1px 0 var(--line));
}

/* ---- prediction-detail scoreboard (scoped so match-card .score-num is untouched) ---- */
@media (max-width: 520px) {
  .pred-hero { padding: 22px 14px 24px !important; }
  .pred-hero .score-num { font-size: 38px !important; }
  .pred-hero .stepper .score-num { width: 56px !important; font-size: 44px !important; }
  .pred-hero .stepper .btn { width: 48px !important; height: 44px !important; }
}

/* ---- calendar sticky date header: clear whichever top bar is present ----
   Both shells now have a sticky top bar, so the date header (inline top:0) must
   stick *below* it or it'd hide behind the bar: 52px for the mobile shell (<820),
   60px for the desktop top nav (≥820). Inline style wins the cascade, hence
   !important on both offsets. The bar's z-index (30 mobile / 50 desktop) sits
   above the date header's z-index:2, so the bar always covers it. */
.cal-date { background: var(--bg); z-index: 2; padding: 4px 0; }
@media (max-width: 819px) { .cal-date { top: 52px !important; } }
@media (min-width: 820px) { .cal-date { top: 60px !important; } }

/* ---- toast clears the fixed bottom-nav on mobile and never intercepts taps ---- */
@media (max-width: 819px) {
  .app-toast { bottom: calc(env(safe-area-inset-bottom, 0px) + 78px) !important; }
}

/* ============================== LANDING PAGE ==============================
   The landing page reuses the app shell & primitives wholesale (topnav, 1080
   container, hero-card, PageHead, .card/.lb, RankChartCard, buttons, gap-* scale)
   so there is no visual jump on sign-in. The only landing-specific rule: the
   center anchor links in the reused topnav collapse on small screens, exactly
   like the app's own .topnav-label does. */
.lp-nav .topnav-item:hover { background: var(--surface-2); color: var(--accent); }
@media (max-width: 720px) { .lp-nav { display: none !important; } }

/* the four rules sit in a single row, reflowing to 2 then 1 column on small screens */
.lp-rules { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
@media (max-width: 900px) { .lp-rules { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .lp-rules { grid-template-columns: 1fr; } }

/* headline stats (Matches/Teams/AI rivals/To join): the auto-fit grid collapses
   to a single column on phones, so force a 2-up layout below the mobile breakpoint
   (inline grid-template-columns wins the cascade, hence !important). */
@media (max-width: 640px) {
  .lp-stats { grid-template-columns: 1fr 1fr !important; }
}

/* "Your AI rivals": on phones drop the label to its own line and keep the three
   AI logos on a single non-wrapping row below it (tighter gap so they fit). */
@media (max-width: 640px) {
  .lp-airivals { flex-direction: column; align-items: flex-start !important; gap: 8px !important; }
  .lp-airivals-list { flex-wrap: nowrap !important; gap: 16px !important; }
}

/* ========================= WORLD CUP 101 (primer page) =========================
   screens-wc101.jsx — same reuse story as the landing page. Page-specific rules:
   the three record tables and the trivia cards reflow like .lp-rules, and the
   low-priority columns (player era, final's host) yield first on phones. */
.wc101-grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
@media (max-width: 980px) { .wc101-grid3 { grid-template-columns: 1fr; } }

.wc101-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 900px) { .wc101-facts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .wc101-facts { grid-template-columns: 1fr; } }

/* Roll of honour: each final is a match-style line (winner · score · runner-up,
   the match cards' 1fr auto 1fr idiom). On phones the full nation names swap to
   FIFA trigrams, the cup icon drops and the cell padding tightens, so the table
   fits a 320px viewport with no horizontal scroll. */
.wc101-final { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }
.wc101-side { display: flex; align-items: center; gap: 9px; min-width: 0; }
.wc101-side.win { justify-content: flex-end; text-align: right; }
.wc101-name-code { display: none; }

/* Per-edition top scorer / most assists are desktop-only garnish: below 900px
   they'd squeeze the match-style final line, so they drop before the host does. */
@media (max-width: 900px) { .wc101-extra { display: none; } }

@media (max-width: 640px) {
  .wc101-era, .wc101-host { display: none; }
  .wc101-name-full { display: none; }
  .wc101-name-code { display: inline; }
  .wc101-cup { display: none !important; }
  .wc101-final { gap: 8px; }
  .wc101-side { gap: 6px; }
  .wc101-honours td, .wc101-honours th { padding-left: 6px; padding-right: 6px; }
}
