:root {
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', 'SFMono-Regular', Consolas, monospace;

  --bg: #05070a;
  --card: #0d1117;
  --card-alt: #080a0f;
  --border: #1f2937;
  --border-soft: rgba(255, 255, 255, 0.05);
  --text: #e2e8f0;
  --text-muted: #94a3b8;
  --accent: #3b82f6;
  --success: #10b981;
  --danger: #ef4444;
  --warning: #f59e0b;
  --indigo: #818cf8;
  --cyan: #22d3ee;
  --hover-overlay: rgba(255, 255, 255, 0.05);
  --hover-overlay-soft: rgba(255, 255, 255, 0.03);
}

/* Light mode - overrides the same custom properties everything else already
   reads through var(), so most of the app re-themes automatically. */
body.light-mode {
  --bg: #f4f6f9;
  --card: #eef1f5;
  --card-alt: #e0e5ec;
  --border: #dde2e9;
  --border-soft: rgba(0, 0, 0, 0.06);
  --text: #161a20;
  --text-muted: #5b6472;
  --hover-overlay: rgba(0, 0, 0, 0.04);
  --hover-overlay-soft: rgba(0, 0, 0, 0.025);

  /* The dark-mode palette's bright/glowing shades (tuned to pop against a
     near-black background) read as neon against a light background instead -
     deeper, less saturated shades of the same hues read as normal text here. */
  --accent: #2563eb;
  --success: #059669;
  --danger: #dc2626;
  --warning: #b45309;
  --indigo: #4f46e5;
  --cyan: #0e7490;
}

* { box-sizing: border-box; }

@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  margin: 0;
  padding: 0;
}

.app-layout {
  display: flex;
  min-height: 100vh;
}

.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  background: var(--bg);
}

.loading-overlay.hidden {
  display: none;
}

.loading-spinner {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 3px solid var(--border);
  border-top-color: var(--cyan);
  animation: spin 0.8s linear infinite;
}

.loading-text {
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

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

.sidebar {
  flex: 0 0 200px;
  background: var(--bg);
  border-right: 1px solid var(--border);
  padding: 24px 12px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  align-self: flex-start;
}

.sidebar-profile {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  padding: 4px 6px 16px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}

.sidebar-avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--border);
  background: var(--card);
  flex-shrink: 0;
}

.sidebar-profile-text {
  min-width: 0;
}

.sidebar-welcome-label {
  font-size: 9px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}

.sidebar-welcome-name {
  font-size: 12px;
  font-weight: 800;
  color: var(--text);
  word-break: break-word;
}

/* Small nudge so the first nav item lands roughly level with the summary
   cards / Open Bets row in the main content column. */
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 14px;
}

.sidebar-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  border: 1px solid transparent;
}

.nav-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.sidebar-item:hover {
  background: var(--hover-overlay);
  color: var(--text);
}

.sidebar-item.active {
  background: rgba(59, 130, 246, 0.1);
  color: var(--accent);
  border-color: rgba(59, 130, 246, 0.2);
}

.sidebar-bottom {
  margin-top: auto;
}

.main-content {
  flex: 1 1 auto;
  min-width: 0;
  padding: 24px;
}

/* Grid (not flex) so the logo can sit dead-center regardless of how wide
   the left group/Balance are, without an absolute-position hack - middle
   column is auto-width and centers its own content via .header-logo-wrap's
   justify-self below. */
header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}

select {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  font-family: var(--font-sans);
}

.panel {
  margin-bottom: 32px;
  width: 100%;
}

.panel h2 {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text);
  opacity: 0.85;
  margin: 0 0 12px;
  text-align: center;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

th, td {
  text-align: left;
  padding: 10px 14px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}

th {
  color: var(--text-muted);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.1em;
}

tr:last-child td {
  border-bottom: none;
}

.result-win, .result-loss, .result-refund, .result-pending {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-weight: 800;
  font-size: 11px;
}

.result-win { color: var(--success); background: rgba(16, 185, 129, 0.15); border: 1px solid rgba(16, 185, 129, 0.3); }
.result-loss { color: var(--danger); background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.3); }
.result-refund { color: var(--warning); background: rgba(245, 158, 11, 0.15); border: 1px solid rgba(245, 158, 11, 0.3); }
.result-pending { color: var(--accent); background: rgba(59, 130, 246, 0.15); border: 1px solid rgba(59, 130, 246, 0.3); }

.empty-row td {
  text-align: center;
  color: var(--text-muted);
  padding: 20px;
}

.pagination {
  display: flex;
  gap: 6px;
  margin-top: 12px;
}

.page-btn {
  background: var(--card);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-mono);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.page-btn:hover {
  background: var(--hover-overlay);
  color: var(--text);
  border-color: rgba(59, 130, 246, 0.4);
}

.page-btn.active {
  background: var(--success);
  color: #05070a;
  border-color: var(--success);
  font-weight: 700;
}

.page-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.page-ellipsis {
  color: var(--text-muted);
  padding: 6px 4px;
  font-size: 13px;
}

