/* ============================================================================
   SHARP SIGNAL — one visual system for the whole site.
   Loaded by index.html (board · lines · bot · arb) and by the standalone
   chart page, so a change here lands everywhere at once.

   The product is read at 1am on a phone with money on the line. Every choice
   below serves legibility first: tabular numerals everywhere a price appears,
   generous line-height in prose and tight leading in data, one accent colour
   that only ever means "this is the thing", and never more than three weights
   of anything on screen at once.
   ========================================================================= */

:root{
  /* ONE SOURCE. tokens.css (generated from brand/tokens.json) loads first and
     defines every colour; this block only maps the names app.css has always
     used onto it. Before this, app.css redefined each hex itself with values
     that had drifted - the one place the product was told to look for its
     colours was the one place it did not. */
  --bg:var(--sur-0);
  --bg-1:var(--sur-1);
  --bg-2:var(--sur-2);
  --bg-3:var(--sur-3);
  --line:var(--line-1);
  /* --line-2, --line-3 come straight from tokens.css */

  --ink:var(--ink-1);
  /* --ink-2, --ink-3 come straight from tokens.css */

  /* --gold, --gold-dim from tokens.css. The washes are derived, not new colours. */
  --gold-2:#E3C778;
  --gold-wash:rgba(201,162,75,.10);
  --gold-line:rgba(201,162,75,.30);

  /* --pos, --neg, --warn, --info from tokens.css */
  --pos-2:#6FC28E;
  --pos-wash:rgba(69,160,106,.13);
  --neg-wash:rgba(220,100,105,.13);

  --ui:var(--f-display);
  --mono:var(--f-mono);

  /* [stated] 2026-09-17: "Make it look more appealing like a modern app
     style", pointing at a rival screener - rounded cards, prices in pills,
     book logos, roomy tap targets. That reverses the 2px "machined" radii
     the Sep 16 terminal pass set, and it is one edit rather than a hundred:
     every card, chip, button, input, segment and pill on all five tabs is
     drawn from these three numbers. The gold, the surfaces and the type are
     untouched - it is still Sharp Signal, it is just not a spreadsheet. */
  --r-sm:7px; --r:11px; --r-lg:15px; --r-pill:999px;
  --bar:52px;
  --shadow:0 1px 0 rgba(0,0,0,.4), 0 14px 38px rgba(0,0,0,.46);
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --lift:0 1px 0 rgba(255,255,255,.03) inset;
  --t:140ms cubic-bezier(.2,.7,.3,1);
}

*{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--ink);
  font:400 13.5px/1.5 var(--ui);
  font-feature-settings:"tnum" 1, "ss01" 1;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  overscroll-behavior-y:none;
}
a{color:var(--gold-2); text-decoration:none}
a:hover{text-decoration:underline}
button,input,select,textarea{font:inherit; color:inherit}
::selection{background:var(--gold); color:#14100A}
:focus-visible{outline:2px solid var(--gold); outline-offset:2px; border-radius:2px}
.num,.mono{font-family:var(--mono); font-variant-numeric:tabular-nums}
.dim{color:var(--ink-3)}
.sp{flex:1}
h1,h2,h3{margin:0; font-weight:700; letter-spacing:-.015em}

/* scrollbars — present, but not shouting */
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:var(--line-2); border-radius:0; border:3px solid var(--bg)}
*::-webkit-scrollbar-thumb:hover{background:var(--line-3)}

/* ── APP BAR ─────────────────────────────────────────────────────────────
   A terminal's chrome is a hairline and a rule. No glass, no pill: the
   wordmark, a segmented tab rail whose current tab is marked by a 2px gold
   rule on its bottom edge, and the state cluster on the right in mono. */
.appbar{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:stretch; gap:18px;
  height:var(--bar); padding:0 18px;
  background:var(--bg);
  border-bottom:1px solid var(--line-2);
}
.mark{
  display:flex; align-items:center; gap:10px; flex:none;
  font-weight:800; font-size:15px; letter-spacing:.06em; line-height:1;
  color:var(--ink); text-decoration:none; white-space:nowrap; text-transform:uppercase;
}
.mark:hover{text-decoration:none}
.mark b{color:var(--gold); font-weight:800}
.mark i{
  font-style:normal; font-size:9px; font-weight:600; letter-spacing:.2em;
  color:var(--ink-3); text-transform:uppercase; padding-left:10px;
  border-left:1px solid var(--line-2); line-height:1;
}

/* the tab rail */
.tabs{display:flex; align-items:stretch; gap:0; flex:none}
.tabs a{
  position:relative; display:flex; align-items:center; gap:7px;
  padding:0 15px; font-size:12.5px; font-weight:600; letter-spacing:.02em;
  color:var(--ink-2); text-decoration:none; white-space:nowrap;
  transition:color var(--t);
}
.tabs a::after{
  content:""; position:absolute; left:10px; right:10px; bottom:-1px; height:2px;
  background:transparent; transition:background var(--t);
}
.tabs a:hover{color:var(--ink); text-decoration:none}
.tabs a[aria-current="page"]{color:var(--ink)}
.tabs a[aria-current="page"]::after{background:var(--gold)}
.tabs a[aria-current="page"] svg{color:var(--gold)}
.tabs svg{width:14px;height:14px;flex:none;color:var(--ink-3);transition:color var(--t)}
.tabs a:hover svg{color:var(--ink-2)}
.tabs .short{display:none}

.bar-right{display:flex; align-items:center; gap:14px; margin-left:auto; min-width:0; overflow:hidden}
.fresh{
  display:flex; align-items:center; gap:8px; min-width:0;
  font:500 11.5px/1 var(--mono); color:var(--ink-2); white-space:nowrap;
  font-variant-numeric:tabular-nums; letter-spacing:.01em;
  overflow:hidden; text-overflow:ellipsis;
}
.fresh > span{min-width:0; overflow:hidden; text-overflow:ellipsis}
.dot{
  width:6px;height:6px;border-radius:50%;background:var(--pos);flex:none;
  box-shadow:0 0 0 3px rgba(69,160,106,.16);
}
.dot.stale{background:var(--warn); box-shadow:0 0 0 3px rgba(199,123,57,.18)}
.dot.dead{background:var(--neg); box-shadow:0 0 0 3px rgba(220,100,105,.18)}
#moved{color:var(--pos-2)}
.who{
  font:500 11.5px/1 var(--ui); color:var(--ink-3); padding-left:16px;
  border-left:1px solid var(--line-2); white-space:nowrap;
  max-width:180px; overflow:hidden; text-overflow:ellipsis; flex:0 1 auto;
}
.who a{color:var(--ink-2)}

/* ── BUTTONS ── */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:9px 16px; border-radius:var(--r-sm); border:1px solid transparent;
  background:var(--gold); color:#14100A; font-size:13px; font-weight:700;
  cursor:pointer; white-space:nowrap; text-decoration:none;
  transition:filter var(--t), transform var(--t), background var(--t), border-color var(--t);
}
.btn:hover{filter:brightness(1.08); text-decoration:none}
.btn:active{transform:translateY(1px)}
.btn:disabled{opacity:.5; cursor:not-allowed}
.btn.ghost{background:var(--bg-2); color:var(--ink-2); border-color:var(--line-2)}
.btn.ghost:hover{color:var(--ink); border-color:var(--line-3); background:var(--bg-3)}
.btn{border-radius:var(--r); min-height:38px}
.btn.sm{padding:7px 13px; font-size:12px; min-height:32px}
.btn.wide{width:100%}

