/* ══════════════════════════════════════════════════════════════════════
   OddsMunch NFL — design system (round 1)
   Dark, data-forward, sportsbook-grade. Everything tunable lives in the
   custom properties below. Fonts are self-hosted from /static/nfl/fonts
   (Barlow Condensed + Inter, both SIL OFL) — no external font CDN.
   ══════════════════════════════════════════════════════════════════════ */

@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('/static/nfl/fonts/BarlowCondensed-500-latin.woff2') format('woff2'); }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('/static/nfl/fonts/BarlowCondensed-600-latin.woff2') format('woff2'); }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 700;
  font-display: swap; src: url('/static/nfl/fonts/BarlowCondensed-700-latin.woff2') format('woff2'); }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 800;
  font-display: swap; src: url('/static/nfl/fonts/BarlowCondensed-800-latin.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400 700;
  font-display: swap; src: url('/static/nfl/fonts/Inter-latin-var.woff2') format('woff2'); }

:root {
  /* ink scale (brand dark base) */
  --ink-950:#0A0C1C; --ink-900:#10132B; --ink-850:#141838; --ink-800:#1A1F45;
  --line:rgba(148,152,255,.10); --line-strong:rgba(148,152,255,.20);

  /* signature accent (OddsMunch violet family) */
  --acc:#8B7CFF; --acc-deep:#5A4AE3; --acc-soft:rgba(139,124,255,.14);
  --acc-border:rgba(139,124,255,.45); --acc-text:#CFC7FF;
  --grad-brand:linear-gradient(135deg,#B3A6FF 0%,#8B7CFF 45%,#5A4AE3 100%);

  /* live/status */
  --live:#6FE8BC;

  /* semantic movement */
  --up:#4FDB94;   --up-soft:rgba(79,219,148,.13);  --up-border:rgba(79,219,148,.4);
  --down:#FF6478; --down-soft:rgba(255,100,120,.12); --down-border:rgba(255,100,120,.4);

  /* text — sub must hold ≥4.5:1 on ink-900 (10-11px labels sit on cards) */
  --tx:#EDEFFF; --tx-mut:#9CA3C7; --tx-sub:#7A81A9;

  /* typography */
  --disp:'Barlow Condensed',-apple-system,'Segoe UI',sans-serif;
  --body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;

  /* shape + rhythm */
  --r-lg:16px; --r-md:12px; --r-sm:8px; --r-full:999px;
  --nav-h:52px;
  --pagew:1140px;
  --gutter:16px;

  /* team accent strip */
  --strip-w:3px;
}

*{box-sizing:border-box;margin:0;padding:0;}
html{color-scheme:dark;-webkit-text-size-adjust:100%;}
body{font-family:var(--body);color:var(--tx);font-size:14px;min-height:100vh;
  background:
    radial-gradient(1100px 500px at 85% -10%, rgba(90,74,227,.22), transparent 60%),
    radial-gradient(900px 420px at -10% 0%, rgba(111,232,188,.06), transparent 55%),
    var(--ink-950);}
a{color:inherit;}

/* ── sticky nav: brand + section tabs, one bar, page name never repeats ── */
.nflnav{position:sticky;top:0;z-index:200;height:var(--nav-h);
  display:flex;align-items:center;gap:14px;padding:0 16px;
  background:rgba(11,13,31,.82);backdrop-filter:blur(14px) saturate(1.5);
  -webkit-backdrop-filter:blur(14px) saturate(1.5);
  border-bottom:1px solid var(--line);}
.nflnav .brand{display:flex;align-items:center;gap:9px;text-decoration:none;flex:0 0 auto;}
.nflnav .dot{width:8px;height:8px;background:var(--live);border-radius:50%;
  box-shadow:0 0 10px rgba(111,232,188,.9),0 0 22px rgba(111,232,188,.35);}
.nflnav .wordmark{font-family:var(--disp);font-weight:800;font-size:18px;letter-spacing:.06em;
  text-transform:uppercase;background:var(--grad-brand);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;line-height:1;
  white-space:nowrap;}
.tabs{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;
  flex:1 1 auto;height:100%;align-items:stretch;}
.tabs::-webkit-scrollbar{display:none;}
.tab{display:flex;align-items:center;padding:0 13px;font-size:12.5px;font-weight:600;
  color:var(--tx-mut);text-decoration:none;white-space:nowrap;position:relative;
  letter-spacing:.02em;}
.tab:hover{color:var(--tx);}
.tab.on{color:var(--tx);}
.tab.on::after{content:'';position:absolute;left:10px;right:10px;bottom:0;height:2.5px;
  background:var(--grad-brand);border-radius:2px 2px 0 0;}
.nav-upd{flex:0 0 auto;font-size:11px;color:var(--tx-sub);display:flex;align-items:center;gap:6px;
  white-space:nowrap;}
.nav-upd .pulse{width:6px;height:6px;border-radius:50%;background:var(--live);
  box-shadow:0 0 8px rgba(111,232,188,.8);position:relative;}
/* the heartbeat the design system promises: a halo ring, transform/opacity only */
@media (prefers-reduced-motion: no-preference){
  .nav-upd .pulse::after{content:'';position:absolute;inset:0;border-radius:50%;
    background:var(--live);animation:heartbeat 2.6s ease-out infinite;}
}
@keyframes heartbeat{0%{transform:scale(1);opacity:.55}70%,100%{transform:scale(2.8);opacity:0}}
/* the site-wide account chip joins .nav-upd inline on desktop; when it can't
   fit the bar (mobile: the scrolling tab row overflows) it falls back to a
   fixed float below the nav, which hovers over content for the whole scroll.
   Anchor that fallback to the document instead: same resting spot, but it
   scrolls away with the top of the page. (!important: the script re-applies
   position:fixed inline on every resize.) */
#om-account-chip:not([inflow]){position:absolute !important;}

/* keyboard focus carries the brand, not the UA default */
.tab:focus-visible,.brand:focus-visible{outline:2px solid var(--acc-border);outline-offset:-2px;}
.seg button:focus-visible,.howto .x:focus-visible{outline:2px solid var(--acc-border);outline-offset:-2px;}
::selection{background:rgba(139,124,255,.35);color:var(--tx);}

/* ── page scaffold ── */
.wrap{padding:20px var(--gutter) 56px;max-width:var(--pagew);margin:0 auto;}
.pagehead{margin:6px 0 14px;display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 16px;}
h1{font-family:var(--disp);font-weight:800;font-size:30px;letter-spacing:.02em;
  text-transform:uppercase;line-height:1.05;}
.pagesub{font-size:12.5px;color:var(--tx-mut);line-height:1.55;max-width:640px;}
h2{font-family:var(--disp);font-weight:700;font-size:17px;letter-spacing:.04em;
  text-transform:uppercase;color:var(--acc);margin:26px 0 8px;}
.caveat{font-size:11.5px;color:var(--tx-mut);margin:6px 0 4px;line-height:1.55;max-width:760px;}
.caveat b{color:var(--tx);}

/* ── controls row (filter + sort) ── */
.controls{display:flex;gap:8px;margin:12px 0 4px;flex-wrap:wrap;align-items:center;}
.filter{flex:1 1 220px;max-width:340px;position:relative;}
.filter input{width:100%;height:38px;padding:0 12px 0 34px;border-radius:var(--r-full);
  background:var(--ink-900);border:1px solid var(--line-strong);color:var(--tx);
  font-family:var(--body);font-size:13px;outline:none;}
.filter input:focus{border-color:var(--acc-border);box-shadow:0 0 0 3px rgba(139,124,255,.12);}
.filter input::placeholder{color:var(--tx-sub);}
.filter svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);opacity:.5;}
.seg{display:flex;border:1px solid var(--line-strong);border-radius:var(--r-full);overflow:hidden;}
.seg button{height:38px;padding:0 15px;background:transparent;border:0;color:var(--tx-mut);
  font-family:var(--body);font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;}