.bet-card-list {
  background: transparent;
  border: none;
  margin-bottom: 12px;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.bet-card-list:empty {
  display: none;
}

.bet-card-header {
  display: grid;
  grid-template-columns: 60px 170px 174px 65px 90px 55px 80px 100px 100px;
  gap: 12px;
  padding: 0 14px 8px;
  color: var(--text-muted);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.1em;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
}

.bet-card-header > div {
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 4px;
}

.bet-card-header > div:hover {
  color: var(--text);
}

.sort-arrow {
  font-size: 9px;
  color: var(--accent);
}

.hidden {
  display: none;
}

.bet-card {
  display: grid;
  grid-template-columns: 60px 170px 174px 65px 90px 55px 80px 100px 100px;
  gap: 12px;
  align-items: center;
  padding: 12px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 13px;
  transition: background 0.15s, border-color 0.15s;
}

.bet-card:hover {
  background: rgba(16, 185, 129, 0.06);
  border-color: rgba(16, 185, 129, 0.3);
}

/* Mobile-only per-card mini header + spacer (see the mobile media query) -
   desktop's .bet-card has no grid-template-areas of its own and relies on
   plain DOM order for its 9 implicit columns, so these extra elements need
   to be fully removed from layout here rather than just visually hidden. */
.bet-card-mini-th,
.bet-card-gap {
  display: none;
}

/* Current Bets/Completed/Awaiting cards render both a full ("$5,400,000")
   and short ("$5.4M") money format side by side (see moneyDual() in
   dashboard.js) - desktop shows the full one by default, mobile swaps to the
   short one instead (see the mobile media query below). */
.money-mobile {
  display: none;
}

.bet-card-kickoff {
  color: var(--text-muted);
  font-size: 11px;
  font-family: var(--font-mono);
  font-weight: 600;
}

.bet-card-match {
  min-width: 0;
}

.match-name {
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 700;
  color: #60a5fa;
  min-width: 0;
}

/* Truncation moved here (off .match-name itself) so the note icon appended
   after it - see dashboard.js's noteIconHtml - never gets clipped by a long
   match name eating the row's own overflow:hidden/ellipsis; min-width: 0 is
   required for a flex child to actually shrink instead of overflowing its
   flex container. */
.match-name-text {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.match-link {
  color: inherit;
  text-decoration: none;
}

.match-link:hover {
  text-decoration: underline;
}

/* Match notes - see dashboard.js's noteIconHtml/toggleMatchNote. Positioned
   relative so the note box can sit as a small floating panel right under the
   icon instead of pushing the rest of the row down. */
.match-note-wrap {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
}

.match-note-icon {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--text-muted);
  opacity: 0.5;
}

.match-note-icon svg {
  width: 6.5px;
  height: 6.5px;
  display: block;
}

.match-note-icon:hover {
  opacity: 0.85;
}

/* A saved note stays visually distinct (bright yellow, matching the TBT
   badge's own color language elsewhere on this same card - see
   .current-bet-tip-badge) even when not hovered, so there's a glanceable
   signal for "this match already has a note" without opening it. */
.match-note-icon.has-note {
  color: #ffe000;
  opacity: 1;
}

body.light-mode .match-note-icon.has-note {
  color: #ca8a04;
}

.match-note-box {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 220px;
  padding: 8px;
  background: var(--card-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

/* .hidden and .match-note-box are equal specificity (one class each), and
   this file's own cascade order put .match-note-box's display: flex after
   .hidden's display: none - so it was winning and every note box showed as
   open from the start, regardless of the hidden class actually being
   present. Confirmed live. This compound selector (two classes) is strictly
   more specific than either alone, so it wins regardless of source order. */
.match-note-box.hidden {
  display: none;
}

.match-note-input {
  width: 100%;
  min-height: 60px;
  resize: vertical;
  padding: 6px;
  font-family: inherit;
  font-size: 12px;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.match-note-close {
  align-self: flex-end;
  padding: 3px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  background: var(--hover-overlay-soft);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}

.match-note-close:hover {
  background: var(--hover-overlay);
}

.match-sport {
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 3px;
}

.match-status {
  font-size: 12px;
  margin-top: 2px;
}

.status-live { color: var(--success); }
.status-upcoming { color: var(--text-muted); }
.status-pending { color: var(--warning); }

.match-score {
  font-size: 12px;
  margin-top: 2px;
  font-family: var(--font-mono);
}

.score-value-current {
  color: var(--warning);
  font-weight: 700;
}

.score-value-history {
  color: var(--text);
  font-weight: 700;
}

.score-win {
  color: #3cff7a;
  font-weight: 700;
  text-shadow: 0 0 6px rgba(60, 255, 122, 0.5);
}

.score-loss {
  color: #ff3b5c;
  font-weight: 700;
  text-shadow: 0 0 6px rgba(255, 59, 92, 0.5);
}

.score-draw {
  color: #ffe83c;
  font-weight: 700;
  text-shadow: 0 0 6px rgba(255, 232, 60, 0.5);
}

/* Light mode only - plain red/green/yellow instead of the neon glow above,
   which is tuned for the dark theme. Dark mode is untouched. */
body.light-mode .score-win {
  color: #16a34a;
  text-shadow: none;
}

body.light-mode .score-loss {
  color: #dc2626;
  text-shadow: none;
}

body.light-mode .score-draw {
  color: #ca8a04;
  text-shadow: none;
}

.score-dash {
  color: var(--text-muted);
}

.score-tag {
  color: var(--text);
}


.pick-name {
  font-weight: 400;
  font-size: 11px;
  color: var(--text);
}

.pick-sub {
  font-size: 11px;
  color: var(--accent);
  margin-top: 2px;
}

.bet-card-payout, .bet-card-stake {
  color: var(--text);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 11px;
}

.bet-card-odds {
  color: var(--text);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 11px;
}

.bet-card-result {
  font-size: 14px;
}

.bet-card-payment {
  color: var(--text-muted);
  font-size: 12px;
}

.payment-pending {
  color: var(--warning);
  font-weight: 700;
}

.bet-card-profit {
  font-weight: 400;
  font-size: 11px;
  font-family: var(--font-mono);
}

.profit-positive {
  color: var(--success);
}

.profit-negative {
  color: var(--danger);
}

.bet-card-empty {
  padding: 20px;
  text-align: center;
  color: var(--text-muted);
}

.bet-card-empty.negative {
  color: var(--danger);
}

/* Current Bets card (v2 layout) - each bet is its own separated, bordered card */

#currentBetsList {
  background: transparent;
  border: none;
  border-radius: 0;
  overflow: visible;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}

/* Each card's actual grid item is now a stable per-match wrapper (see
   dashboard.js's renderCurrentBets - keyed so an unchanged card's DOM node
   is never rebuilt on a poll, only the specific one whose content actually
   changed) - display:contents removes the wrapper's own box entirely so its
   .bet-card-v2 child still participates directly in this grid exactly as
   before, just with one harmless extra level in the DOM tree. */
#currentBetsList .bet-card-slot {
  display: contents;
}

/* When the card count is odd, the last card has no partner in its row - span it
   across both columns and center it at a single column's width, so 1 card sits
   centered, 3rd sits centered below the first two, etc. Checked on the wrapper
   (the real grid item/DOM sibling now) rather than .bet-card-v2 itself, which
   display:contents leaves nested one level deeper. */
#currentBetsList .bet-card-slot:last-child:nth-child(odd) .bet-card-v2 {
  grid-column: 1 / -1;
  justify-self: center;
  width: calc((100% - 12px) / 2);
}

.bet-card-v2 {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 12px;
  transition: background 0.2s, border-color 0.2s;
}

.bet-card-v2:hover {
  background: rgba(16, 185, 129, 0.06);
  border-color: rgba(16, 185, 129, 0.3);
}

.bet-card-v2.is-live {
  border-color: rgba(59, 130, 246, 0.4);
}

.bet-card-v2.is-unlabeled {
  opacity: 0.75;
}

.unlabeled-note {
  color: var(--warning) !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  font-style: italic;
}

.bet-card-v2-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.tip-card {
  /* .tips-results is a grid, which stretches every card in a row to match the
     tallest one - a card with fewer bet-part rows than its row-mate ends up
     taller than its own content, leaving dead space below the actions row.
     Centering the content block within that extra height keeps top/bottom
     spacing equal instead of everything staying packed to the top. */
  justify-content: center;
}

.tip-card .bet-card-v2-top {
  align-items: center;
}

.match-info {
  min-width: 0;
}

.match-info .match-name {
  font-size: 12px;
}

.team {
  color: var(--text);
}

.bet-card-v2.is-live .team {
  color: var(--accent);
}

.team-upcoming {
  color: var(--success);
}

.vs {
  color: var(--text-muted);
  font-weight: 400;
  margin: 0 2px;
}

.match-subtitle {
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tip-bet-indicator {
  display: inline-block;
  margin-top: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(16, 185, 129, 0.15);
  color: var(--success);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* One shared grid for every part row - locks the odds/% columns to the same
   width and position across all rows (instead of each row sizing to its own
   content), and since the columns are auto-sized rather than 1fr, the whole
   block hugs the left side of the card instead of spreading odds/% out to the
   far right edge. */
/* Shared grid so odds/% stay in fixed, aligned columns across every row
   (not each row sizing independently) - gap kept tight so the columns sit
   close together instead of spread out. */
.tip-bet-rows {
  display: grid;
  grid-template-columns: minmax(0, auto) auto auto auto;
  align-items: center;
  gap: 6px 3px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 11px;
}

.tip-bet-desc {
  text-align: left;
  color: var(--accent);
  font-weight: 600;
  white-space: nowrap;
}

.tip-bet-odds {
  text-align: left;
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.tip-bet-pct {
  text-align: left;
  font-family: var(--font-sans);
  font-weight: 500;
  color: var(--text-muted);
}

.tip-bet-check {
  text-align: right;
  color: var(--success);
  font-weight: 700;
  min-width: 14px;
}

/* A row you've already placed a bet on - the whole row fills green (not the
   text), checkmark fills in at the end (the checkmark column is always
   reserved, empty otherwise, so unmatched rows don't jump around when a match
   is found later). Each cell gets its own background rather than one shared
   box (they're separate grid items, not wrapped in a row element) - the
   padding + matching negative margin makes adjacent cells' backgrounds meet
   at the column gap so the row reads as one continuous highlighted bar. */
.tip-bet-desc.tip-bet-matched,
.tip-bet-odds.tip-bet-matched,
.tip-bet-pct.tip-bet-matched,
.tip-bet-check.tip-bet-matched {
  background: rgba(16, 185, 129, 0.18);
  padding: 4px 6px;
  margin: -4px -3px;
  border-radius: 4px;
}


.media-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(59, 130, 246, 0.12);
  color: var(--accent);
  margin-top: 4px;
  transition: background 0.15s, color 0.15s;
}

.media-btn:hover {
  background: var(--accent);
  color: #ffffff;
}

.media-btn svg {
  width: 13px;
  height: 13px;
}

.media-btn-disabled {
  background: var(--hover-overlay);
  color: var(--text-muted);
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* TBT Tips */

.tips-paste-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
}

.tips-header-logo-wrap {
  text-align: center;
  margin-top: -40px;
  margin-bottom: 8px;
}

.header-left-group {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* Grid's middle column (see header's own comment) - justify-self:center is
   what actually centers this regardless of the left group/Balance widths. */
.header-logo-wrap {
  display: flex;
  align-items: center;
  justify-self: center;
}

.header-logo {
  height: 65px;
  width: auto;
  object-fit: contain;
}

.tbt-logo {
  /* A percentage height on an <img> doesn't resolve against a flex-stretched
     (indefinite) parent height - it falls back to the image's huge natural
     pixel size instead. Match the textarea's own min-height explicitly. */
  height: 110px;
  width: auto;
  object-fit: contain;
  flex-shrink: 0;
  filter: grayscale(1);
}

.tips-textarea {
  width: 500px;
  min-height: 110px;
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  font-family: var(--font-sans);
  font-size: 13px;
  resize: none;
}

/* Same footprint as the .panel h2 label it replaces (font-size/weight/
   letter-spacing/centering) but as an actual clickable button. */
.tip-add-toggle-btn {
  display: block;
  margin: 0 auto;
  padding: 6px 16px;
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: #ffffff;
  background: #4b5563;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: opacity 0.15s;
}

.tip-add-toggle-btn:hover {
  opacity: 0.85;
}

/* Same specificity fix as .tip-add-box.hidden above - this button's own
   display:block otherwise wins over the generic .hidden class. */
.tip-add-toggle-btn.hidden {
  display: none;
}

.tip-add-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

/* Wins over .tip-add-box's own display:flex on equal specificity + later
   source order, so toggling .hidden actually hides the box instead of
   leaving it (and the Add Tip button) both visible at once. */
.tip-add-box.hidden {
  display: none;
}

.tip-add-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
}

.tip-add-search-btn,
.tip-add-remove-btn {
  padding: 8px 20px;
  border: none;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: opacity 0.15s;
}

.tip-add-search-btn {
  background: var(--accent);
  color: #ffffff;
}

.tip-add-remove-btn {
  background: var(--danger);
  color: #ffffff;
}

.tip-add-search-btn:hover,
.tip-add-remove-btn:hover {
  opacity: 0.85;
}

.tips-status {
  font-size: 12px;
  color: var(--text-muted);
}

.tips-results-header {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text);
  opacity: 0.85;
  text-align: center;
  margin: 0 0 12px;
}

.tips-results {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.tips-results .tip-card:last-child:nth-child(odd) {
  grid-column: 1 / -1;
  justify-self: center;
  width: calc((100% - 12px) / 2);
}

.tip-card-actions {
  display: flex;
  gap: 10px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.tip-action-btn {
  flex: 1;
  text-align: center;
  padding: 8px 12px;
  border-radius: 8px;
  background: #C1C1C1;
  color: #1a1a1a;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: opacity 0.15s;
}

.tip-action-btn:hover {
  opacity: 0.85;
}

.tip-action-btn.tip-action-secondary {
  background: var(--accent);
  border: none;
  color: #ffffff;
  flex: 0 0 auto;
}

.tip-action-btn.tip-action-secondary.tip-action-365 {
  background: #323232;
}

/* GosuGamers' own brand red (matches gosu.png's logo mark). */
.tip-action-btn.tip-action-secondary.tip-action-gosu {
  background: #a51c1c;
}

/* hawk.live - Dota 2's primary live scoring source (see hawklive.js), distinct
   from GosuGamers' own red since it's a separate provider in its own right. */
.tip-action-btn.tip-action-secondary.tip-action-hawk {
  background: #1c5aa5;
}

.tip-action-btn.tip-action-remove {
  background: var(--danger);
  color: #ffffff;
  flex: 0 0 auto;
  border: none;
  cursor: pointer;
  font-family: var(--font-sans);
}

.tip-action-btn.tip-action-disabled {
  background: var(--hover-overlay);
  color: var(--text-muted);
  opacity: 0.5;
  cursor: not-allowed;
}

.tip-seed-toggle-btn.hidden {
  display: none;
}

.tip-seed-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

.tip-seed-box.hidden {
  display: none;
}

.tip-seed-input {
  flex: 1 1 200px;
  min-width: 150px;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: 12px;
}

.tip-seed-save-btn,
.tip-seed-cancel-btn {
  flex: 0 0 auto;
}

/* --- Parlays --- */

.parlay-search-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 20px;
}

/* Narrower and stacked (button below, not beside) - explicit user choice
   over the wide side-by-side row this used to be. */
.parlay-search-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  width: 320px;
  max-width: 100%;
}

.parlay-search-input {
  width: 100%;
  padding: 10px 14px;
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: var(--font-sans);
  font-size: 13px;
  text-align: center;
}

.parlay-search-btn {
  width: 100%;
  padding: 8px 20px;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: opacity 0.15s;
}

.parlay-search-btn:hover {
  opacity: 0.85;
}

.parlay-search-btn:disabled {
  background: var(--hover-overlay);
  color: var(--text-muted);
  opacity: 0.6;
  cursor: not-allowed;
}

.parlay-search-status {
  font-size: 12px;
  color: var(--text-muted);
}

/* Up to PARLAY_MAX_SEARCH_RESULTS (6) cards, exactly 3 per row and
   centered - same fixed-column-grid technique used for Parlays itself
   before that got reverted to a single column (see .parlays-list's own
   comment) - here it's still the right fit since search results are
   genuinely meant to sit side by side while picking bet types. */
/* flex-wrap, not a fixed grid-template-columns - a CSS grid always reserves
   every declared track regardless of how many items actually exist, so 1-2
   cards sat hugging the left of a (correctly centered) 3-column block
   instead of reading as centered themselves (confirmed live, same bug
   .parlays-list hit earlier - see its own comment). Flex-wrap centers each
   wrapped row independently, so 1 card centers alone, 2 center as a pair,
   and a 4th+ card centers on its own row below. max-width caps the
   container at exactly 3 fixed-width cards + gaps so wrapping kicks in
   after 3 rather than however many happen to fit the panel's real width.
   Sync with .parlay-search-card's own width below if either changes. */
.parlay-search-results-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  max-width: calc(300px * 3 + 12px * 2);
  margin: 0 auto 20px;
}