/* segmented control */
.seg{display:inline-flex; border:1px solid var(--line-2); border-radius:var(--r-pill); background:var(--bg-2); padding:3px; gap:2px}
/* Six market buttons are 283px of content and a 320px phone gives the filter
   row 272px. They wrap onto a second line rather than losing "Totals". */
@media(max-width:560px){
  .seg{flex-wrap:wrap; border-radius:var(--r-sm)}
  .seg button{flex:1 1 auto}
}
.seg button{
  background:transparent; border:0; border-right:1px solid var(--line);
  padding:7px 13px; color:var(--ink-2); font-size:13px; font-weight:500;
  cursor:pointer; white-space:nowrap; transition:background var(--t), color var(--t);
}
.seg button{border-right:0; border-radius:var(--r-pill); padding:7px 13px}
.seg button:hover{color:var(--ink); background:var(--bg-3)}
/* the selected segment is a FILLED pill, not an underline: on a phone an
   inset 2px rule under 11px type is invisible at arm's length */
.seg button.on,.seg button[aria-pressed="true"]{
  background:var(--gold); color:#14100A; box-shadow:none; font-weight:700;
}
.seg .short{display:none}

/* inputs */
/* MATCH EVERY TEXT-ISH INPUT, NOT A LIST OF TYPES. `<input id="oddsA">` has no
   type ATTRIBUTE, so input[type=text] does not select it - the arb calculator's
   two price boxes rendered as white browser defaults with near-invisible text,
   on the one screen where reading the number is the entire job. */
select,textarea,
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]){
  min-height:38px;
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-sm);
  padding:8px 11px; color:var(--ink); font-size:13px;
  transition:border-color var(--t), background var(--t);
}
select:hover,input:not([type=range]):hover{border-color:var(--line-3)}
select:disabled{opacity:.45}
select{
  appearance:none; padding-right:28px;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
  background-position:calc(100% - 15px) 55%,calc(100% - 10px) 55%;
  background-size:5px 5px; background-repeat:no-repeat;
}
input[type=search]{min-width:200px; flex:1 1 190px}
input[type=range]{accent-color:var(--gold)}
input[type=checkbox]{accent-color:var(--gold); width:15px; height:15px}
.field{display:flex; flex-direction:column; gap:6px}
.field > label,.lbl{
  font-size:12.5px; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
  color:var(--ink-2);
}

/* ── LAYOUT ── */
.view{display:none}
.view.on{display:block}
.pad{padding:20px 18px 56px}
.wrap{max-width:1560px; margin:0 auto}
.narrow{max-width:820px; margin:0 auto}
.card{
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm), var(--lift);
}
.card-p{padding:18px 20px}
.card h2,.sec-h{
  font-size:11px; font-weight:700; letter-spacing:.15em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 12px;
}
.hr{height:1px; background:var(--line); margin:18px 0}
.lead{color:var(--ink-2); font-size:14px; line-height:1.6; margin:0 0 16px; max-width:62ch}

/* stat row */
.sum{display:flex; flex-wrap:wrap; gap:10px; margin-bottom:16px}
.stat{
  flex:1 1 150px; background:var(--bg-1); border:1px solid var(--line-2);
  border-radius:var(--r-lg); padding:15px 16px 14px; position:relative; overflow:hidden;
  box-shadow:var(--shadow-sm), var(--lift);
}
/* a 2px rule down the left edge of a rounded tile reads as a rendering
   artefact; the accent moves to the top edge where the corner curves with it */
.stat::before{content:""; position:absolute; left:0; right:0; top:0; height:2px;
  background:linear-gradient(90deg, var(--gold-line), transparent 62%)}
.stat b{
  display:block; font-family:var(--mono); font-size:27px; font-weight:600;
  letter-spacing:-.02em; line-height:1.05; font-variant-numeric:tabular-nums;
}
.stat b.gold{color:var(--gold-2)}
.stat span{display:block; margin-top:4px; font-size:10px; letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3); font-weight:600}

/* filter rail */
.filters{
  display:flex; flex-wrap:wrap; gap:10px; align-items:center;
  padding:12px 13px; margin-bottom:14px;
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm), var(--lift);
}
.ev{display:inline-flex; align-items:center; gap:9px; font-size:12px; color:var(--ink-2); white-space:nowrap}
.ev input{width:118px}
.ev b{font-family:var(--mono); color:var(--gold-2); min-width:46px; text-align:right}
.tog{display:inline-flex; align-items:center; gap:7px; font-size:12px; color:var(--ink-2); cursor:pointer; white-space:nowrap}

/* ── TABLE ── */
/* FIXED LAYOUT, ON PURPOSE.
   Auto layout sizes a column to its content, so one long fixture plus one long
   prop name pushed the EV off the right edge - in three separate width bands,
   and max-width on a <td> does nothing to stop it. .tablewrap cannot be given
   overflow-x either: a scroll container there makes the sticky header stick to
   the BOX instead of the page, which is what shoved it down over row 1 the
   first time this was built. So the numbers get the pixels they need, the two
   prose columns split whatever is left, and text that will not fit ellipses. */
/* THE LIST IS A CARD. .tablewrap may never take overflow - a scroll box here
   makes the sticky header stick to the BOX and shove itself over row 1 (the
   Sep 5 bug) - so the rounding is drawn on the wrap and on the first and last
   header cells, and the table inside simply shares its background. */
.tablewrap{overflow:visible; background:var(--bg-1); border:1px solid var(--line-2);
  border-radius:var(--r-lg); box-shadow:var(--shadow-sm), var(--lift)}
table{width:100%; border-collapse:collapse; font-variant-numeric:tabular-nums; table-layout:fixed}
#v-board tbody tr.row > td{overflow:hidden}
#v-board thead th:nth-child(3){width:122px}   /* best book  */
#v-board thead th:nth-child(4){width:76px}    /* price      */
#v-board thead th:nth-child(5){width:68px}    /* fair       */
#v-board thead th:nth-child(6){width:88px}    /* EV         */
#v-board thead th:nth-child(7){width:64px}    /* hold       */
#v-board thead th:nth-child(8){width:58px}    /* books      */
#v-board thead th:nth-child(9){width:124px}   /* devigged   */
/* MEASURED, 2026-09-10: an 8-character code plus the copy glyph is 125px and
   this column was 112, so every code on the board was clipped on a desktop -
   with tr.row > td{overflow:hidden} above, silently. The tap cell was 4px
   short of "Tap to bet ↗" for the same reason. table-layout:fixed means these
   pixels come out of the two prose columns, which ellipsis by design. */
#v-board thead th:nth-child(10){width:130px}  /* code       */
#v-board thead th:nth-child(11){width:116px}  /* tap        */
/* HEADERS ARE LABELS, NOT FOOTNOTES. They were ink-3 at 10px - 3.3:1 against
   the surface, under the 4.5 bar - so the one row that tells you what every
   column IS was the hardest text on the page to read. ink-2 now, 10.5px, and
   the sorted column gets a 2px gold rule instead of an arrow you can miss. */
