/* ============================================================
   B&O FOOTBALL — design tokens
   Single light theme on a charcoal page ground: dark ground,
   light cards, so the pick rows read as raised panels.
   ============================================================ */
:root{
  --navy:#0B2265;
  --navy-deep:#071845;
  --red:#E31837;
  --red-dim:#c1122d;

  /* charcoal page ground so the light pick cards pop off it */
  --bg:#1B2030;
  --bg-grad:linear-gradient(180deg,#232941 0%,#171B28 100%);
  /* text sitting directly on the charcoal rather than on a card */
  --on-bg:#F2F5FB;
  --on-bg-2:#A7B2C6;
  --on-bg-3:#7E8AA1;
  --on-bg-line:rgba(255,255,255,.14);
  /* the tab bar sits on the charcoal, not on a card */
  --nav-bg:#151A28;
  --nav-line:rgba(255,255,255,.10);
  --surface:#FFFFFF;
  --surface-2:#F7F8FB;
  --surface-3:#EEF1F7;
  --line:#DDE2EC;
  --line-strong:#C6CEDC;

  --text:#0E1524;
  --text-2:#495468;
  --text-3:#7C8699;

  --accent:var(--navy);
  --accent-text:#FFFFFF;
  --pick:#0B2265;
  --pick-hover:#16358C;
  --pick-text:#FFFFFF;
  /* Key picks are GOLD, not red.
     Red now means exactly one thing — your pick is losing or lost — and a
     color cannot mean both "worth double" and "you lost".
     #d4af37 reads as metal where amber read as orange. --key-ink is the only
     text color legible on it. */
  --key:#d4af37;
  --key-ink:#5c4033;
  /* Gold as TEXT, on a light background. #d4af37 is metal: against the row
     greys it measures 1.98:1, which is not a colour, it is a rumour. This is
     the same hue taken down until it reads (5.7:1 on --surface-2). */
  --key-text:#7a5f08;
  --key-hi:#ffdf73;        /* the highlight that sweeps across on assignment */

  --good:#0E7C4A;
  --good-bg:#E4F5EC;
  --bad:#B4232F;
  --bad-bg:#FCE9EB;
  --warn:#8A5A00;
  --warn-bg:#FDF3DC;
  --live:#C4451C;

  --shadow:0 1px 2px rgba(0,0,0,.20),0 8px 24px -12px rgba(0,0,0,.45);
  --shadow-lg:0 2px 4px rgba(0,0,0,.28),0 24px 48px -20px rgba(0,0,0,.55);
  --radius:14px;
  --radius-sm:10px;

  --facemask:#C9D0DC;
  --helmet-stroke:rgba(0,0,0,.20);
}

*{box-sizing:border-box;margin:0;padding:0}
body{
  font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  background:var(--bg);
  background-image:var(--bg-grad);
  color:var(--text);
  -webkit-font-smoothing:antialiased;
  line-height:1.5;
  /* A backstop for the same thing: nothing on this site is meant to be read
     by scrolling the PAGE sideways. `clip` rather than `hidden` because hidden
     makes the element a scroll container, which breaks `position:sticky` on
     the header and on the poolwide name column. */
  overflow-x:clip;
}
h1,h2,h3,.cond{font-family:'Barlow Condensed','Inter',sans-serif;letter-spacing:.01em}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
a{color:var(--accent);text-decoration:none}
table{border-collapse:collapse;width:100%}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:6px}

/* ---------- utility ---------- */
.wrap{max-width:1180px;margin:0 auto;padding:0 16px}
.hide{display:none !important}
/* Set while a dialog is open. Without it the standings scroll behind the
   dialog on a phone, which is what "floats all over" looks like. */
body.modal-open{overflow:hidden}
.mono{font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
.tiny{font-size:11px}
.muted{color:var(--text-2)}
.muted3{color:var(--text-3)}
.center{text-align:center}
.right{text-align:right}
.row{display:flex;align-items:center;gap:10px}
.spread{display:flex;align-items:center;justify-content:space-between;gap:12px}
.wrapflex{flex-wrap:wrap}

/* ---------- login ---------- */
#boLogin{
  min-height:100svh;width:100%;
  background:radial-gradient(1200px 700px at 50% -10%,#123 0%,transparent 60%),
             linear-gradient(160deg,#071845 0%,#0B2265 45%,#050f2e 100%);
  display:flex;align-items:center;justify-content:center;padding:24px;
  overflow:auto;
}
.login-card{
  width:100%;max-width:420px;background:var(--surface);
  border-radius:20px;padding:28px 26px 24px;box-shadow:var(--shadow-lg);
  border:1px solid var(--line);
}
.login-logo{display:block;height:96px;margin:0 auto 6px}
.login-card h1{font-size:30px;text-align:center;line-height:1;text-transform:uppercase;font-weight:700}
.login-sub{text-align:center;color:var(--text-2);font-size:12.5px;margin:6px 0 20px;letter-spacing:.04em;text-transform:uppercase;font-weight:600}
.seg{display:flex;background:var(--surface-3);border-radius:11px;padding:4px;gap:4px;margin-bottom:18px}
.seg button{flex:1;padding:9px 8px;border-radius:8px;font-size:13px;font-weight:600;color:var(--text-2);transition:.15s}
.seg button[aria-selected="true"]{background:var(--surface);color:var(--text);box-shadow:var(--shadow)}
label.fld{display:block;margin-bottom:12px}
label.fld span{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text-3);margin-bottom:6px}
/* Every text-ish input, listed explicitly. type=email was missing, which left
   the one input on the sign-in page completely unstyled — default width,
   default border, and Chrome's pale-blue autofill showing through. */
input[type=text],input[type=email],input[type=password],input[type=number],
input[type=search],input[type=tel],input[type=url],select{
  width:100%;padding:11px 12px;border:1px solid var(--line-strong);border-radius:10px;
  background:var(--surface-2);color:var(--text);font-size:16px;font-family:inherit;
  -webkit-appearance:none;appearance:none;
  transition:border-color .15s,box-shadow .15s;
}
input::placeholder{color:var(--text-3)}
input:focus,select:focus{
  outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(11,34,101,.18);
}

/* Chrome paints autofilled fields pale blue and ignores `background`. A large
   inset shadow is the only reliable override; the absurd transition delay stops
   it repainting on blur. */
input:-webkit-autofill,
input:-webkit-autofill:hover{
  -webkit-text-fill-color:var(--text);
  box-shadow:0 0 0 1000px var(--surface-2) inset;
  caret-color:var(--text);
  transition:background-color 9999s ease-out 0s;
}
input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--text);
  box-shadow:0 0 0 1000px var(--surface-2) inset, 0 0 0 3px rgba(11,34,101,.18);
}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:12px 18px;border-radius:11px;font-weight:700;font-size:14px;
  background:var(--accent);color:var(--accent-text);transition:.15s;width:100%;
}
/* Brighten only the FILLED buttons.
   `filter:brightness(1.08)` is right for navy and actively wrong for anything
   pale: .btn.ghost sits on #EEF1F7, and 8% brighter clips it to white, so
   hovering a ghost button on a white card made it vanish. The same applied to
   .btn.ghost.danger, whose own hover colour was being washed out underneath.
   Pale buttons darken on hover instead — see below. */
.btn:not(.ghost):not(.gsi):hover{filter:brightness(1.08)}
.btn.red{background:var(--red)}
/* A hairline at rest as well as on hover: a ghost button with no border is
   only findable by its fill, and its fill is nearly the colour of the card. */
.btn.ghost{background:var(--surface-3);color:var(--text);border:1px solid var(--line)}
.btn.sm{width:auto;padding:8px 13px;font-size:12.5px;border-radius:9px}
.login-note{font-size:11.5px;color:var(--text-3);text-align:center;margin-top:14px;line-height:1.5}
.linklike{
  display:block;margin:9px auto 0;font-size:12px;font-weight:700;color:var(--accent);
  text-decoration:underline;text-underline-offset:2px;padding:4px 8px;border-radius:7px;
}
.linklike:disabled{color:var(--text-3);text-decoration:none;cursor:default}
.btn:disabled{opacity:.62;cursor:default;filter:none}