/* Same fixed width as .parlay-card - explicit user choice so a searched
   match and an already-added parlay card read as the same size. */
/* Same min-width:0 fix as .parlay-card's own comment - prevents a long
   team/tournament name from forcing this wider than its flex-basis. */
.parlay-search-card {
  flex: 0 0 300px;
  min-width: 0;
  max-width: 100%;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px;
  font-size: 12px;
}

.parlay-search-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.parlay-search-close-btn {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: var(--hover-overlay);
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.parlay-search-close-btn:hover {
  background: var(--danger);
  color: #ffffff;
}

.parlay-search-teams {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.parlay-search-subtitle {
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}

.parlay-pick-row {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.parlay-pick-btn {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

.parlay-pick-btn.parlay-pick-selected {
  background: rgba(59, 130, 246, 0.18);
  border-color: var(--accent);
  color: var(--accent);
}

.parlay-market-select {
  width: 100%;
  margin-top: 12px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12px;
}

.parlay-market-fields {
  margin-top: 10px;
}

.parlay-market-note {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 10px;
}

.parlay-value-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

.parlay-value-row label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.parlay-value-input {
  width: 90px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12px;
}

.parlay-odds-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}

.parlay-odds-row label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.parlay-odds-input {
  width: 90px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12px;
}

.parlay-add-targets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.parlay-add-target-btn {
  padding: 8px 14px;
  border: none;
  border-radius: 8px;
  background: var(--success);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: opacity 0.15s;
}

.parlay-add-target-btn.parlay-add-new-btn {
  background: var(--hover-overlay);
  color: var(--text);
}

.parlay-add-target-btn:hover {
  opacity: 0.85;
}

.parlays-list-header {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--text);
  opacity: 0.85;
  text-align: center;
  margin: 0 0 12px;
}

/* Vertically stacked, one per row - explicit user choice, unlike the
   two-column .tips-results grid. */
/* Centered, single-column stack - explicit user choice over an earlier
   multi-column grid attempt (see git history), reverted once seen rendered:
   a lone Parlay #1 sat left-aligned under a "3 fixed columns" grid instead
   of reading as centered. */
/* Side by side, same flex-wrap-and-center technique as
   .parlay-search-results-list (see its own comment for why not a fixed
   grid-template-columns) - up to 3 per row, centered whether there's 1, 2,
   or 3+ cards, wrapping onto a new centered row after that. */
.parlays-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  max-width: calc(320px * 3 + 14px * 2);
  margin: 0 auto;
}

/* min-width:0 overrides a flex item's own default min-width:auto - without
   it, a long unbreakable value inside (a big stake number, a long team
   name) can force this wider than its flex-basis instead of wrapping/
   truncating within it, which is exactly why two cards with different
   content were rendering at two different widths despite an identical
   flex-basis. */
.parlay-card {
  flex: 0 0 320px;
  min-width: 0;
  max-width: 100%;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
}

.parlay-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.parlay-card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.parlay-status {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.parlay-status-pending {
  background: var(--hover-overlay);
  color: var(--text-muted);
}

.parlay-status-won {
  background: rgba(16, 185, 129, 0.15);
  color: var(--success);
}

.parlay-status-lost {
  background: rgba(239, 68, 68, 0.15);
  color: var(--danger);
}

.parlay-delete-btn {
  padding: 6px 14px;
  border: none;
  border-radius: 8px;
  background: var(--danger);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: opacity 0.15s;
}

.parlay-delete-btn:hover {
  opacity: 0.85;
}

.parlay-legs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.parlay-leg-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.parlay-leg-match {
  flex: 1;
  min-width: 0;
}

.parlay-leg-teams {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.parlay-leg-pick {
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 2px;
}

.parlay-leg-countdown {
  font-size: 10px;
  color: var(--accent);
  margin-top: 2px;
}

.parlay-leg-odds-value {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
}

.parlay-leg-edit-btn {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-left: 4px;
  border: none;
  border-radius: 50%;
  background: var(--hover-overlay);
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.parlay-leg-edit-btn:hover {
  background: var(--accent);
  color: #ffffff;
}

.parlay-leg-check {
  flex: 0 0 auto;
  width: 20px;
  text-align: center;
  font-weight: 700;
}

.parlay-leg-win {
  color: var(--success);
}

.parlay-leg-loss {
  color: var(--danger);
}

.parlay-leg-push {
  color: var(--warning);
  font-size: 11px;
}

.parlay-leg-pending {
  color: var(--text-muted);
}

.parlay-leg-remove {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: var(--hover-overlay);
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.parlay-leg-remove:hover {
  background: var(--danger);
  color: #ffffff;
}

.parlay-card-footer {
  display: flex;
  gap: 20px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.parlay-stake-field,
.parlay-payout-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.parlay-stake-value-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.parlay-stake-field label,
.parlay-payout-field label {
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.parlay-stake-input {
  width: 140px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12px;
}

.parlay-payout-value {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--success);
  font-size: 13px;
  padding-top: 4px;
}

.tip-seed-status {
  flex-basis: 100%;
  font-size: 11px;
  color: var(--text-muted);
}

.score-area {
  min-width: 0;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  text-align: right;
}

/* Reserves the same height whether or not a LIVE badge is actually shown, so the
   score/countdown line below always lands at the same vertical position. */
.badge-slot {
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: center;
}

.live-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(239, 68, 68, 0.15);
  color: var(--danger);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.05em;
  animation: pulse-soft 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.live-badge::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--danger);
  margin-right: 5px;
}

.starts-in-label {
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}

.big-score {
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 800;
  color: #ff3b5c;
  line-height: 1.1;
  align-self: center;
  text-align: center;
}

.big-score.countdown {
  font-size: 16px;
  font-weight: 700;
  font-family: var(--font-mono);
  color: var(--success);
}

.big-score.unknown {
  font-size: 13px;
  font-family: var(--font-sans);
  font-weight: 600;
  color: var(--text-muted);
}

.live-time {
  font-size: 10px;
  color: var(--success);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  min-height: 14px;
  align-self: center;
  text-align: center;
}

.tennis-score-mini {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: #ff3b5c;
  opacity: 0.7;
  line-height: 1.1;
  align-self: center;
  text-align: center;
}

/* The still-live set's point score only (dashboard.js's volleyballScoreBlock
   - finished sets don't get a line here at all, just counted into the
   Over/Under Total running total shown next to the bet type instead). */
.volleyball-set-line {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  color: #ff3b5c;
  opacity: 0.7;
  line-height: 1.25;
  align-self: center;
  text-align: center;
}

/* The running total next to an Over/Under Total bet's own name
   (dashboard.js's betTypeLabel) - volleyball's own points total (its score
   is sets won, not points) and basketball's combined score both use this -
   only shown while the bet is still open, so green instead of the bet-type
   text's own blue keeps it reading as "still live/moving" rather than part
   of the bet's fixed name. */
.live-running-total {
  color: var(--success);
}

/* Break Point/Match Point tag next to tennis's live game-point score, see
   dashboard.js's tennisScoreBlock. MP is the higher-stakes moment (red,
   matches the danger color used elsewhere for "this matters now" signals),
   BP a notable-but-not-decisive one (amber). */
.tennis-point-tag {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.tennis-point-tag-bp {
  background: rgba(245, 158, 11, 0.16);
  color: var(--warning);
}

.tennis-point-tag-mp {
  background: rgba(239, 68, 68, 0.16);
  color: var(--danger);
}

/* Batting team's runs/wickets (overs) line and live commentary, see
   dashboard.js's cricketScoreBlock - same treatment as tennis's/volleyball's
   own mini score lines. */
.cricket-score-line {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: #ff3b5c;
  opacity: 0.7;
  line-height: 1.25;
  align-self: center;
  text-align: center;
}

/* Live supplementary score line - Dota 2 kill count (hawk.live) or
   Counter-Strike's current-map round score (strafe.com), see dashboard.js's
   scoreBlock. Same layout treatment as tennis's set-score sub-line, red and
   not bold to read as a plain secondary stat rather than another score. */
.live-sub-score {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  color: var(--danger);
  opacity: 0.7;
  line-height: 1.1;
  align-self: center;
  text-align: center;
}

/* Even 4-column row (Bet Type/Stake/Odds/Potential Return) below a divider, so
   columns line up the same way across every card regardless of text length.
   align-items:start keeps every column's content flush with the top of the
   row even when Bet Type wraps to two lines, so the card's bottom padding
   below it stays visually consistent across cards. */
.bet-detail-group {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: start;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.bet-detail-potential-return {
  text-align: right;
}

.bet-detail-bet-type .bet-detail-value {
  white-space: normal;
  word-wrap: break-word;
  font-size: 11px;
  font-family: var(--font-sans);
}

.bet-type-selection {
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
}

.bet-type-outcome {
  font-size: 10px;
  font-weight: 400;
  color: var(--text);
  margin-top: 2px;
}

.bet-detail-stake .bet-detail-value,
.bet-detail-odds .bet-detail-value,
.bet-detail-potential-return .bet-detail-value {
  font-family: var(--font-mono);
}

.bet-detail-label {
  font-size: 9px;
  color: var(--text-muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.bet-detail-value {
  margin-top: 3px;
  font-weight: 700;
  color: var(--text);
}

.bet-detail-value.selection {
  color: var(--accent);
}

.bet-detail-value.odds {
  color: var(--text);
}

.odds-high {
  color: var(--warning);
}

.bet-detail-value.positive {
  color: #3cff7a;
}

/* Grouped bet rows inside current-bet cards */

.bet-rows {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.bet-row-header {
  display: grid;
  grid-template-columns: 2fr 16px 1fr 0.8fr 1.2fr;
  gap: 8px;
  padding-bottom: 5px;
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.bet-row-header div:last-child {
  text-align: right;
}

.bet-row {
  display: grid;
  grid-template-columns: 2fr 16px 1fr 0.8fr 1.2fr;
  gap: 8px;
  padding: 5px 0;
  align-items: center;
}

/* Live "currently covering" checkmark for Over/Asian Handicap bets - always
   reserves this column's width (empty otherwise) so rows don't shift when
   it appears/disappears as the live score changes. */
.bet-row-check {
  color: var(--success);
  font-weight: 700;
  font-size: 12px;
  text-align: center;
}

.bet-row + .bet-row {
  border-top: 1px solid var(--border-soft);
}

.bet-row-type .bet-type-selection {
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
}

.current-bet-tip-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 224, 0, 0.16);
  color: #ffe000;
  text-shadow: 0 0 6px rgba(255, 224, 0, 0.6);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

/* Light mode only - the neon glow reads fine on the near-black dark theme but
   looks out of place on a light background, so it's dropped for a plain
   yellow here instead. Dark mode above is untouched. */
body.light-mode .current-bet-tip-badge {
  background: rgba(202, 138, 4, 0.14);
  color: #ca8a04;
  text-shadow: none;
}

/* Same treatment as .current-bet-tip-badge, distinct purple so it reads as a
   different signal at a glance (part of an active parlay, not a TBT tip). */
.current-bet-parlay-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(239, 68, 68, 0.16);
  color: #f87171;
  text-shadow: 0 0 6px rgba(239, 68, 68, 0.5);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

body.light-mode .current-bet-parlay-badge {
  background: rgba(220, 38, 38, 0.14);
  color: var(--danger);
  text-shadow: none;
}

.current-bet-combined-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(120, 170, 255, 0.16);
  color: #78aaff;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

.parlay-add-from-bet-btn {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border: none;
  border-radius: 999px;
  background: var(--hover-overlay);
  color: var(--text-muted);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  vertical-align: middle;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.parlay-add-from-bet-btn:hover {
  background: var(--success);
  color: #ffffff;
}

.parlay-add-from-bet-box {
  padding: 8px 0 2px;
}

.parlay-add-from-bet-box.hidden {
  display: none;
}

.parlay-add-from-bet-box .parlay-add-targets {
  margin: 0;
  padding: 0;
  border: none;
}

.bet-row-type .bet-type-outcome {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-muted);
  margin-top: 1px;
}

.bet-row-stake,
.bet-row-odds {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  color: var(--text);
}

.bet-row-payout {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  color: #3cff7a;
  text-align: right;
}

/* Light mode only - dark mode's neon green above is untouched. */
body.light-mode .bet-row-payout {
  color: #16a34a;
}

/* Manual label form — shown on unlabeled current bet cards */

.label-form-wrap {
  padding: 10px 0 2px;
  border-top: 1px solid var(--border-soft);
}

/* Awaiting Payment/Completed Bets' .bet-card has no grid-template-areas on
   desktop (implicit 9-column DOM-order grid) and named areas on mobile - this
   explicit column span works for both without needing a named area of its
   own, placing the form on its own full-width row after the rest of the card. */
.bet-card-label-form-wrap {
  grid-column: 1 / -1;
}

.label-add-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-muted);
  font-size: 11px;
  font-family: var(--font-sans);
  padding: 4px 10px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.label-add-btn:hover,
.label-add-btn.active {
  color: var(--accent);
  border-color: var(--accent);
}

.label-form {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
  align-items: center;
}

.label-form.hidden { display: none; }

.label-input,
.label-select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 11px;
  font-family: var(--font-sans);
  padding: 4px 8px;
  outline: none;
  transition: border-color 0.15s;
}

.label-input:focus,
.label-select:focus { border-color: var(--accent); }

.label-input[name="matchName"] { flex: 1 1 180px; }
.label-select { flex: 0 1 130px; }
.label-input[type="datetime-local"] { flex: 0 1 160px; color-scheme: dark; }

.label-save-btn {
  background: var(--accent);
  border: none;
  border-radius: 4px;
  color: #fff;
  font-size: 11px;
  font-family: var(--font-sans);
  font-weight: 600;
  padding: 4px 14px;
  cursor: pointer;
  transition: opacity 0.15s;
}

.label-save-btn:hover { opacity: 0.85; }
.label-save-btn:disabled { opacity: 0.5; cursor: default; }

/* "Mark Paid" action — shown on Awaiting Payment rows only (see
   paymentActionsHtml in dashboard.js) */

.payment-action-wrap { margin-top: 4px; }

.payment-action-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.payment-action-menu.hidden { display: none; }

/* Torn API / Sofascore online status badges */

.header-search-wrap {
  position: relative;
  align-self: center;
}

/* Mobile-only elements (see the mobile media query for their actual
   appearance) - desktop shows the search input directly and already has the
   Torn username in the sidebar profile block, so all three stay hidden here. */
.header-mobile-row,
.header-username,
.header-search-toggle {
  display: none;
}

.header-search-input {
  width: 200px;
  height: 34px;
  background: var(--card);
  color: var(--text);
  border: 2px solid var(--border);
  border-radius: 10px;
  padding: 0 30px 0 14px;
  font-family: var(--font-sans);
  font-size: 13px;
}

.header-search-input::placeholder {
  color: var(--text-muted);
}

.header-search-clear {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: 8px;
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.header-search-clear:hover {
  color: var(--text);
}

/* Wins the display:flex from .header-search-results below on equal
   specificity + later source order, so toggling .hidden actually hides it
   instead of leaving an empty bordered pill visible. */
.header-search-results.hidden {
  display: none;
}

.header-search-results {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 6px;
  width: 480px;
  max-height: 420px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 60;
}

.search-result-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
}

.search-result-match {
  min-width: 0;
  flex: 1;
}

.search-result-date {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 2px;
}

.search-result-profit {
  font-family: var(--font-mono);
  font-weight: 700;
  white-space: nowrap;
}

/* Sidebar settings item + balance display + panel header row */

.balance-display {
  text-align: right;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 14px;
  padding: 10px 18px;
  min-width: 200px;
  justify-self: end;
}

.balance-label {
  font-size: 10px;
  color: var(--text-muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.15em;
}

.balance-label::after {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  margin-left: 6px;
  box-shadow: 0 0 6px rgba(16, 185, 129, 0.7);
  vertical-align: middle;
}

.balance-value {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 800;
  color: var(--success);
  margin-top: 2px;
}

/* Wraps the range selector + table together so the selector's flex-end
   alignment lines up with the table's actual (fit-content) right edge -
   i.e. right above the Profit column - instead of the wider panel's edge. */
.table-align-wrap {
  width: fit-content;
  margin: 0 auto;
}

.table-align-wrap .bet-card-header,
.table-align-wrap .bet-card-list {
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}

/* Desktop home for #rangeSelectRow (see index.html/dashboard.js's own
   comments on why it physically moves between here and #mobileRangeAnchor) -
   replaces the old chart panel's own bottom margin now that the range picker
   is the only thing above Current Bets. */
.range-select-panel {
  margin-bottom: 24px;
}

.range-select-row {
  display: flex;
  justify-content: flex-end;
}

.range-select-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-muted);
  font-weight: 600;
}

.range-select-wrap select {
  padding: 3px 6px;
  font-size: 11px;
}

/* Settings modal */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

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

.modal {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 16px;
  width: 360px;
  max-width: 90vw;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  border-bottom: 1px solid var(--border);
}

.modal-header h2 {
  margin: 0;
  font-size: 15px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.modal-cancel {
  margin-top: 8px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-sans);
}

.modal-cancel:hover {
  background: var(--hover-overlay);
}

.modal-body {
  padding: 16px;
  display: flex;
  flex-direction: column;
}

/* The settings form wraps every field so Safari/Chrome offer to save the API
   key to their password manager (see index.html's own comment) - it's now
   .modal-body's only direct child, so it needs the same flex layout that
   used to apply straight to .modal-body's children, or everything inside
   would collapse back to plain block stacking with none of the existing
   spacing rules between fields. */
.modal-body form {
  display: flex;
  flex-direction: column;
}

.modal-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text);
  margin-top: 12px;
}

.modal-label:first-child {
  margin-top: 0;
}

/* Groups a .modal-label with its .info-icon on one line - the row (not the
   label itself) now carries the top spacing between fields, since the label
   is no longer always the direct flex child of .modal-body. */
.modal-label-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
}

.modal-label-row:first-child {
  margin-top: 0;
}

.modal-label-row .modal-label {
  margin-top: 0;
}

/* Replaces the old always-visible .modal-hint definitions - the same text now
   only shows up as a hover/focus tooltip, so the settings list reads as a
   list of controls instead of a page of documentation. */
.info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border: 1px solid var(--text-muted);
  border-radius: 50%;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 700;
  text-transform: none;
  letter-spacing: normal;
  cursor: help;
  position: relative;
}

.info-icon::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  margin-top: 6px;
  width: max-content;
  max-width: min(220px, 60vw);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text);
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.4;
  white-space: normal;
  text-align: left;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  pointer-events: none;
  z-index: 10;
}