thead th{
  position:sticky; top:var(--bar); z-index:5;
  background:var(--bg-2); text-align:left; padding:12px 12px 10px;
  font-size:10.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-2); white-space:nowrap; cursor:pointer; user-select:none;
  border-bottom:1px solid var(--line-2); transition:color var(--t);
  box-shadow:inset 0 -2px 0 transparent;
}
thead th:hover{color:var(--ink)}
thead th:first-child{border-top-left-radius:var(--r-lg)}
thead th:last-child{border-top-right-radius:var(--r-lg)}
thead th.num,td.num{text-align:right}
td.sharpcol{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* The date lives in the Game column as secondary text, so the header has to
   say so - the column sorted by kickoff the whole time and nothing on screen
   admitted it. Dim, small, and it inherits the gold when the column sorts. */
thead th .hd{font-style:normal; font-weight:400; color:var(--ink-3); font-size:10px}
thead th.sorted .hd{color:inherit; opacity:.75}
thead th.sorted{color:var(--gold); box-shadow:inset 0 -2px 0 var(--gold)}
thead th.sorted::after{content:" ↓"; font-size:9px}
thead th.sorted.asc::after{content:" ↑"}
tbody tr.row{border-bottom:1px solid var(--line); cursor:pointer; transition:background var(--t)}
tbody tr.row:hover{background:var(--bg-2)}
tbody tr.row.open{background:var(--bg-2)}
tbody tr.row:last-child{border-bottom:0}
tbody tr.row.open td{border-bottom-color:transparent}
/* Denser. 9px of padding on every row was airy and the numbers inside were
   13px - a data product wants the opposite: 7px rows, 14px numerals. */
/* 7px rows were right for a terminal and wrong for a thumb. 11px puts a row
   at ~46px, over the 44px target size, without losing the dense feel. */
td{padding:11px 12px; vertical-align:middle}
td.dim{color:var(--ink-3)}
/* CAP THE PROSE, NOT THE NUMBERS. Hiding whole columns at breakpoints was not
   enough on its own: a long fixture and a long bet name together still pushed
   the EV off the right edge in three separate width bands, and .tablewrap
   cannot be given overflow-x - a scroll container there makes the sticky
   header stick to the BOX instead of the page, which is what shoved it down
   over row 1 the first time. So the two text columns are the ones that give. */
.game{display:flex; flex-direction:column; gap:2px; min-width:0}
/* text-overflow DOES NOTHING ON A FLEX CONTAINER. This span is display:flex so
   the league pill can sit beside the fixture, and the ellipsis it declared has
   never once rendered - the fixture was hard-cut mid-word instead ("San
   Francisco 49ers @ Los Angel"). The truncation has to live on the text child,
   and that child needs min-width:0 or it refuses to shrink at all. */
.game .g{font-size:13px; display:flex; align-items:center; gap:7px; min-width:0; overflow:hidden}
.g > .lg{flex:none}
.g > .gm{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.game .lg{
  font-size:9px; font-weight:700; letter-spacing:.1em; color:var(--ink-2);
  border:1px solid var(--line-2); border-radius:var(--r-sm); padding:1px 5px; flex:none;
}
.game .t{font-size:11px; color:var(--ink-3)}
td.bet .n{font-size:13px; font-weight:600; display:flex; align-items:center; gap:7px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
td.bet .m{white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
td.bet .m{font-size:11px; color:var(--ink-3); margin-top:1px}
.flag{
  font-size:9px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--warn); border:1px solid rgba(199,123,57,.4); border-radius:var(--r-sm); padding:1px 5px;
}
.book{display:inline-flex; align-items:center; gap:6px; font-size:12.5px; white-space:nowrap;
  max-width:100%; overflow:hidden; text-overflow:ellipsis}
/* A BOOK NEEDS A MARK, NOT A CHARACTER. The glyph was a 10px symbol in the
   book's colour and read as punctuation; boxed, it reads as a logo tile at a
   glance, which is how every betting app labels a price. */
.book .glyph{
  font-size:9px; width:19px; height:19px; flex:none;
  display:inline-grid; place-items:center;
  border:1px solid currentColor; border-radius:var(--r-sm);
  background:var(--bg-2);
}
/* THE BOOK NAME IS THE BET LINK. [stated] 2026-09-10: "Link to bet should be
   the name of the book for easy click straight to betslip." It has to LOOK
   tappable without turning the ladder into a wall of blue: the name takes the
   ink colour and an arrow, and only underlines on hover. The arrow is also
   the honest signal - a book we hold no link for renders as plain text with
   no arrow, so a member can tell before tapping which ones go somewhere. */
a.booklink{color:var(--ink); text-decoration:none; border-radius:var(--r-sm);
  margin:-3px -6px; padding:3px 6px; transition:background var(--t), color var(--t)}
a.booklink:hover,a.booklink:focus-visible{color:var(--gold-2); background:var(--bg-2);
  text-decoration:none}
a.booklink .ext{font-size:9px; color:var(--ink-3); margin-left:1px}
a.booklink:hover .ext{color:var(--gold)}
/* A finger is not a mouse: give it a real target on a phone. */
@media(max-width:560px){ a.booklink{padding:6px; margin:-6px} }
td.price{font-family:var(--mono); font-weight:600; font-size:15.5px; position:relative; letter-spacing:-.01em}
/* A PRICE THAT CAME OFF THE SOCKET. web_push re-prices a row from the
   websocket between screener cycles, so some prices on the board are seconds
   old and some are up to a cycle old. The dot says which - quietly, because it
   is reassurance, not information you act on. */
.livedot{
  display:inline-block; width:5px; height:5px; border-radius:50%;
  background:var(--pos); margin-right:6px; vertical-align:middle;
  box-shadow:0 0 0 2px rgba(79,180,119,.18);
}
@media (prefers-reduced-motion:no-preference){
  .livedot{animation:pulse 2.6s ease-in-out infinite}
  @keyframes pulse{0%,100%{opacity:.55}50%{opacity:1}}
}
td.fair{font-family:var(--mono); font-size:13px; color:var(--ink-2)}
.evcell{
  display:inline-block; min-width:64px; text-align:right;
  font-family:var(--mono); font-weight:600; font-size:13.5px;
  padding:5px 9px; border-radius:var(--r-sm);
}
.evcell.p3{color:#0C1710; background:var(--pos-2)}
.evcell.p2{color:var(--pos-2); background:var(--pos-wash)}
.evcell.p1{color:var(--pos)}
.evcell.z{color:var(--ink-3)}
.evcell.n{color:var(--neg)}
.code{
  display:inline-flex; align-items:center; gap:5px; font-family:var(--mono);
  white-space:nowrap;
  font-size:11.5px; color:var(--ink-2); background:var(--bg-2);
  border:1px solid var(--line-2); border-radius:var(--r-pill); padding:5px 10px;
}
.code button{background:none; border:0; color:var(--ink-3); cursor:pointer; padding:0 1px; font-size:11px}
.code button:hover{color:var(--gold)}
.code.copied{border-color:var(--pos); color:var(--pos-2)}
.tap{
  font-size:12px; font-weight:600; color:var(--gold-2); white-space:nowrap;
  border:1px solid var(--gold-line); border-radius:var(--r-pill); padding:8px 14px;
  display:inline-block; transition:background var(--t); background:var(--gold-wash);
}
.tap:hover{background:var(--gold-wash); text-decoration:none}
.tap .short{display:none}
.tap.off{color:var(--ink-3); border-color:var(--line); cursor:default}
.lock{font-size:12px; color:var(--ink-3); white-space:nowrap}
.mask{filter:blur(4.5px); opacity:.5; user-select:none; pointer-events:none}

/* price movement flashes */
@keyframes fl-up{0%{background:rgba(79,180,119,.34)}100%{background:transparent}}
@keyframes fl-dn{0%{background:rgba(208,96,90,.32)}100%{background:transparent}}
@keyframes fl-new{0%{background:rgba(201,162,75,.26)}100%{background:transparent}}
td.up,.ladder .up{animation:fl-up 2.4s ease-out}
td.dn,.ladder .dn{animation:fl-dn 2.4s ease-out}
tr.row.new>td{animation:fl-new 3s ease-out}
tr.row.new>td:first-child{box-shadow:inset 3px 0 0 var(--gold)}

/* expanded row */
tr.detail>td{padding:2px 12px 18px; background:var(--bg-2)}
.fairline{
  display:flex; flex-wrap:wrap; gap:20px; padding:12px 2px 14px;
  font-size:12px; color:var(--ink-3); border-bottom:1px solid var(--line);
  margin-bottom:12px;
}
.fairline b{color:var(--ink); font-family:var(--mono)}
.fairline b.gold{color:var(--gold-2)}
/* MEASURED, NOT EYEBALLED. minmax(150px) + 92 + 92 + minmax(120px) plus three
   14px gaps is a 496px FLOOR, and a phone gives this grid a 362px box - so the
   "against fair" column was cut off the right edge of every expanded row on an
   iPhone, and the page scrolled sideways to 510px because of it. The phone
   rules further down give the bar its own full-width line instead of a fourth
   column; nothing is hidden, it is re-stacked. */
.ladder{display:grid; grid-template-columns:minmax(150px,1fr) 92px 92px minmax(120px,1.4fr); gap:1px 14px; align-items:center; font-size:12.5px}
.ladder .h{font-size:9px; font-weight:700; letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3); padding-bottom:6px}
.ladder .price{font-family:var(--mono); font-weight:600; text-align:right}
.ladder > div{padding:4px 0}
.ladder .anchor{color:var(--ink-2)}
/* BOTH SIDES. book | this side | other side; BEST and AVERAGE rows first.
   The row's own side is marked, the other side is context. */
.bothcap{font-size:12px; color:var(--ink-2); padding:0 0 8px; max-width:660px; font-weight:600}
/* THE BOOK GRID, BUILT LIKE AN APP. A panel of its own inside the drawer,
   two price columns over a summary band, rows at a thumb's height, and the
   best price on each side carried in a green pill. */
.ladder2{
  display:grid; grid-template-columns:minmax(132px,1.1fr) minmax(94px,1fr) minmax(94px,1fr);
  gap:0 10px; align-items:center; font-size:12.5px; max-width:660px;
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-lg);
  padding:4px 14px 10px; box-shadow:var(--lift);
}
.ladder2 .h{font-size:9px; font-weight:700; letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3); padding:12px 0 8px; align-self:end; min-height:0}
.ladder2 .h.side{text-transform:none; letter-spacing:0; font-size:13px; font-weight:700; color:var(--ink-1); text-align:right; line-height:1.25}
.ladder2 .h.side i{display:block; font-style:normal; font-size:9px; letter-spacing:.12em; text-transform:uppercase; color:var(--gold); font-weight:700; margin-top:2px}
.ladder2 > div{padding:9px 0; border-bottom:1px solid var(--line-1); min-width:0; min-height:44px; display:flex; flex-direction:column; justify-content:center}
/* the summary band: BEST and AVERAGE sit on their own tinted strip */
.ladder2 .lab{font-size:10px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-2)}
/* the band must not be striped. A grid `gap` is not paintable, so each cell
   bleeds its own background 5px into the gutters either side. */