/* ---------- header ---------- */
header.top{
  position:sticky;top:0;z-index:40;
  background:linear-gradient(180deg,var(--navy) 0%,var(--navy-deep) 100%);
  color:#fff;box-shadow:0 2px 14px rgba(0,0,0,.28);
}
.top-in{display:flex;align-items:center;gap:14px;height:60px}
.brand{display:flex;align-items:center;gap:10px;min-width:0}
/* very thin white keyline, just enough to lift the shield off the navy header */
.brand img{height:38px;display:block;
  filter:drop-shadow(1px 0 0 #fff) drop-shadow(-1px 0 0 #fff)
         drop-shadow(0 1px 0 #fff) drop-shadow(0 -1px 0 #fff)}
.brand-txt{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:21px;line-height:1;text-transform:uppercase;letter-spacing:.02em;white-space:nowrap}
.brand-txt small{display:block;font-size:9.5px;letter-spacing:.16em;opacity:.65;font-family:'Inter',sans-serif;font-weight:600;margin-top:2px}
.top-right{margin-left:auto;display:flex;align-items:center;gap:8px}
.chip{
  display:flex;align-items:center;gap:7px;background:rgba(255,255,255,.11);
  padding:6px 11px 6px 7px;border-radius:99px;font-size:12.5px;font-weight:600;
}
.avatar{width:24px;height:24px;border-radius:50%;background:var(--red);display:grid;place-items:center;font-size:10.5px;font-weight:800}
.icon-btn{width:34px;height:34px;border-radius:9px;background:rgba(255,255,255,.11);display:grid;place-items:center;font-size:15px;transition:.15s}
.usermenu{position:relative}
.usermenu .chip{transition:.15s}
.usermenu .caret{font-size:10px;opacity:.7;margin-left:1px}
.usermenu .menu{
  position:absolute;right:0;top:calc(100% + 7px);min-width:172px;z-index:60;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:var(--shadow-lg);padding:5px;overflow:hidden;
}
.usermenu .menu button{
  display:block;width:100%;text-align:left;padding:9px 11px;border-radius:7px;
  font-size:13.5px;font-weight:600;color:var(--text);transition:.12s;
}

nav.tabs{background:var(--nav-bg);border-bottom:1px solid var(--nav-line);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 10px 24px -14px rgba(0,0,0,.75);
  position:sticky;top:60px;z-index:35}
.tabs-in{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none}
.tabs-in::-webkit-scrollbar{display:none}
.tabs button{
  padding:13px 14px 11px;font-size:13px;font-weight:600;color:var(--on-bg-2);
  border-bottom:3px solid transparent;white-space:nowrap;transition:.15s;
}
.tabs button[aria-current="page"]{color:#fff;border-bottom-color:var(--red);font-weight:700}
.tabs .mgr-tab{color:#FF6076}

/* 72px here was a sixth of a short window spent on nothing. Enough to show the
   page has ended, no more. */
main{padding:20px 0 28px}
.page-head{margin-bottom:16px}

/* ---------- week navigator ---------- */
.wk-nav{display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.wk-btn{
  width:34px;height:34px;border-radius:9px;background:var(--surface);border:1px solid var(--line);
  font-size:17px;font-weight:700;color:var(--text-2);display:grid;place-items:center;transition:.14s;
}
.wk-btn:disabled{opacity:.4;cursor:default}
.wk-nav select{width:auto;min-width:168px;padding:8px 11px;font-size:14px}
.wk-now{
  font-size:12px;font-weight:700;color:var(--on-bg-2);text-decoration:underline;
  text-underline-offset:2px;padding:6px 8px;border-radius:7px;
}
.wk-note{
  background:var(--warn-bg);color:var(--warn);border:1px solid rgba(138,90,0,.28);
  border-radius:var(--radius-sm);padding:10px 13px;margin-bottom:12px;font-size:12.5px;line-height:1.5;
}

/* ---------- quick picks ---------- */
.qp-bar{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:10px 13px;margin-bottom:12px;box-shadow:var(--shadow);
}
.qp-lab{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
.qp{
  padding:7px 11px;border-radius:9px;border:1px solid var(--line-strong);background:var(--surface-2);
  font-size:12.5px;font-weight:700;color:var(--text-2);transition:.14s;
}
.qp:disabled{opacity:.45;cursor:not-allowed}
.qp-note{font-size:11px;color:var(--text-3);margin-left:auto}
.qp-busy{
  display:flex;align-items:center;gap:8px;margin-left:auto;
  font-size:12px;font-weight:700;color:var(--accent);
}
.spin{
  width:14px;height:14px;flex-shrink:0;border-radius:50%;
  border:2px solid var(--line-strong);border-top-color:var(--accent);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation-duration:2s}}
@media (max-width:560px){
  .qp-note{margin-left:0;width:100%}
  .wk-nav select{flex:1;min-width:0}
}

/* ---------- what-if ---------- */
.wi-b{
  display:flex;align-items:center;justify-content:center;gap:7px;padding:8px 7px;border-radius:8px;
  border:1.5px solid var(--line-strong);background:var(--surface-2);color:var(--text-2);
  font-size:12.5px;font-weight:700;transition:.14s;
}
.wi-b.on{background:var(--accent);border-color:var(--accent);color:#fff}
.wi-b img{width:22px;height:22px;object-fit:contain;flex-shrink:0}
#boMain{padding-top:16px}
.page-head h2{font-size:30px;text-transform:uppercase;line-height:1;font-weight:700;color:var(--on-bg)}
.page-head p{color:var(--on-bg-2);font-size:13.5px;margin-top:5px}

/* ---------- cards ---------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.card-pad{padding:16px 18px}
.card-h{padding:13px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.card-h h3{font-size:17px;text-transform:uppercase;font-weight:700;letter-spacing:.02em}
.card-h .right-tools{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}

.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:12px;margin-bottom:18px}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:13px 15px;box-shadow:var(--shadow)}
.stat .lab{font-size:10.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-3)}
.stat .val{font-family:'Barlow Condensed',sans-serif;font-size:30px;font-weight:700;line-height:1.05;margin-top:3px}
.stat .sub{font-size:11.5px;color:var(--text-2);margin-top:2px}
.stat.accent{background:linear-gradient(160deg,var(--navy) 0%,var(--navy-deep) 100%);border-color:transparent;color:#fff}
.stat.accent .lab{color:rgba(255,255,255,.62)}
.stat.accent .sub{color:rgba(255,255,255,.78)}
.stat.skins{background:linear-gradient(160deg,var(--red) 0%,#8f0f22 100%);border-color:transparent;color:#fff}
.stat.skins .lab{color:rgba(255,255,255,.68)}
.stat.skins .sub{color:rgba(255,255,255,.82)}

/* ---------- pills / badges ---------- */
.pill{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:99px;font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase}
.pill.live{background:var(--bad-bg);color:var(--live)}
.pill.final{background:var(--surface-3);color:var(--text-2)}
.pill.open{background:var(--good-bg);color:var(--good)}
.pill.lock{background:var(--surface-3);color:var(--text-3)}
.pill.warnp{background:var(--warn-bg);color:var(--warn)}
.pill.keyp{background:var(--key);color:#fff}
.dot{width:6px;height:6px;border-radius:50%;background:currentColor}
.dot.pulse{animation:pulse 1.4s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}}

/* ---------- sticky pick progress ---------- */
.pickbar{
  position:sticky;top:104px;z-index:30;margin-bottom:14px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:12px 16px;
}
.pickbar-row{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.meter{flex:1;min-width:180px}
.meter-lab{display:flex;justify-content:space-between;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);margin-bottom:5px}
.meter-bar{height:7px;background:var(--surface-3);border-radius:99px;overflow:hidden}
.meter-fill{height:100%;border-radius:99px;transition:width .3s ease}
.meter-fill.blue{background:linear-gradient(90deg,var(--accent),#4a74d8)}
.meter-fill.red{background:linear-gradient(90deg,var(--red),#ff5f74)}
.save-state{font-size:12px;font-weight:600;color:var(--good);display:flex;align-items:center;gap:6px;white-space:nowrap}

/* ---------- game rows ---------- */
.slot-d{font-weight:600;color:var(--on-bg-3);letter-spacing:0}
.slot-h{
  display:flex;align-items:center;gap:9px;margin:20px 0 9px;
  font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--on-bg-2);
}
.slot-h::after{content:"";flex:1;height:1px;background:var(--on-bg-line)}
.game{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);margin-bottom:9px;overflow:hidden;
}
.game.locked{background:var(--surface-2)}

/* The rail marks SETTLED, not "has a verdict". A live game tints its footer
   only; the rail appears at the whistle. That is what makes provisional and
   final distinguishable without reading the word. */
.game.v-win{border-left:4px solid var(--good);border-radius:0 var(--radius) var(--radius) 0}
.game.v-loss{border-left:4px solid var(--bad);border-radius:0 var(--radius) var(--radius) 0}
/* ONE LAYOUT, EVERY WIDTH.
   Two team rows in column 1, the key column alongside in column 2 spanning
   both of them. This used to be two columns facing each other on a laptop and
   two stacked rows on a phone — two layouts, two content orders, and they
   drifted. The gaps are 1px of the container's own background, which is what
   draws the hairlines between the cells. */
.game-body{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  grid-template-rows:auto auto;
  gap:1px;
  background:var(--line);
}
/* No keys this week, or the game has locked and the scores have the strip. */
.game-body.nokey{grid-template-columns:minmax(0,1fr)}

.team-btn{
  display:flex;align-items:center;gap:11px;padding:13px 14px;text-align:left;
  border:2px solid transparent;transition:.14s;position:relative;min-width:0;
  min-height:62px;background:var(--surface);
}
.team-btn.away{grid-column:1;grid-row:1;border-radius:0}
.team-btn.home{grid-column:1;grid-row:2}
/* `:not(.sel)` is load-bearing, not tidiness. `.game.locked .team-btn` is three
   classes and `.team-btn.sel` is two, so without it the locked rule WINS and
   the chosen team loses its navy fill — while `.team-btn.sel .tname` (also
   three) keeps setting the text white. White on light grey: the pick you made
   is invisible on every game that has kicked off, which is most of them by
   Sunday afternoon. */
.game.locked .team-btn:not(.sel){background:var(--surface-2)}
.team-btn.sel{background:var(--pick);border-color:var(--pick);color:var(--pick-text)}
.team-btn.sel .tname{color:#fff}
.team-btn.dis{cursor:not-allowed;opacity:.92}

.helmet{width:52px;height:52px;flex-shrink:0;object-fit:contain;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}
.tinfo{flex:1;min-width:0}
/* City, NICKNAME (spread), record — one order, every screen size. */
.tcity{font-size:11px;color:var(--text-3)}
.tname{font-family:'Barlow Condensed',sans-serif;font-size:19px;font-weight:700;line-height:1.1;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trec{font-size:11px;font-weight:700;color:var(--text-3);font-variant-numeric:tabular-nums;margin-top:1px;min-height:1em}
.team-btn.sel .tcity{color:rgba(255,255,255,.62)}
.team-btn.sel .trec{color:rgba(255,255,255,.72)}

/* The spread hangs off the team's own name at the same size and face, so it
   reads as part of the name rather than as a second number competing for the
   right-hand edge. */
.tname-line{font-weight:600;color:var(--accent);white-space:nowrap}
.team-btn.sel .tname-line{color:rgba(255,255,255,.88)}

/* The key marker, once the KEY column has been handed to the scores. Gold,
   boxed, and a LETTER rather than a colour alone — a tint by itself is no use
   to a colour-deficient reader. */
.kflag{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:17px;height:16px;padding:0 4px;margin-left:6px;vertical-align:2px;
  border-radius:4px;border:1px solid rgba(0,0,0,.18);
  background:var(--key);color:var(--key-ink);
  font-family:Inter,-apple-system,sans-serif;
  font-size:10px;font-weight:800;line-height:1;letter-spacing:.02em;
}

.tscore{font-family:'Barlow Condensed',sans-serif;font-size:36px;font-weight:700;
  margin-left:auto;line-height:.95;font-variant-numeric:tabular-nums;
  min-width:44px;text-align:right;flex:none}

/* WHICH TEAM IS AT HOME. Centred on the hairline between the two rows, which
   is exactly where "at" belongs when the card is read top to bottom.
   pointer-events:none so it cannot eat a tap meant for the button. */
.at-mark{
  position:absolute;top:0;left:50%;
  transform:translate(-50%,-50%);z-index:2;pointer-events:none;
  padding:1px 9px;border-radius:999px;
  background:var(--surface);border:1px solid var(--line-strong);
  font-size:9.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  color:var(--text-3);line-height:1.5;
}
/* It straddles the picked row's edge, so it must not vanish into the navy. */
.team-btn.sel .at-mark{background:var(--surface);color:var(--text-3)}
.game.locked .at-mark{background:var(--surface-2)}

/* The key column: one cell, the full height of the matchup, because a key
   belongs to the GAME rather than to one of its two rows. */
.vs{
  grid-column:2;grid-row:1 / span 2;
  display:flex;align-items:stretch;
  min-width:0;background:var(--surface-2);
}
.game.locked .vs{background:var(--surface-3)}
.keybtn{
  display:flex;align-items:center;justify-content:center;
  width:100%;min-width:62px;padding:10px;
  border:none;border-radius:0;background:transparent;
  font-size:11px;font-weight:800;letter-spacing:.09em;color:var(--text-3);
  text-transform:uppercase;transition:.14s;
}
.keybtn.on{background:var(--key);color:var(--key-ink)}

/* ONE sweep of light when you assign a key pick, then it settles to flat gold.
   Deliberately not a loop: the only thing that moves perpetually on this page
   is the live-game dot, and if five key picks also shimmer forever then motion
   stops meaning "this is changing right now". A single sweep rewards the tap
   and then gets out of the way. */
@keyframes key-sweep{from{background-position:200% 0}to{background-position:-200% 0}}
.keybtn.on.sparkle{
  background-image:linear-gradient(90deg,var(--key) 0%,var(--key-hi) 50%,var(--key) 100%);
  background-size:200% 100%;
  animation:key-sweep 1.2s linear 1;
}
@media (prefers-reduced-motion:reduce){
  /* Some players have this on for real reasons; an animation that ignores it
     can make people genuinely unwell. */
  .keybtn.on.sparkle{animation:none;background-image:none}
}
.keybtn:disabled{opacity:.4;cursor:not-allowed}
/* Three slots: an empty spacer, YOUR verdict centerd, the GAME's clock right.
   Keeping the two states in separate slots is what stops a game-state word
   from reading as a statement about whether you have picked. */
.game-foot{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:8px;
  padding:7px 14px;border-top:1px solid var(--line);font-size:11.5px;
}
.verdict{text-align:center;font-weight:800;letter-spacing:.07em;white-space:nowrap}
.when{
  text-align:right;color:var(--text-3);font-size:11px;white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.game-foot .dot.live{
  display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--bad);margin-right:5px;vertical-align:1px;
}
.v-winning .game-foot{background:var(--good-bg)}
.v-winning .verdict{color:var(--good)}
.v-losing  .game-foot{background:var(--bad-bg)}
.v-losing  .verdict{color:var(--bad)}
.v-win     .game-foot{background:var(--good-bg)}
.v-win     .verdict{color:var(--good)}
.v-loss    .game-foot{background:var(--bad-bg)}
.v-loss    .verdict{color:var(--bad)}
.v-nopick  .game-foot{background:var(--warn-bg)}
.v-nopick  .verdict{color:var(--warn)}
.v-void    .game-foot{background:var(--surface-3)}
.v-void    .verdict{color:var(--text-2)}


/* ---------- tables ---------- */
/* `overflow-x:auto` cannot pair with `overflow-y:visible` — the used value
   becomes auto — so this box is ALSO the nearest scrolling ancestor vertically.
   A sticky th therefore sticks to the top of this box, which is as tall as its
   content and never scrolls, so the header just rides off with the page. That
   is why `position:sticky` below has never done anything.
   `.tbl-tall` bounds the height, which gives the header something to stick
   inside. `overflow:hidden` is not an option here — it would kill the scroll. */
/* `overscroll-behavior-x:contain` stops a sideways swipe that reaches the end
   of this table from CHAINING to the document underneath. Without it, scrolling
   the poolwide grid to its right-hand edge and carrying on drags the whole page
   sideways — header, tab bar and all — which looks like the app has come apart
   rather than like a table that has run out. */
.tbl-scroll{overflow-x:auto;overscroll-behavior-x:contain;border-radius:inherit}
.tbl-tall{max-height:calc(100vh - 250px);min-height:260px;overflow-y:auto}
/* THE SAME BOX, SIZED FOR A TABLE AT THE BOTTOM OF THE PAGE.
   `.tbl-tall` reserves 250px because the tables that use it sit near the top,
   under a page head and a week picker. Poolwide sits at the END of My Picks, so
   by the time you have scrolled to it all of that has gone by and the only
   things still above it are the sticky site header and the tab bar — about
   100px, not 250. Reserving 250 there left the grid using barely half a short
   window with a slab of empty page beneath it, which is what this fixes.
   `svh` rather than `vh`: on mobile `vh` is the tallest the viewport ever gets,
   so with the address bar showing it overshoots and reintroduces the gap. */
.tbl-fill{max-height:calc(100svh - 118px);min-height:260px;overflow-y:auto}
table.std{font-size:13.5px;min-width:560px}
/* ...except the plain one. Season standings is rank + name + points, and a
   560px floor forced a phone to scroll sideways to see the points — the one
   column anybody opened it for. The wide tables keep their floor via their own
   modifier classes (.pw, .hist, .lq, .lx). */
table.std.fit{min-width:0;width:100%}
table.std.fit .rk{width:2.6em;text-align:center;padding-left:8px;padding-right:4px}
table.std.fit .pts{width:4.2em;text-align:right}
table.std.fit td,table.std.fit th{padding-left:8px;padding-right:8px}
table.std.fit .entry-nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
table.std th{
  text-align:left;padding:9px 12px;font-size:10.5px;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--text-3);border-bottom:1px solid var(--line);
  background:var(--surface-2);position:sticky;top:0;white-space:nowrap;z-index:2;
}
/* The thead is a solid fill with square corners sitting inside a rounded card,
   so its top corners poke out past the curve. Rounding the end cells hides it,
   and the shorthand-free form keeps the bottom square against the first row. */
table.std thead tr:first-child th:first-child{border-top-left-radius:var(--radius)}
table.std thead tr:first-child th:last-child{border-top-right-radius:var(--radius)}
/* Sticky cells do not paint the collapsed border, so it comes back as a shadow.
   Without this the first row appears to slide under a header with no edge. */
table.std th{box-shadow:0 1px 0 var(--line)}
table.std td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
/* YOUR ROW, everywhere it appears.
   This used to be a red wash. Red already means "this pick lost" in the
   poolwide grid and "down on the week" elsewhere, so tinting your whole row
   with it reads as a verdict rather than as "this one is you" — and on
   Poolwide it tinted result cells that were carrying their own green or red.
   A navy rail down the left edge plus a YOU badge says the same thing in a
   colour that means nothing else, and still says it to someone who cannot
   separate the two pale tints at all. */
table.std tbody tr.me td{font-weight:700}
table.std tbody tr.me > td:first-child{box-shadow:inset 3px 0 0 var(--navy)}
table.std tbody tr.me .entry-nm{color:var(--navy)}
.you{
  display:inline-block;margin-left:6px;padding:1px 4px;border-radius:3px;
  background:var(--navy);color:#fff;font-size:8.5px;font-weight:800;
  letter-spacing:.06em;vertical-align:1px;
}
.rk{font-family:'Barlow Condensed',sans-serif;font-size:19px;font-weight:700;width:44px;color:var(--text-2)}
.rk.m1{color:#B8860B}.rk.m2{color:#8792A6}.rk.m3{color:#A9702F}
.pts{font-family:'Barlow Condensed',sans-serif;font-size:20px;font-weight:700;font-variant-numeric:tabular-nums}
.entry-nm{font-weight:600}
.delta{font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums}
.delta.up{color:var(--good)}.delta.dn{color:var(--bad)}.delta.fl{color:var(--text-3)}
.money-tag{font-size:11.5px;font-weight:800;color:var(--good);white-space:nowrap}

/* ---------- what-if ---------- */
.wi-grid{display:grid;grid-template-columns:minmax(300px,380px) 1fr;gap:16px;align-items:start}
@media (max-width:900px){.wi-grid{grid-template-columns:1fr}}
.wi-game{padding:11px 14px;border-bottom:1px solid var(--line)}
.wi-game:last-child{border-bottom:none}
.wi-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:7px}
.wi-name{font-size:12.5px;font-weight:600}
.wi-toggle{display:grid;grid-template-columns:1fr 1fr;gap:5px}
.wi-toggle button{
  padding:7px 6px;border-radius:8px;border:1.5px solid var(--line-strong);
  font-size:11.5px;font-weight:700;background:var(--surface-2);color:var(--text-2);transition:.14s;
  display:flex;align-items:center;justify-content:center;gap:5px;
}
.wi-toggle button.on{background:var(--accent);border-color:var(--accent);color:#fff}
.wi-toggle button .mini{width:26px;height:26px;flex-shrink:0;object-fit:contain;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
.scen-note{
  font-size:12px;padding:10px 14px;background:var(--warn-bg);color:var(--warn);
  font-weight:600;border-bottom:1px solid var(--line);
}

/* ---------- money ---------- */
.ledger{font-size:13px}
.ledger th{font-size:10.5px}
.pot-row{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px dashed var(--line);font-size:13.5px}
.pot-row:last-child{border-bottom:none}
.pot-row.total{font-weight:800;border-top:2px solid var(--line-strong);border-bottom:none;margin-top:4px;padding-top:10px;font-size:15px}
.pot-row .amt{font-variant-numeric:tabular-nums;font-weight:700}
.balance-ok{background:var(--good-bg);color:var(--good);padding:10px 14px;border-radius:var(--radius-sm);font-size:12.5px;font-weight:700;display:flex;gap:8px;align-items:center;margin-top:12px}

/* ---------- manager ---------- */
.mgr-banner{
  background:linear-gradient(135deg,#1c1030,#2a1240);color:#fff;border-radius:var(--radius);
  padding:14px 18px;margin-bottom:16px;display:flex;gap:13px;align-items:flex-start;
  border:1px solid rgba(255,255,255,.12);
}
.mgr-banner .ic{font-size:19px;line-height:1.2}
.mgr-out{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;line-height:1.6;
  white-space:pre-wrap;word-break:break-word;background:var(--surface-2);
  border:1px solid var(--line);border-radius:10px;padding:11px 12px;color:var(--text-2);
  max-height:340px;overflow:auto;
}
.mgr-banner b{display:block;font-size:14px;margin-bottom:3px}
.mgr-banner p{font-size:12.5px;color:rgba(255,255,255,.72);line-height:1.5}
.line-row{display:grid;grid-template-columns:1fr 130px 96px;gap:9px;align-items:center;padding:9px 0;border-bottom:1px solid var(--line)}
.line-row:last-child{border-bottom:none}
.line-row .mt{font-size:13px;font-weight:600}
.line-row select,.line-row input{padding:7px 9px;font-size:13px;border-radius:8px}
.paste{width:100%;min-height:120px;padding:12px;border:1px solid var(--line-strong);border-radius:10px;background:var(--surface-2);color:var(--text);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;resize:vertical}
.subgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:8px}
.subcard{padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2);font-size:12.5px}
.subcard .nm{font-weight:700;margin-bottom:3px}
.subcard.done{border-color:var(--good);background:var(--good-bg)}
.subcard.part{border-color:var(--warn);background:var(--warn-bg)}
.subcard.none{border-color:var(--bad);background:var(--bad-bg)}

/* ---------- rules ---------- */
.rules h3{font-size:19px;text-transform:uppercase;margin:22px 0 8px;font-weight:700}
.rules h3:first-child{margin-top:0}
.rules p{font-size:14px;color:var(--text-2);margin-bottom:10px;max-width:70ch}
.rules ul{margin:0 0 12px 20px}
.rules li{font-size:14px;color:var(--text-2);margin-bottom:5px}
.rules strong{color:var(--text)}
.pay-tier{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin:12px 0}
.tier{padding:12px 14px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2)}
.tier .t{font-size:10.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--text-3)}
.tier .v{font-family:'Barlow Condensed',sans-serif;font-size:25px;font-weight:700;margin-top:2px}


/* ---------- My Picks: whole week on one screen ---------- */
.mp-sum{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin-bottom:12px}
.mp-s{background:var(--surface-2);border:1px solid var(--line);border-radius:10px;padding:8px 10px}
.mp-s .l{font-size:9.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
.mp-s .v{font-family:'Barlow Condensed',sans-serif;font-size:22px;font-weight:700;line-height:1.1;white-space:nowrap}
.mp-s .of{font-size:13px;opacity:.55;font-weight:600}

/* Only rendered when a pick or a key pick is missing. A banner that is always
   there stops being read. */
.mp-gap{
  display:flex;flex-direction:column;gap:2px;
  background:var(--warn-bg);color:var(--warn);border:1px solid rgba(138,90,0,.28);
  border-radius:var(--radius-sm);padding:11px 14px;margin-bottom:12px;
}
.mp-gap b{font-size:13.5px}
.mp-gap span{font-size:12px;opacity:.9}
.mp-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.mp{
  display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:8px;min-width:0;
  background:var(--surface-2);border:1px solid var(--line);
}
.mp img{width:21px;height:21px;object-fit:contain;flex-shrink:0}
.mp .ab{font-family:'Barlow Condensed',sans-serif;font-weight:700;font-size:15px;line-height:1;white-space:nowrap}
.mp .ln{font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.mp-opp{font-size:10px;color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mp .st{margin-left:auto;font-size:11px;font-weight:800;flex-shrink:0}
/* Gold pill, always present on a key pick — including after the whistle, where
   a bare "0" cannot say whether you dropped one point or two. */
.mp-key{
  margin-left:auto;flex-shrink:0;
  font-size:10px;font-weight:800;letter-spacing:.06em;line-height:1.4;
  background:var(--key);color:var(--key-ink);padding:2px 7px;border-radius:6px;
}
.mp-key + .st{margin-left:6px}
.mp.win{background:var(--good-bg);border-color:rgba(14,124,74,.32);box-shadow:inset 3px 0 0 var(--good)}
.mp.win .st{color:var(--good)}
.mp.loss{background:var(--bad-bg);border-color:rgba(180,35,47,.32);box-shadow:inset 3px 0 0 var(--bad)}
.mp.loss .st{color:var(--bad)}
.mp.none{background:var(--warn-bg);border-color:rgba(138,90,0,.35)}
.mp.none .st{color:var(--warn)}
.mp.none .ab{color:var(--warn)}
@media (max-width:900px){.mp-grid{grid-template-columns:repeat(3,1fr)}}
@media (max-width:560px){
  .mp-grid{grid-template-columns:repeat(2,1fr);gap:5px}
  .mp{padding:5px 7px;gap:5px}
  .mp img{width:19px;height:19px}
  .mp-key{padding:1px 5px;font-size:9.5px;letter-spacing:.04em}
  .mp .ab{font-size:14px}
  .mp-opp{display:none}          /* drop the opponent to guarantee one screen */
  .mp-s .v{font-size:19px}
  .mp-s .of{font-size:11.5px}
}

/* ---------- my account ---------- */
.acct-note{
  border-radius:var(--radius-sm);padding:11px 14px;margin-bottom:12px;
  font-size:13px;font-weight:700;
}
.acct-note.ok{background:var(--good-bg);color:var(--good);border:1px solid rgba(14,124,74,.3)}
.acct-note.bad{background:var(--bad-bg);color:var(--bad);border:1px solid rgba(180,35,47,.3)}
.paid-badge{
  display:flex;flex-direction:column;gap:3px;border-radius:var(--radius-sm);
  padding:12px 14px;margin-bottom:14px;
}
.paid-badge b{font-size:14px}
.paid-badge span{font-size:12.5px;opacity:.9;line-height:1.5}
.paid-badge.ok{background:var(--good-bg);color:var(--good);border:1px solid rgba(14,124,74,.3)}
.paid-badge.no{background:var(--warn-bg);color:var(--warn);border:1px solid rgba(138,90,0,.3)}
.pay-box{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
/* Venmo's own blue, so the button is recognizable as theirs rather than ours */
.btn.venmo{background:#3D95CE;width:auto;padding:12px 20px;white-space:nowrap}
.pay-facts{display:flex;flex-direction:column;gap:4px;min-width:0}
.pay-facts div{display:flex;gap:8px;align-items:baseline;font-size:12.5px;flex-wrap:wrap}
.pay-facts span{color:var(--text-3)}
.pay-facts b{font-variant-numeric:tabular-nums}
@media (max-width:560px){
  .pay-box{flex-direction:column;align-items:stretch}
  .btn.venmo{width:100%}
}

/* ---------- payment method picker ---------- */
.m-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px;margin-bottom:14px}
.m-tile{
  display:flex;flex-direction:column;align-items:center;gap:5px;padding:13px 9px;
  border:1.5px solid var(--line-strong);border-radius:var(--radius-sm);
  background:var(--surface-2);transition:.14s;text-align:center;
}
.m-tile.on{border-color:var(--accent);background:#eef2fb;box-shadow:0 0 0 3px rgba(11,34,101,.14)}
.m-tile img{width:44px;height:44px;flex-shrink:0}
/* A face is cropped to a circle. A brand mark is not: the Venmo and Zelle
   glyphs are rounded squares, and a circular crop shears their corners. They
   keep their own silhouette and simply sit inside the box. */
.m-tile img.face{border-radius:50%;object-fit:cover}
.m-tile img.logo{border-radius:9px;object-fit:contain}
.m-name{font-size:12.5px;font-weight:700;color:var(--text);line-height:1.2}
.m-hint{font-size:10.5px;color:var(--text-3);line-height:1.3}
.m-chip{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.m-chip img{flex-shrink:0}
.m-chip img.face{border-radius:50%;object-fit:cover}
.m-chip img.logo{border-radius:4px;object-fit:contain}
.m-dot{width:8px;height:8px;border-radius:50%;background:var(--line-strong);flex-shrink:0}
/* ---------- history ---------- */
table.std.hist{min-width:420px}
table.std.hist.at{min-width:760px}
.hy{font-family:'Barlow Condensed',sans-serif;font-size:19px;font-weight:700;
  color:var(--text-2);white-space:nowrap;width:60px}
.hist-real{font-size:11.5px;color:var(--text-3)}
.hist-src{font-size:11.5px;margin-top:12px;text-align:center}
.hpod{padding:6px 12px!important}
.pod{display:flex;align-items:baseline;gap:8px;padding:3px 0;font-size:13px}
.pod-r{font-size:10.5px;font-weight:800;letter-spacing:.06em;color:var(--text-3);
  width:30px;flex-shrink:0}
.pod-n{font-weight:700}
.pod-p{margin-left:auto;font-variant-numeric:tabular-nums;color:var(--text-3);font-size:12px}
.pod.m1 .pod-r{color:#B8860B}.pod.m1 .pod-n{color:var(--navy)}
.pod.m2 .pod-r{color:#8792A6}
.pod.m3 .pod-r{color:#A9702F}
.stat .sub{font-size:11px;color:var(--text-3);margin-top:1px}
/* Used wherever the page has to explain a judgement rather than state a fact. */
.note-card{
  margin-top:12px;padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--warn-bg);border:1px solid var(--warn);
  font-size:12.5px;line-height:1.55;color:var(--text-2);max-width:80ch;
}
.note-card b{color:var(--text)}

.fh-bad{color:var(--bad)}

/* ---------- poolwide picks ---------- */
/* The 16-column matrix is gone — see the .pwl list further down. What survives
   is the three pieces the pick chips still use: the logo, the gold key marker,
   and the screen-reader text that says in words what the picture carries. */
.pw-logo{object-fit:contain;vertical-align:middle}
/* The key marker: gold, boxed, and a letter rather than a colour alone — a
   tint on its own is no use to the ~8% of men with a colour deficiency, and
   this pool is mostly men. */
.pw-k{
  position:absolute;right:-7px;bottom:-4px;
  display:inline-flex;align-items:center;justify-content:center;
  min-width:13px;height:13px;padding:0 2px;border-radius:3px;
  background:var(--key);color:var(--key-ink);
  font-size:9px;font-weight:800;line-height:1;border:1px solid rgba(0,0,0,.18);
}
/* Screen-reader-only: the cell's meaning in words, since the picture carries it. */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- history link queue ---------- */
table.std.lq{min-width:620px}
table.std.lq td{vertical-align:top;padding:11px 12px}
.lq-act{white-space:nowrap;display:flex;gap:6px;padding-top:12px!important}
.lq-warn{font-size:11.5px;color:var(--warn);font-weight:600;line-height:1.45;
  margin-top:5px;max-width:46ch}
.lq-bad{background:var(--warn-bg)}

/* The decision, said on the row you clicked rather than in a toast at the
   bottom of a long table. It holds for a moment, then the row leaves. */
.lq-done td{font-size:13px}
.lq-approved,.lq-approved:hover{background:var(--good-bg)}
.lq-approved b{color:var(--good)}
.lq-rejected,.lq-rejected:hover{background:var(--surface-3)}
.lq-rejected b{color:var(--text-2)}
.lq-done{animation:lqFade .25s ease-out}
@keyframes lqFade{from{opacity:.3}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.lq-done{animation:none}}

/* ---------- lines editor ---------- */
table.std.lx{min-width:640px}
table.std.lx td{vertical-align:top;padding:10px 12px}
.lx-when{font-size:11.5px;color:var(--text-3);white-space:nowrap;padding-top:16px!important}
.lx-teams{display:flex;align-items:center;gap:7px}
.lx-at{font-size:10.5px;color:var(--text-3);text-transform:uppercase;font-weight:700}
.lx-team{
  display:flex;align-items:center;gap:6px;padding:6px 10px 6px 7px;
  border:1.5px solid var(--line-strong);border-radius:999px;background:var(--surface-2);
  font-size:12.5px;font-weight:700;color:var(--text-2);white-space:nowrap;
}
/* The favorite is stated in words as well as colour — which team is favored is
   the whole meaning of the row, so it must not rest on a border tint alone. */
.lx-team.on{border-color:var(--navy);background:var(--navy);color:#fff}
.lx-team.on::after{content:'FAV';font-size:9px;letter-spacing:.08em;opacity:.75}
.lx-team:disabled{opacity:.5}
.lx-in input{
  width:78px;text-align:center;font-size:16px;font-weight:700;
  font-variant-numeric:tabular-nums;padding:8px 6px;
}
.lx-in input.bad{border-color:var(--bad);background:var(--bad-bg)}
.lx-now{font-size:12.5px;white-space:nowrap;padding-top:16px!important}
.lx-bad{font-size:11.5px;color:var(--bad);margin-top:6px}
/* Moving a line players may already have picked against deserves to be noticed. */
.lx-was{font-size:10.5px;color:var(--warn);font-weight:700;margin-top:2px}
.lx-locked{opacity:.6}

/* the whole-number ruling */
.lx-rule{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px}
.lx-rule-q{font-size:11.5px;color:var(--warn);font-weight:700}
.lx-chip{
  font-size:11.5px;font-weight:700;padding:4px 9px;border-radius:6px;
  border:1.5px solid var(--line-strong);background:var(--surface-2);color:var(--text-2);
  white-space:nowrap;
}
.lx-chip em{font-style:normal;font-weight:500;opacity:.72;margin-left:4px}
.lx-chip.on{border-color:var(--navy);background:#eef2fb;color:var(--navy)}

/* ---------- sortable headers ---------- */
table.std th.sortable{padding:0}
table.std th.sortable button{
  display:flex;align-items:center;gap:4px;width:100%;
  padding:9px 12px;font:inherit;color:inherit;letter-spacing:inherit;
  text-transform:inherit;background:none;border:0;text-align:left;
}
table.std th.sortable .arrow{font-size:9px;line-height:1;width:8px;flex-shrink:0}
table.std th[aria-sort]:not([aria-sort="none"]) button{color:var(--accent)}

/* ---------- roster ---------- */
table.std.rost{min-width:1040px}
/* Every cell is a single line now that the name, real name and email each have
   their own column, so middle-align reads straight across the row. */
table.std.rost td{vertical-align:middle}
.ctr{text-align:center}
.m-solo{vertical-align:middle}
.m-solo.face{border-radius:50%;object-fit:cover}
.m-solo.logo{border-radius:6px;object-fit:contain}
.m-word{font-size:11.5px;font-weight:700;color:var(--text-2)}
/* A payment handle is a single atomic string — you copy it or you type it, so
   breaking "@Joe-Ogarek" across two lines makes it harder to read and no easier
   to use. Nothing here wraps; the table scrolls sideways instead. That is the
   right trade on a manager-only screen where every row must stay one line tall,
   so the eye can track across eight columns. */
.pay-to{display:flex;gap:7px;align-items:center;white-space:nowrap}
.pay-h{font-size:12px;color:var(--text-2);white-space:nowrap}
table.std.rost td,table.std.rost th{white-space:nowrap}
/* the note is the one field that should take whatever width is left */
table.std.rost td:last-child,table.std.rost th:last-child{white-space:normal;min-width:220px}

/* email + copy */
.eml{display:flex;gap:6px;align-items:center;font-size:11.5px}
/* No truncation either, for the same reason: a half-shown address is no use to
   someone about to write to a winner, and the column can simply be as wide as
   the widest address. */
.eml-t{color:var(--text-3);white-space:nowrap}
.cpy{
  font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  padding:2px 7px;border-radius:5px;border:1px solid var(--line-strong);
  background:var(--surface-2);color:var(--text-2);flex-shrink:0;
}
.cpy.done{border-color:var(--good);color:var(--good);background:var(--good-bg)}

/* per-player note */
.note-in{
  width:100%;min-width:150px;padding:6px 9px;font-size:12.5px;
  border:1px solid var(--line);border-radius:6px;background:var(--surface-2);
}
.note-in:focus{border-color:var(--accent);background:var(--surface)}
.note-in.saved{border-color:var(--good);background:var(--good-bg)}

/* ---------- mark-paid dialog ---------- */
.pd-who{font-size:13.5px;margin-bottom:12px}
.m-grid.tight{grid-template-columns:repeat(auto-fit,minmax(88px,1fr));gap:6px;margin-bottom:12px}
.m-tile.sm{padding:9px 6px;gap:4px}
.m-tile.sm img{width:34px;height:34px}
.m-blank{
  width:34px;height:34px;border-radius:6px;background:var(--surface-3);
  display:flex;align-items:center;justify-content:center;
  font-weight:800;color:var(--text-3);font-size:15px;
}
.chk{display:flex;gap:9px;align-items:flex-start;font-size:12.5px;line-height:1.45;
  padding:10px 12px;border-radius:8px;background:var(--surface-2);border:1px solid var(--line)}
.chk input{margin-top:2px;flex-shrink:0;width:15px;height:15px}
.chk-warn{background:var(--warn-bg);border-color:var(--warn)}
.pd-note{font-size:12px;color:var(--text-3);line-height:1.5}

/* ---------- branded confirm ---------- */
/* THE DIALOG HAD NO HEIGHT LIMIT, WHICH ONLY SHOWED UP ON A PHONE.
   The group picker is the first dialog tall enough to exceed a small screen,
   and three separate faults surfaced together:

   1. `align-items:center` on a flex container CLIPS an over-tall child at the
      TOP, and the clipped part cannot be scrolled to — the classic flex
      centering overflow. `margin:auto` on the card centers it identically when
      it fits and pushes it to the top when it does not, which is scrollable.
   2. The card had no max-height, so a 61-row list made it taller than the
      screen with its buttons somewhere past the bottom.
   3. Nothing stopped the PAGE behind from scrolling, so dragging the list
      moved the standings underneath and the whole thing felt unmoored.

   `dvh` rather than `vh`: on iOS `vh` is the viewport with the address bar
   hidden, so a `vh` cap is taller than what you can actually see and puts the
   Save button under the browser chrome. */
#boModal{
  position:fixed;inset:0;z-index:90;display:flex;justify-content:center;
  padding:20px;background:rgba(7,24,69,.62);
  overflow-y:auto;overscroll-behavior:contain;
}
.modal-card{
  /* `min-width:0` is why the dialog was wider than the phone. A flex item's
     default `min-width:auto` refuses to shrink below its content, so one long
     row or a pair of buttons pushed the whole card past the screen edge and the
     page scrolled sideways — cutting off Save on one screen and half the New
     group button on another. `width:100%` is only a PREFERRED size; min-width
     overrides it upward. */
  width:100%;max-width:min(420px,100%);min-width:0;margin:auto;
  background:var(--surface);border-radius:18px;
  box-shadow:var(--shadow-lg);border:1px solid var(--line);
  /* Head and foot hold still; only the body scrolls. Buttons you cannot reach
     are the whole complaint. */
  display:flex;flex-direction:column;max-height:calc(100dvh - 40px);overflow:hidden;
}
.modal-head{
  flex-shrink:0;
  display:flex;align-items:center;gap:11px;padding:15px 20px;
  background:linear-gradient(180deg,var(--navy) 0%,var(--navy-deep) 100%);color:#fff;
}
/* the same thin white keyline the header shield uses, so it does not wash out */
.modal-head img{height:30px;display:block;
  filter:drop-shadow(1px 0 0 #fff) drop-shadow(-1px 0 0 #fff)
         drop-shadow(0 1px 0 #fff) drop-shadow(0 -1px 0 #fff)}
.modal-head h3{font-size:19px;text-transform:uppercase;font-weight:700;letter-spacing:.02em}
.modal-body{padding:18px 20px;font-size:14px;color:var(--text-2);line-height:1.55;
  overflow-y:auto;overscroll-behavior:contain;min-height:0;min-width:0}
.modal-body b{color:var(--text)}
.modal-foot{flex-shrink:0;display:flex;gap:9px;padding:14px 20px 18px;
  border-top:1px solid var(--line);background:var(--surface)}
.modal-foot .btn{min-width:0;white-space:nowrap}
.modal-foot .btn{width:auto;flex:1}

/* ---------- toast ---------- */
/* Hidden means hidden. The old rule offset it by 120% of its OWN height from
   bottom:22px, which left the top of the pill poking above the fold — a stray
   red bubble on every screen, tappable, covering content on a phone. */
#boToast{
  position:fixed;bottom:22px;left:50%;
  transform:translateX(-50%) translateY(calc(100% + 32px));
  opacity:0;visibility:hidden;pointer-events:none;
  background:var(--navy-deep);color:#fff;padding:11px 20px;border-radius:99px;
  font-size:13px;font-weight:600;box-shadow:var(--shadow-lg);z-index:80;
  transition:transform .3s cubic-bezier(.2,.9,.3,1),opacity .2s,visibility .3s;
  max-width:calc(100vw - 32px);text-align:center;
}
#boToast.show{
  transform:translateX(-50%) translateY(0);
  opacity:1;visibility:visible;
}

/* ---------- mobile ---------- */
/* ---------- tablet / narrow desktop: scale down, keep side-by-side ---------- */
@media (max-width:760px){
  .page-head h2{font-size:25px}
  .brand-txt{font-size:18px}
  .brand-txt small{display:none}
  .stat .val{font-size:25px}
  .wi-grid{grid-template-columns:1fr}
}

/* ---------- phone: the side-by-side card cannot fit, so stack it ----------
   At 390px the two-column card leaves ~45px for a team name once a score is
   present. Stacked full-width rows give ~200px instead. Pure CSS: the grid
   collapses to one column and `order` puts away, home, then the KEY strip. */
@media (max-width:560px){
  .page-head h2{font-size:23px}
  .page-head p{font-size:12.5px}
  .pickbar{top:104px;padding:11px 13px}
  .pickbar-row{gap:12px}
  .meter{min-width:130px}

  /* The layout itself is no longer a phone variant — it is THE layout. Only
     the sizes change here. */
  .team-btn{padding:12px 11px;gap:9px;min-height:58px}
  .helmet{width:48px;height:48px}
  .tname{font-size:17px}
  .tscore{font-size:32px;min-width:38px}
  .keybtn{min-width:54px;padding:10px 6px;font-size:10.5px}

  .slot-h{margin:18px 0 8px;font-size:11px}
  .game-foot{padding:8px 12px}
  .stat .val{font-size:24px}
  .card-h{padding:12px 14px}
  .card-pad{padding:14px}
  .wrap{padding:0 12px}
}

/* ---------- custom groups ---------- */
/* The View: control sits above the tabs, because the group you are watching is
   a property of the page rather than of the cut you happen to be on. */
.grp-bar{display:flex;align-items:center;gap:8px;margin-bottom:10px;flex-wrap:wrap}
.grp-lab{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--on-bg-2)}
.grp-bar .sel{width:auto;min-width:11em;padding:7px 10px;font-size:13px}

/* The second rank column. Deliberately quiet: when a group is on, the number
   that answers "am I beating Dave" is the big one, and the pool position is
   context rather than the headline. It is still THERE, because it is the number
   that decides the money. */
.rk-pool{font-family:'Barlow Condensed',sans-serif;font-size:14px;width:44px;
  text-align:center;color:var(--text-3);font-weight:600}
table.std.pw .rk-pool{font-size:11.5px}

/* The manage list */
.grp-item{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:9px 0;border-bottom:1px solid var(--line);flex-wrap:wrap}
.grp-item>div:first-child{min-width:0;overflow-wrap:anywhere;flex:1}
.grp-item:last-of-type{border-bottom:none}
.grp-acts{display:flex;gap:6px;flex-shrink:0}
.btn.ghost.danger{color:var(--bad)}

/* The member picker. Capped and scrollable: sixty-one rows would push the save
   button off a laptop screen, and a dialog you have to scroll to submit is one
   people abandon. */
.grp-form .inp{width:100%;max-width:100%}
.grp-count{margin:8px 0 6px}
.grp-list{max-height:min(42dvh,340px);overflow-y:auto;overscroll-behavior:contain;
  border:1px solid var(--line);border-radius:10px;background:var(--surface-2);
  -webkit-overflow-scrolling:touch}
.grp-row{display:flex;align-items:center;gap:9px;padding:9px 11px;font-size:13.5px;
  border-bottom:1px solid var(--line);cursor:pointer}
/* THE SEARCH APPEARED NOT TO WORK BECAUSE OF THIS ONE LINE.
   `el.hidden = true` hides via the UA stylesheet's `[hidden]{display:none}`,
   which ANY author `display` rule outranks — and the rule above sets
   `display:flex`. So every row stayed visible however the filter was typed,
   and the bug looked like broken JavaScript rather than losing CSS. */
.grp-row[hidden]{display:none}
/* A long name plus a screen name can be wider than a phone. `min-width:0` lets
   the flex child shrink below its content — without it the row pushes the card
   wide and the whole dialog scrolls sideways. */
.grp-row>span{min-width:0;overflow-wrap:anywhere}
.grp-row:last-child{border-bottom:none}
.grp-row input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}
/* You are always in your own group, so your checkbox is checked and disabled.
   Shown rather than hidden: a list of 61 that omitted you would make the
   "4 players" count look wrong. */
.grp-me{background:var(--surface-3)}
.grp-me input{cursor:not-allowed}

/* ---------- groups on a phone ---------- */
@media (max-width:560px){
  /* Edge to edge, with the dialog anchored to the bottom of the screen where a
     thumb actually reaches. The picker is the one dialog people use standing
     up, one-handed, with a list to scroll. */
  #boModal{padding:0}
  .modal-card{max-width:none;margin:auto 0 0;border-radius:18px 18px 0 0;
    max-height:92dvh;border-bottom:none}
  .modal-foot{padding-bottom:max(18px,env(safe-area-inset-bottom))}
  .modal-foot .btn{padding:13px 14px;font-size:15px}

  /* Taller rows and a bigger box: the list is the point of this dialog, and a
     44px target is the smallest a checkbox should be under a thumb. */
  .grp-list{max-height:52dvh}
  .grp-row{padding:12px 13px;font-size:14.5px;min-height:44px}
  .grp-row input{width:20px;height:20px}

  /* The View bar wraps rather than squeezing the select into nothing. */
  .grp-bar .sel{flex:1;min-width:0}
  .grp-item{flex-wrap:wrap;gap:6px}
}

/* ==========================================================================
   SIGN IN — the fast paths, and the "or" that separates them from the form
   ========================================================================== */

.login-fast{display:flex;flex-direction:column;gap:10px;margin-bottom:4px}

/* Both fast paths are the same pill, at the same size.
   Google asks that its button be "at least as prominent" as other third-party
   sign-in options, with similar visual weight. Making the pair identical
   satisfies that and happens to look better than two buttons of different
   shapes stacked on each other. */
.login-fast .btn{
  width:100%;display:flex;align-items:center;justify-content:center;
  gap:10px;border-radius:999px;padding:10px 12px;
  font-size:14px;line-height:20px;min-height:40px;
}

/* ---- Sign in with Google -------------------------------------------------
   Google's published spec for a custom light-theme button, to the value:
   fill #FFFFFF, 1px #747775 stroke inside, text #1F1F1F at 14/20 in Google
   Sans Medium, and the standard-colour G at a fixed size on white.
   Hover is Google's own elevation rather than a colour change, because the
   fill is required to stay white. */
.login-fast .gsi{
  background:#FFFFFF;
  color:#1F1F1F;
  border:1px solid #747775;
  font-family:"Google Sans","Roboto",Inter,-apple-system,sans-serif;
  font-weight:500;
}
.login-fast .gsi:active{background:#F2F2F2}
.login-fast .gsi img{display:block;flex-shrink:0}

/* ---- Sign in with a passkey ---------------------------------------------- */
.login-fast .pk{
  background:var(--surface);color:var(--text);
  border:1px solid var(--line-strong);font-weight:600;
}
.login-fast .pk:active{background:var(--surface-3)}
.login-fast .pk .ic{display:inline-flex;flex-shrink:0}

/* The person-and-key glyph, wherever it appears. currentColor throughout, so
   one drawing serves the login button and the dark security-card tile. */
.pk-glyph{width:19px;height:19px;display:block}
.sec-ic .pk-glyph{width:16px;height:16px}
.sec-ic img{display:block;width:16px;height:16px}

/* An icon that is ALREADY a tile — its own background, its own rounded corners
   — replaces the grey square rather than sitting inside it. Nesting one would
   give it a second, slightly larger frame in a different colour. */
.sec-ic.tile{background:none;padding:0;overflow:hidden}
.sec-ic.tile img{width:26px;height:26px;border-radius:8px}

/* A rule with a word sitting in the gap. The pseudo-elements carry the line so
   the word needs no background of its own — a background would have to match
   the card and would go wrong the moment the card's color did. */
.or{display:flex;align-items:center;gap:10px;margin:14px 0 12px}
.or::before,.or::after{content:"";flex:1;height:1px;background:var(--line)}
.or span{font-size:10.5px;font-weight:700;letter-spacing:.10em;
         text-transform:uppercase;color:var(--text-3)}

/* "optional" next to a field label, so nobody hunts for a password they have
   not set. Smaller and lighter than the label, on the same line. */
.fld > span small{font-weight:600;font-size:10px;letter-spacing:.06em;
                  text-transform:uppercase;color:var(--text-3);margin-left:6px}

/* ==========================================================================
   HOW YOU SIGN IN — the security card on My Account
   ========================================================================== */

.sec-rows{display:flex;flex-direction:column;border-top:1px solid var(--line)}

.sec-row{
  display:grid;
  grid-template-columns:26px minmax(0,1fr) auto;   /* minmax(0,1fr): see below */
  gap:12px;align-items:start;
  padding:14px 0;border-bottom:1px solid var(--line);
}
/* minmax(0,1fr) rather than 1fr, because a grid track's default minimum is its
   content's own minimum width — so one long unbroken string (a credential id,
   an email) would push the track wider than the card and give the page a
   horizontal scrollbar on a phone. */

.sec-ic{
  width:26px;height:26px;border-radius:8px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  background:var(--surface-3);color:var(--text-2);font-size:13px;line-height:1;
}

.sec-txt{min-width:0}
.sec-txt > b{display:block;font-size:14px;margin-bottom:3px}
.sec-txt > span{display:block;font-size:12.5px;line-height:1.5;color:var(--text-2);
                max-width:62ch;overflow-wrap:anywhere}

.sec-tag{
  display:inline-block;vertical-align:1px;margin-left:7px;
  padding:1px 7px;border-radius:99px;
  font-size:9.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  background:var(--surface-3);color:var(--text-3);
}
.sec-tag.on{background:var(--good-bg);color:var(--good)}

.sec-act{display:flex;flex-direction:column;gap:6px;align-items:stretch}
.sec-act .btn{white-space:nowrap}

.pk-list{list-style:none;margin:10px 0 2px;padding:0;
         display:flex;flex-direction:column;gap:2px}
.pk-list li{
  display:flex;gap:10px;align-items:center;justify-content:space-between;
  padding:8px 10px;border-radius:var(--radius-sm);background:var(--surface-2);
}
.pk-list li > div:first-child{min-width:0}
.pk-list b{display:block;font-size:12.5px;color:var(--text)}
.pk-list .tiny{display:block;font-size:10.5px}
.pk-act{display:flex;gap:4px;flex-shrink:0}
.pk-act .danger{color:var(--bad)}

.pw-note{font-size:12px;color:var(--text-3);margin-top:8px;min-height:17px}
.pw-note.ok{color:var(--good);font-weight:600}

/* The phone puts the action under the text rather than beside it. Three
   columns at 360px leaves the middle one about twelve characters wide, which
   turns every explanation into a vertical ribbon. */
@media (max-width:560px){
  .sec-row{grid-template-columns:26px minmax(0,1fr)}
  .sec-act{grid-column:2;flex-direction:row;flex-wrap:wrap;margin-top:8px}
  .sec-act .btn{flex:1 1 auto}
  .pk-list li{flex-wrap:wrap}
}

/* The legal links under the sign-in form. Quiet — they are there to be found
   when looked for, not to compete with the button above them. */
.login-legal{margin-top:14px;text-align:center;font-size:11px;color:var(--text-3)}
.login-legal a{color:var(--text-3);text-decoration:none}

/* "The rank beside this is computed from a stale cache." Small and quiet: it
   is a note for the manager, not an alarm for the player, whose own points are
   correct either way. */
.mp-s .stale{
  display:inline-flex;align-items:center;justify-content:center;
  width:13px;height:13px;margin-left:5px;border-radius:50%;
  background:var(--warn);color:#fff;font-size:9px;font-weight:800;
  cursor:help;vertical-align:1px;
}

/* The unattributed archive list. */
.ua-hint{font-size:11.5px;color:var(--good);margin-top:2px}
.ua-rec{white-space:nowrap;font-size:12.5px;color:var(--text-2)}
table.std.lq td{vertical-align:top}

/* The Payout To cell is a button now. It still has to read as the destination
   rather than as a control, so it only looks clickable under the cursor. */
.pay-go{background:none;border:1px solid transparent;border-radius:9px;
        padding:5px 8px;margin:-5px -8px;cursor:pointer;font:inherit;color:inherit;
        text-align:left;transition:.12s}
.pay-go:active{background:var(--surface-3)}
/* What they are still owed, when the pool owes them anything. */
.pay-owed{margin-left:7px;padding:1px 6px;border-radius:99px;
          background:var(--good-bg);color:var(--good);font-weight:800;font-size:10.5px}

.pay-dlg-to{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:15px}
.pay-dlg-note{font-size:11.5px;color:var(--text-3);line-height:1.5;margin-top:8px;
              background:var(--surface-2);border-radius:8px;padding:8px 10px}

/* ==========================================================================
   PAYOUTS — the live week, then the ledger

   BUILT FOR THE PHONE FIRST. Most of the pool opens this on a phone, and the
   first version was laid out for a laptop and folded badly: three 38px numbers
   in a flex row wrapped into a stack with the operators stranded, and the
   ledger's three-column grid pushed "Week 1" onto two lines with the amount
   adrift below it. Named grid areas fix the second properly — the week and the
   money read as one line on any width, and the names take the row underneath.
   ========================================================================== */
.po-banner{background:linear-gradient(160deg,var(--navy) 0%,var(--navy-deep) 100%);
  color:#fff;border-radius:var(--radius);padding:16px 18px;margin-top:12px;box-shadow:var(--shadow)}
.po-banner.done{opacity:.8}
.po-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap}
.po-tag{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;opacity:.75;font-weight:700}
.po-why{font-size:11.5px;opacity:.65}
.po-sum{display:flex;align-items:center;gap:16px;margin-top:12px}
.po-parts{display:flex;align-items:center;gap:16px}
.po-part{min-width:0}
.po-n{font-family:"Barlow Condensed",Inter,sans-serif;font-size:36px;font-weight:700;line-height:1}
.po-n.zero{opacity:.45}
.po-n.skins{color:var(--key-hi)}
.po-n.win{color:#6BD99A}
.po-l{font-size:10px;text-transform:uppercase;letter-spacing:.05em;opacity:.7;font-weight:600;margin-top:2px}
.po-op{font-size:20px;opacity:.45;font-weight:300}

.po-ledger{padding:0;overflow:hidden}
.po-lhead{padding:13px 16px;border-bottom:1px solid var(--line);font-weight:800;
  font-size:12px;text-transform:uppercase;letter-spacing:.05em;
  display:flex;justify-content:space-between;gap:10px}
.po-lhead span{color:var(--good)}

/* One row, three areas. On a phone the amount moves up beside the week rather
   than sitting in a column of its own, which is what was breaking. */
.po-row{display:grid;gap:2px 12px;padding:12px 16px;border-bottom:1px solid var(--line);
  grid-template-columns:76px minmax(0,1fr) auto;
  grid-template-areas:"wk who amt";align-items:center}
.po-row:last-child{border-bottom:0}
.po-row.latest{background:var(--surface-2)}
.po-wk{grid-area:wk;font-weight:800;font-size:12px;color:var(--navy)}
.po-who{grid-area:who;font-size:13.5px;min-width:0;overflow-wrap:anywhere;line-height:1.45}
.po-who em{display:block;font-style:normal;font-size:11.5px;color:var(--text-3);margin-top:2px}
.po-amt{grid-area:amt;font-size:18px;font-weight:800;white-space:nowrap;text-align:right}
.po-ov{background:var(--warn-bg);color:var(--warn);border-radius:4px;padding:1px 5px;
  font-size:9px;font-weight:800;text-transform:uppercase;margin-left:5px;vertical-align:1px}

@media (max-width:620px){
  /* The sum stacks: the two parts that make it up, then the total, which is
     the number anyone actually came to read. */
  .po-sum{display:block}
  .po-parts{gap:14px}
  .po-parts .po-n{font-size:23px}
  .po-eq{display:none}
  .po-total{margin-top:12px;padding-top:12px;border-top:1px solid rgba(255,255,255,.16)}
  .po-total .po-n{font-size:40px}

  .po-row{grid-template-columns:minmax(0,1fr) auto;
          grid-template-areas:"wk amt" "who who";align-items:baseline}
  .po-wk{font-size:11.5px}
  .po-who{margin-top:4px}
  .po-amt{font-size:20px}
}

/* The live week's label, in the same green as the total beneath it — the two
   are the same thought ("this is what is on the table now"), so they read as
   one rather than as a warning above a number. */
.po-banner .po-tag{color:#6BD99A;opacity:1}
/* The aside naming who the hosting fee goes to. */
.pot-row small{color:var(--text-3);font-weight:500}

/* "Dee Quang @deeq19" — the collector, then where the money actually goes. */
.pay-via{color:var(--text-3);font-weight:600;margin-left:5px}

/* --------------------------------------------- manager sign-in link ------ */
/* Two buttons in the roster's action cell. They wrap rather than squeeze,
   because on a phone the table already scrolls sideways and a squeezed button
   is how "Mark unpaid" becomes "Mark unpa…". */
.rost-acts { display: flex; gap: 6px; flex-wrap: wrap; }

/* The link itself. A credential is worth showing in full rather than
   truncating: the manager needs to be able to see what they are about to send,
   and an ellipsis in the middle of a token teaches nothing. */
.sl-box {
  margin: 10px 0 12px; padding: 10px 12px;
  background: var(--surface-3); border: 1px solid var(--line);
  border-radius: 10px;
}
.sl-url {
  display: block; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; line-height: 1.5; word-break: break-all; color: var(--text);
}
.sl-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }

/* ------------------------------------------------------- stats sub-tab --- */
.st-controls {
  display: grid; gap: 6px 10px; align-items: center; margin-top: 12px;
  grid-template-columns: auto 1fr auto 1fr;
}
.st-controls .inp { min-width: 0; }          /* stops a long name widening the grid */
@media (max-width: 560px) {
  /* Two rows of label+select on a phone: four columns would squeeze both
     selects to the point where a screen name is unreadable. */
  .st-controls { grid-template-columns: auto 1fr; }
}

/* --- weekly finish chart --- */
/* Wide seasons scroll sideways rather than compressing: eighteen bars squeezed
   into a phone's width makes every bar four pixels and the numbers collide. */
.rc-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rc { display: block; max-width: 100%; height: auto; }
.rc-bar { fill: var(--pick); }
.rc-bar.rc-pod { fill: var(--good); }
.rc-bar.rc-win { fill: var(--key); }
.rc-empty { fill: var(--surface-3); }
/* Not monospace. "58th" in a mono face is wider than the bar it sits on; the
   proportional face fits four characters in the same slot. */
.rc-val {
  text-anchor: middle; font-size: 11px; font-weight: 700;
  fill: var(--text-2);
}
.rc-wk { text-anchor: middle; font-size: 10px; fill: var(--text-3); }
.rc-dash { text-anchor: middle; font-size: 12px; fill: var(--text-3); }

/* --- team grid --- */
.tg-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.tg-card {
  display: flex; gap: 10px; align-items: center; min-width: 0;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2);
}
.tg-helm { flex: none; object-fit: contain; }
.tg-body { min-width: 0; }                   /* lets the name ellipsis instead of overflowing */
.tg-nm {
  font-size: 12.5px; font-weight: 600; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tg-rec {
  font-size: 16px; font-weight: 700; line-height: 1.2;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.tg-rec.good { color: var(--good); }
.tg-rec.bad  { color: var(--bad); }
.tg-split { display: flex; gap: 8px; font-size: 11px; color: var(--text-3); }
td.good { color: var(--good); }
td.bad  { color: var(--bad); }

/* --- rank chart axis labels --- */
/* A grid around the scroller, not inside it: labels placed in the SVG would
   scroll away from the data as soon as a long season overflowed. */
.rc-wrap {
  display: grid; gap: 2px 8px; align-items: center;
  grid-template-columns: auto minmax(0, 1fr);
}
.rc-y {
  writing-mode: vertical-rl; transform: rotate(180deg);
  justify-self: center; text-align: center;
  font-size: 11px; font-weight: 600; color: var(--text-3); letter-spacing: .02em;
}
.rc-y-sub { font-weight: 400; opacity: .8; }
.rc-x {
  grid-column: 2; text-align: center;
  font-size: 11px; font-weight: 600; color: var(--text-3); letter-spacing: .02em;
}

/* --- pick-type share --- */
.tt-share b { font-size: 14px; }
.tt-share span { display: block; }

/* --- team grid sort --- */
.tg-sort { margin: 0 0 10px; }
/* The sort row is a secondary control sitting inside a card, so it is quieter
   and tighter than the page-level segmented tabs it borrows its markup from. */
.seg.sm button { padding: 6px 8px; font-size: 12px; }
/* The chart's own measure toggle, above the plot. */
.rc-modes { margin: 0 0 10px; max-width: 320px; }

/* ----------------------------------------------------------- podium ------ */
/* Three blocks standing on a floor, winner centre and tallest. The shape is
   read before a single word is, so the heights do the work and the colours
   only confirm it. */
.pd-wrap { margin-top: 12px; }
.pd { display: grid; grid-template-columns: 1fr 1.14fr 1fr; gap: 8px; align-items: end; }
.pd-blk {
  border: 1px solid var(--line); border-bottom: none;
  border-radius: 12px 12px 0 0; padding: 14px 10px 16px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  min-width: 0; gap: 2px;
}
/* The fade runs top to bottom, colour at the head and white at the floor, so
   three blocks of different heights still share one horizon. */
.pd-blk.g { background: linear-gradient(180deg, #FBF3D8 0%, #fff 72%); border-color: #E7D08C; min-height: 216px; }
.pd-blk.s { background: linear-gradient(180deg, #EFF1F5 0%, #fff 72%); border-color: #D5DAE3; min-height: 178px; }
.pd-blk.b { background: linear-gradient(180deg, #F7EDE2 0%, #fff 72%); border-color: #E3CBAE; min-height: 160px; }

.pd-cup { width: 46px; height: 46px; flex: none; margin-bottom: 2px; }
.pd-badge {
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  font-size: 12px; font-weight: 800; color: #fff; flex: none; margin-bottom: 6px;
}
.pd-blk.s .pd-badge { background: linear-gradient(145deg, #A5AEBC, #8C97A8); }
.pd-blk.b .pd-badge { background: linear-gradient(145deg, #BE8A52, #A9743F); }

.pd-lab {
  font-size: 10.5px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: #C9A227;
}
.pd-nm { font-size: 19px; font-weight: 800; line-height: 1.15; overflow-wrap: anywhere; }
.pd-blk.s .pd-nm, .pd-blk.b .pd-nm { font-size: 15px; }
.pd-re { font-size: 12px; color: var(--text-2); line-height: 1.3; }
.pd-amp { font-size: 12px; color: var(--text-3); font-weight: 700; line-height: 1.1; }

.pd-pts { margin-top: auto; padding-top: 10px; }
.pd-pts .n { font-size: 24px; font-weight: 800; line-height: 1; color: #C9A227; }
.pd-blk.s .pd-pts .n { font-size: 19px; color: #8C97A8; }
.pd-blk.b .pd-pts .n { font-size: 19px; color: #A9743F; }
.pd-pts .l {
  font-size: 10px; color: var(--text-3); text-transform: uppercase;
  letter-spacing: .05em; margin-top: 2px;
}

/* Without a floor the blocks read as three loose cards of random heights. */
.pd-floor { height: 6px; background: var(--line-strong); border-radius: 0 0 4px 4px; }

.pd-empty { opacity: .42; }
.pd-empty .pd-nm { font-size: 12.5px; font-weight: 600; color: var(--text-3); font-style: italic; }
.pd-note { font-size: 12px; color: var(--text-3); margin-top: 10px; max-width: 66ch; }

@media (max-width: 560px) {
  .pd { gap: 5px; }
  .pd-blk { padding: 12px 6px 14px; }
  .pd-nm { font-size: 15px; }
  .pd-blk.s .pd-nm, .pd-blk.b .pd-nm { font-size: 12.5px; }
  .pd-re { font-size: 10.5px; }
  .pd-cup { width: 38px; height: 38px; }
  .pd-pts .n { font-size: 20px; }
  .pd-blk.s .pd-pts .n, .pd-blk.b .pd-pts .n { font-size: 16px; }
}
/* Divides a player's archive career from their pick record on the same page. */
.st-head {
  font-size: 13px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-3); margin: 18px 0 8px;
}

/* --- a player's season-by-season table --- */
/* The finish cell reads "6th of 60" as ONE fact, so it must not break across
   two lines — which is exactly what it did at the width the auto layout gave
   it, leaving "of" stranded above "60". */
.std.career td.rk .fin { white-space: nowrap; }
.std.career td.rk .of { font-weight: 400; font-size: 11.5px; color: var(--text-3); }
/* Fixed widths for the three narrow columns so "Entered as" absorbs the slack
   instead of Points sprawling across half the table. */
.std.career th:nth-child(1), .std.career td:nth-child(1) { width: 4.5em; }
.std.career th:nth-child(2), .std.career td:nth-child(2) { width: 7em; }
.std.career th:nth-child(3), .std.career td:nth-child(3) { width: 5.5em; }

/* ---------- poolwide picks: one row per player, expandable ---------- */
/* This was a 16-column matrix. On a phone that meant scrolling sideways to see
   anything, and never being able to read a name and a late-week game at the
   same time. The leaderboard is the primary thing here and the picks are the
   drill-down, so the list says so. */
.pwl{border-top:1px solid var(--line)}
.pwl-item{border-bottom:1px solid var(--line)}
.pwl-item.me{box-shadow:inset 3px 0 0 var(--navy)}
.pwl-item.me .pwl-nm{color:var(--navy)}

.pwl-row{
  display:grid;align-items:center;gap:10px;width:100%;text-align:left;
  grid-template-columns:2.2em minmax(0,1fr) auto auto 14px;
  padding:11px 14px;background:none;transition:.12s;
}
.pwl-rk{font-size:12.5px;color:var(--text-3);text-align:center;font-variant-numeric:tabular-nums}
.pwl-pool{font-size:11px;color:var(--text-3);text-align:center}
.pwl-nm{
  font-weight:700;font-size:13.5px;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.pwl-wl{font-size:11.5px;color:var(--text-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.pwl-k{color:var(--key-ink);background:var(--key);border-radius:3px;padding:0 3px;font-weight:800;font-size:10px}
.pwl-pts{
  font-family:'Barlow Condensed',sans-serif;font-size:21px;font-weight:700;
  line-height:1;min-width:1.4em;text-align:right;font-variant-numeric:tabular-nums;
}
.pwl-chev{color:var(--text-3);font-size:17px;line-height:1;transition:transform .15s}
.pwl-row[aria-expanded="true"] .pwl-chev{transform:rotate(90deg)}

.pwl-picks{background:var(--surface-2);border-top:1px solid var(--line);padding:10px 12px 12px}
/* Chips wrap to the width available, so a phone gets four across and a laptop
   gets the whole week on one line. No breakpoint, and nothing to keep in step. */
.pwc-grid{display:grid;gap:6px;grid-template-columns:repeat(auto-fill,minmax(72px,1fr))}
.pwc{
  position:relative;
  display:flex;flex-direction:column;align-items:center;gap:2px;
  padding:6px 4px 5px;border-radius:9px;border:1px solid var(--line);
  background:var(--surface);min-width:0;
}
/* Deliberately NOT a positioning context: the key marker hangs off the chip's
   own corner, not off the logo. With position:relative here it anchored to the
   helmet instead and floated in the middle of the box. */
.pwc-pick{display:inline-flex;line-height:0}
/* Top-right corner of the chip, tucked just inside the border. */
.pwc .pw-k{top:3px;right:3px;bottom:auto;left:auto}
.pwc-opp{font-size:9.5px;font-weight:700;color:var(--text-3);white-space:nowrap}
.pwc-dash{font-size:16px;color:var(--line-strong);line-height:24px}
/* Result is carried by colour AND by something else, for the fifth of the pool
   who cannot rely on the hue: a covered pick keeps a full-strength logo, a
   losing one is greyed and faded. */
.pwc.hit{background:var(--good-bg);border-color:var(--good)}
.pwc.miss{background:var(--bad-bg);border-color:var(--bad)}
.pwc.miss .pw-logo{opacity:.45;filter:grayscale(1)}
.pwc.open .pw-logo{opacity:.72}
.pwc.none{background:var(--surface-2);border-style:dashed}

@media (max-width:560px){
  .pwl-row{grid-template-columns:2em minmax(0,1fr) auto auto 12px;gap:8px;padding:10px 12px}
  .pwl-nm{font-size:13px}
  .pwl-pts{font-size:19px}
  .pwc-grid{grid-template-columns:repeat(auto-fill,minmax(66px,1fr));gap:5px}
}
/* The ceiling beside the score: "12 / 19". Quiet, because the number that
   matters is what they HAVE — the second one is only context for how much of
   the week is still in front of them. */
.pwl-max{font-family:Inter,-apple-system,sans-serif;font-size:11.5px;font-weight:600;
  color:var(--text-3);letter-spacing:-.01em}
/* The sheet / quick-view toggle. Narrow, because two options do not need the
   width of a page-level tab strip. */
.pv-seg{max-width:300px;margin-top:10px}
/* A button that has to read as a link: it sits inside a sentence. */
/* A button that has to read as a link inside a sentence. It sits in the page
   head, which is on the dark ground — navy on charcoal was very nearly
   invisible, which is what made it look broken rather than quiet. */
.linkish{background:none;border:0;padding:0;font:inherit;color:inherit;
  font-weight:700;text-decoration:underline;text-underline-offset:2px;cursor:pointer}
/* On a light card the same control takes the accent, where it reads properly. */
.card .linkish,.mp-sum .linkish{color:var(--accent)}

/* ---------- live game decoration ---------- */
/* All of this renders only while a game is being PLAYED. The pick sheet is used
   hardest before kickoff, when none of it exists, so the card people pick on is
   exactly as uncluttered as it was. */
/* The football takes the SPREAD's colour, so the two things the card picks out
   on a team's row — what you are laying and who has the ball — read as one
   voice rather than as two unrelated accents. */
.ball{display:inline-flex;align-items:center;flex:none;margin-left:8px;color:var(--accent)}
.team-btn.home .ball,.team-btn.away .ball{order:0}
.ball.rz{color:var(--bad)}                 /* inside the twenty */
.team-btn.sel .ball{color:rgba(255,255,255,.88)}
.team-btn.sel .ball.rz{color:#FFB4B4}
.poss{display:block}
/* The markings — two end stripes and one lace — are cut-outs, so they are
   painted in the row's own background. Hard-coding them white left a
   white-on-white ball the moment the row you picked turned navy.

   SCOPED TO `.ink`, not to `path`. The looser selector also stroked the ball's
   own body, which has no stroke-width of its own and so picked up the default
   1px — a faint outline around the leather that nobody asked for and which
   only showed at the sizes nobody looks at. */
.poss .shell{fill:currentColor}
.poss .ink{fill:none;stroke:var(--surface);stroke-width:1.4;stroke-linecap:round}
.game.locked .team-btn:not(.sel) .poss .ink{stroke:var(--surface-2)}
.team-btn.sel .poss .ink{stroke:var(--pick)}

/* Down and distance sits in the footer slot that was empty, so it costs no
   height at all. */
.foot-dd{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dd{font-size:11.5px;font-weight:700;color:var(--text-2);font-variant-numeric:tabular-nums}
.dd.rz{color:var(--bad)}

/* The last play is the one thing that adds height, so it is quiet and capped at
   two lines — long enough for the sentence, short enough that sixteen live
   cards do not become a wall of commentary. */
.lastplay{
  padding:7px 14px 9px;border-top:1px solid var(--line);
  font-size:11.5px;line-height:1.45;color:var(--text-3);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.lp-tag{
  font-size:9px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--text-3);opacity:.75;margin-right:7px;
}
@media (max-width:560px){
  .lastplay{padding:6px 12px 8px;font-size:11px}
  .dd{font-size:11px}
}

/* The three summary figures are buttons now — each opens the weekly standings
   they are summarising. They must still read as figures, so the affordance is
   a hover and a cursor rather than a border. */
/* Button resets ONLY — the tile keeps the surface and border it had, or the
   three figures stop reading as a row of cards. */
.mp-s{display:block;width:100%;text-align:left;font:inherit;color:inherit;
  cursor:pointer;transition:.12s}
/* The leader's name sits on the same line as their score, in the body font
   rather than the condensed numerals — it is a name, not a figure. */
.mp-s .ldr{font-family:Inter,-apple-system,sans-serif;font-size:12.5px;
  font-weight:700;color:var(--text-2)}
.mp-s .v{display:flex;align-items:baseline;gap:6px;min-width:0}
.mp-s .v > .ldr{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto}
/* A quiet line under the spreads header saying when they last moved, so the
   Copy email button has something to be about. */
.lx-pub{padding:9px 18px 0;font-size:12px;color:var(--text-3)}
.lx-pub b{color:var(--text-2)}
/* Something is owed to the league. Louder than "nothing has moved", because it
   is the one state that needs an action from you. */
.lx-pub.owed{color:var(--warn)}
.lx-pub.owed b{color:var(--warn)}

/* ---------- poolwide, as a grid ---------- */
.pw-mode{max-width:260px;margin:12px 0 0}
.gw-note{font-size:13px;color:var(--text);margin:0 0 8px;max-width:78ch}
.gw-note.muted{color:var(--text-3);font-size:12.5px}
.gw-note b{color:var(--navy)}

/* SHRINK TO FIT, NEVER STRETCH.
   `table.std` carries `min-width:560px`, which is right for a two-column table
   that would otherwise look lost. Here it was the bug behind "the tightening
   only worked on the wide view": with four game columns the table was being
   forced out to 560px and the spare width shared among the cells, so the
   still-playing grid was airy and the all-started one — which overflows 560 on
   its own — was correctly tight. */
table.std.gw{font-size:12.5px;min-width:0;width:auto}
table.std.gw th,table.std.gw td{white-space:nowrap}

/* ONE SCROLLBAR, NOT TWO.
   The box used to bound its own height and scroll its own rows, which meant
   reading a long week took two gestures — scroll inside the grid, then scroll
   the page to get past it. Now the whole grid is laid out and THE PAGE is the
   only thing that scrolls; the header and your pinned row stick to the
   viewport, below the site chrome.
   `top` is the site header (60) plus the tab bar (44); the pinned row sits one
   grid header below that again. A test derives all four numbers rather than
   trusting the constants. */
.gw-box{border-radius:inherit}
.gw-box:not(.gw-wide) table.std.gw thead th{top:104px}
.gw-box:not(.gw-wide) .gw-pin > td{top:150px}      /* 104 + the 46px header */

/* Once the columns genuinely overflow, sideways room has to come from
   somewhere. The box becomes a HORIZONTAL scroller and nothing more: no height
   cap, so its content height is its own height and there is still nothing to
   scroll inside it vertically. The page stays the only vertical scrollbar,
   which is the whole point.

   EVERY VERTICAL OFFSET MUST BE SCOPED AWAY FROM THIS MODE.
   `overflow-x:auto` forces `overflow-y` to compute to auto, which makes the box
   the scrollport for everything inside it. A `top` meant to clear the SITE
   chrome is then measured from the BOX instead — so an unscoped `top:104px`
   on the header did not pin it anywhere, it shoved it 104px down the table,
   where it sat on top of a player's row and hid them completely.

   `top:auto` rather than `position:static`, because the horizontal pin is
   still wanted and still works: the name column stays put while the games
   scroll sideways. Only the vertical half is switched off. */
.gw-box.gw-wide{overflow-x:auto;overscroll-behavior-x:contain}
.gw-box.gw-wide table.std.gw thead th{top:auto}
.gw-box.gw-wide .gw-pin > td{top:auto}

/* THE HEADER HEIGHT IS FIXED ON PURPOSE. The pinned "you" row sticks directly
   beneath the header, and `top` has to be a number — so the header cannot be
   allowed to be whatever three lines of text happen to measure. */
table.std.gw thead th{height:46px;padding:5px 8px;vertical-align:middle}

/* The one pinned column. Opaque, always: a translucent sticky cell lets the
   picks scroll visibly underneath the name, which once looked like a rendering
   glitch and was simply a colour with an alpha channel. */
/* THE CAP BELONGS ON THE NAME, NOT ON THE CELL.
   Capping the cell meant the number had to cover the rank AND eleven pixels of
   padding as well, so a stated 88px left the text about sixty — and names were
   cut far shorter than the figure suggested. `--gw-name` is the width of the
   NAME, which is what anyone setting it is actually thinking about. */
.gw-nm{
  position:sticky;left:0;z-index:2;background:var(--surface);
  font-weight:700;white-space:nowrap;
}
/* 113px is what DAWGPOUNDGIRL measures at 12.5px bold, measured in a browser
   rather than guessed — the guess was eleven pixels short and quietly cut the
   one name the width was chosen to fit. */
.gw-who{
  display:inline-block;vertical-align:bottom;max-width:var(--gw-name,116px);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
table.std.gw thead .gw-nm{background:var(--surface-2);z-index:4}
.gw-rk{display:inline-block;min-width:1.8em;color:var(--text-3);font-weight:600}
.gw-pts{font-variant-numeric:tabular-nums;font-weight:700}
.gw-max{color:var(--text-3);font-weight:600;font-size:11px}
.gw-wl{font-variant-numeric:tabular-nums;color:var(--text-3);font-size:11.5px}

/* Your row, pinned under the header as a reference while the rest scrolls. */
.gw-pin > td{
  position:sticky;z-index:3;top:46px;
  background:var(--surface-3);box-shadow:inset 0 -1px 0 var(--line-strong);
}
.gw-pin > td.gw-nm{z-index:5}               /* pinned both ways: outrank both */
tbody tr.me:not(.gw-pin) .gw-nm{color:var(--navy);box-shadow:inset 3px 0 0 var(--navy)}

/* A game column. `hot` is one with points at stake against the people above
   you — the number in the header is how many. */
.gw-g{text-align:center!important;min-width:58px}
.gw-mu{font-size:11px;font-weight:700;color:var(--text-2)}
.gw-at{color:var(--text-3);font-weight:400;margin:0 1px}
.gw-sc{font-size:10.5px;color:var(--text-3);font-variant-numeric:tabular-nums}
.gw-sw{font-size:9.5px;letter-spacing:.04em;color:var(--text-3)}
/* A column whose result you actually need. `odd` is the rare one where what
   you need is your own pick to LOSE, which deserves to look different from
   the ordinary case rather than quietly reading the same. */
.gw-g.hot{background:#FBF3D8}
.gw-g.hot .gw-sw{color:#8A6D1F;font-weight:800}
.gw-g.hot.odd{background:#F7E6E6}
.gw-g.hot.odd .gw-sw{color:var(--bad)}

.gw-need{margin:2px 0 8px;padding-left:18px;font-size:13px;line-height:1.6}
.gw-need li{margin:0}
.gw-odd{color:var(--bad);font-size:12px}

.gw-c{text-align:center;padding:5px 8px!important;position:relative}
.gw-ab{font-weight:600;font-variant-numeric:tabular-nums}
/* Agreement is the common case and the boring one, so it is what fades.
   Disagreement is what the column is being scanned for. */
.gw-c.same .gw-ab{opacity:.38;font-weight:500}
.gw-c.diff .gw-ab{font-weight:800}
.gw-c.diff::after{
  content:'';position:absolute;left:4px;right:4px;bottom:2px;height:2px;
  border-radius:2px;background:var(--navy);opacity:.55;
}
.gw-c.none .gw-ab{color:var(--line-strong)}
/* Result, carried by colour AND by weight, for the fifth of the pool who
   cannot rely on the hue. */
.gw-c.hit{background:var(--good-bg)}
.gw-c.miss{background:var(--bad-bg)}
.gw-c.miss .gw-ab{text-decoration:line-through;opacity:.6}
.gw-c .pw-k{position:static;margin-left:3px;vertical-align:1px}

/* A PHONE GETS A MUCH TIGHTER GRID.
   The shared table padding is 9px 12px, which is right for a two-column table
   and absurd for one with seven columns: three cells of chrome cost more width
   than a game column. Everything here is squeezed so four live games and the
   names fit a 390px screen without scrolling sideways at all.
   The header height and the pinned row's offset are overridden TOGETHER — they
   are two halves of one number, and a test pairs them at every breakpoint. */
@media (max-width:560px){
  table.std.gw{font-size:11px}
  table.std.gw th,table.std.gw td{padding:4px 5px!important}
  table.std.gw thead th{height:42px;padding:4px 5px!important}
  .gw-box:not(.gw-wide) .gw-pin > td{top:146px}    /* 104 + the 42px header */

  /* Sized so DAWGPOUNDGIRL — the longest name in the pool worth fitting —
     just lands, and nothing longer does. Measured against the name itself, so
     the rank and the padding are not quietly eating into it. */
  .gw-nm{padding-left:6px!important}
  /* 100px at 11px bold, measured. Anything longer truncates, which is the
     deal: one name fits exactly and the column costs nothing more. */
  .gw-who{max-width:var(--gw-name,102px)}
  .gw-rk{min-width:1.3em;margin-right:1px}
  .gw-pts{font-size:12px}
  .gw-max{font-size:9.5px}
  .gw-wl{font-size:10px}

  .gw-g{min-width:40px}
  .gw-mu{font-size:9.5px}
  .gw-at{margin:0}
  .gw-sc{font-size:9px}
  .gw-sw{font-size:8.5px;letter-spacing:0}
  .gw-c{padding:4px 3px!important}
  .gw-ab{font-size:11px}
  /* The key marker is a badge inside an already narrow cell. */
  .gw-c .pw-k{margin-left:2px;min-width:11px;height:11px;font-size:8px;padding:0 1px}

  .gw-note{font-size:12.5px}
  .gw-need{padding-left:16px;font-size:12.5px;line-height:1.5}
  .gw-odd{font-size:11.5px}
  .pw-mode{max-width:100%}
}

/* ---------- hover, only where hovering is a thing ---------- */
/* THE BUG THIS FIXES. A tap on a touch screen leaves the element in :hover
   until something else is tapped, so the KEY button sat in its hover colour
   instead of resolving to gold — it looked like the tap had half-worked.
   Every rule whose selector is purely :hover lives in here, so a phone never
   applies any of them. Rules that mix a hover selector with a plain one are
   left where they are, because moving those would take the plain styling with
   them. */
@media (hover:hover) and (pointer:fine){
  .btn.ghost:hover{background:var(--line);border-color:var(--line-strong)}
  .linklike:hover:not(:disabled){background:var(--surface-3)}
  .icon-btn:hover{background:rgba(255,255,255,.2)}
  .usermenu .chip:hover{background:rgba(255,255,255,.19)}
  .usermenu .menu button:hover{background:var(--surface-3)}
  .tabs button:hover{color:var(--on-bg)}
  .wk-btn:hover:not(:disabled){background:var(--surface-3);color:var(--text)}
  .wk-now:hover{color:var(--on-bg);background:rgba(255,255,255,.07)}
  .qp:hover:not(:disabled){border-color:var(--accent);color:var(--accent);background:var(--surface)}
  .wi-b:hover{border-color:var(--accent)}
  /* hover is scoped away from .sel — otherwise it out-specifies the selected rule
     and leaves white text on a light gray fill */
  .team-btn:not(.dis):not(.sel):hover{background:var(--surface-3)}
  .team-btn.sel:not(.dis):hover{background:var(--pick-hover);border-color:var(--pick-hover)}
  .keybtn:hover:not(:disabled){background:var(--surface-3);color:var(--key)}
  table.std tbody tr:hover{background:var(--surface-2)}
  .wi-toggle button:hover{border-color:var(--accent)}
  .m-tile:hover{border-color:var(--accent);background:var(--surface)}
  .lq-bad:hover{background:var(--warn-bg)}
  .lx-team:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
  .lx-chip:hover{border-color:var(--accent)}
  table.std th.sortable button:hover{color:var(--accent)}
  .cpy:hover{border-color:var(--accent);color:var(--accent)}
  .btn.ghost.danger:hover{background:var(--bad-bg);border-color:var(--bad)}
  .grp-row:hover{background:var(--surface-3)}
  .login-fast .gsi:hover{
    background:#FFFFFF;
    box-shadow:0 1px 2px rgba(60,64,67,.30),0 1px 3px 1px rgba(60,64,67,.15);
  }
  .login-fast .pk:hover{background:var(--surface-2);border-color:var(--text-3)}
  .login-legal a:hover{color:var(--text-2);text-decoration:underline}
  .pay-go:hover{background:var(--surface-2);border-color:var(--line-strong)}
  .pwl-row:hover{background:var(--surface-2)}
  .linkish:hover{color:var(--on-bg)}
  .card .linkish:hover{color:var(--pick-hover)}
  .mp-s:hover{background:var(--surface-3);border-color:var(--line-strong)}
}
/* The roster's one page-level action. */
.rost-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}

/* ---------- how the pool split: the grid's last row ---------- */
/* It sits under the columns it counts, so no column position has to be held in
   the head to read it. */
.gw-split > td{border-top:2px solid var(--line-strong);background:var(--surface-2);
  padding-top:6px;padding-bottom:6px;vertical-align:top}
/* The label is pinned with the names, so it has to FIT the name column — it
   cannot be allowed to set its own width and push the sticky block out over
   the picks. It wraps instead. */
.gw-split > td.gw-nm{font-size:10px;font-weight:700;letter-spacing:.04em;
  line-height:1.2;text-transform:uppercase;color:var(--text-3);
  white-space:normal}
.gw-sp{text-align:center}
/* Team over count, with the bar between them: the cell has to look nothing
   like the score sitting in the column header above it. */
.sp-side{line-height:1.3}

/* NO OPACITY HERE, AND THAT IS THE POINT.
   The quiet side used to be the same colours at .55 opacity, which measured
   1.85:1 against the row — and dragged the gold key count down to 1.44:1,
   washing out the one number in the cell nobody can infer from anything else.
   Opacity fades EVERYTHING, including the part that was already the weakest.
   So the two sides differ by weight and by one step of ink, both of which stay
   legible, and the BAR carries the actual emphasis. */
.sp-ab{display:block;font-size:11px;font-weight:800;color:var(--text)}
.sp-n{display:block;font-size:10.5px;font-weight:700;color:var(--text-2);
  font-variant-numeric:tabular-nums}
.sp-side.thin .sp-ab{font-weight:700;color:var(--text-2)}
.sp-side.thin .sp-n{font-weight:600}
.sp-k{color:var(--key-text);font-weight:800}
/* One bar, split at the share that took the away side — the proportion is the
   thing the eye wants, and two numbers alone do not give it.

   The SPLIT follows the side (left is the team on the top line); the COLOURS
   follow the majority, so the bold segment is always the popular pick. Those
   are two different questions and the bar used to answer only the first. */
.sp-bar{height:5px;border-radius:3px;overflow:hidden;margin:4px 0;
  background:var(--navy)}                       /* the home side, when it leads */
.sp-bar span{display:block;height:100%;background:var(--line-strong)}
.sp-bar.lead-away{background:var(--line-strong)}
.sp-bar.lead-away span{background:var(--navy)}