.info-icon:hover::after,
.info-icon:focus::after {
  opacity: 1;
  visibility: visible;
}

.modal-hint {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
  margin-bottom: 6px;
}

.modal-input {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--font-sans);
}

.modal-save {
  margin-top: 16px;
  background: var(--accent);
  color: #ffffff;
  border: none;
  border-radius: 10px;
  padding: 10px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-sans);
}

.modal-save:hover {
  opacity: 0.9;
}

.modal-status {
  margin-top: 8px;
  font-size: 12px;
  color: var(--success);
  min-height: 14px;
}

/* ---------- Mobile (phones/small tablets) ----------
   Everything below only applies at this width - desktop layout above is
   untouched. Turns the sidebar into a fixed bottom icon bar (a left rail
   still steals width asymmetrically, shifting the rest of the page off-
   center), stacks the header and card grids to a single column, drops the
   growth chart, and lets the dense fixed-column tables (Awaiting Payment /
   Completed Bets) scroll horizontally within their own row instead of
   overflowing/breaking the page - a full stacked-card rework of those
   tables would need dashboard.js render changes too, out of scope for a
   CSS-only pass. */
@media (max-width: 768px) {
  /* A left-side icon rail still steals width asymmetrically, shifting
     everything else off-center on a narrow screen - a plain in-flow top bar
     instead frees the full viewport width for main-content below it.
     (position:fixed was tried here first but rendered inconsistently on
     iOS Safari, overlapping the header underneath it - a normal in-flow
     element sidesteps that entirely, nothing can render behind it.) */
  .app-layout {
    flex-direction: column;
  }

  .sidebar {
    position: static;
    /* Desktop's "flex: 0 0 200px" sets a fixed 200px *width* in the row-
       layout sidebar - .app-layout switches to a column flex container on
       mobile, so that same flex-basis gets reinterpreted as a fixed
       *height* instead, forcing a 200px bar no matter how little content is
       in it. height:auto alone doesn't override a flex-basis - the actual
       fix is resetting flex-basis itself so the bar sizes to its content. */
    flex: 0 0 auto;
    width: 100%;
    height: auto;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 2px;
    gap: 28px;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }

  .sidebar-profile {
    display: none;
  }

  /* .sidebar-nav (3 icons) and .sidebar-bottom (2 icons) used to each get
     flex:1 (an even 50/50 split of the row) and independently space-around
     their own icons - since one group has 3 icons and the other has 2, that
     produced visibly different gaps between icons depending on which group
     they were in. Sizing both to their own content (not stretched) and
     giving every gap - within each group, and between the two groups on
     .sidebar itself - the same fixed value makes all 5 icons evenly spaced
     as one continuous row instead of two independently-distributed halves. */
  .sidebar-nav,
  .sidebar-bottom {
    display: flex;
    flex-direction: row;
    flex: 0 0 auto;
    justify-content: flex-start;
    margin: 0;
    gap: 28px;
  }

  .sidebar-item span {
    display: none;
  }

  .sidebar-item {
    justify-content: center;
    padding: 3px 10px;
  }

  .sidebar .nav-icon {
    width: 18px;
    height: 18px;
  }

  .main-content {
    padding: 12px;
  }

  /* Single column - each of the three header children (left group, logo,
     Balance) becomes its own full-width centered row instead of the desktop
     3-column layout, in source order (left group, logo, Balance - see
     index.html), so no explicit order/row placement is needed here. */
  header {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 10px;
    margin-bottom: 16px;
  }

  .header-left-group {
    width: 100%;
    flex-direction: column;
    gap: 8px;
  }

  .header-logo-wrap {
    justify-content: center;
  }

  /* Username + search trigger share one row - the glass button is pinned to
     the right edge (position:absolute) rather than using justify-content, so
     the username can be truly centered across the *whole* row instead of
     just centered in the leftover space next to the button. */
  .header-mobile-row {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    gap: 8px;
  }

  .header-username {
    display: block;
    width: 100%;
    text-align: center;
    font-size: 11px;
    color: var(--text-muted);
  }

  .header-username strong {
    color: var(--text);
    font-weight: 700;
  }

  /* Search collapses to just a magnifying-glass button - tapping it (see the
     click handler in dashboard.js) reveals the real input in its place
     instead of the input always taking up space. flex:0 0 auto by default
     (sized to the button alone) so it sits snug next to the username on the
     shared row - .search-active below switches it to fill the row instead,
     once there's an actual input to show. */
  .header-search-wrap {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }

  /* Stretches to fill the whole row (both edges pinned) once there's an
     actual input to show, rather than staying sized to just the button. */
  .header-search-wrap.search-active {
    left: 0;
  }

  .header-search-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    padding: 6px;
    cursor: pointer;
  }

  .header-search-toggle svg {
    width: 20px;
    height: 20px;
  }

  .header-search-input,
  .header-search-clear {
    display: none;
  }

  .header-search-wrap.search-active .header-search-toggle {
    display: none;
  }

  .header-search-wrap.search-active .header-search-input {
    display: block;
  }

  .header-search-wrap.search-active .header-search-clear {
    display: flex;
  }

  .header-search-input {
    width: 100%;
    max-width: 260px;
  }

  .header-search-results {
    width: 90vw;
    left: 50%;
    transform: translateX(-50%);
  }

  .balance-display {
    min-width: 0;
    text-align: center;
    justify-self: center;
  }

  /* Kept low-key on purpose - this is a filter control, not something that
     should compete visually with the bet panels below it. */
  .range-select-row {
    justify-content: center;
    margin-bottom: 14px;
  }

  .range-select-wrap {
    font-size: 10px;
    opacity: 0.75;
  }

  .range-select-wrap select {
    font-size: 11px;
    padding: 3px 6px;
  }

  /* Desktop's -40px pulls the TBT logo up to sit closer to the header above
     it, on the assumption of more vertical space there - on mobile that same
     pull puts it right up against the Balance card, so it's relaxed to a
     small positive gap instead. */
  .tips-header-logo-wrap {
    margin-top: 12px;
  }

  /* Current Bets / Completed Bets collapse toggles - saves scroll space,
     desktop never gets the .collapsed class toggled visually since neither
     of these two rules exist outside this mobile block. */
  .collapsible-header {
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
  }

  .collapse-chevron {
    font-size: 11px;
    color: var(--text-muted);
    display: inline-block;
    transition: transform 0.15s;
  }

  .collapse-chevron::before {
    content: '\25BE';
  }

  .collapsible-panel.collapsed .collapse-chevron {
    transform: rotate(-90deg);
  }

  .collapsible-panel.collapsed .collapsible-body {
    display: none;
  }

  #currentBetsList,
  .tips-results {
    grid-template-columns: 1fr;
  }

  .parlay-search-results-list,
  .parlays-list {
    max-width: 100%;
  }

  .parlay-search-card,
  .parlay-card {
    flex-basis: 100%;
  }

  #currentBetsList .bet-card-slot:last-child:nth-child(odd) .bet-card-v2,
  .tips-results .tip-card:last-child:nth-child(odd) {
    width: 100%;
  }

  .tips-textarea {
    width: 100%;
  }

  .parlay-search-row {
    width: 100%;
  }

  .parlay-card-footer {
    flex-direction: column;
    gap: 10px;
  }

  /* "Place Bet in Torn" (flex:1) already stretches to fill the row when
     present, so this only visibly changes anything for the "View on ..."/
     Remove buttons on a tip with no matching Torn bet - those are flex:0 0
     auto and previously sat flush-left with nothing to center them. */
  .tip-card-actions {
    justify-content: center;
  }

  .table-align-wrap {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
  }

  /* Awaiting Payment / Completed Bets reflow from a desktop table row into a
     stacked card (mobile/code.html's layout) - same underlying elements as
     the desktop table (kickoff/match/pick/odds/stake/result/payment/payout/
     profit), just regrouped into a 4-column grid via named areas instead of
     a new markup structure. Column headers don't apply once rows are cards. */
  .bet-card-header {
    display: none;
  }

  /* Unscoped (not just inside .table-align-wrap) - Awaiting Payment's list
     isn't wrapped in that div but needs the same full-width treatment as
     Completed Bets' and Current Bets' lists once cards stack single-column. */
  .bet-card-list {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
  }

  .bet-card {
    display: grid;
    /* Fixed proportional fr units only - no auto/minmax content-sized tracks
       (see the min-width:0 comment below for why). Same 5-column shape as
       Current Bets' own card grid (.bet-row/.bet-row-header - "2fr 16px 1fr
       0.8fr 1.2fr") including its empty 16px checkmark-width spacer column,
       so Stake/Odds/Profit land at the same x-position as their Current Bets
       counterparts when scrolling between the two sections. */
    grid-template-columns: 2fr 16px 1fr 0.8fr 1.2fr;
    grid-template-areas:
      "kickoff  kickoff  kickoff  kickoff  kickoff"
      "match    match    match    match    result"
      "hdrtype  hdrgap   hdrstake hdrodds  hdrprofit"
      "pick     gap      stake    odds     profit";
    column-gap: 10px;
    row-gap: 6px;
    padding: 10px 14px;
    border-left-width: 3px;
    border-left-style: solid;
    width: 100%;
    max-width: 100%;
    overflow: hidden;
    /* Content-dependent column sizing (the previous minmax(0,1fr)/auto mix)
       let each column's width depend on that column's own content, which
       real iPhone screenshots showed rendering each card at a visibly
       different overall width - not reproducible in a Chromium-based
       preview, and not fixed by min-width:0 alone, so the fixed fr units
       above and this min-width:0 (the standard fix for a flex/grid item's
       automatic minimum-size default overriding an explicit width) both
       stayed even after moving to fr units, as a hard backstop. */
    min-width: 0;
  }

  .bet-card-result-win { border-left-color: var(--success); }
  .bet-card-result-loss { border-left-color: var(--danger); }
  .bet-card-result-refund { border-left-color: var(--warning); }
  .bet-card-result-pending,
  .bet-card-result-none { border-left-color: var(--border); }

  .bet-card-kickoff {
    grid-area: kickoff;
    display: flex;
    gap: 4px;
  }

  /* The two lines kickoffCell() outputs (date, time) become "date · time"
     on one line instead of stacked, without needing to touch the JS. */
  .bet-card-kickoff > div:last-child::before {
    content: '\00B7\0020';
  }

  .bet-card-match { grid-area: match; }

  /* Per-card mini header ("Bet Type / Stake / Odds / Profit"), matching
     Current Bets' own per-card .bet-row-header - hidden entirely outside
     this mobile block (see the base .bet-card-mini-th/.bet-card-gap rule),
     since desktop already has one shared header above the whole list. */
  .bet-card-mini-th {
    display: block;
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
  }

  .bet-card-mini-th-type { grid-area: hdrtype; }
  .bet-card-mini-th-gap { grid-area: hdrgap; }
  .bet-card-mini-th-stake { grid-area: hdrstake; }
  .bet-card-mini-th-odds { grid-area: hdrodds; }
  .bet-card-mini-th-profit { grid-area: hdrprofit; text-align: right; }
  .bet-card-gap { display: block; grid-area: gap; }

  .bet-card-pick {
    grid-area: pick;
    min-width: 0;
  }

  /* Belt-and-suspenders alongside .bet-card's own overflow:hidden - forces
     wrapping even if Safari still tries to size the track to this text's
     un-shrunk content width. */
  .bet-card-pick .pick-name,
  .bet-card-pick .pick-sub {
    overflow-wrap: break-word;
    word-break: break-word;
  }
  .bet-card-odds { grid-area: odds; }
  .bet-card-stake { grid-area: stake; }

  .bet-card-result {
    grid-area: result;
    justify-self: end;
  }

  .bet-card-profit {
    grid-area: profit;
    justify-self: end;
    align-self: end;
    font-size: 15px;
    font-weight: 700;
  }

  /* Not part of mobile/code.html's card - .bet-card-profit already covers
     the monetary outcome, and payment status is a secondary detail. */
  .bet-card-payment,
  .bet-card-payout {
    display: none;
  }

  .match-sport {
    display: inline-block;
    background: var(--hover-overlay);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 1px 6px;
    margin-top: 4px;
  }

  /* Tournament name and the fire-odds emoji dropped on mobile only - sport
     alone is enough context at this size, and a long tournament name
     ("World Cup Qualification Asia 1st Round Group...") was suspected of
     contributing to the card-width inconsistency reported on a real phone. */
  .subtitle-competition,
  .odds-fire {
    display: none;
  }

  /* Swap back to the short money format on mobile (desktop shows the full
     one by default - see the base .money-mobile rule above). */
  .money-full {
    display: none;
  }
  .money-mobile {
    display: inline;
  }

  /* Current Bets / TBT Tips cards get the same left-edge accent language as
     the Awaiting/Completed cards above, instead of the desktop's all-around
     border - green while the match is actually live, neutral otherwise. */
  .bet-card-v2 {
    border-left-width: 3px;
    border-left-color: var(--border);
    /* Same fix as .bet-card above: as a grid item, this defaults to a
       content-based min-width, so an unbreakable long match name (nowrap +
       ellipsis on .match-name-text) still forced the card - and the whole
       page - wider instead of actually truncating. min-width: 0 lets it
       shrink to the grid track's real width so the ellipsis can take effect. */
    width: 100%;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
  }

  .bet-card-v2.is-live {
    border-left-color: var(--success);
  }

}