.ladder2 .lab,.ladder2 .pc.best,.ladder2 .pc.avg{
  background:var(--bg-2); box-shadow:-5px 0 0 var(--bg-2), 5px 0 0 var(--bg-2);
}
.ladder2 .lab{border-radius:var(--r-sm) 0 0 var(--r-sm)}
.ladder2 .pc.best:last-of-type,.ladder2 .pc.avg:last-of-type{border-radius:0 var(--r-sm) var(--r-sm) 0}
.ladder2 .pc{text-align:right; font-family:var(--mono); line-height:1.15; align-items:flex-end}
.ladder2 .pc b{font-weight:600; display:block; font-size:15px; letter-spacing:-.01em}
.ladder2 .pc small{display:block; font-size:10.5px; font-family:var(--ui); color:var(--ink-3); margin-top:3px}
.ladder2 .pc small.p1,.ladder2 .pc small.p2,.ladder2 .pc small.p3{color:var(--pos-2)}
.ladder2 .pc small.n{color:var(--neg)}
.ladder2 .pc.best b{
  color:#0C1710; background:var(--pos-2); border-radius:var(--r-sm);
  padding:3px 9px; display:inline-block; font-weight:700;
}
.ladder2 .pc.best small{color:var(--ink-3)}
.ladder2 .pc.avg{color:var(--ink-2)}
.ladder2 .pc.empty{color:var(--ink-3); font-size:15px}
.ladder2 .anchor{color:var(--ink-2)}
.ladder2 .onesided{font-size:11px; color:var(--ink-3); padding:10px 0 0; border-bottom:0; line-height:1.45; min-height:0}
.ladder2 .up{animation:fl-up 2.4s ease-out}
.ladder2 .dn{animation:fl-dn 2.4s ease-out}
.bar{position:relative; height:6px; background:var(--bg-3); border-radius:var(--r-sm); overflow:hidden}
.bar i{position:absolute; left:50%; top:0; bottom:0; width:1px; background:var(--line-3)}
.bar b{position:absolute; top:0; bottom:0; left:50%; border-radius:0 var(--r-sm) var(--r-sm) 0}
.bar b.p{background:var(--pos)}
.bar b.n{background:var(--neg); transform:translateX(-100%); transform-origin:right}
.empty{padding:56px 20px; text-align:center; color:var(--ink-3)}

/* ── PREVIEW / GATE ── */
.previewbar{
  border-radius:var(--r-lg);
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:12px 16px; margin-bottom:14px;
  background:var(--bg-1);
  border:1px solid var(--gold-line); border-left:3px solid var(--gold); border-radius:var(--r); font-size:13px; color:var(--ink-2);
}
.previewbar b{color:var(--ink)}
.gate{display:grid; place-items:center; min-height:calc(100vh - var(--bar)); padding:24px}
.gate .card{max-width:520px; padding:34px; text-align:center}
.gate h1{font-size:26px; margin-bottom:12px}
.gate h1 b{color:var(--gold)}
.gate p{color:var(--ink-2); line-height:1.65; margin:0 0 22px}
.gate .btn{margin:5px 4px}

footer{
  display:flex; flex-wrap:wrap; gap:22px; padding:22px 18px 40px;
  border-top:1px solid var(--line); color:var(--ink-3); font-size:11.5px;
}
footer b{color:var(--ink-2)}

/* ── responsive ── */
@media(max-width:1180px){ .hide-w{display:none} }
/* A TABLET IS NOT A WIDE DESKTOP EITHER. At 820px seven columns still ran off
   the right edge, and .tablewrap does not scroll - it clips. The code moves
   into the row you open and the bet link becomes its arrow. */
@media(max-width:1080px){
  .hide-m{display:none}
  .col-code{display:none}
  .only-code{display:inline}
  .tap .full{display:none}
  .tap .short{display:inline}
}
/* THE BAR IS WHAT OVERFLOWED AT 940-1000px, not the table: wordmark + four tabs
   + the freshness line + the account all on one row is about 1,030px of
   content. It drops the tabs to their own row well before that. */
@media(max-width:1200px){ .who{display:none} }
@media(max-width:1080px){
  .appbar{height:auto; flex-wrap:wrap; padding:9px 14px; gap:10px}
  /* the rail never scrolls: five tabs that FIT beat five that hide one */
  .tabs{order:3; width:100%; overflow-x:visible; border-radius:0}
  .bar-right{margin-left:auto}
  thead th{top:0}
}
@media(max-width:900px){
  .seg .full{display:none} .seg .short{display:inline}
}
.only-s,.only-code{display:none}
@media(max-width:900px){ .mark i{display:none} }