.seg button.on{background:var(--acc-soft);color:var(--acc-text);}
.count-note{font-size:11.5px;color:var(--tx-sub);margin-left:auto;}

/* ── data tables ──
   ONE sticky header, opaque, rows pass beneath — the rules that make it
   hold everywhere:
   - the card carries NO overflow property (hidden hijacked the sticky
     containing block; clip triggered a Chromium repaint bug where the
     stuck th cells stopped painting their background, so rows showed
     through a transparent header). Top corners are rounded on the th
     cells instead.
   - the FLAT SOLID fill lives on the th CELLS (sticky paints per-cell;
     thead gets the same solid as belt-and-braces). Never the body's
     radial-gradient — a gradient fragment would misalign while stuck.
   - the header sticks 1px above the nav's underside so no seam of
     scrolling row content can peek through at the top edge, and its
     bottom border is a SOLID color (a translucent border is itself a
     seam rows would show through).
   - border-collapse:separate so row borders can't paint through the
     stuck header; no tbody cell z-index reaches the header's. */
.tblcard{background:var(--ink-900);
  border:1px solid var(--line);border-radius:var(--r-lg);margin-top:12px;}
.tblwrap{width:100%;}
table.data{width:100%;border-collapse:separate;border-spacing:0;}
table.data, table.data *{transition:none;}   /* re-sorting must be instant */
table.data thead{background:var(--ink-900);}
table.data th{position:sticky;top:calc(var(--nav-h) - 1px);z-index:5;
  background:var(--ink-900);background-clip:padding-box;
  padding:10px 12px;text-align:left;font-size:10px;font-weight:700;
  color:var(--tx-sub);text-transform:uppercase;letter-spacing:.09em;
  border-bottom:1px solid #282C52;white-space:nowrap;}
table.data th:first-child{border-top-left-radius:calc(var(--r-lg) - 1px);}
table.data th:last-child{border-top-right-radius:calc(var(--r-lg) - 1px);}
table.data th.sortable{cursor:pointer;user-select:none;}
table.data th.sortable:hover{color:var(--tx-mut);}
table.data th .arr{opacity:.0;font-size:9px;margin-left:3px;}
table.data th.sorted .arr{opacity:1;color:var(--acc);}
table.data td{padding:10px 12px;font-size:13.5px;border-bottom:1px solid var(--line);
  color:var(--tx-mut);}
table.data tbody tr:last-child td{border-bottom:0;}
@media (hover:hover){
  table.data tbody tr:hover td{background:rgba(139,124,255,.04);}
}
th.num,td.num{text-align:right;font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;}
td.num{color:var(--tx);font-weight:600;}
td.dim{color:var(--tx-sub);font-weight:400;}

/* player cell: team strip + avatar + name/matchup + position chip */
td.player{padding-left:14px;position:relative;min-width:190px;}
td.player::before{content:'';position:absolute;left:0;top:8px;bottom:8px;width:var(--strip-w);
  border-radius:2px;background:var(--team,#7C82A8);
  box-shadow:0 0 8px color-mix(in srgb,var(--team,#7C82A8) 55%,transparent);}
.pwrap{display:flex;align-items:center;gap:10px;}
.avatar{flex:0 0 auto;width:34px;height:34px;border-radius:50%;position:relative;
  background:color-mix(in srgb,var(--team,#7C82A8) 26%,var(--ink-800));
  border:1px solid color-mix(in srgb,var(--team,#7C82A8) 55%,transparent);
  display:flex;align-items:center;justify-content:center;overflow:hidden;}
.avatar .init{font-family:var(--disp);font-weight:700;font-size:12.5px;color:var(--tx);
  letter-spacing:.03em;}
.avatar img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top;}
.pmeta{min-width:0;}
.pname{color:var(--tx);font-weight:600;font-size:13.5px;line-height:1.25;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:7px;}
.pos{flex:0 0 auto;font-family:var(--disp);font-size:10.5px;font-weight:700;letter-spacing:.08em;
  color:var(--tx-mut);background:var(--ink-800);border:1px solid var(--line-strong);
  border-radius:4px;padding:1px 5px;line-height:1.35;}
.psub{font-size:11px;color:var(--tx-sub);line-height:1.3;margin-top:1px;white-space:nowrap;
  font-variant-numeric:tabular-nums;}
.psub b{color:var(--tx-mut);font-weight:600;}

/* odds cells */
.odds{display:inline-block;min-width:52px;text-align:right;padding:3px 9px;border-radius:var(--r-full);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  font-weight:600;font-size:13px;color:var(--tx-mut);}
/* unposted: quiet by design — a small dim tick, tooltip carries the words */
td .odds.na{color:var(--tx-sub);font-weight:400;opacity:.45;font-size:11px;cursor:help;}
.odds.best{background:var(--acc-soft);border:1px solid var(--acc-border);color:var(--acc-text);
  box-shadow:0 0 12px rgba(139,124,255,.10);}

/* movement */
.mv{display:inline-flex;align-items:center;gap:5px;font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
  font-weight:700;font-size:13px;padding:3px 10px;border-radius:var(--r-full);}
.mv.up{color:var(--up);background:var(--up-soft);border:1px solid var(--up-border);}
.mv.down{color:var(--down);background:var(--down-soft);border:1px solid var(--down-border);}
.mv.flat{color:var(--tx-sub);}
.legend{display:flex;gap:16px;flex-wrap:wrap;font-size:11.5px;color:var(--tx-sub);margin-top:8px;}
.legend .up{color:var(--up);} .legend .down{color:var(--down);}

/* mover highlight cards */
.movers{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:10px;margin-top:12px;}
.mcard{background:linear-gradient(180deg,var(--ink-900),var(--ink-950));border:1px solid var(--line);
  border-radius:var(--r-md);padding:12px 14px;position:relative;overflow:hidden;}
.mcard::before{content:'';position:absolute;left:0;top:0;bottom:0;width:var(--strip-w);
  background:var(--team,#7C82A8);}
.mcard .mtop{display:flex;align-items:center;gap:9px;margin-bottom:8px;}
.mcard .mprice{display:flex;align-items:baseline;gap:8px;font-variant-numeric:tabular-nums;}
.mcard .now{font-family:var(--disp);font-weight:800;font-size:26px;letter-spacing:.02em;}
.mcard .was{font-size:12px;color:var(--tx-sub);text-decoration:line-through;}
.mcard .mbook{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--tx-sub);margin-top:2px;}

/* "how to read this" — one dismissible line per table */
.howto{display:flex;align-items:flex-start;gap:9px;margin-top:12px;padding:9px 12px;
  font-size:11.5px;line-height:1.5;color:var(--tx-mut);
  background:rgba(139,124,255,.06);border:1px solid var(--line);border-radius:var(--r-sm);}
.howto b{color:var(--acc-text);font-weight:600;}
.howto .hicon{flex:0 0 auto;color:var(--acc);font-weight:700;font-size:12px;line-height:1.5;}
.howto .x{margin-left:auto;flex:0 0 auto;background:none;border:0;color:var(--tx-sub);
  cursor:pointer;font-size:15px;line-height:1;padding:2px 4px;}
.howto .x:hover{color:var(--tx);}

/* density: body.compact tightens every table on the page */
body.compact table.data td{padding:5px 10px;font-size:12.5px;}
body.compact .avatar{width:26px;height:26px;}
body.compact .avatar .init{font-size:10px;}
body.compact .pname{font-size:12.5px;}
body.compact .psub{font-size:10px;}
body.compact .odds{padding:1px 7px;min-width:46px;font-size:12px;}
body.compact .mv{padding:1px 8px;font-size:12px;}
body.compact td.player::before{top:5px;bottom:5px;}

/* tap-to-expand breakdown (mobile): generated .xrow under the tapped row */
tr.open td{background:rgba(139,124,255,.07);}
tr.xrow>td{padding:2px 14px 12px;background:rgba(139,124,255,.05);}
.xgrid{display:grid;grid-template-columns:1fr auto;gap:7px 16px;padding-top:9px;font-size:12.5px;}
.xgrid .xk{color:var(--tx-sub);font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.08em;align-self:center;}
.xgrid .xv{text-align:right;color:var(--tx);font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;}
.xgrid .xv .na{color:var(--tx-sub);font-weight:400;}

/* badges */
.badge{display:inline-block;font-size:9.5px;font-weight:700;text-transform:uppercase;
  letter-spacing:.07em;padding:3px 9px;border-radius:var(--r-full);vertical-align:2px;
  background:var(--acc-soft);border:1px solid var(--acc-border);color:var(--acc-text);}
.badge.raw{background:rgba(255,180,84,.12);border-color:rgba(255,180,84,.4);color:#FFB454;}
.badge.devig{background:var(--up-soft);border-color:var(--up-border);color:var(--up);}

/* implied-probability bar */
.pbar{display:inline-block;width:74px;height:5px;border-radius:3px;background:var(--ink-800);
  overflow:hidden;vertical-align:2px;margin-left:9px;}
.pbar i{display:block;height:100%;background:var(--grad-brand);border-radius:3px;}

/* empty / dark states */
.empty{text-align:center;padding:44px 18px;color:var(--tx-mut);font-size:13px;line-height:1.6;}
.empty .big{font-family:var(--disp);font-weight:700;font-size:19px;letter-spacing:.04em;
  text-transform:uppercase;color:var(--tx);display:block;margin-bottom:6px;}
.darkcard{text-align:center;padding:58px 22px;margin-top:16px;
  background:linear-gradient(180deg,var(--ink-900),var(--ink-950));
  border:1px solid var(--line);border-radius:var(--r-lg);}
.darkcard .big{font-family:var(--disp);font-weight:800;font-size:26px;letter-spacing:.04em;
  text-transform:uppercase;display:block;margin-bottom:10px;}
.darkcard p{color:var(--tx-mut);font-size:13.5px;line-height:1.65;max-width:520px;margin:0 auto;}

.footnote{font-size:11px;color:var(--tx-sub);text-align:center;margin-top:26px;
  padding-top:14px;border-top:1px solid var(--line);line-height:1.6;}

/* ── mobile ── */
@media (max-width:760px){
  .nflnav{gap:10px;padding:0 12px;}
  .nflnav .wordmark{font-size:15px;}
  .nav-upd{display:none;}   /* term.css re-shows it dot-only so the account chip can dock */
  .wrap{--gutter:10px;padding:14px var(--gutter) 48px;}
  h1{font-size:25px;}
  /* the table becomes its own bounded scroll viewport: the header pins
     to the TOP of the wrap (top:0 here overrides the desktop calc(var(--nav-h) - 1px) —
     inheriting it was what detached the PLAYER cell onto row 1), the
     player column pins LEFT, and the corner cell pins on both axes.
     Rows scroll vertically inside the wrap, so column labels never
     leave the screen; numeric columns scroll horizontally beneath the
     pinned player column. */
  .tblwrap{overflow:auto;-webkit-overflow-scrolling:touch;
    max-height:calc(100vh - 76px);max-height:calc(100dvh - 76px);}
  table.data{min-width:560px;}
  table.data th{position:sticky;top:0;z-index:5;}
  table.data th:first-child{position:sticky;top:0;left:0;z-index:7;background:var(--ink-900);}
  td.player{position:sticky;left:0;z-index:4;background:var(--ink-900);
    box-shadow:8px 0 12px -8px rgba(0,0,0,.55);}
  table.data td{padding:11px 10px;}             /* generous tap targets */
  tr.expandable{cursor:pointer;}
  /* the expansion cell spans the whole (wide) table — pin its content so
     the breakdown reads without horizontal scrolling */
  .xgrid{position:sticky;left:10px;max-width:calc(100vw - 44px);}
  .controls{gap:6px;}
  .count-note{display:none;}
}
@media (max-width:480px){
  .movers{grid-template-columns:1fr 1fr;}
  /* slim the pinned column so at least one full price column shows
     beside it before any horizontal scrolling */
  td.player{min-width:168px;max-width:186px;}
  .pname{font-size:13px;}
  .psub{font-size:10.5px;}
}