/* --- Admin page - deliberately minimal, no live polling/diffing like the
   rest of the app (see loadAdminUsers/loadAdminUserBets in dashboard.js) -
   just a plain list and a plain row layout reusing the existing color
   variables/panel spacing. */
.admin-users-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.admin-user-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: var(--card);
  cursor: pointer;
  transition: background 0.15s;
}

.admin-user-row:hover {
  background: var(--hover-overlay);
}

.admin-user-name {
  font-weight: 700;
  color: var(--text);
}

.admin-user-lastseen {
  font-size: 12px;
  color: var(--text-muted);
}

.admin-bets-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.admin-bets-header h2 {
  margin: 0;
}

.admin-back-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 12px;
  font-family: var(--font-sans);
  padding: 4px 10px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.admin-back-btn:hover {
  color: var(--text);
  border-color: var(--text-muted);
}

.admin-bets-updated {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 10px;
}

.admin-bets-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.admin-bet-row {
  display: grid;
  grid-template-columns: 1fr auto auto auto auto;
  align-items: center;
  gap: 16px;
  padding: 12px 16px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.admin-bet-match-name {
  font-weight: 700;
  color: var(--text);
}

.admin-bet-sport {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

.admin-bet-pick {
  color: var(--accent);
  font-weight: 600;
}

.admin-bet-odds,
.admin-bet-stake,
.admin-bet-payout {
  font-family: var(--font-mono);
  font-weight: 700;
  text-align: right;
  white-space: nowrap;
}

@media (max-width: 768px) {
  .admin-bet-row {
    grid-template-columns: 1fr;
    justify-items: start;
    gap: 4px;
  }

  .admin-bet-odds,
  .admin-bet-stake,
  .admin-bet-payout {
    text-align: left;
  }
}