/* ── THE PHONE, MEASURED IN A REAL BROWSER AT 320-560px ──────────────────
   [stated] 2026-09-10, over an iPhone screenshot with the fourth tab and the
   "against fair" column both cut off the right edge: "if I get on my computer
   should fit to size if I open on my phone should fit to size missing a ton
   of info looking on my phone."

   Two elements were wider than the screen, and both were measured rather than
   guessed at (390px viewport, expanded row):

       nav.tabs   362px box, 454px of content   -> "Arb calculator" off-screen
       .ladder    362px box, 496px of content   -> "against fair" cut in half

   and the page's scrollWidth was 510 against a 390 viewport, so the whole
   document slid sideways underneath the header.

   THE TABS DID NOT LOOK BROKEN, WHICH IS WHY THIS LASTED. The 1080px rule
   gives them overflow-x:auto with the scrollbar hidden, so on a phone the
   fourth tab was not missing - it was one horizontal swipe away, with nothing
   on screen to say so. Four tabs that FIT beat four tabs that scroll. */
@media(max-width:620px){
  .tabs{overflow-x:visible; padding:3px 2px}
  .tabs a{flex:1 1 0; min-width:0; justify-content:center; gap:5px;
          padding:8px 4px; font-size:12.5px}
  .tabs .full{display:none}
  .tabs .short{display:inline}
}
/* Under ~430px even the icons have to go, or "Lines" starts truncating. */
@media(max-width:430px){
  .tabs svg{display:none}
  .tabs a{font-size:13px; padding:8px 2px}
}
/* THE BAR GETS ITS OWN LINE RATHER THAN A COLUMN. Four columns cannot fit a
   phone at any font size that is still readable - but nothing here is worth
   hiding, so the against-fair bar moves under each book and spans the full
   width, which makes it a BETTER gauge on a phone than the 120px stub it was
   on a desktop. Targeted by class, not :nth-child(4n): a hidden header cell
   shifts grid auto-placement by one and silently skews every row after it. */
@media(max-width:560px){
  .ladder{grid-template-columns:minmax(0,1fr) auto auto; gap:0 10px; font-size:13px}
  .ladder2{grid-template-columns:minmax(84px,1fr) minmax(76px,.92fr) minmax(76px,.92fr); gap:0 8px; font-size:12px; padding:2px 10px 8px}
  .ladder2 .h.side{font-size:12px}
  .ladder2 .pc b{font-size:14px}
  .ladder2 .pc.best b{padding:3px 7px}
  .ladder .barh{display:none}
  .ladder .barcell{grid-column:1 / -1; padding:1px 0 9px}
  .ladder .bar{height:5px}
  .ladder > div{padding:3px 0}
  .fairline{gap:8px 14px; font-size:12.5px}
}
@media(max-width:780px){
  .pad{padding:14px 12px 44px}
  .hide-s{display:none}
  .who{display:none}
  .filters{padding:10px}
  input[type=search]{min-width:0; flex:1 1 100%}
  .stat{padding:11px 13px}
  .stat b{font-size:21px}
  .stat span{font-size:9px}
  /* SEVEN COLUMNS DO NOT FIT A PHONE, AND overflow:visible does not scroll -
     it just cuts the Bet column in half. The book moves inline under the bet
     name and the code moves into the row you expand. */
  .only-s,.only-code{display:inline}
  /* A PHONE DOES NOT GET A TABLE. Eleven columns squeezed into 390px cut the
     EV off the right edge, and overflow:visible does not scroll - it just
     hides it. Each row becomes a two-line block instead: the bet and the
     fixture on the left, the price and the EV held to the right. Everything
     else lives in the row you tap open. */
  #v-board table,#v-board tbody,#v-board tr,#v-board td{display:block}
  #v-board thead{display:none}
  #v-board tbody tr.row{
    display:grid; grid-template-columns:minmax(0,1fr) auto auto;
    grid-template-areas:"bet price ev" "game price ev";
    gap:1px 10px; align-items:center; padding:10px 2px;
  }
  #v-board tbody tr.row > td{padding:0}
  #v-board .c-bet{grid-area:bet; min-width:0}
  #v-board .c-game{grid-area:game; min-width:0}
  #v-board .c-price{grid-area:price; text-align:right; font-size:14px}
  #v-board .c-ev{grid-area:ev; text-align:right}
  #v-board .c-fair,#v-board .c-x,#v-board .col-book,#v-board .col-code,#v-board .c-tap{display:none}
  #v-board .game .g{white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-size:12px; color:var(--ink-3)}
  #v-board table{table-layout:auto}
  #v-board tbody tr.row > td{overflow:visible}
  #v-board td.bet .n{font-size:13.5px; white-space:normal; overflow:visible}
  #v-board td.bet .m{font-size:11px}
  #v-board tr.detail > td{display:block; padding:2px 2px 14px}
  .evcell{min-width:0; padding:2px 7px; font-size:12.5px}
  .only-s .tap{padding:5px 10px}
}

/* ============================================================================
   THE INTERACTIVE CHART — used by the Lines tab and the standalone /chart page.
   Sizing note that cost an evening: a canvas carries an intrinsic aspect ratio
   from its width/height ATTRIBUTES. Sized with height:100% inside a box whose
   own height is not definite, the browser falls back to that ratio, so setting
   a 2496x2496 backing store made the box 1248px SQUARE. Positioned absolutely
   it is measured against its parent and the ratio never applies.
   ========================================================================= */
.ch{display:flex; flex-direction:column; min-height:0; gap:8px}
.ch-bar{display:flex; flex-wrap:wrap; gap:8px; align-items:center}
.ch-stage{
  position:relative; flex:1 1 auto; min-height:200px;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden;
}
.ch-stage canvas,.ch-mini canvas{
  position:absolute; inset:0; display:block; width:100%; height:100%;
  touch-action:none; cursor:crosshair;
}
.ch-mini{
  position:relative; flex:none; height:62px;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden;
}
.ch-mini canvas{cursor:ew-resize}
/* Pinnacle's limit - its own strip on the price chart's clock, never a
   second axis on the price itself */
.ch-lim{flex:none; display:flex; flex-direction:column; gap:4px}
.ch-lim[hidden]{display:none}
.ch-lim-h{display:flex; justify-content:space-between; gap:8px;
  font-family:var(--mono); font-size:11.5px; color:var(--ink-1)}
