* { box-sizing: border-box; }
:root {
  /* EdgeBeacon brand cyan — matches the lighthouse glow in the logo. Reused
     for the wordmark, the active-tab underline, and any small accents that
     should carry the brand through the UI. */
  --brand: #22d3ee;
  --brand-dim: #0891b2;
  --brand-glow: rgba(34, 211, 238, 0.28);

  /* Surface layers — the page goes from deepest (body) to brightest (active
     hover). Laddering helps content feel elevated instead of flat. */
  --surface-0: #0a0e14;       /* deepest — body */
  --surface-1: #11161f;       /* section containers */
  --surface-2: #161c28;       /* table cells / cards */
  --surface-3: #1c2230;       /* headers / controls */
  --surface-4: #232a3a;       /* hover raise */
  --border-soft: #202838;
  --border-mid:  #2a3243;
  --border-hot:  #3a4760;

  --text-hi:  #f1f5fb;
  --text-md:  #c8d2e3;
  --text-lo:  #8a99b5;
  --text-dim: #5a6a85;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 18px;

  --shadow-card: 0 10px 30px -10px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35);
  --shadow-float: 0 20px 48px -18px rgba(0, 0, 0, 0.7), 0 4px 12px rgba(0, 0, 0, 0.4);

  --ease-out: cubic-bezier(0.2, 0.9, 0.3, 1);
}
html { scroll-behavior: smooth; }
body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-feature-settings: "cv11", "ss01", "ss03";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background:
    radial-gradient(1200px 600px at 8% -10%, rgba(34, 211, 238, 0.08), transparent 60%),
    radial-gradient(900px 500px at 95% 0%, rgba(59, 130, 246, 0.07), transparent 55%),
    radial-gradient(1100px 700px at 50% 120%, rgba(168, 85, 247, 0.05), transparent 60%),
    linear-gradient(180deg, #0a0e14 0%, #0b1017 100%);
  background-attachment: fixed;
  color: var(--text-hi);
  margin: 0;
  padding: 0 28px 56px;
  letter-spacing: -0.005em;
}
/* Thin custom scrollbars so overflow areas feel product-grade.
   Bumped from near-invisible slate (#252d3e on #0f1524) to a lighter
   cyan-tinted track so the scrollbar is actually discoverable against
   the dark page background. Hover state brightens further for feedback. */
*::-webkit-scrollbar { width: 12px; height: 12px; }
*::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.04);
  border-radius: 10px;
}
*::-webkit-scrollbar-thumb {
  background: #4a5a78;
  border-radius: 10px;
  border: 2px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: #6b7ea0;
  background-clip: content-box;
  border: 2px solid transparent;
}
*::-webkit-scrollbar-thumb:active {
  background: #22d3ee;
  background-clip: content-box;
  border: 2px solid transparent;
}
/* Firefox — it only supports scrollbar-color (thumb track) and scrollbar-width */
* {
  scrollbar-color: #4a5a78 rgba(255, 255, 255, 0.04);
  scrollbar-width: thin;
}

header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 0 18px;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 18px;
  position: relative;
  z-index: 5;
}
/* When either Markets or Sportsbooks dropdown (both inside header > .status)
   is open, catapult the whole header above every later stacking context —
   the support bar, tab filter bars, sticky table headers, and data rows.
   Without this the dropdown paints behind those later elements because the
   default header z-index can't compete with their built-up stacking. */
header:has(.books-dropdown-wrap.open) {
  z-index: 3000;
}
header::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(34, 211, 238, 0.35) 50%, transparent 100%);
  opacity: 0.5;
}
h1 { margin: 0; font-size: 22px; letter-spacing: 0.3px; }

/* ---------------------------------------------------------------------------
   Brand lockup — lighthouse logo to the left, "EdgeBeacon" wordmark to the
   right. "Edge" reads in the default light color; "Beacon" picks up the
   brand cyan so the mark matches the reference logo lockup.

   Design notes:
   - Logo sits flush on the header background (no framed box) so the mark
     floats, matching how premium product headers (YouTube Premium, Amazon
     Prime, Dodgers) present their marks.
   - The SVG has the baked-in dark canvas rect removed, so only the
     lighthouse + beam remain, and they can visually overlap the wordmark
     baseline for a tight lockup rather than sitting in a panel.
   - Drop-shadow is a whisper of cyan so the beam still feels "lit"
     without dominating the element.
   --------------------------------------------------------------------------- */
.brand {
  display: inline-flex; align-items: center; gap: 14px;
  line-height: 1;
}
.brand-logo {
  width: 56px; height: 56px;
  display: block;
  /* Nudge the lighthouse down a hair so its visual center — the lamp room,
     not the geometric middle — lines up with the wordmark's cap height. */
  transform: translateY(1px);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5))
          drop-shadow(0 0 16px rgba(34, 211, 238, 0.3));
  transition: filter 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.brand:hover .brand-logo {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5))
          drop-shadow(0 0 24px rgba(34, 211, 238, 0.5));
  transform: translateY(1px) scale(1.03);
}
.brand-wordmark {
  font-size: 32px; font-weight: 800; letter-spacing: -0.02em;
  line-height: 1;
}
.brand-edge   { color: #f8fafc; }
.brand-beacon {
  background: linear-gradient(135deg, #22d3ee 0%, #38bdf8 50%, #0891b2 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 0 28px rgba(34, 211, 238, 0.25);
}
.status {
  display: flex; align-items: center; gap: 10px;
  font-size: 12.5px; color: var(--text-lo);
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--border-soft);
  padding: 7px 14px;
  border-radius: 999px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-variant-numeric: tabular-nums;
  position: relative;
}
/* Lift .status (which contains the Markets & Sportsbooks dropdown triggers)
   out of the header's shared stacking soup whenever a dropdown is open. */
.status:has(.books-dropdown-wrap.open) {
  z-index: 3000;
}
.status b { color: var(--text-hi); font-weight: 600; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot.live {
  background: #22c55e;
  box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.18), 0 0 12px rgba(34, 197, 94, 0.6);
  animation: dot-pulse 2s ease-in-out infinite;
}
.dot.stale { background: #f59e0b; box-shadow: 0 0 10px rgba(245, 158, 11, 0.5); }
.sep { opacity: 0.3; }
@keyframes dot-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.18), 0 0 12px rgba(34, 197, 94, 0.6); }
  50%      { box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.08), 0 0 16px rgba(34, 197, 94, 0.4); }
}

.controls {
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px;
  padding: 14px 18px;
  background: linear-gradient(180deg, rgba(28, 34, 48, 0.6) 0%, rgba(22, 28, 40, 0.6) 100%);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  margin-bottom: 16px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: var(--shadow-card);
  /* backdrop-filter creates a stacking context; position + z-index ensure
     dropdowns inside this bar paint above plain later siblings like the
     .market-section table card. */
  position: relative;
  z-index: 5;
}
/* When a dropdown inside any .controls bar is actively open, raise THAT bar
   far above every other .controls (e.g. the Lines tab's Auto-refresh bar)
   and above every table/sticky header that comes later in the DOM. Without
   this, the dropdown paints behind the next tab-filter bar or the table
   because they share the same stacking level. `:has()` lets us do this
   purely in CSS — no JS class-flipping needed. */
.controls:has(.books-dropdown-wrap.open),
.controls:has(.weights-chip-wrap.open) {
  z-index: 2000;
}
.controls label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-md); font-weight: 500; }
.controls input[type="range"] { accent-color: var(--brand); width: 180px; }
.controls input[type="checkbox"] { accent-color: var(--brand); width: 15px; height: 15px; }
.filter { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-lo); }

/* DFS-app anchor picker on the Fantasy tab. This is the primary row filter
   on that tab (selects which DFS book's lines populate the table), so it
   gets a heavier visual treatment than the secondary filters (sport, team,
   etc.) sitting next to it. */
.dfs-anchor-picker {
  background: #172033;
  border: 1px solid #2a3958;
  border-radius: 8px;
  padding: 6px 12px;
  color: #cbd5e1;
}
.dfs-anchor-picker .dfs-anchor-label {
  color: #93c5fd;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.dfs-anchor-picker select {
  background: #0f1829;
  color: #e5e9f0;
  border: 1px solid #2a3958;
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 13px;
  font-weight: 600;
}
.chips { display: flex; flex-wrap: wrap; gap: 6px; max-width: 560px; }
.chip {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  border-radius: 999px; padding: 3px 10px; font-size: 12px; cursor: pointer;
}
.chip.on { background: #2563eb; color: white; border-color: #2563eb; }
.auto { margin-left: auto; }

button#refresh-btn {
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418; border: 0;
  padding: 9px 20px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  font-family: inherit;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 0 0 1px rgba(34, 211, 238, 0.4),
    0 6px 16px -4px rgba(34, 211, 238, 0.55);
  transition: box-shadow 0.2s var(--ease-out), transform 0.1s var(--ease-out), filter 0.2s var(--ease-out);
}
button#refresh-btn:hover:not(:disabled) {
  filter: brightness(1.08);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.3) inset,
    0 0 0 1px rgba(34, 211, 238, 0.55),
    0 10px 22px -4px rgba(34, 211, 238, 0.75);
  transform: translateY(-1px);
}
button#refresh-btn:active:not(:disabled) { transform: translateY(0); filter: brightness(0.95); }
button#refresh-btn:disabled { opacity: 0.55; cursor: progress; }