.ch-lim-h .sub{color:var(--ink-3)}
.ch-lim-c{position:relative; height:78px;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r); overflow:hidden}
.ch-lim-c canvas{position:absolute; inset:0; display:block; width:100%; height:100%}
.ch-lim-none{font-family:var(--mono); font-size:11.5px; color:var(--ink-3)}
.ch-read{
  position:absolute; top:10px; left:74px; min-width:212px;
  max-width:min(330px,calc(100% - 20px));
  background:rgba(8,9,12,.95); border:1px solid var(--line-2); border-radius:var(--r);
  padding:11px 12px; font-size:12px; pointer-events:none; box-shadow:var(--shadow);
  backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px);
}
.ch-read.pinned{pointer-events:auto}
.ch-read h3{margin:0 0 2px; font-family:var(--mono); font-size:12.5px; font-weight:600; color:var(--gold-2); letter-spacing:0}
.ch-read .when{color:var(--ink-3); font-size:11px; margin-bottom:9px}
.ch-read table{width:100%; border-collapse:collapse}
.ch-read td{padding:2px 0; font-size:12px; color:var(--ink-2); white-space:nowrap}
.ch-read td.v{text-align:right; font-family:var(--mono); color:var(--ink)}
.ch-read tr.fair td{color:var(--gold-2); font-weight:700; border-bottom:1px solid var(--line); padding-bottom:6px}
.ch-read tr.fair td.v{color:var(--gold-2)}
.ch-read tr.best td.v{color:var(--pos-2)}
.ch-read tr.sharp td:first-child::after{content:" ·"; color:var(--gold)}
.ch-read .close{position:absolute; top:4px; right:7px; background:none; border:0; color:var(--ink-3); cursor:pointer; font-size:16px; line-height:1; padding:2px 4px}
.ch-read .close:hover{color:var(--ink)}
.ch-read .hint{margin-top:8px; color:var(--ink-3); font-size:11px}
.ch-legend{display:flex; flex-wrap:wrap; gap:6px; flex:none; max-height:88px; overflow-y:auto}
/* open and now, one row per line drawn (chart.js _openNow) */
.ch-oc{flex:none; display:flex; flex-direction:column;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r); padding:4px 12px}
.ch-oc:empty{display:none}
.ch-oc-r{display:grid; grid-template-columns:minmax(0,1fr) 96px 112px; gap:10px; align-items:center;
  padding:5px 0; border-top:1px solid var(--line)}
.ch-oc-r:first-child{border-top:0}
.ch-oc-h{font-size:10.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-3); padding:4px 0 2px}
.ch-oc-h span:not(:first-child){text-align:right}
.ch-oc-r .nm{display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--ink-2); min-width:0}
.ch-oc-r .nm i{width:9px; height:9px; border-radius:50%; flex:none}
.ch-oc-r .v{text-align:right; font-family:var(--mono); font-size:13px; color:var(--ink); line-height:1.2}
.ch-oc-r .v small{display:block; font-family:var(--ui); font-size:10.5px; color:var(--ink-3)}
.ch-oc-r .v.now{font-weight:700}
@media (max-width:560px){ .ch-oc-r{grid-template-columns:minmax(0,1fr) 78px 96px; gap:8px} }
.chip{
  display:inline-flex; align-items:center; gap:7px; cursor:pointer; user-select:none;
  border:1px solid var(--line); background:var(--bg-1); border-radius:var(--r-pill);
  padding:4px 11px 4px 8px; font-size:12px; color:var(--ink-3);
  transition:border-color var(--t), background var(--t), color var(--t);
}
.chip{border-radius:var(--r-pill); padding:6px 11px}
.chip:hover{border-color:var(--line-3)}
.chip .sw{width:9px; height:9px; border-radius:50%; background:currentColor; flex:none}
.chip.on{color:var(--ink); background:var(--bg-3)}
.chip .pr{font-family:var(--mono); font-size:11px; color:var(--ink-3)}
.chip.on .pr{color:var(--ink-2)}
.ch-table{flex:none; max-height:36vh; overflow:auto; border:1px solid var(--line); border-radius:var(--r)}
.ch-table table{width:100%; border-collapse:collapse; font-size:12px; font-variant-numeric:tabular-nums}
.ch-table th{
  position:sticky; top:0; background:var(--bg-1); text-align:right; padding:8px 10px;
  font-size:9px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-3);
  font-weight:700; border-bottom:1px solid var(--line); white-space:nowrap;
}
.ch-table th:first-child,.ch-table td:first-child{text-align:left}
.ch-table td{padding:5px 10px; text-align:right; font-family:var(--mono); color:var(--ink-2); border-bottom:1px solid rgba(35,39,51,.5); white-space:nowrap}
.ch-table td.f{color:var(--gold-2)}

/* ── HOW OLD IS THIS PRICE ─────────────────────────────────────────
   [stated] 2026-09-10, over a board screenshot: "this line on dk has already
   moved to 500 so need to get it off if it's no longer a play."

   The board showed one clock - when the page was assembled - and that clock
   was always seconds old. Measured on the live stack in a single second:
   board.built 0.01 min, market-index blocks 0.1-1.0 min, and the sweeps the
   odds actually came from 26.9, 27.8 and 27.9 minutes. The websocket
   re-prices five books continuously and reaches none of the 1,226 player
   props on the board, so most rows were as old as that last number and
   nothing on the page said so.

   Amber, not red: a 20-minute-old price is usually still there. It is a
   prompt to look before betting, not a claim that the market is gone - and
   it is never a filter, because hiding the row would lose a market that is
   probably still on offer at a slightly different number. */
.staledot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--warn, #C9A24B);
  vertical-align: middle;
  opacity: .85;
}

/* The row keeps its full contrast: the price is real, it is just not
   new. Dimming the whole line would rank it below rows that are merely
   worse, which is a different statement from the one being made. */