/* Stale-data banner — red strip that sits between the header and the tab
   nav when the latest poll is older than STALE_BANNER_THRESHOLD_SECONDS
   (see dashboard.html). Designed to be hard to miss without being visually
   hostile: muted red background, white text, inline refresh button. */
.stale-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 8px 16px 0;
  padding: 10px 14px;
  border-radius: 8px;
  background: linear-gradient(90deg, #4c1d1d 0%, #5a1f1f 100%);
  border: 1px solid #7a2b2b;
  color: #fecaca;
  font-size: 13px;
  line-height: 1.4;
}
/* `display: flex` above overrides the browser's default `hidden` attribute
   behavior (which applies `display: none`). This rule restores hidden's
   effect so `banner.hidden = true` in JS actually hides the banner. */
.stale-banner[hidden] { display: none; }
.stale-banner b { color: #fff5f5; }
.stale-banner button {
  background: #fff5f5;
  color: #4c1d1d;
  border: 0;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.stale-banner button:hover { background: #fee2e2; }

/* Support strip — thin always-visible row under the header with the support
   email. Muted so it doesn't compete with the stale-data banner or the main
   UI, but legible enough that users notice where to send bug reports. */
.support-bar {
  margin: 12px 0 18px;
  padding: 10px 18px;
  border-radius: var(--radius-md);
  background:
    linear-gradient(180deg, rgba(34, 211, 238, 0.04) 0%, rgba(34, 211, 238, 0.02) 100%),
    rgba(22, 28, 40, 0.5);
  border: 1px solid rgba(34, 211, 238, 0.12);
  color: var(--text-lo);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: center;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 4px 12px -6px rgba(34, 211, 238, 0.15);
}

/* Free-trial countdown banner — sits between the support strip and the
   sport tabs. Two visual tones: subtle (calm cyan tint, default) and
   warn (amber tint, kicks in during the last 7 days). The amber tone
   reads "your trial is genuinely about to end" without being
   alarmist-red. */
.trial-banner {
  margin: 0 0 18px;
  padding: 9px 16px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(34, 211, 238, 0.08) 0%, rgba(34, 211, 238, 0.04) 100%);
  border: 1px solid rgba(34, 211, 238, 0.2);
  color: #cbd5e1;
  font-size: 12.5px;
  line-height: 1.45;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}
.trial-banner-pill {
  display: inline-block;
  padding: 2px 8px;
  background: rgba(34, 211, 238, 0.18);
  color: #22d3ee;
  border: 1px solid rgba(34, 211, 238, 0.35);
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.trial-banner-msg b {
  color: #ffffff;
  font-weight: 700;
}
.trial-banner-email {
  color: #22d3ee;
  font-weight: 600;
  user-select: all;
}
/* Final-week tone: warm amber, more attention-grabbing. */
.trial-banner-warn {
  background: linear-gradient(180deg, rgba(251, 191, 36, 0.1) 0%, rgba(251, 191, 36, 0.04) 100%);
  border-color: rgba(251, 191, 36, 0.35);
  color: #fde68a;
}
.trial-banner-warn .trial-banner-pill {
  background: rgba(251, 191, 36, 0.2);
  color: #fbbf24;
  border-color: rgba(251, 191, 36, 0.45);
}
.trial-banner-warn .trial-banner-msg b { color: #fef3c7; }
.trial-banner-warn .trial-banner-email { color: #fbbf24; }

/* Trial-ended page — uses the auth shell. The actions block centers
   the secondary call-to-action so the post-trial messaging doesn't
   look like a dead end. */
.trial-ended-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin-top: 16px;
}
.support-bar a {
  color: #60a5fa;
  font-weight: 600;
  text-decoration: none;
}
.support-bar a:hover { text-decoration: underline; }
/* Plain-text email (no link) — user-selectable, monospace-ish for clarity. */
.support-email {
  color: #60a5fa;
  font-weight: 600;
  user-select: all;
}
/* Copy-to-clipboard button sits inline with the email. Keeps its own subtle
   border so it reads as clickable without shouting. "copied" class gives a
   brief green flash after a successful copy. */
.support-copy-btn {
  margin: 0 8px;
  padding: 3px 12px;
  background: rgba(34, 211, 238, 0.08);
  border: 1px solid rgba(34, 211, 238, 0.25);
  color: #7dd3fc;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  line-height: 1.5;
  vertical-align: baseline;
  transition: all 0.2s var(--ease-out);
  font-family: inherit;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.support-copy-btn:hover {
  background: rgba(34, 211, 238, 0.15);
  border-color: rgba(34, 211, 238, 0.5);
  color: #bae6fd;
}
.support-copy-btn.copied {
  background: rgba(34, 197, 94, 0.15);
  border-color: rgba(34, 197, 94, 0.5);
  color: #86efac;
}

table {
  width: 100%; border-collapse: collapse; font-size: 13px;
  background: linear-gradient(180deg, #161c27 0%, #141922 100%);
  border-radius: 12px; overflow: hidden;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.03) inset,
    0 8px 20px rgba(0, 0, 0, 0.3);
  border: 1px solid #242c3b;
}
thead th {
  text-align: left; padding: 11px 14px;
  background: linear-gradient(180deg, #1d2432 0%, #161c28 100%);
  color: #b8c5da; font-weight: 700; cursor: pointer; user-select: none;
  border-bottom: 1px solid #2a3243;
  letter-spacing: 0.3px;
  transition: color 0.12s ease;
}
thead th:hover { color: #e5e9f0; }
thead th.asc::after { content: " ▲"; color: #3b82f6; }
thead th.desc::after { content: " ▼"; color: #3b82f6; }

tbody tr { border-bottom: 1px solid #1e2532; transition: background 0.12s ease; }
tbody tr:last-child { border-bottom: 0; }
tbody tr:hover { background: #19212e; }
tbody td { padding: 10px 14px; }
td.ev { font-weight: 700; color: #2ecc71; }
td.muted { color: #6b7c97; }
.market {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; background: #222a37; color: #93a4bf;
  padding: 2px 6px; border-radius: 4px;
}

.empty { padding: 30px; text-align: center; color: #6b7c97; }

footer {
  margin-top: 14px; font-size: 12px; color: #6b7c97;
  display: flex; gap: 10px; align-items: center;
}

/* Dashboard footer — multi-row variant that adds Terms/Privacy/Contact
   links and the responsible-gambling disclaimer below the existing
   "last update" status row. Layout stacks vertically on narrow viewports
   and lays out as 3 horizontal blocks on wide ones. */
footer.dashboard-footer {
  margin-top: 32px;
  padding: 20px 0 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  text-align: center;
  font-size: 12px;
  color: #6b7c97;
}
.dashboard-footer-status {
  display: flex;
  gap: 10px;
  align-items: center;
}
.dashboard-footer-links {
  display: flex;
  gap: 4px;
  align-items: center;
  font-size: 12.5px;
}
.dashboard-footer-links a {
  color: #93a4bf;
  text-decoration: none;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  transition: color 0.15s ease, background 0.15s ease;
}
.dashboard-footer-links a:hover {
  color: #22d3ee;
  background: rgba(34, 211, 238, 0.06);
}
.dashboard-footer-disclaimer {
  font-size: 11px;
  color: #6b7c97;
  opacity: 0.85;
  max-width: 480px;
  line-height: 1.5;
}
.dashboard-footer-disclaimer b { color: #93a4bf; }

/* Tabs — product-style secondary nav. Sits on a divider with a brand-glow
   accent under the active item so it reads as a deliberate product surface
   rather than a generic HTML tab bar. */
nav.tabs {
  display: flex; gap: 2px; padding: 10px 0 0;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 16px;
  position: relative;
}
nav.tabs .tab {
  background: transparent; color: var(--text-lo); border: 0;
  padding: 10px 18px; font-size: 13.5px; font-weight: 600;
  cursor: pointer; border-bottom: 2px solid transparent;
  display: inline-flex; align-items: center; gap: 8px;
  transition: color 0.2s var(--ease-out), border-color 0.2s var(--ease-out), background 0.2s var(--ease-out);
  letter-spacing: -0.005em;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
  font-family: inherit;
  position: relative;
  margin-bottom: -1px;
}
nav.tabs .tab:hover {
  color: var(--text-hi);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.02) 0%, transparent 100%);
}
/* Active tab: brand cyan underline + glow + stronger color so it reads as
   "you are here" from across the page. */
nav.tabs .tab.active {
  color: var(--text-hi);
  border-bottom-color: var(--brand);
  background: linear-gradient(180deg, rgba(34, 211, 238, 0.06) 0%, transparent 100%);
}
nav.tabs .tab.active::after {
  content: "";
  position: absolute;
  left: 10%; right: 10%; bottom: -1px; height: 2px;
  background: var(--brand);
  border-radius: 2px 2px 0 0;
  box-shadow: 0 0 16px 2px var(--brand-glow);
}
.badge {
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-lo);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.tab.active .badge {
  background: var(--brand);
  color: #051418;
  font-weight: 700;
  box-shadow: 0 0 12px rgba(34, 211, 238, 0.4);
}

/* Sport tabs — top-level "All sports / MLB / NBA" selector that lives above
   the main feature tabs. Segmented-control style inside a subtle container
   pill, for a product-like control surface rather than free-floating pills. */
nav.sport-tabs {
  display: inline-flex; flex-wrap: wrap; gap: 4px;
  padding: 4px;
  margin-bottom: 12px;
  background: rgba(17, 22, 31, 0.6);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
nav.sport-tabs .sport-tab {
  background: transparent;
  color: var(--text-lo);
  border: 0;
  border-radius: 999px;
  padding: 7px 18px;
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit;
  letter-spacing: -0.005em;
  transition: background 0.2s var(--ease-out), color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
nav.sport-tabs .sport-tab:hover {
  color: var(--text-hi);
  background: rgba(255, 255, 255, 0.04);
}
nav.sport-tabs .sport-tab.active {
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418;
  box-shadow:
    0 2px 8px rgba(34, 211, 238, 0.4),
    0 0 0 1px rgba(34, 211, 238, 0.45) inset,
    0 1px 0 rgba(255, 255, 255, 0.25) inset;
}

/* Live/Upcoming filter — same pill style as sport-tabs but slightly smaller
   and using a red accent for the Live button so the in-progress state is
   eye-catching. Rendered under the sport picker and above the main tab bar. */
nav.live-filter-tabs {
  display: inline-flex; flex-wrap: wrap; gap: 4px;
  padding: 4px;
  margin-bottom: 14px;
  background: rgba(17, 22, 31, 0.6);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
nav.live-filter-tabs .live-filter-tab {
  background: transparent;
  color: var(--text-lo);
  border: 0;
  border-radius: 999px;
  padding: 6px 16px;
  font-size: 12.5px; font-weight: 600;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit;
  letter-spacing: -0.005em;
  transition: background 0.2s var(--ease-out), color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
nav.live-filter-tabs .live-filter-tab:hover {
  color: var(--text-hi);
  background: rgba(255, 255, 255, 0.04);
}
nav.live-filter-tabs .live-filter-tab.active {
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418;
  box-shadow:
    0 2px 8px rgba(34, 211, 238, 0.4),
    0 0 0 1px rgba(34, 211, 238, 0.45) inset,
    0 1px 0 rgba(255, 255, 255, 0.25) inset;
}
/* Red pulse dot on the "Live only" pill for quick visual grounding. */
nav.live-filter-tabs .live-filter-tab .lf-dot {
  color: #ef4444; font-size: 10px; line-height: 1;
}
nav.live-filter-tabs .live-filter-tab.active[data-live="live"] {
  background: #dc2626; border-color: #ef4444;
  box-shadow: 0 0 0 1px #ef4444 inset;
}
nav.live-filter-tabs .live-filter-tab.active[data-live="live"] .lf-dot {
  color: white;
}
/* Small count badge on each pill — lets the user see how many rows live in
   each bucket without toggling between pills. */
nav.live-filter-tabs .live-filter-tab .lf-count {
  display: inline-block;
  background: rgba(255,255,255,0.08);
  color: #cbd5e1;
  font-size: 11px; font-weight: 600;
  padding: 1px 7px;
  border-radius: 999px;
  margin-left: 4px;
  min-width: 18px;
  text-align: center;
}
nav.live-filter-tabs .live-filter-tab.active .lf-count {
  background: rgba(255,255,255,0.22);
  color: white;
}

/* Inline sport badge shown next to matchups in the "All sports" merged view.
   A small colored pill so the sport a row belongs to is obvious without
   having to look at the header tab. */
.sport-tag {
  display: inline-block;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 6px;
  vertical-align: 1px;
  white-space: nowrap;
  border: 1px solid transparent;
}
.sport-tag-mlb { background: #3f1d1d; color: #fca5a5; border-color: #5b2626; }
.sport-tag-nba { background: #3a2514; color: #fdba74; border-color: #5c3820; }
/* WNBA uses the league's brand orange (closer to #ff6200) but muted for
   dark-mode legibility. Distinct enough from NBA (#5c3820 warm-brown) that
   rows from the two basketball leagues read clearly at a glance in the
   combined "All sports" view. */
.sport-tag-wnba { background: #3a1e24; color: #fda4af; border-color: #5c2d36; }

/* Live game indicators — a pulsing red LIVE badge for in-play games, score +
   clock in place of the scheduled time, and a neutral "Final" pill for
   recently completed games. */
.live-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  margin-left: 6px;
  vertical-align: 1px;
  white-space: nowrap;
}
.live-badge.live-live {
  background: #7f1d1d;
  color: #fecaca;
  border: 1px solid #b91c1c;
  animation: live-pulse 1.6s ease-in-out infinite;
}
.live-badge.live-final {
  background: #1f2937;
  color: #94a3b8;
  border: 1px solid #334155;
}
@keyframes live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.55); background: #7f1d1d; }
  50%      { box-shadow: 0 0 0 5px rgba(239, 68, 68, 0.00); background: #991b1b; }
}

/* The status line under the matchup — replaces the scheduled-time caption
   for in-play / final games. Score is bold + bright, clock/inning is muted. */
.live-status {
  display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12px;
}
.live-status-live .live-score { color: #fecaca; font-weight: 800; }
.live-status-final .live-score { color: #cbd5e1; font-weight: 700; }
.live-score { font-variant-numeric: tabular-nums; letter-spacing: 0.2px; }
.live-clock {
  color: #facc15;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.3px;
}
.live-status-final .live-clock { color: #94a3b8; }
.live-kickoff { color: #6b7c97; font-size: 11px; }

/* Book label: logo badge + name, used in table headers and the arbitrage grid.
   The hyperlink/arrow was removed because the click target sent users to a
   sportsbook's homepage, which wasn't useful inside the dashboard. */
.book-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1;
  vertical-align: middle;
  white-space: nowrap;
}
.book-label .book-logo {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  border-radius: 5px;
  display: inline-block;
  /* Real brand logos from the CDN often arrive with transparent or dark
     backgrounds; a soft neutral pad keeps them legible on the dashboard's
     dark rows without competing with logos that already have their own fill. */
  background: #f6f7f9;
  object-fit: contain;
  /* Small inset so the logo doesn't bleed to the corners of the rounded box. */
  padding: 1px;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.25);
}
.book-label .book-label-name {
  font-weight: 600;
  letter-spacing: 0.2px;
}
/* Slightly bigger logo in the row-group column heads where the header text
   dominates — the badge should feel aligned with the 12px uppercase label. */
table.grid thead th.bookhead .book-logo { width: 20px; height: 20px; flex-basis: 20px; }
.fantasy-grid thead th.bookhead .book-logo { width: 20px; height: 20px; flex-basis: 20px; }

/* Inputs + misc controls */
.controls input[type="number"], .controls select {
  background: #1a2230; color: #e5e9f0; border: 1px solid #263145;
  padding: 5px 8px; border-radius: 6px; font-size: 13px;
  width: 100px;
}
.controls select { width: auto; }
/* Odds-range inputs are paired (min / to / max) so they need to be compact. */
.controls input.odds-range-input { width: 66px; text-align: center; }
.odds-range-sep { font-size: 12px; color: #6b7c97; padding: 0 2px; }
.hint { font-size: 12px; color: #6b7c97; max-width: 600px; }
button.primary {
  background: #3b82f6; color: white; border: 0; padding: 6px 14px;
  border-radius: 6px; cursor: pointer; font-size: 13px;
}
button.logbtn {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  padding: 2px 10px; border-radius: 4px; cursor: pointer; font-weight: 700;
}
button.logbtn:hover { background: #2563eb; color: white; border-color: #2563eb; }
button.settle {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  padding: 1px 8px; border-radius: 4px; cursor: pointer;
  font-size: 11px; font-weight: 700; margin-right: 3px;
}
button.settle:hover { background: #2563eb; color: white; }

/* Stats row on bet log */
.stats-row {
  display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.stat {
  background: linear-gradient(180deg, #171d28 0%, #141922 100%);
  border: 1px solid #242c3b;
  border-radius: 10px;
  padding: 11px 16px; min-width: 110px;
  display: flex; flex-direction: column; gap: 3px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.03) inset,
    0 4px 12px rgba(0, 0, 0, 0.25);
}
.stat .k { color: #7d8ca8; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.8px; font-weight: 600; }
.stat .v { color: #e5e9f0; font-size: 19px; font-weight: 700; letter-spacing: 0.2px; font-variant-numeric: tabular-nums; }
.stat .v.pos { color: #2ecc71; }
.stat .v.neg { color: #e74c3c; }
td.pos { color: #2ecc71; }
td.neg { color: #e74c3c; }

/* ==========================================================================
   OddsJam-style grid: rows = games/markets, columns = sportsbooks.
   ========================================================================== */
.market-section {
  margin-bottom: 32px;
  /* NOTE: do NOT add backdrop-filter here — it creates a new stacking
     context that traps absolutely-positioned dropdowns (Markets /
     Sportsbooks) behind this section. The opaque-ish gradient + shadow
     already give it the elevated card look without needing blur. */
  background:
    linear-gradient(180deg, #1c2230 0%, #141922 100%);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  overflow: auto;           /* horizontal scroll when many books */
  position: relative;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset,
    0 20px 48px -20px rgba(0, 0, 0, 0.7),
    0 4px 12px rgba(0, 0, 0, 0.35);
}
table.grid {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 12.5px;
  width: max-content;       /* let columns size to content */
  min-width: 100%;
}
table.grid thead th {
  background: linear-gradient(180deg, #1f2635 0%, #161c28 100%);
  color: var(--text-md);
  font-weight: 600;
  padding: 13px 14px;
  border-bottom: 1px solid var(--border-mid);
  text-align: left;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 3;
  letter-spacing: 0.02em;
  font-size: 11.5px;
  text-transform: uppercase;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 2px 8px rgba(0, 0, 0, 0.2);
}
table.grid thead th.rowhead {
  left: 0;
  z-index: 5;
  min-width: 220px;
  max-width: 250px;
  font-size: 11.5px;
  color: var(--text-md);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  background: linear-gradient(180deg, #252d3f 0%, #1a2130 100%);
  border-right: 1px solid var(--border-mid);
}
table.grid thead th.fairhead {
  color: #fbbf24;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  background: linear-gradient(180deg, #26220f 0%, #1a1708 100%);
  border-bottom-color: rgba(251, 191, 36, 0.25);
}
table.grid thead th.bookhead {
  font-size: 11px;
  text-align: center;
  min-width: 120px;
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 600;
}
table.grid tbody td {
  border-bottom: 1px solid rgba(255, 255, 255, 0.035);
  padding: 0;
  vertical-align: stretch;
}
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tbody td.rowhead {
  position: sticky;
  left: 0;
  z-index: 2;
  background: linear-gradient(90deg, rgba(27, 33, 47, 0.95) 0%, rgba(22, 28, 40, 0.95) 100%);
  padding: 13px 16px;
  min-width: 220px;
  max-width: 250px;
  border-right: 1px solid var(--border-mid);
  font-size: 13px;
  line-height: 1.45;
  transition: background 0.2s var(--ease-out);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
table.grid tbody tr:hover td.rowhead {
  background: linear-gradient(90deg, rgba(40, 48, 68, 0.95) 0%, rgba(30, 37, 52, 0.95) 100%);
}
table.grid tbody tr:hover td.price-cell .stack {
  background: rgba(34, 211, 238, 0.03);
}

.gamecell .matchup { color: var(--text-hi); font-weight: 600; letter-spacing: -0.005em; }
.gamecell .player {
  color: var(--text-hi);
  font-weight: 700;
  font-size: 13.5px;
  letter-spacing: -0.01em;
}
/* Arbitrage tab: player name used when the arb is on a player prop. Matches
   the weight/color of the Lines/Props .player style so prop arbs read the
   same way as their underlying prop rows. */
.arb-player { color: var(--text-hi); font-weight: 700; font-size: 13.5px; line-height: 1.25; letter-spacing: -0.01em; }
/* Muted game-matchup subline under the player name on prop arbs. */
.arb-subline { color: var(--text-lo); font-size: 11.5px; line-height: 1.2; margin-top: 2px; }
/* Team name heading for team_totals rows — same weight as .player so the
   individual team (not the full matchup) reads as the row subject. */
.gamecell .team-name { color: var(--text-hi); font-weight: 700; font-size: 13.5px; letter-spacing: -0.01em; }
.gamecell .muted { color: var(--text-lo); }
.gamecell .small { font-size: 11.5px; }

/* Player headshot — rendered inline with the player's name on player-prop
 * rows (Lines/Props tabs) and on Fantasy rows. Circular crop, sized to
 * align with a single line of text. Falls back to /static/player-default.svg
 * via `onerror` when the MLB/ESPN CDN 404s or the player couldn't be
 * resolved on the server. */
.player-headshot {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, #1a2133 0%, #0f1524 100%);
  object-fit: cover;
  flex-shrink: 0;
  display: inline-block;
  vertical-align: middle;
  margin-right: 8px;
  border: 1.5px solid rgba(34, 211, 238, 0.2);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.4),
    0 2px 6px rgba(0, 0, 0, 0.35);
  transition: border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
tr:hover .player-headshot {
  border-color: rgba(34, 211, 238, 0.5);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.4),
    0 0 10px rgba(34, 211, 238, 0.25);
}
.gamecell .player-headshot { margin-right: 8px; }
.fan-player .player-headshot { margin-right: 4px; }

/* Each price cell stacks two rows (the two sides of the market). */
.stack {
  display: flex;
  flex-direction: column;
}
.side-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; gap: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.03);
  cursor: default;
  transition: background 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
  min-height: 36px;
}

/* OddsJam-style per-book line label, shown between the side label and the
   price in each book cell. Monospace + tabular-nums keeps vertical alignment
   clean even when some cells have signs (+13 / +12.5). */
.side-row .cell-line {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: #cbd5e1;
  background: #1f2937;
  border: 1px solid #2b3648;
  border-radius: 3px;
  padding: 1px 5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Amber tint when the cell's posted line differs from the sharp-weighted
   consensus line — this is the OddsJam-style "line shopping" cue. */
.side-row .cell-line.off-line {
  background: #3a2a0a;
  color: #fbbf24;
  border-color: #78350f;
  font-weight: 700;
}
.side-row.off-line-cell { box-shadow: inset 0 0 0 1px #78350f55; }
.side-row.off-line-cell:hover { background: #1f1a0c; }
.side-row:last-child { border-bottom: 0; }
.side-row .sidelabel {
  color: var(--text-lo);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 80px;
}
.side-row .price {
  font-weight: 700;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
  font-size: 13.5px;
  letter-spacing: -0.01em;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
}
.side-row.muted .price { color: #4d5b72; font-weight: 500; }
.side-row.best {
  background: linear-gradient(90deg, #0f3a28 0%, #12402d 55%, #0e3024 100%);
  box-shadow: inset 2px 0 0 #22c55e, inset 0 0 0 1px rgba(34, 197, 94, 0.12);
}
.side-row.best .price { color: #6ee7b7; text-shadow: 0 0 8px rgba(110, 231, 183, 0.18); }
.side-row.best::after {
  content: "★";
  color: #facc15;
  font-size: 10px;
  margin-left: 4px;
  align-self: center;
  filter: drop-shadow(0 0 4px rgba(250, 204, 21, 0.45));
}
.side-row.valuecell { box-shadow: inset 3px 0 0 #facc15; }
.side-row .evtag {
  font-size: 10px; font-weight: 700; padding: 1px 5px;
  border-radius: 3px; font-variant-numeric: tabular-nums;
}
.evtag.ev-pos { background: #14532d; color: #86efac; }
.evtag.ev-tiny { background: #223455; color: #93c5fd; }
.evtag.ev-neg { background: #3a1e1e; color: #fca5a5; }

/* ---------------------------------------------------------------------------
   Per-book price cell — uniform column layout.

   The generic .side-row above uses flex + space-between, which means every
   optional slot that's missing (line chip, edge tag) causes the remaining
   elements to shift x-position. That produced the ragged look in the book
   columns where some rows had team-name-on-far-left / price-on-far-right
   and other rows stacked everything in the middle.

   Inside a .price-cell we switch to a 6-column grid so every element lands
   in its own fixed slot regardless of whether the neighbors are present:
     col 1 (12px) — parlay checkmark
     col 2 (1fr)  — side label (team / Over / Under), truncates
     col 3 (44px) — line chip (e.g. -1.5 / 8)   — may be empty
     col 4 (52px) — price (e.g. +130 / -165)
     col 5 (44px) — edge tag (e.g. -2.1%)        — may be empty
     col 6 (14px) — best-price star (.best::after) — may be empty
   --------------------------------------------------------------------------- */
.price-cell .side-row {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) 44px 52px 44px 14px;
  align-items: center;
  gap: 6px;
}
.price-cell .side-row .parlay-mark { grid-column: 1; margin: 0; }
.price-cell .side-row .sidelabel { grid-column: 2; max-width: none; }
.price-cell .side-row .cell-line { grid-column: 3; justify-self: center; }
.price-cell .side-row .price { grid-column: 4; justify-self: end; }
.price-cell .side-row .evtag { grid-column: 5; justify-self: center; }
.price-cell .side-row.best::after { grid-column: 6; margin: 0; justify-self: center; }

.fair-cell {
  background: linear-gradient(180deg, #1c2030 0%, #171b28 100%);
  border-right: 1px solid #2a3243;
}
.fair-cell .side-row { cursor: default; }
.fair-cell .side-row:hover { background: transparent; }
.fair-cell .price.fair { color: #fde68a; font-weight: 600; }

/* "% to Hit" consensus column (OddsJam-style) */
table.grid thead th.hithead {
  color: #bbf7d0;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 800;
  background: linear-gradient(180deg, #173023 0%, #0f241a 100%);
  text-align: center;
}
.hit-cell {
  background: linear-gradient(180deg, #112418 0%, #0e2015 100%);
  border-right: 2px solid #1f3a2c;
  min-width: 120px;
}
.hit-cell .side-row { cursor: default; padding: 8px 10px; }
.hit-cell .side-row:hover { background: transparent; }
.hit-cell .hitpct {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: #e5e9f0;
  font-size: 14px;
}
.hit-cell .sidelabel { color: #93a4bf; max-width: 70px; }
.hit-row.hit-strong {
  background: linear-gradient(90deg, #14532d 0%, #166534 55%, #15803d 100%);
  box-shadow: inset 2px 0 0 #22c55e;
}
.hit-row.hit-strong .hitpct { color: #bbf7d0; text-shadow: 0 0 6px rgba(187, 247, 208, 0.18); }
.hit-row.hit-mid    { background: linear-gradient(90deg, #165234 0%, #15713a 70%, #134a2a 100%); }
.hit-row.hit-mid    .hitpct { color: #d1fae5; }
.hit-row.hit-soft   { background: #1b2c24; }
.hit-row.hit-soft   .hitpct { color: #a7f3d0; }
.hit-row.hit-low    { background: #1a2026; }
.hit-row.hit-low    .hitpct { color: #94a3b8; }
/* Best cross-book EV% chip rendered inline inside the % to Hit cell on Props
   rows. Sits to the right of the hit%, making the "Best +EV" sort ordering
   self-explanatory without the user having to scan per-book cells. Slightly
   tighter padding than the per-cell evtag so it fits cleanly in the hit
   column's compact layout. */
.hit-cell .side-ev {
  margin-left: 8px;
  padding: 2px 6px;
  font-size: 11px;
  font-weight: 700;
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
}

/* Best Book / Best Odds frozen columns — they sit between the % to Hit cell
   and the per-book price grid, telling the user at a glance which book is
   posting the best price on each side and what that price is. The header
   styling matches .hithead but in the cyan brand palette so the two
   recommendation columns visually pair together. Cells get a subtle gradient
   so they read as a distinct "shopping" column-group separate from both the
   green hit-rate column and the per-book grid. */
table.grid thead th.bestbookhead,
table.grid thead th.bestoddshead {
  color: #a5f3fc;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 800;
  background: linear-gradient(180deg, #0e2a35 0%, #0a1f28 100%);
  text-align: center;
}
.best-book-cell,
.best-odds-cell {
  background: linear-gradient(180deg, #0d2129 0%, #0a1922 100%);
  min-width: 130px;
}
.best-book-cell { border-left: 2px solid #134150; }
.best-odds-cell { border-right: 2px solid #134150; }
.best-book-cell .side-row,
.best-odds-cell .side-row {
  cursor: default;
  padding: 8px 10px;
}
.best-book-cell .side-row:hover,
.best-odds-cell .side-row:hover {
  background: transparent;
}
.best-book-cell .sidelabel,
.best-odds-cell .sidelabel {
  color: #93a4bf;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* Spread point labels ("+6.5" / "-6.5") and Over/Under labels never
     truncate — both are short. Moneyline rows render no .sidelabel at all
     (handled in bestSideLabelHtml). No max-width needed. */
}
.best-book-cell .book-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.best-book-cell .book-label-name {
  font-size: 12px;
  color: #e0f2fe;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 110px;
}
.best-book-cell .book-logo {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.best-odds-cell .best-price {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: #e0f2fe;
  font-size: 14px;
}
.best-empty .price,
.best-empty .muted { color: #475569; }

/* Collapsible wrapper around market pills (so a huge prop list doesn't push
   the Books button and other controls below the fold). */
.market-pills-wrap {
  margin-bottom: 12px; border-bottom: 1px solid #222831; padding-bottom: 10px;
}
.market-pills-wrap > summary {
  cursor: pointer; user-select: none;
  color: #cbd5e1; font-size: 13px; font-weight: 600;
  padding: 6px 0; list-style: none;
}
.market-pills-wrap > summary::-webkit-details-marker { display: none; }
.market-pills-wrap > summary::before {
  content: "▸ "; color: #6b7c97; display: inline-block;
  transition: transform 0.15s; transform-origin: center;
}
.market-pills-wrap[open] > summary::before { content: "▾ "; }
.market-pills-wrap .market-pills-hint { color: #6b7c97; font-weight: 400; margin-left: 4px; }

/* Market filter pills (above the grid) */
.pills {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 8px 0 0; margin: 0;
}
.pill {
  background: linear-gradient(180deg, #1c2432 0%, #171d28 100%);
  color: #cbd5e1; border: 1px solid #2a3243;
  border-radius: 999px; padding: 6px 14px; font-size: 13px;
  cursor: pointer; font-weight: 600;
  display: inline-flex; align-items: center; gap: 8px;
  letter-spacing: 0.2px;
  transition: background 0.14s ease, color 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}
.pill:hover {
  background: linear-gradient(180deg, #2a3447 0%, #222b3b 100%);
  border-color: #3a4760;
  color: #f1f5fb;
}
.pill.on {
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418;
  border-color: rgba(34, 211, 238, 0.55);
  box-shadow:
    0 0 0 1px rgba(34, 211, 238, 0.45) inset,
    0 1px 0 rgba(255, 255, 255, 0.2) inset,
    0 4px 14px -4px rgba(34, 211, 238, 0.55);
}
.pill-count {
  background: rgba(255,255,255,0.15); color: inherit;
  font-size: 11px; font-weight: 700; padding: 1px 7px;
  border-radius: 10px; min-width: 16px; text-align: center;
}
.pill.on .pill-count { background: rgba(5, 20, 24, 0.25); color: #051418; }

/* Pagination bar */
.pager {
  display: flex; align-items: center; justify-content: center;
  gap: 18px; padding: 16px 0; color: #93a4bf; font-size: 13px;
}
.pager .pg-info b { color: #e5e9f0; }
.pgbtn {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  border-radius: 6px; padding: 6px 14px; font-size: 13px;
  cursor: pointer; font-weight: 600;
}
.pgbtn:hover:not([disabled]) { background: #2563eb; color: white; border-color: #2563eb; }
.pgbtn[disabled] { opacity: 0.4; cursor: not-allowed; }

.pointtag {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11px; background: #263145; color: #cbd5e1;
  padding: 1px 5px; border-radius: 3px; margin-left: 4px;
}

/* "OFF-LINE · mkt 7" — the row's posted line differs from the sharp
   consensus across books. Amber because it's an opportunity, not an error:
   the hit% column has already been upgraded to the distribution estimate
   so +EV should be visible immediately. */
.outlier-badge {
  display: inline-block;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  background: #3a2a0a;
  color: #fbbf24;
  border: 1px solid #78350f;
  padding: 1px 6px;
  border-radius: 3px;
  margin-top: 2px;
  white-space: nowrap;
}

/* Live in-game stat shown next to the O/U pointtag for player props on
   in-play games — e.g. "Current: 1 TB". Turns green when the Over has
   already cleared the line. */
.livestat {
  display: inline-block;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11px;
  font-weight: 600;
  background: #1e293b;
  color: #cbd5e1;
  border: 1px solid #334155;
  padding: 1px 6px;
  border-radius: 3px;
  margin-left: 4px;
  white-space: nowrap;
}
.livestat-hit {
  background: #14532d;
  color: #86efac;
  border-color: #166534;
}

/* Confidence-signal chip row rendered under each grid row's game label.
   Four flavors:
     .conf-thin   — fewer than THIN_BOOK_THRESHOLD books pricing this side
                    (warning amber/red — the EV math is on a small sample)
     .conf-age    — line age in min / hr (neutral grey)
     .conf-stable — no cell on the row has moved since first seen (green)
     .conf-moved  — at least one cell has moved (amber)
   Sized to match .pointtag so chips stack cleanly below the matchup line.
   .conf-row uses flex-wrap so long slates (4+ chips) break cleanly on
   narrow viewports rather than pushing the row wider.
   Note: .conf-books was dropped — broad book consensus is already implicit
   in the EV% / hit% computation, so an always-on count chip was visual
   noise without earning its real estate. Thin coverage IS surfaced now,
   via .conf-thin, because that's the one case where the count meaningfully
   changes the read on an edge. */
.conf-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.conf-chip {
  display: inline-block;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2px;
  padding: 1px 6px;
  border-radius: 3px;
  white-space: nowrap;
  border: 1px solid transparent;
}
.conf-thin {
  /* Warning style — softer than .conf-moved (which uses amber) so the two
     can coexist on the same row without competing for attention. Reads as
     "heads up" rather than "danger". */
  background: #3a1f1f;
  color: #fca5a5;
  border-color: #7f1d1d;
}
.conf-age {
  background: #1e293b;
  color: #94a3b8;
  border-color: #334155;
}
.conf-stable {
  background: #14532d;
  color: #86efac;
  border-color: #166534;
}
.conf-moved {
  background: #3a2a0a;
  color: #fbbf24;
  border-color: #78350f;
}

/* Inline market indicator shown next to the player/matchup in the flat "All
   markets" view, so users can tell which prop market each row belongs to. */
.market-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  background: #1e3a5f;
  color: #93c5fd;
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 6px;
  vertical-align: 1px;
  white-space: nowrap;
}

/* Tiny line/prop badge inside the global Markets dropdown chips. Lives as a
 * sibling of .book-chip-name (not nested in it) so it doesn't consume the
 * label's ellipsis width — flex-shrink:0 pins it to the right of the chip. */
.market-chip-tag {
  font-size: 9px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: #7c8ba8;
  padding: 1px 5px;
  border-radius: 3px;
  background: #263145;
  flex-shrink: 0;
}
.books-dropdown .book-chip.on .market-chip-tag {
  background: #0f3a22;
  color: #8ee0b0;
}

/* Status pills */
.pill {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px;
}
.pill-open { background: #1e3a5f; color: #93c5fd; }
.pill-won  { background: #14532d; color: #86efac; }
.pill-lost { background: #5b1a1a; color: #fca5a5; }
.pill-push { background: #3a3a1a; color: #fde68a; }
.pill-void { background: #2a2a2a; color: #a3a3a3; }

/* Dialog */
dialog {
  background: #151a22; color: #e5e9f0; border: 1px solid #263145;
  border-radius: 10px; padding: 20px; width: 520px; max-width: 92vw;
}
dialog::backdrop { background: rgba(0,0,0,0.6); }
dialog h3 { margin: 0 0 14px; font-size: 16px; }
.form-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px;
}
.form-grid label {
  display: flex; flex-direction: column; font-size: 12px; color: #93a4bf;
  gap: 4px;
}
.form-grid label.full { grid-column: span 2; }
.form-grid input, .form-grid textarea {
  background: #0e1116; color: #e5e9f0; border: 1px solid #263145;
  padding: 6px 8px; border-radius: 6px; font-size: 13px; font-family: inherit;
  width: 100%;
}
dialog menu {
  display: flex; justify-content: flex-end; gap: 8px; padding: 0;
  margin-top: 16px; list-style: none;
}
dialog menu button {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  padding: 7px 14px; border-radius: 6px; cursor: pointer; font-size: 13px;
}

/* ==========================================================================
   Sportsbooks filter — header dropdown
   ========================================================================== */
.books-dropdown-wrap {
  position: relative; display: inline-block;
}
/* Raise the whole wrapper when the dropdown is open so the menu paints above
   any later sibling stacking contexts (table cards, sticky table headers,
   etc.). Fixes the bug where the Markets / Sportsbooks panel appeared
   behind the grid on some pages. */
.books-dropdown-wrap.open { z-index: 100; }
.books-trigger {
  background: linear-gradient(180deg, rgba(28, 34, 48, 0.8) 0%, rgba(22, 28, 40, 0.8) 100%);
  color: var(--text-md);
  border: 1px solid var(--border-mid);
  padding: 8px 14px; border-radius: 10px;
  cursor: pointer;
  font-size: 13px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 8px;
  font-family: inherit;
  letter-spacing: -0.005em;
  transition: all 0.2s var(--ease-out);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.books-trigger:hover {
  background: linear-gradient(180deg, rgba(40, 48, 68, 0.9) 0%, rgba(30, 37, 52, 0.9) 100%);
  color: var(--text-hi);
  border-color: var(--border-hot);
  box-shadow: 0 4px 12px -4px rgba(0, 0, 0, 0.5);
}
.books-dropdown-wrap.open .books-trigger {
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418;
  border-color: rgba(34, 211, 238, 0.55);
  box-shadow:
    0 0 0 1px rgba(34, 211, 238, 0.4) inset,
    0 1px 0 rgba(255, 255, 255, 0.2) inset,
    0 4px 14px -4px rgba(34, 211, 238, 0.55);
}
.books-trigger .books-btn-count {
  background: rgba(255,255,255,0.14); color: inherit;
  font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 10px;
  font-variant-numeric: tabular-nums;
}
.books-trigger:hover .books-btn-count { background: rgba(255,255,255,0.2); }
.books-dropdown-wrap.open .books-btn-count {
  background: rgba(5, 20, 24, 0.25);
  color: #051418;
}
.books-trigger .books-trigger-caret {
  color: inherit; font-size: 10px; transition: transform 0.15s;
}
.books-dropdown-wrap.open .books-trigger-caret { transform: rotate(180deg); }

.books-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px); right: 0;
  z-index: 50;
  width: 500px; max-width: 88vw;
  /* Fully opaque, layered gradient so the panel reads as a solid floating card
     against the (newly brighter) page background. Previously the flat #151a22
     fill looked washed-out against the glass table behind it. */
  background:
    linear-gradient(180deg, #171d2a 0%, #101622 100%);
  border: 1px solid rgba(34, 211, 238, 0.22);
  border-radius: 14px;
  padding: 16px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.35),
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 24px 64px -16px rgba(0, 0, 0, 0.85),
    0 8px 20px -4px rgba(0, 0, 0, 0.55);
}
.books-dropdown-wrap.open .books-dropdown { display: block; }

.books-dropdown-title {
  color: #e5e9f0; font-size: 13px; font-weight: 700; margin-bottom: 10px;
}

.books-dropdown .book-presets {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding-bottom: 10px; margin-bottom: 10px;
  border-bottom: 1px solid #222831;
}
.books-dropdown .book-presets button {
  background: #1a2230; color: #cbd5e1; border: 1px solid #263145;
  border-radius: 999px; padding: 5px 12px; font-size: 12px;
  cursor: pointer; font-weight: 600;
}
.books-dropdown .book-presets button:hover {
  background: #2563eb; color: white; border-color: #2563eb;
}
.books-dropdown .book-search-wrap { margin-bottom: 10px; }
.books-dropdown #books-search {
  background: #0e1116; color: #e5e9f0; border: 1px solid #263145;
  padding: 7px 10px; border-radius: 6px; font-size: 13px;
  font-family: inherit; width: 100%;
}

.books-dropdown #books-grid,
.books-dropdown #markets-grid,
.books-dropdown #lines-markets-grid,
.books-dropdown #props-markets-grid,
.books-dropdown #fantasy-markets-grid {
  display: grid;
  /* 180px min gives multi-word labels ("Moneyline (Q1)", "Player P+R+A",
   * "Pitcher Strikeouts") room to render in full without truncation; the
   * 1fr max lets the grid fill the 500px-wide panel (≈2 cols wide). */
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 6px;
  max-height: 340px;
  overflow-y: auto;
  padding-right: 4px;
}
.books-dropdown .book-chip {
  background: #0e1116; color: #cbd5e1; border: 1px solid #263145;
  border-radius: 6px; padding: 7px 10px; font-size: 12.5px;
  cursor: pointer; font-weight: 600; text-align: left;
  display: flex; align-items: center; gap: 8px;
  transition: background 0.08s, border-color 0.08s;
  user-select: none;
}
.books-dropdown .book-chip:hover { background: #1a2230; border-color: #3b82f6; }
.books-dropdown .book-chip.on {
  background: #14532d; color: #bbf7d0; border-color: #2ecc71;
}
.books-dropdown .book-chip.on:hover { background: #166534; }
.books-dropdown .book-chip .book-chip-mark {
  display: inline-block;
  width: 16px; height: 16px;
  border-radius: 3px;
  border: 1px solid #3a4358;
  background: transparent;
  color: transparent;
  text-align: center; line-height: 14px;
  font-size: 11px; font-weight: 800;
  flex-shrink: 0;
}
.books-dropdown .book-chip.on .book-chip-mark {
  background: #2ecc71; border-color: #2ecc71; color: #0e1116;
}
.books-dropdown .book-chip .book-chip-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
}
.books-dropdown .book-empty {
  grid-column: 1 / -1;
  padding: 20px; color: #6b7c97; text-align: center; font-size: 13px;
}

/* Sport-section header inside the per-tab Markets dropdown — shown when the
 * user is viewing more than one sport so MLB / NBA chips don't interleave
 * alphabetically. Spans the full grid row (same trick as .book-empty).
 * Uses the same cyan gradient as button#refresh-btn so the app's accent
 * color shows up consistently wherever the UI is highlighting something. */
.books-dropdown .market-group-header {
  grid-column: 1 / -1;
  margin-top: 10px;
  padding: 5px 10px 6px;
  background: linear-gradient(135deg, #22d3ee 0%, #0891b2 100%);
  color: #051418;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  border-radius: 6px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset;
}
/* First header has no extra top gap — it sits right under the presets row. */
.books-dropdown .market-group-header:first-child {
  margin-top: 0;
}

/* ===================== Sharp-weights chip + popover =====================
   Lives in <header>; click to toggle a popover that lists per-book weights
   driving the consensus fair line.  Mirrors the visual language of the
   Sportsbooks/Markets triggers but renders a read-only table. */
.weights-chip-wrap {
  position: relative;
  display: inline-block;
}
.weights-chip-wrap.open { z-index: 100; }
.weights-chip {
  background: #1b2030;
  border: 1px solid #2b3144;
  color: #cfd6e4;
  padding: 3px 8px;
  border-radius: 999px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 1;
  height: 22px;
}
.weights-chip:hover { background: #232a3d; border-color: #3a4358; }
.weights-chip-caret { font-size: 10px; color: #6b7c97; }
.weights-chip-wrap.open .weights-chip {
  background: #232a3d; border-color: #4d5f86; color: #e5e9f0;
}

.weights-popover {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 50;
  width: 320px;
  max-height: 420px;
  overflow: hidden;
  background: #161b26;
  border: 1px solid #2b3144;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  padding: 10px 12px;
  color: #cfd6e4;
  font-size: 12px;
}
.weights-chip-wrap.open .weights-popover {
  display: block;
}
.weights-popover-title {
  font-weight: 700;
  color: #e5e9f0;
  font-size: 13px;
  margin-bottom: 4px;
}
.weights-popover-sub {
  color: #6b7c97;
  font-size: 11px;
  margin-bottom: 8px;
  line-height: 1.4;
}
.weights-popover-sub b { color: #cfd6e4; font-weight: 600; }
.weights-popover-list {
  max-height: 280px;
  overflow-y: auto;
  padding-right: 4px;
}
.weights-popover-empty {
  color: #6b7c97;
  text-align: center;
  padding: 12px 0;
}

.weights-row {
  display: grid;
  grid-template-columns: 110px 1fr 36px;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
}
.weights-row-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #cfd6e4;
}
.weights-row-val {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: #e5e9f0;
  font-weight: 600;
}
.weights-row-bar {
  position: relative;
  background: #0e1116;
  border: 1px solid #2b3144;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
}
.weights-row-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #3a4358, #5a6b8c);
  transition: width 120ms ease;
}
.weights-row.sharp .weights-row-bar-fill { background: linear-gradient(90deg, #2ecc71, #46e08a); }
.weights-row.mid   .weights-row-bar-fill { background: linear-gradient(90deg, #f1c40f, #f7d558); }
.weights-row.rec   .weights-row-bar-fill { background: linear-gradient(90deg, #4d5f86, #6b7c97); }
.weights-row.sharp .weights-row-val { color: #46e08a; }

.weights-popover-foot {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid #2b3144;
  color: #6b7c97;
  font-size: 11px;
}
.weights-popover-foot b { color: #cfd6e4; font-weight: 600; }

/* ===== Fantasy tab =====
   The Fantasy grid piggybacks on .market-section / table.grid (see the shared
   OddsJam-style grid block above) for sticky-left columns and horizontal
   scroll. The overrides below just dial in per-column widths and inherit the
   per-book cell styling from the main grid. */
.fantasy-table { width: 100%; border-collapse: collapse; }  /* legacy — unused after redesign */
.fantasy-table thead th {
  text-align: left; padding: 11px 14px;
  background: linear-gradient(180deg, #1d2432 0%, #161c28 100%);
  color: #b8c5da; font-weight: 700; font-size: 11.5px;
  letter-spacing: 0.4px;
  border-bottom: 1px solid #2a3243;
}
.fantasy-table tbody td {
  padding: 11px 14px; border-bottom: 1px solid #1e2532;
  vertical-align: middle; font-size: 13px;
}
.fantasy-table tbody tr:hover { background: #19212e; }
.fan-player { font-weight: 600; color: #e5e9f0; display: flex; align-items: center; gap: 8px; }
.fan-matchup { font-size: 11px; margin-top: 2px; }
.fan-time    { font-size: 11px; }

/* Column widths on the new grid layout. The book columns come from the shared
   .bookhead rule (min-width: 112px) so we don't need per-book widths here. */
.fantasy-grid .rowhead   { min-width: 220px; }
.fantasy-grid .col-ou    { width: 72px;  text-align: center; }
.fantasy-grid .col-stat  { min-width: 160px; }
/* Stat column uses the shared .market-tag pill (same blue badge as the Lines
   tab). Kill its default 6px left margin since it lives alone in the cell
   rather than being glued to a matchup label. */
.fantasy-grid .col-stat .market-tag { margin-left: 0; }
.fantasy-grid .col-line  { width: 110px; text-align: center; }
.fantasy-grid .col-ev    { width: 90px;  text-align: center; font-variant-numeric: tabular-nums; }
/* Line Edge column — how many points the DFS line is shaded vs the most
   extreme sharp-book alt line. Signed, so positive=advantage to bettor. */
.fantasy-grid .col-line-edge { width: 80px; text-align: center; font-variant-numeric: tabular-nums; }
.fantasy-grid td.col-ou,
.fantasy-grid td.col-stat,
.fantasy-grid td.col-line,
.fantasy-grid td.col-ev,
.fantasy-grid td.col-line-edge,
.fantasy-grid td.price-cell {
  padding: 10px 12px; vertical-align: middle; font-size: 13px;
}
/* Line Edge tiers: strong (≥1 full point of edge) gets a green chip-ish
   background; partial-point positive is just green text; zero is muted;
   negative is red. */
.fantasy-grid td.col-line-edge.le-strong { color: #86efac; background: #0f2f22; }
.fantasy-grid td.col-line-edge.le-pos    { color: #86efac; }
.fantasy-grid td.col-line-edge.le-zero   { color: #94a3b8; }
.fantasy-grid td.col-line-edge.le-neg    { color: #fca5a5; }
.fantasy-grid td.hit-cell {
  padding: 10px 12px; vertical-align: middle; font-size: 13px;
  font-variant-numeric: tabular-nums; text-align: center;
}
.fantasy-grid td.hit-cell.hit-strong { color: #2ecc71; background: #0f2f22; }
.fantasy-grid td.hit-cell.hit-mid    { color: #cbd5e1; }
.fantasy-grid td.hit-cell.hit-weak   { color: #9fb0ca; }
.fantasy-grid .dfs-book-inline {
  font-size: 11px; color: #a7b5cc; margin-left: 4px;
}
/* The inline DFS-book badge in the Line column is visually smaller than
   header badges — keep the logo to 14px so it doesn't dominate the number. */
.fantasy-grid .dfs-book-inline .book-logo { width: 14px; height: 14px; flex-basis: 14px; }
.fantasy-grid .dfs-book-inline .book-label { gap: 4px; }
.fantasy-grid .dfs-book-inline .book-label-name { font-weight: 500; }
.fantasy-grid .fan-price {
  display: flex; align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums;
}
/* Per-book line stacked above the odds. Muted by default; amber when it
   differs from the DFS anchor line so the eye catches off-line quotes. */
.fantasy-grid .fan-book-line {
  font-size: 11px; color: #7a8aa6; line-height: 1.15;
  font-variant-numeric: tabular-nums; text-align: center;
}
.fantasy-grid .fan-book-line.off-line {
  color: #f59e0b; font-weight: 600;
}
.fantasy-grid td.price-cell { text-align: center; }
.fantasy-grid td.price-cell.ev-pos  b { color: #2ecc71; }
.fantasy-grid td.price-cell.ev-tiny b { color: #cbd5e1; }
.fantasy-grid td.price-cell.ev-neg  b { color: #e74c3c; }

/* Team picker — custom dropdown with an inline quick-search input. */
.fantasy-team-picker { position: relative; display: inline-block; }
.fantasy-team-trigger {
  background: #1a2230; color: #cfd6e4; border: 1px solid #222831;
  border-radius: 6px; padding: 6px 10px; cursor: pointer; font-size: 13px;
  min-width: 140px; text-align: left;
}
.fantasy-team-trigger:hover { background: #222a38; }
.fantasy-team-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 80;
  background: #151a22; border: 1px solid #222831; border-radius: 8px;
  padding: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  width: 240px;
}
.fantasy-team-menu input[type=text] {
  width: 100%; padding: 6px 8px; border-radius: 6px;
  background: #0f141c; color: #e5e9f0; border: 1px solid #222831;
  font-size: 13px; box-sizing: border-box;
}
.fantasy-team-list {
  margin-top: 6px; max-height: 260px; overflow-y: auto;
}
.team-pick-row {
  padding: 6px 8px; border-radius: 4px; font-size: 13px;
  color: #cfd6e4; cursor: pointer;
}
.team-pick-row:hover { background: #1a2230; }
.team-pick-row.active {
  background: #1d3350; color: #e5e9f0; font-weight: 600;
}

/* O/U pill — Over = green, Under = red so the user can scan at a glance. */
.ou-badge {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.3px;
}
.ou-over  { background: #0f2f22; color: #2ecc71; border: 1px solid #1d5a3e; }
.ou-under { background: #2f1616; color: #e74c3c; border: 1px solid #5a2a2a; }

/* Hit % color bands — OddsJam uses a green gradient. We just use three buckets. */
.col-hit.hit-strong { color: #2ecc71; background: #0f2f22; }
.col-hit.hit-mid    { color: #cbd5e1; }
.col-hit.hit-weak   { color: #9fb0ca; }

/* EV color bands reuse the same scheme as the Lines grid. */
.col-ev.ev-pos  { color: #2ecc71; font-weight: 700; }
.col-ev.ev-tiny { color: #cbd5e1; }
.col-ev.ev-neg  { color: #e74c3c; }
.col-ev.muted   { color: #6b7c97; }

/* ===== Parlay builder ===== */
.click-leg {
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, transform 80ms ease;
}
.click-leg:hover {
  background: #1d2738 !important;
  border-color: #3a4358 !important;
}
.click-leg:focus {
  outline: 2px solid #3b82f6;
  outline-offset: -2px;
}
.click-leg.in-parlay {
  background: #1a2f4a !important;
  border-color: #3b82f6 !important;
  box-shadow: inset 0 0 0 1px #3b82f6;
}
.parlay-mark {
  display: inline-block;
  width: 12px;
  color: #3b82f6;
  font-weight: 700;
  margin-right: 4px;
  text-align: center;
}

.parlay-tray {
  position: fixed;
  right: 18px;
  bottom: 0;
  width: 360px;
  max-width: calc(100vw - 36px);
  background: #151a22;
  border: 1px solid #2b3144;
  border-bottom: 0;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.55);
  z-index: 40;
  font-size: 13px;
  color: #e5e9f0;
  display: flex;
  flex-direction: column;
}
.parlay-tray.collapsed .parlay-body { display: none; }
.parlay-tray.collapsed .parlay-toggle-caret { transform: rotate(180deg); }

.parlay-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #1a2230;
  border: 0;
  color: #e5e9f0;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  width: 100%;
  text-align: left;
}
.parlay-toggle:hover { background: #202a3c; }
.parlay-toggle-label { flex: 1; }
.parlay-toggle-count {
  background: #263145;
  color: #9fb0ca;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 700;
  min-width: 22px;
  text-align: center;
}
.parlay-toggle-count.has-legs {
  background: #3b82f6;
  color: #ffffff;
}
.parlay-toggle-caret {
  font-size: 10px;
  color: #6b7c97;
  transition: transform 150ms ease;
}

.parlay-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px 14px;
  max-height: 62vh;
  overflow-y: auto;
  border-top: 1px solid #2b3144;
}

.parlay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.parlay-title { font-weight: 600; color: #cfd6e4; font-size: 13px; }
.parlay-btn {
  background: #1a2230;
  color: #cbd5e1;
  border: 1px solid #2b3144;
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
}
.parlay-btn:hover { background: #232a3d; border-color: #3a4358; }

.parlay-legs {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.parlay-empty {
  color: #6b7c97;
  font-size: 12px;
  padding: 10px 6px;
  text-align: center;
  border: 1px dashed #2b3144;
  border-radius: 6px;
}
.parlay-leg {
  background: #121821;
  border: 1px solid #232a3b;
  border-radius: 6px;
  padding: 8px 10px;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  align-items: start;
}
.parlay-leg-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.parlay-leg-top {
  color: #cfd6e4;
  font-weight: 600;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.parlay-leg-mid {
  color: #9fb0ca;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.parlay-leg-foot {
  color: #6b7c97;
  font-size: 11px;
  display: flex;
  gap: 8px;
  align-items: center;
}
.parlay-leg-foot .price {
  color: #e5e9f0;
  font-weight: 600;
}
.parlay-leg-foot .ev-pos { color: #2ecc71; font-weight: 600; }
.parlay-leg-foot .ev-neg { color: #e74c3c; font-weight: 600; }
.parlay-leg-x {
  background: transparent;
  border: 0;
  color: #6b7c97;
  cursor: pointer;
  font-size: 16px;
  padding: 0 4px;
  line-height: 1;
  align-self: start;
}
.parlay-leg-x:hover { color: #e74c3c; }

.parlay-warn {
  background: #3a2a12;
  color: #f1c27d;
  border: 1px solid #5a3f1b;
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 11px;
  line-height: 1.4;
}

.parlay-summary {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid #2b3144;
}
.parlay-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: #9fb0ca;
}
.parlay-summary-row b {
  color: #e5e9f0;
  font-weight: 700;
  font-size: 13px;
}
.parlay-summary-row .ev-pos { color: #2ecc71; }
.parlay-summary-row .ev-neg { color: #e74c3c; }

.parlay-stake-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 6px;
  border-top: 1px dashed #232a3b;
  margin-top: 2px;
}
.parlay-stake-row label {
  color: #9fb0ca;
  font-size: 12px;
  flex: 0 0 auto;
}
.parlay-stake-row input {
  background: #0e1116;
  color: #e5e9f0;
  border: 1px solid #2b3144;
  border-radius: 6px;
  padding: 5px 8px;
  font-size: 13px;
  width: 100%;
  flex: 1;
}
.parlay-stake-row input:focus {
  outline: none;
  border-color: #3b82f6;
}
.parlay-payout {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: #9fb0ca;
}
.parlay-payout b {
  color: #2ecc71;
  font-weight: 700;
  font-size: 13px;
}

/* Sticky horizontal scrollbar — pinned to the bottom of the viewport,
   mirrors the horizontal scroll of whichever .market-section the user is
   currently looking at. JS sets `left`, `width`, and the inner spacer's
   width to match the tracked section, and toggles `display`. We sit at
   z-index 30 — above the table (which uses 2-5) but below the parlay
   tray (40) so the tray's bottom-right corner is never blocked. The
   native scrollbar inside this element is what the user actually drags;
   we just tell the OS "here's a 1px-tall element wider than the box, go
   draw chrome." Height is sized to roughly match a typical OS thin
   scrollbar so it doesn't add visible chrome on platforms that hide
   scrollbars by default. */
#sticky-hscroll {
  display: none;
  position: fixed;
  bottom: 0;
  height: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  z-index: 30;
  background: rgba(15, 20, 28, 0.85);
  border-top: 1px solid var(--border-soft);
  /* Backdrop blur is lovely if supported, but harmless if not — gates on
     CSS @supports so older browsers fall back to the solid translucent
     background above. */
  backdrop-filter: blur(6px);
}
#sticky-hscroll-inner {
  height: 1px;
  /* width set dynamically via JS to match the tracked .market-section's
     scrollWidth so the OS scrollbar matches the table's actual scroll
     range. */
}

/* User account menu — small avatar circle in the header that opens a
   dropdown with the user's email and a sign-out button. Only rendered when
   the viewer is signed in (template gates on current_user). */
.user-menu {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.user-menu-trigger {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.user-menu-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, #22d3ee 0%, #0ea5b7 100%);
  color: #051014;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.2) inset,
    0 2px 8px rgba(0, 0, 0, 0.3);
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.user-menu-trigger:hover .user-menu-avatar {
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 4px 12px rgba(34, 211, 238, 0.4);
}
.user-menu-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 220px;
  background: linear-gradient(180deg, #1a2133 0%, #131828 100%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  padding: 12px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 20px 40px -10px rgba(0, 0, 0, 0.6);
  z-index: 50;
  display: none;
}
.user-menu.open .user-menu-dropdown { display: block; }
.user-menu-email {
  color: #cbd5e1;
  font-size: 12px;
  font-weight: 500;
  padding: 6px 8px 10px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  word-break: break-all;
}
.user-menu-signout {
  margin-top: 8px;
  width: 100%;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 6px;
  color: #fca5a5;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.user-menu-signout:hover {
  background: rgba(220, 38, 38, 0.1);
  border-color: rgba(220, 38, 38, 0.4);
}