tr.row.aged .price { color: var(--warn, #C9A24B); }

.fairline b.aged { color: var(--warn, #C9A24B); }

.stalecount { color: var(--warn, #C9A24B); }

@media (max-width: 620px) {
  /* the dot survives the phone layout; the tooltip does not, so the
     ladder's own "prices Nm old" line is where the number lives there */
  .staledot { width: 5px; height: 5px; margin-right: 4px; }
}

/* ── the in-play tab ───────────────────────────────────────── */
/* A count on the tab itself, so "is anything live" is answerable without
   opening it. Hidden entirely at zero rather than showing a 0. */
.seg button .segn{font-family:ui-monospace,monospace; font-style:normal;
  font-size:10px; font-weight:600; line-height:1; padding:2px 5px; margin-left:6px;
  border-radius:2px; background:var(--neg); color:#12080A;
  font-variant-numeric:tabular-nums}
.seg button .pip{display:inline-block; width:6px; height:6px; border-radius:50%;
  background:var(--neg); margin-right:6px; vertical-align:middle}
.livebar{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:0 0 12px; padding:9px 12px; background:var(--bg-1);
  border:1px solid var(--line); border-left:2px solid var(--neg,#DC6469);
  border-radius:var(--r-sm-t,2px); font-size:13px; color:var(--ink-2,#A8A49B)}
.livebar b{color:var(--ink-1,#F4F1EA); font-weight:600}
.livebar .pip{width:8px; height:8px; border-radius:50%; flex:none;
  background:var(--neg,#DC6469); box-shadow:0 0 0 3px rgba(220,100,105,.18)}
@media(prefers-reduced-motion:no-preference){
  .livebar .pip{animation:livepulse 2.4s ease-in-out infinite}
}
@keyframes livepulse{0%,100%{opacity:1}50%{opacity:.45}}



/* ── VIEW HEADER ─────────────────────────────────────────────────────────
   Every tab opens the same way: an eyebrow, the title, one line of lead, and
   the live meta on the right - one baseline, one row. */
.page-h{display:flex; align-items:flex-end; justify-content:space-between; gap:20px; flex-wrap:wrap;
  padding:6px 0 14px; margin-bottom:14px; border-bottom:1px solid var(--line-2)}
.page-h .eyebrow{display:block; font:700 10px/1 var(--ui); letter-spacing:.2em; text-transform:uppercase;
  color:var(--gold); margin-bottom:8px}
.page-h h1{font-size:22px; font-weight:700; letter-spacing:-.01em; line-height:1.15; margin:0}
.page-h .lead{margin:6px 0 0; max-width:70ch; color:var(--ink-2); font-size:13px; line-height:1.55}
.page-h .meta{font:500 11.5px/1.6 var(--mono); color:var(--ink-3); text-align:right; white-space:nowrap}
.page-h .meta b{color:var(--ink-2); font-weight:500}

/* ── PROP TRENDS ─────────────────────────────────────────────────────────
   One row = one live prop: who, the number, what the market charges, how
   often it has actually happened. The row IS the chart: the last ten games
   are drawn as a strip of ten cells inside the L10 column. */

/* the filter rail, grouped by job: find / scope / thresholds */
.rail{display:flex; gap:0; align-items:stretch; flex-wrap:wrap;
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-lg);
  margin-bottom:14px; box-shadow:var(--shadow-sm), var(--lift)}
.rail-g{display:flex; gap:10px; align-items:flex-end; padding:10px 14px 12px; min-width:0;
  border-right:1px solid var(--line)}
.rail-g:last-child{border-right:0}
.rail-g.grow{flex:1 1 260px}
.rail-g.tail{margin-left:auto}
.rail-g .eyebrow{position:absolute; top:6px; left:14px; font:700 9px/1 var(--ui); letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3)}
.rail-g{position:relative; padding-top:22px}
.rail .field{min-width:0; display:flex; flex-direction:column; gap:4px}
.rail .field > span{font:600 12px/1.2 var(--ui); letter-spacing:.05em; text-transform:uppercase; color:var(--ink-2)}
.rail .field > span b{color:var(--gold); font-weight:700; letter-spacing:0; text-transform:none; font-family:var(--mono)}
.rail input,.rail select{width:100%; min-width:0; box-sizing:border-box; height:32px; font-size:13px}
.rail input[type=search]{min-width:0; flex:0 0 auto; width:100%}
.rail-g.grow .field{flex:1 1 150px}
.rail input[type=range]{width:130px; min-width:0; padding:0; margin:0; height:32px; accent-color:var(--gold); background:none; border:0}
.rail .check{display:flex; align-items:center; gap:7px; font:12.5px/1.3 var(--ui); color:var(--ink-2); height:32px; white-space:nowrap}
.rail .check input{width:14px; height:14px; flex:0 0 auto}
.rail .btn{height:32px; padding:0 12px}
.t-meta{display:flex; gap:14px; align-items:baseline; flex-wrap:wrap;
  font:500 11.5px/1.5 var(--mono); color:var(--ink-3); padding:0 2px 10px}
.t-meta b{color:var(--ink-2); font-weight:500}
.t-meta i{font:12px/1.5 var(--ui); color:var(--ink-3); font-style:italic}
.t-upsell{background:var(--bg-1); border:1px solid var(--gold-line); border-left:3px solid var(--gold);
  border-radius:var(--r); padding:11px 14px; margin:0 0 12px; font:13px/1.55 var(--ui); color:var(--ink-2);
  display:flex; gap:12px; align-items:center; flex-wrap:wrap}
.t-upsell b{color:var(--ink)}

#t-table{width:100%; border-collapse:collapse; font:13px/1.35 var(--ui); table-layout:fixed}
#t-table th{background:var(--bg-2); font:700 10.5px/1.3 var(--ui); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-2); text-align:left; padding:10px 9px 8px; border-bottom:1px solid var(--line-2);
  cursor:pointer; white-space:nowrap; user-select:none; position:sticky; top:var(--bar); z-index:5;
  background:var(--bg); box-shadow:inset 0 -2px 0 transparent}
#t-table th:hover{color:var(--ink)}
#t-table th.sorted{color:var(--gold); box-shadow:inset 0 -2px 0 var(--gold)}
/* `#t-table th` (an id) outranks `.t-r` (a class): without this the numeric
   headers stayed left-aligned over right-aligned numbers, ~120px apart.
   [stated] "the coulms do not even line up with the printed text at the top". */
#t-table th.t-r{text-align:right}
#t-table td{padding:7px 9px; border-bottom:1px solid var(--line); vertical-align:middle}
#t-table tbody tr:not(.t-drawer){cursor:pointer; transition:background var(--t)}
#t-table tbody tr:not(.t-drawer):hover{background:var(--bg-1)}
#t-table tbody tr.open{background:var(--bg-2)}
#t-table tbody tr.open td{border-bottom-color:transparent}
/* column widths - the numbers get the pixels they need, the two prose columns
   split the rest and ellipse (same rule as the board) */
#t-table th:nth-child(3){width:96px}    /* price  */
#t-table th:nth-child(4){width:64px}    /* fair   */
#t-table th:nth-child(5){width:74px}    /* EV     */
#t-table th:nth-child(6){width:64px}    /* L5     */
#t-table th:nth-child(7){width:158px}   /* L10 + strip: 10x6 + 9x2 + 7 + '90%' + n = ~140, measured */
#t-table th:nth-child(8){width:64px}    /* all    */
#t-table th:nth-child(9){width:70px}    /* vs opp */
#t-table th:nth-child(10){width:52px}   /* def    */
#t-table th:nth-child(11){width:82px}   /* gap    */
.t-r{text-align:right; font-family:var(--mono); font-variant-numeric:tabular-nums; font-size:13.5px}
.t-name{min-width:0; overflow:hidden}
.t-name b{display:block; color:var(--ink); font-weight:600; font-size:13.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.t-sub{display:block; font:11px/1.3 var(--ui); color:var(--ink-3); font-style:normal; margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.t-sub .pos{color:var(--ink-2); font-weight:600}
.t-n{font:10px var(--mono); color:var(--ink-3); font-style:normal; margin-left:4px}
.t-hi{color:var(--pos)} .t-lo{color:var(--neg)} .t-dim{color:var(--ink-3)}
.t-lock{color:var(--gold-dim); letter-spacing:2px; font-family:var(--mono)}
tr.t-changed td{opacity:.6}

/* THE ROW IS THE CHART. Ten cells, most recent on the right, a hit in green,
   a miss in red, a push hollow. 2px gaps between marks and the % stays
   printed beside it - the colour is the accelerator, never the only signal. */
.hits{display:inline-flex; gap:2px; vertical-align:middle; margin-right:7px; height:10px}
.hits i{display:block; width:6px; height:10px; border-radius:1px; background:var(--line-2)}
.hits i.h{background:var(--pos)}
.hits i.m{background:var(--neg); opacity:.8}
.hits i.p{background:transparent; border:1px solid var(--line-3)}
.hits i.n{visibility:hidden}
.l10cell{display:inline-flex; align-items:center; justify-content:flex-end; gap:0; white-space:nowrap}

/* THE GAP IS THE POINT OF THE PAGE, so it gets the weight: 14.5px, bold, a
   tinted chip when it clears 20 points, dimmed when the history belongs to a
   different team. */
.gapchip{display:inline-block; min-width:60px; text-align:right; font:700 14.5px/1.2 var(--mono);
  padding:3px 7px; border-radius:var(--r-sm); font-variant-numeric:tabular-nums}
.gapchip.up{color:var(--pos)} .gapchip.dn{color:var(--neg)}
.gapchip.big.up{background:var(--pos-wash)} .gapchip.big.dn{background:var(--neg-wash)}
.gapchip.off{color:var(--ink-3); background:none}

/* the drawer: a surface-2 panel with a 2px gold rule on the left */
#t-table .t-drawer > td{padding:0; background:var(--bg-2)}
.t-detail{display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,1fr); gap:16px 22px;
  padding:14px 16px 16px 18px; border-left:2px solid var(--gold)}
.t-detail .lab{font:700 9.5px/1 var(--ui); letter-spacing:.16em; text-transform:uppercase; color:var(--ink-3); margin-bottom:8px}
.t-barwrap{position:relative; display:flex; align-items:flex-end; gap:3px; height:64px;
  padding-bottom:2px; border-bottom:1px solid var(--line-2)}
.t-bar{flex:1 1 0; min-width:8px; border-radius:2px 2px 0 0; background:var(--neg); opacity:.55}
.t-bar.hit{background:var(--pos); opacity:.95}
.t-line{position:absolute; left:0; right:0; height:0; border-top:1px dashed var(--gold)}
.t-line::after{content:attr(data-v); position:absolute; right:0; top:-14px; font:600 10px var(--mono); color:var(--gold)}
.t-bars .t-sub{margin-top:6px; white-space:normal}
.t-splits{display:grid; grid-template-columns:repeat(auto-fit,minmax(96px,1fr)); gap:8px; align-content:start}
.t-splits div{background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-sm); padding:8px 10px}
.t-splits i{display:block; font:700 9.5px/1.3 var(--ui); letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-3); font-style:normal; margin-bottom:3px}
.t-splits b{font:600 17px/1.1 var(--mono); color:var(--ink)}
.t-splits u{display:block; font:10px var(--mono); color:var(--ink-3); text-decoration:none; margin-top:3px}
.t-warn{grid-column:1/-1; margin:0; font:12.5px/1.55 var(--ui); color:var(--ink-2);
  background:var(--neg-wash); border:1px solid var(--neg); border-radius:var(--r-sm); padding:9px 12px}
.t-warn b{color:var(--ink)}
.t-actions{grid-column:1/-1; display:flex; gap:10px; align-items:center}
.t-actions .btn{padding:7px 14px; font-size:12.5px}
.t-empty{padding:28px 0; color:var(--ink-3); font:14px var(--ui); text-align:center}

/* ELEVEN COLUMNS CANNOT SHARE 320px. The sweep found the HEADERS clipped
   ("Player" is 58px in a 29px column) at every phone width. The board already
   answers this by moving columns into the row you open rather than squeezing
   them, so this does the same: the phone keeps the four that decide something
   and the market rides along under the player's name. */
.t-onlynarrow{display:none}
@media (max-width:1100px){
  #t-table th:nth-child(6),#t-table td:nth-child(6),   /* L5  */
  #t-table th:nth-child(8),#t-table td:nth-child(8)    /* all */
  {display:none}
}
@media (max-width:900px){
  #t-table th:nth-child(4),#t-table td:nth-child(4),   /* fair    */
  #t-table th:nth-child(9),#t-table td:nth-child(9),   /* vs opp  */
  #t-table th:nth-child(10),#t-table td:nth-child(10)  /* def     */
  {display:none}
  .t-detail{grid-template-columns:minmax(0,1fr)}
  .rail-g{border-right:0; border-bottom:1px solid var(--line); flex:1 1 100%}
  .rail-g:last-child{border-bottom:0}
  .rail input[type=search]{width:100%}
}
@media (max-width:680px){
  #t-table th:nth-child(2),#t-table td:nth-child(2),   /* market  */
  #t-table th:nth-child(3),#t-table td:nth-child(3)    /* price   */
  {display:none}
  #t-table th:nth-child(7){width:122px}
  .l10cell .t-n{display:none}
  #t-table th:nth-child(11){width:70px}
  .t-onlynarrow{display:block}
  #t-table th,#t-table td{padding:8px 6px}
  .hits i{width:5px}
  .hits{gap:1px}
  .rail-g{flex-wrap:wrap; gap:8px 10px}
  .rail input[type=range]{width:110px}
  .page-h .meta{text-align:left}
}
/* THE DRAWER WAS RESIZING THE COLUMNS IT SAT UNDER: a colspan wider than the
   visible column count made a table-layout:fixed table allocate the missing
   slots and squeeze every visible column - but only once a row was OPENED.
   The colspan is set from the DOM (syncSpan in trends.js) so it follows the
   breakpoints above instead of restating them. */

/* ── the fifth tab, and one thing it exposed ─────────────────────────────
   A FIFTH TAB MOVED THE BAR'S BREAKPOINT. Four tabs + wordmark + freshness +
   account measured clean at 1180px; five did not. The wrap has to happen
   earlier. */
@media(max-width:1280px){
  .appbar{height:auto; flex-wrap:wrap; padding:8px 14px 0; gap:8px 14px; align-items:center}
  .tabs{order:3; width:100%; margin:0 -14px; padding:0 8px; border-top:1px solid var(--line)}
  .tabs a{padding:10px 12px}
  .tabs a::after{bottom:0}
  .bar-right{margin-left:auto}
  thead th,#t-table th{top:0}
}
/* PRE-EXISTING, FOUND WHILE MEASURING THIS: `.fresh` is white-space:nowrap
   and its full sentence is 336px, so on a 320px phone the page scrolled
   sideways - with four tabs too, on the board, before Trends existed. */
.fresh{min-width:0}
@media(max-width:1500px){ .fresh .stalecount{display:none} }
@media(max-width:820px){
  .fresh{overflow:hidden; text-overflow:ellipsis; display:block}
}
@media(max-width:620px){
  .tabs{padding:0 2px}
  .tabs a{flex:1 1 0; min-width:0; justify-content:center; gap:5px; padding:10px 4px; font-size:12px}
}

/* ── THE PHONE GETS THE TABLE FIRST ──────────────────────────────────────
   Four filter groups stacked took the entire first screen before a single
   row appeared. The rail folds behind one button on a phone and the lead
   paragraph goes; the eyebrow and the title say enough. */
.rail-toggle{display:none}
@media (max-width:680px){
  .page-h .lead{display:none}
  .page-h{padding-bottom:10px; margin-bottom:10px}
  .page-h .meta{font-size:11px}
  .rail-toggle{display:flex; align-items:center; justify-content:space-between; width:100%;
    margin:0 0 10px; padding:9px 12px; background:var(--bg-1); border:1px solid var(--line-2);
    border-radius:var(--r); color:var(--ink); font:600 12.5px var(--ui); cursor:pointer}
  .rail-toggle b{font:500 11px var(--mono); color:var(--gold)}
  .rail{display:none}
  .rail.open{display:flex}
  /* the name gets the room: wrap instead of ellipse, and the numerics give */
  .t-name b{white-space:normal; overflow:visible; text-overflow:clip; line-height:1.2}
  #t-table th:nth-child(5){width:62px}
  #t-table th:nth-child(7){width:108px}
  #t-table th:nth-child(11){width:64px}
  .gapchip{min-width:0; font-size:13.5px; padding:2px 5px}
  .t-r{font-size:12.5px}
}

/* At 320-360 the name column had 50px left and a first name is 66px - it
   cannot wrap inside one word. The strip is the L10 on a narrow phone: the
   percentage beside it goes, and the name gets the pixels back. Measured. */
@media (max-width:360px){
  .l10cell > span:last-child{display:none}
  .hits i{width:4px} .hits{gap:1px; margin-right:0}
  #t-table th:nth-child(5){width:56px}
  #t-table th:nth-child(7){width:64px}
  #t-table th:nth-child(11){width:60px}
  #t-table th,#t-table td{padding:8px 5px}
}

/* a book with no bet link opens its sportsbook (2026-10-13) */
.booklink.home .site{font-size:10px; color:var(--ink-3); margin-left:4px; font-weight:600; letter-spacing:.02em}
.tap.home{opacity:.85}
