/* Fantasy Command — design system
   One stylesheet for the landing page, the auth page and the app, so a change to spacing
   or colour lands everywhere at once. */

:root{
  /* SURFACES: four roles, not four tints. Each step is a lightness step, because in a dark
     UI depth is surface lightness plus a hairline -- a shadow on #0a0c10 has nothing left
     to darken. */
  --bg:#0a0c10;          /* page floor */
  --sunk:#0f1218;        /* inputs, wells, sticky rail headers */
  --card:#161b26;        /* cards, league tiles, rail */
  --raised:#1f2634;      /* hover, active row, chips */
  --pop:#242c3d;         /* menus and popovers, which sit above everything */
  --bg2:var(--sunk); --card2:var(--raised);   /* the old names, so 40+ existing uses hold */

  /* BORDERS AS ALPHA, so one token is the same perceived weight on every surface. A solid
     #242a36 is a 1.23:1 edge on a card and a different edge on a popover. */
  --line:rgba(255,255,255,.08);
  --line2:rgba(255,255,255,.14);
  --hair:rgba(255,255,255,.05);   /* dividers INSIDE a card, which should barely exist */
  --rule:#272c38;                 /* SOLID, and only for .glance, which uses the token as a
                                     FILL behind a 1px grid gap -- an alpha there would
                                     composite against the page, not the card. */

  /* TEXT. --faint was #6b7484: 3.77:1 on a card, which FAILS WCAG AA, and it was the colour
     of the game clock, the down-and-distance and the play timestamp -- every perishable
     thing on the page, all of it at 10-11px, read on a phone outdoors on a Sunday. */
  --txt:#e9ecf1;         /* 14.6:1 */
  --dim:#a8b2c4;         /* 8.1:1  -- now the default for ALL micro-labels */
  --faint:#8b93a4;       /* 5.6:1  -- and never used for text below 13px again */

  --acc:#4f8cff;         /* interaction only, never emphasis */
  --acc-txt:#6ea1ff;     /* accent AS TEXT; --acc itself is marginal on a raised surface */
  --acc2:#9b87ff;        /* was #7c5cff at 4.09:1, also an AA failure */
  --win:#34d399;         /* teal-green survives deuteranopia better than #22c55e */
  --lose:#fb7185;
  --rz:#ff6557;          /* RED ZONE ONLY. Never the same red as losing: today one colour
                            means both "your back is on the 4-yard line" (excellent) and
                            "you are behind" (not), on the same screen. */
  --go:var(--win); --bad:var(--lose);          /* the old names, for landing and draft tabs */
  --warn:#f59e0b;

  --qb:#a78bfa; --rb:#34d399; --wr:#60a5fa; --te:#fbbf24; --k:#94a3b8; --dst:#f472b6;

  /* TYPE. Six ranks and nothing between them. Weight is a semantic channel: 400 body,
     600 titles, 700 micro-caps, and 800 reserved exclusively for numerals. */
  --fs-hero:clamp(28px,6.5vw,38px);
  --fs-score:28px; --fs-2:16px; --fs-title:13px; --fs-body:15px;
  --fs-meta:12px; --fs-micro:11px;              /* HARD FLOOR. Nothing below 11px. */
  --tr-display:-.022em; --tr-tight:-.012em; --tr-caps:.08em;

  --r:12px; --r2:8px; --rp:999px;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.28);
  /* NO "Inter". There is no @font-face and no font link in the repository, so it resolved
     only on machines that happened to have it installed -- which means debugging a page the
     users do not see, and font-weight:750 rendering as a true 750 here and a synthesised
     bold for them. */
  --sans:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
:root{color-scheme:dark}   /* native selects and every scrollbar stop rendering light-mode */

/* One focus ring for the whole product. There was none: `grep -c "aria-" app.html` returned
   0 and no :focus-visible rule existed in 638 lines. */
:where(a,button,[tabindex],summary,input,select,label.opt):focus-visible{
  outline:2px solid var(--acc); outline-offset:2px; border-radius:var(--r2);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--txt); font-family:var(--sans);
  font-size:15px; line-height:1.55; -webkit-font-smoothing:antialiased;
}
a{color:var(--acc); text-decoration:none}
a:hover{text-decoration:underline}
/* ONE PAGE WIDTH, SET PER TAB.
   1180px is a reading measure and it is the right one for News, Waivers, Draft, Start/Sit,
   Connect, Account, the landing page and the login page -- their lines run about 125
   characters at that width already, so widening them would make them worse.
   Headquarters is not a reading surface, it is a dashboard, and at 1180px it rendered as a
   ribbon down the middle of a 2878px monitor with 849px of dead black each side. It gets the
   glass. Everything else keeps exactly the value it has today. */
:root{ --shell:1180px }
body[data-tab="hq"]{ --shell:min(2400px, calc(100vw - 48px)) }
/* NO TRANSITION on the width. Animating it means every tab click reflows the whole page and
   the sticky nav with it -- a 1200px slide at 2878px -- and it made the measured max-width
   race the probe, reading 1180px at one viewport and 2326px at another from the same rule.
   Dashboards snap. */
.wrap{max-width:var(--shell); margin:0 auto; padding:0 22px}
.hidden{display:none !important}

/* ---------- top navigation ---------- */
.nav{
  position:sticky; top:0; z-index:50; background:rgba(10,12,16,.86);
  backdrop-filter:blur(12px); border-bottom:1px solid var(--line);
}
.nav .wrap{display:flex; align-items:center; gap:18px; height:62px}
.brand{display:flex; align-items:center; gap:10px; font-weight:700; font-size:17px;
  letter-spacing:-.02em; color:var(--txt)}
.brand:hover{text-decoration:none}
.mark{
  width:28px; height:28px; border-radius:8px; flex:0 0 auto;
  background:linear-gradient(135deg,var(--acc),var(--acc2));
  display:grid; place-items:center; font-size:15px; font-weight:800; color:#fff;
}
.navspace{flex:1}
.navlink{color:var(--dim); font-size:14px; font-weight:500}
.navlink:hover{color:var(--txt); text-decoration:none}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:10px 18px; border-radius:var(--r2); border:1px solid var(--line2);
  background:var(--card2); color:var(--txt); font:600 14px var(--sans);
  cursor:pointer; transition:.15s; white-space:nowrap;
}
.btn:hover{background:#222836; text-decoration:none}
.btn.primary{
  background:var(--acc); border-color:rgba(255,255,255,.16); color:#fff;
}
.btn.primary:hover{filter:brightness(1.08)}
.btn.big{padding:14px 26px; font-size:16px}
.btn.ghost{background:transparent}
.btn:disabled{opacity:.55; cursor:not-allowed}

/* ---------- landing ---------- */
.hero{padding:84px 0 68px; text-align:center; position:relative; overflow:hidden}
.hero::before{
  content:""; position:absolute; inset:-40% 20% auto; height:460px;
  background:radial-gradient(ellipse at center,rgba(79,140,255,.16),transparent 70%);
  pointer-events:none;
}
.pill{
  display:inline-flex; align-items:center; gap:8px; padding:5px 13px; border-radius:999px;
  border:1px solid var(--line2); background:var(--card); color:var(--dim);
  font-size:12.5px; font-weight:600; letter-spacing:.02em; margin-bottom:22px;
}
.pill .dot{width:6px; height:6px; border-radius:50%; background:var(--go)}
h1.big{
  font-size:clamp(34px,5.2vw,58px); line-height:1.06; letter-spacing:-.03em;
  font-weight:800; margin:0 0 18px;
}
h1.big em{
  font-style:normal;
  background:linear-gradient(120deg,var(--acc),var(--acc2));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.lede{font-size:clamp(16px,2vw,19px); color:var(--dim); max-width:660px; margin:0 auto 30px}
.cta{display:flex; gap:12px; justify-content:center; flex-wrap:wrap}
.mini{color:var(--faint); font-size:13px; margin-top:16px}

.section{padding:56px 0; border-top:1px solid var(--line)}
.eyebrow{
  color:var(--acc); font-size:12px; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; margin:0 0 10px;
}
h2.sec{font-size:clamp(24px,3.4vw,34px); letter-spacing:-.02em; margin:0 0 12px; font-weight:700}
.secsub{color:var(--dim); max-width:640px; margin:0 0 34px}

.grid{display:grid; gap:16px; grid-template-columns:repeat(auto-fit,minmax(272px,1fr))}
.feature{
  background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  padding:22px; transition:.18s;
}
.feature:hover{border-color:var(--line2); transform:translateY(-2px)}
.feature .ico{
  width:36px; height:36px; border-radius:10px; display:grid; place-items:center;
  background:var(--card2); border:1px solid var(--line2); font-size:17px; margin-bottom:14px;
}
.feature h3{margin:0 0 7px; font-size:16px; font-weight:700; letter-spacing:-.01em}
.feature p{margin:0; color:var(--dim); font-size:14px}

.note{
  border-left:3px solid var(--line2); padding:2px 0 2px 16px; color:var(--dim);
  font-size:14px; margin:26px 0 0;
}
.foot{border-top:1px solid var(--line); padding:26px 0 40px; color:var(--faint); font-size:13px}

/* ---------- auth page ---------- */
.authWrap{min-height:100vh; display:grid; place-items:center; padding:40px 20px}
.authCard{
  width:100%; max-width:432px; background:var(--card); border:1px solid var(--line);
  border-radius:16px; padding:30px 28px 26px; box-shadow:var(--shadow);
}
.authLogo{display:flex; align-items:center; justify-content:center; gap:10px; margin:0 0 4px}
.authTagline{text-align:center; color:var(--dim); font-size:14px; margin:0 0 22px}
/* Auth tabs, taken from FieldSync (public/auth.css .authTab).
   Two segmented buttons whose active state is a background fill read as a half-filled box
   when the fill is close to the strip colour -- which is exactly the fault I shipped here.
   FieldSync solved this long ago by making the active state an UNDERLINE instead: the tabs
   are transparent, the container carries a bottom border, and .active draws a 2px accent
   bar via ::after. There is no ambiguity possible, because nothing is filled. */
.authTabs{display:flex; border-bottom:1px solid var(--line); margin-bottom:22px}
.authTab{
  flex:1; border:0; background:transparent; padding:12px 10px; cursor:pointer;
  font:800 14px var(--sans); color:var(--faint); position:relative; transition:.15s;
}
.authTab:hover{color:var(--dim)}
.authTab.active{color:var(--txt)}
.authTab.active::after{
  content:""; position:absolute; bottom:-1px; left:16px; right:16px; height:2px;
  background:var(--acc); border-radius:2px;
}
.authForm{display:flex; flex-direction:column; gap:14px}
.authRow{display:grid; grid-template-columns:1fr 1fr; gap:12px}
.authField{display:flex; flex-direction:column; gap:6px}
.authField label{font-size:12.5px; font-weight:600; color:var(--dim); letter-spacing:.01em}
.authField input{
  padding:11px 13px; border-radius:var(--r2); border:1px solid var(--line2);
  background:var(--bg2); color:var(--txt); font:15px var(--sans); transition:.15s;
}
.authField input:focus{
  outline:0; border-color:var(--acc); box-shadow:0 0 0 3px rgba(79,140,255,.16);
}
.authField input::placeholder{color:var(--faint)}
.authBtn{
  margin-top:4px; padding:12px; border:0; border-radius:var(--r2);
  background:linear-gradient(135deg,var(--acc),var(--acc2)); color:#fff;
  font:700 15px var(--sans); cursor:pointer; transition:.15s;
}
.authBtn:hover{filter:brightness(1.08)}
.authBtn:disabled{opacity:.6; cursor:progress}
.authError{
  background:rgba(239,68,68,.1); border:1px solid rgba(239,68,68,.35); color:#fca5a5;
  padding:9px 12px; border-radius:var(--r2); font-size:13.5px;
}
.authOk{
  background:rgba(34,197,94,.1); border:1px solid rgba(34,197,94,.35); color:#86efac;
  padding:9px 12px; border-radius:var(--r2); font-size:13.5px;
}
.authHint{color:var(--faint); font-size:12.5px; text-align:center; margin:14px 0 0}
/* .authForgotRow / .authForgotLink / .authFormInfo, from FieldSync public/auth.css */
.authForgotRow{display:flex; justify-content:center; margin-top:2px}
.authForgotLink{
  border:0; background:transparent; color:var(--acc); font:600 13px var(--sans);
  cursor:pointer; padding:4px
}
.authForgotLink:hover{text-decoration:underline}
.authFormInfo{color:var(--dim); font-size:13.5px; margin:0 0 4px; text-align:center}

/* ---------- app shell ---------- */
.tabs{display:flex; gap:2px; border-bottom:1px solid var(--line); margin-bottom:22px}
.tab{
  padding:11px 18px; border:0; background:transparent; color:var(--dim);
  font:600 14.5px var(--sans); cursor:pointer; border-bottom:2px solid transparent;
  margin-bottom:-1px; transition:.15s;
}
.tab:hover{color:var(--txt)}
.tab.active{color:var(--txt); border-bottom-color:var(--acc)}
.panel{padding-bottom:60px}
.card{background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  padding:20px; margin-bottom:16px}
.card h3{margin:0 0 4px; font-size:15px; font-weight:700}
.card .sub{color:var(--dim); font-size:13.5px; margin:0 0 14px}
.cols{display:grid; gap:16px; grid-template-columns:1.35fr 1fr}
@media(max-width:900px){.cols{grid-template-columns:1fr} .authRow{grid-template-columns:1fr}}

.hero2{background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  padding:30px 22px; text-align:center; margin-bottom:18px}
.hero2 .kick{font-size:12px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--dim); margin-bottom:8px}
.hero2 .name{font-size:clamp(26px,4vw,40px); font-weight:800; letter-spacing:-.02em}
.hero2 .meta{color:var(--dim); font-size:14px; margin-top:6px}
.hero2.go{border-color:rgba(34,197,94,.4); background:linear-gradient(180deg,rgba(34,197,94,.07),var(--card))}

.plist{display:flex; flex-direction:column}
.prow{display:flex; align-items:center; gap:12px; padding:11px 2px;
  border-bottom:1px solid var(--line)}
.prow:last-child{border-bottom:0}
.tag{
  font:700 10.5px var(--sans); letter-spacing:.05em; padding:3px 7px; border-radius:5px;
  min-width:38px; text-align:center; color:#0a0c10; background:var(--k);
}
.tag.QB{background:var(--qb)} .tag.RB{background:var(--rb)} .tag.WR{background:var(--wr)}
.tag.TE{background:var(--te)} .tag.K{background:var(--k)} .tag.DST{background:var(--dst)}
.pname{font-weight:600; flex:1; min-width:0}
.pname small{display:block; color:var(--faint); font-weight:400; font-size:12.5px}
.pnum{color:var(--dim); font-size:13px; font-variant-numeric:tabular-nums; text-align:right}

.alert{background:rgba(245,158,11,.09); border:1px solid rgba(245,158,11,.3);
  color:#fcd34d; padding:11px 14px; border-radius:var(--r2); font-size:14px; margin-bottom:12px}
.empty{color:var(--dim); text-align:center; padding:38px 12px}
.spin{display:inline-block; width:15px; height:15px; border:2px solid var(--line2);
  border-top-color:var(--acc); border-radius:50%; animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}
code.k{background:var(--bg2); border:1px solid var(--line); border-radius:5px;
  padding:1px 6px; font-size:13px}

/* setup steps */
.steps{margin:6px 0 0; padding-left:22px; color:var(--txt)}
.steps li{margin:0 0 10px; line-height:1.7}
.steps .btn{margin:0 4px; cursor:grab}
.hint{color:var(--faint); font-size:12.5px}

/* upcoming pick chips and the recent feed */
.picks{display:flex; gap:6px; justify-content:center; margin-top:14px; flex-wrap:wrap}
.pk{font:600 12px var(--sans); color:var(--dim); border:1px solid var(--line2);
    border-radius:6px; padding:3px 9px; font-variant-numeric:tabular-nums}
.pk.first{color:var(--txt); border-color:var(--acc); background:rgba(79,140,255,.10)}
.prow.mineRow{background:rgba(79,140,255,.07); border-radius:6px}

/* Draft view: three columns that fit one screen without scrolling.
   Best available is the narrowest of the three -- it only needs a name, a position tag and
   a survival percentage, so the width it had was wasted. */
.cols3{display:grid; gap:14px; grid-template-columns:1fr 0.95fr 0.9fr; align-items:start}
@media(max-width:1100px){.cols3{grid-template-columns:1fr 1fr}}
@media(max-width:780px){.cols3{grid-template-columns:1fr}}
.cols3 .card{margin-bottom:0}
.plist.tight .prow{padding:7px 2px}
.plist.tight .pname small{font-size:11.5px}
/* a shorter hero leaves room for the three columns below it */
.hero2{padding:20px 18px}
.hero2 .name{font-size:clamp(23px,3.2vw,34px)}

/* lineup slots */
.lineup{display:flex; flex-direction:column; gap:5px}
.sl{display:flex; align-items:center; gap:9px; background:var(--bg2);
    border:1px solid var(--line); border-radius:8px; padding:7px 10px}
.sl .nm{font-weight:600; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis;
        white-space:nowrap}
.sl .pj{color:var(--faint); font-size:12px; white-space:nowrap}
.sl.empty{border-style:dashed; background:transparent}
.sl.empty .nm{color:var(--faint); font-style:italic; font-weight:400}
.needs{display:flex; flex-wrap:wrap; gap:6px; margin-top:10px}
.need{font:600 11.5px var(--sans); border:1px dashed var(--line2); border-radius:999px;
      padding:3px 9px; color:var(--dim)}
.need.QB{color:var(--qb); border-color:var(--qb)}
.need.RB{color:var(--rb); border-color:var(--rb)}
.need.WR{color:var(--wr); border-color:var(--wr)}
.need.TE{color:var(--te); border-color:var(--te)}
.need.FLEX{color:var(--wr); border-color:var(--line2)}
.need.K{color:var(--k); border-color:var(--k)}
.need.DST{color:var(--dst); border-color:var(--dst)}
.benchWrap{margin-top:12px; padding-top:11px; border-top:1px solid var(--line)}
.benchLbl{font:700 10.5px var(--sans); letter-spacing:.1em; text-transform:uppercase;
          color:var(--dim); margin-bottom:7px}
.tag.FLEX{background:linear-gradient(90deg,var(--rb),var(--wr))}

/* ---------------------------------------------------------------------------
   VISUAL HIERARCHY
   Every block on these tabs was a .card with an h3, so a page-level section and
   a minor sub-panel were typographically identical -- twelve stacked cards read
   as one continuous article with no way to skim it. Three levels now:
     .sect        a page-level section header, outside any card, with a rule
     .card h3     a panel heading inside a section
     .card.quiet  supporting material that should recede, not compete
   -------------------------------------------------------------------------- */
.sect{
  margin:34px 0 14px; padding-bottom:9px;
  border-bottom:1px solid var(--line2);
  display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap;
}
.sect:first-child{margin-top:8px}
.sect .eyebrow{
  font:700 10.5px var(--sans); letter-spacing:.14em; text-transform:uppercase;
  color:var(--acc); margin:0 0 3px;
}
.sect h2{
  font:700 20px/1.2 var(--sans); letter-spacing:-.02em; margin:0; color:var(--txt);
}
.sect .note2{
  color:var(--dim); font-size:13px; margin:0 0 2px auto; text-align:right; max-width:46%;
}
@media(max-width:700px){ .sect .note2{margin:6px 0 0; text-align:left; max-width:100%} }

/* a panel heading is now clearly subordinate to a section header */
.card h3{font-size:14.5px; letter-spacing:0}

/* supporting material recedes rather than competing for attention */
.card.quiet{
  background:transparent; border-style:dashed; border-color:var(--line);
  padding:15px 17px;
}
.card.quiet h3{color:var(--dim); font-size:12.5px; letter-spacing:.05em;
  text-transform:uppercase}
.card.quiet .plist .prow{border-bottom:0; padding:5px 2px}
.card.quiet small, .card.quiet .pname{font-size:12.5px; color:var(--dim); font-weight:400}

/* one idea per callout at the top of a tab, instead of a wall of warnings */
.lead{
  background:linear-gradient(180deg,rgba(79,140,255,.07),transparent);
  border:1px solid var(--line2); border-left:3px solid var(--acc);
  border-radius:var(--r2); padding:12px 15px; margin:0 0 10px;
  font-size:14px; color:var(--txt);
}

/* an item inside a section, colour-coded by whether you can act on it */
.card.item{border-left:3px solid var(--line2)}
.card.item.free{border-left-color:var(--go)}
.card.item.mine{border-left-color:var(--warn)}
.card.item.taken{border-left-color:var(--line2); opacity:.82}

/* ---------------------------------------------------------------------------
   DRAFT STATES
   A scheduled draft, a live draft and a finished one are three different
   screens. They used to share one treatment -- a big centred hero -- which is
   why a finished draft announced "Nothing to pick" in 48px type and a league
   drafting in two weeks showed a live-tracking setup card.
   -------------------------------------------------------------------------- */
.cd{
  background:linear-gradient(180deg,rgba(79,140,255,.10),rgba(79,140,255,.02));
  border:1px solid var(--line2); border-radius:var(--r2);
  padding:22px 24px; margin:0 0 14px; text-align:center;
}
.cdkick{font:700 10.5px var(--sans); letter-spacing:.16em; text-transform:uppercase;
  color:var(--acc); margin:0 0 12px}
.cdrow{display:flex; gap:10px; justify-content:center; flex-wrap:wrap; margin:0 0 12px}
.cdcell{
  min-width:74px; padding:10px 12px; border-radius:10px;
  background:var(--card2,rgba(255,255,255,.035)); border:1px solid var(--line);
}
.cdcell b{display:block; font:800 30px/1 var(--sans); letter-spacing:-.02em; color:var(--txt);
  font-variant-numeric:tabular-nums}
.cdcell span{display:block; margin-top:4px; font-size:11px; color:var(--dim);
  text-transform:uppercase; letter-spacing:.08em}
.cdgo{font:800 26px/1.1 var(--sans); color:var(--go)}
.cdwhen{color:var(--txt); font-size:14px}
.cdpicks{color:var(--dim); font-size:13px; margin-top:7px}
@media(max-width:560px){
  .cdcell{min-width:60px; padding:8px 9px}
  .cdcell b{font-size:23px}
}

/* a finished draft leads with the team, not with the absence of a pick */
.donebar{
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  background:var(--card); border:1px solid var(--line2); border-left:3px solid var(--go);
  border-radius:var(--r2); padding:16px 19px; margin:0 0 14px;
}
.donebar .kick{font:700 10.5px var(--sans); letter-spacing:.14em; text-transform:uppercase;
  color:var(--go); margin:0 0 4px}
.donebar .dname{font:700 21px/1.2 var(--sans); letter-spacing:-.02em; color:var(--txt)}
.donebar .dmeta{color:var(--dim); font-size:13px; margin-top:3px}
.doneacts{display:flex; gap:8px; flex-wrap:wrap}

/* label/value rows for the league-format card */
.kv{display:flex; flex-direction:column}
.kvrow{display:flex; justify-content:space-between; gap:14px; padding:7px 2px;
  border-bottom:1px solid var(--line)}
.kvrow:last-child{border-bottom:0}
.kvrow .k{color:var(--dim); font-size:12.5px}
.kvrow .v{color:var(--txt); font-size:13px; text-align:right; font-weight:600}

/* "this page is out of date" -- shown, never acted on automatically */
.newbuild{
  display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
  background:linear-gradient(180deg,rgba(240,180,41,.13),rgba(240,180,41,.03));
  border:1px solid rgba(240,180,41,.42); border-left:3px solid var(--warn);
  border-radius:var(--r2); padding:12px 16px; margin:0 0 14px; font-size:14px;
}

/* ---------------------------------------------------------------------------
   CONNECT STATE
   The Connect tab showed five numbered setup steps to everyone, with a single
   green line under step five saying it was already done. Read top to bottom
   that is an instruction to redo it. The state now leads, and the steps are
   shown only to someone who still has to follow them.
   -------------------------------------------------------------------------- */
.cstate{border-radius:var(--r2); padding:15px 17px; margin:2px 0 4px;
  border:1px solid var(--line2)}
.cstate.ok{border-left:3px solid var(--go);
  background:linear-gradient(180deg,rgba(61,220,132,.09),rgba(61,220,132,.02))}
.cstate.warn{border-left:3px solid var(--warn);
  background:linear-gradient(180deg,rgba(240,180,41,.10),rgba(240,180,41,.02))}
.cstate .cs1{font:700 15px/1.3 var(--sans); color:var(--txt)}
.cstate.ok .cs1{color:var(--go)}
.cstate.warn .cs1{color:var(--warn)}
.cstate .cs2{margin-top:5px; font-size:13.5px; color:var(--txt)}
.cstate .cs3{margin-top:9px; font-size:13px; color:var(--dim)}
.cstate .cs4{margin-top:11px; font-size:12.5px}
.cstate .cs4 a{color:var(--dim)}
.cstate .cs4 a:hover{color:var(--acc)}

/* ---------------------------------------------------------------------------
   FINISHED DRAFT LAYOUT
   Was .cols3 (1fr 0.95fr 0.9fr) holding one lineup card and one empty one, so
   a nine-slot lineup plus bench became a narrow column tall enough to scroll
   while two thirds of the row sat unused.
   -------------------------------------------------------------------------- */
.done2{display:grid; gap:14px; grid-template-columns:1.45fr 1fr; align-items:start}
@media(max-width:900px){.done2{grid-template-columns:1fr}}
.done2 .card{margin-bottom:0}

/* slots flow across the width instead of stacking one per row */
.lineup.grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(205px,1fr)); gap:6px;
}

/* the round marker on the pick list */
.rd{
  flex:0 0 auto; min-width:30px; text-align:center; padding:2px 5px; border-radius:5px;
  font:700 10.5px var(--sans); letter-spacing:.04em; color:var(--dim);
  background:rgba(255,255,255,.045); border:1px solid var(--line);
}

/* ---------------------------------------------------------------------------
   PROVIDER TAGS
   Two leagues can share a name across two services, and the advice differs by
   service -- ESPN needs a bookmarklet mid-draft, Yahoo does not. So which one
   you are looking at is shown, not inferred. ESPN blue, Yahoo purple.
   -------------------------------------------------------------------------- */
.ptag{
  display:inline-block; padding:3px 8px; border-radius:6px;
  font:700 10.5px var(--sans); letter-spacing:.1em; text-transform:uppercase;
  border:1px solid transparent; white-space:nowrap;
}
.ptag.espn{
  color:#9dc4ff; background:rgba(79,140,255,.16); border-color:rgba(79,140,255,.42);
}
.ptag.yahoo{
  color:#c9b6ff; background:rgba(124,92,255,.18); border-color:rgba(124,92,255,.45);
}

/* the same two identities on the Connect tab, so the sections read as services */
.svc{display:flex; align-items:center; gap:9px; margin:0 0 8px}
.svc h3{margin:0}
#yahooBox{border-left:3px solid rgba(124,92,255,.55); padding-left:15px}

/* "new since you last looked" -- a marker, not a shout */
.newdot{
  font:700 9.5px var(--sans); letter-spacing:.1em; text-transform:uppercase;
  color:var(--go); background:rgba(61,220,132,.13);
  border:1px solid rgba(61,220,132,.4); border-radius:20px; padding:2px 7px;
}
.card.item.fresh{border-left-color:var(--go)}

/* opinion and analysis: worth reading, not a team announcement */
.vchip{
  font:700 9.5px var(--sans); letter-spacing:.1em; text-transform:uppercase;
  color:#c9b6ff; background:rgba(124,92,255,.14);
  border:1px solid rgba(124,92,255,.42); border-radius:20px; padding:2px 7px;
}
.card.item.opinion{border-left-color:#7c5cff; background:rgba(124,92,255,.035)}

/* a checkbox that reads as a sentence rather than a form field */
.opt{display:flex; align-items:flex-start; gap:9px; margin:7px 0; font-size:13.5px;
  color:var(--txt); cursor:pointer}
.opt input{margin:2px 0 0; accent-color:var(--acc)}

/* ========================= FANTASY HEADQUARTERS =========================
   Game day, every league at once. The rule that keeps it from becoming a wall:
   ONE thing is allowed to be loud at a time, and it is whatever has the shortest
   shelf life. Red zone (90 seconds) outranks a close game (an hour) outranks the
   day's totals (all afternoon). Everything else is quiet by construction.

   WHAT LEADS, in order, and nothing else is allowed to compete:
     1. the red-zone banner   -- expires in ninety seconds
     2. the glance numbers    -- largest type on the page, but NEUTRAL; size carries them
     3. my score in a card    -- 28/800 against the opponent's 16/600
     4. the margin            -- small, but the only coloured text in a card
     5. the newest big play   -- one 420ms animation, once
     6. live rail scores
     7. everything else is grey. */

/* TABULAR FIGURES, set once on the containers rather than leaf by leaf. Deliberately NOT on
   body: proportional figures are correct in prose. Without this a score going 9.7 -> 89.7
   shoves the whole row sideways on every poll, which is most of why the page felt unstable. */
.glance,.lg,.gm,.pl,.cdcell,.fp,.prow,.hqpill,.tdp{
  font-variant-numeric:tabular-nums lining-nums;
  font-feature-settings:"tnum" 1,"lnum" 1;
}

.hqwrap{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:18px;align-items:start}
@media (max-width:1100px){ .hqwrap{grid-template-columns:minmax(0,1fr)} }

/* THE SURFACE RECIPE. Lightness step, hairline, and a 1px inset top highlight -- the bevel
   is light catching the top edge, which is what reads as "object" on a near-black ground.
   :not(.quiet) matters: .card.quiet is deliberately transparent and dashed, and a
   background-image paints regardless of background-color, so it would gain a white wash. */
.card:not(.quiet),.lg,.sb{
  background-color:var(--card);
  background-image:linear-gradient(180deg,rgba(255,255,255,.045) 0,rgba(255,255,255,0) 56px);
  border:1px solid var(--line);border-radius:var(--r);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07),
             0 1px 2px rgba(0,0,0,.5),
             0 10px 24px -18px rgba(0,0,0,.85);
}

/* The glance. Three numbers, readable from across a room. The 1px grid gaps are filled by
   the .glance background, which is why --rule is solid where every other border is alpha. */
/* ONE HEADER ROW. The glance and the controls used to be two stacked rows costing ~183px of
   the first screen between them, to carry three numbers and two buttons. */
.hqhead{display:flex;align-items:stretch;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.hqhead .glance{flex:1 1 520px;margin-bottom:0}
.hqhead .hqbar{margin-bottom:0;align-items:center;flex:0 0 auto}

.glance{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--rule);
  border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  box-shadow:0 1px 2px rgba(0,0,0,.5),0 10px 24px -18px rgba(0,0,0,.85)}
.glance > div{background:var(--card);padding:16px 18px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07)}
/* Weight 800 and line-height 1. The old rule had no line-height at all, so a 30px glyph sat
   in a 46px line box inherited from body -- more of why the cards read as loose than any
   colour token. */
.glance .gv{font-size:var(--fs-hero);font-weight:800;letter-spacing:var(--tr-display);
  line-height:1;color:var(--txt)}
.glance .gv .sub2{font-size:.45em;font-weight:600;color:var(--dim);letter-spacing:0}
.glance .gl{font-size:var(--fs-micro);text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--dim);margin-top:8px;font-weight:700;line-height:1.3}
.glance .gs{font-size:var(--fs-meta);color:var(--dim);margin-top:4px}
@media (max-width:620px){ .glance{grid-template-columns:1fr 1fr}
  .glance > div:last-child{grid-column:1/-1} }

/* RED ZONE. The only saturated fill on the page and the only thing allowed to move, because
   it is the only thing that expires in ninety seconds. Its red is --rz, which is NOT the red
   that means "you are losing" -- one colour cannot mean a great thing and a bad thing on the
   same screen. */
.rz{display:flex;align-items:center;gap:12px;background:linear-gradient(90deg,
  color-mix(in srgb,var(--rz) 20%,transparent),color-mix(in srgb,var(--rz) 4%,transparent));
  border:1px solid color-mix(in srgb,var(--rz) 45%,transparent);
  border-radius:var(--r);padding:13px 16px;margin-bottom:14px}
.rz .dot{width:9px;height:9px;border-radius:50%;background:var(--rz);flex:0 0 auto;
  animation:rzpulse 2s cubic-bezier(.4,0,.6,1) infinite}
/* Fades, never scales. A dot that changes SIZE is far more irritating in peripheral vision
   than one that changes opacity, and this sits on screen for the whole drive. */
@keyframes rzpulse{50%{opacity:.45}}
.rz b{color:var(--txt);font-size:var(--fs-micro);font-weight:700;
  letter-spacing:var(--tr-caps);text-transform:uppercase}
.rz .names{color:var(--txt);font-weight:600}

/* THE SCOREBOARD. Every league the user is showing, and on a wide monitor all of them at
   once -- this is the thing the page exists for and it is the thing that leads.
 *
 * auto-FILL, which this used to be, keeps creating empty tracks: at 2400px it made eight
 * columns, so two leagues rendered as two 268px chips against 1800px of black. auto-FIT
 * collapses the empty tracks instead, and the .nN class caps how far a card may stretch so
 * two leagues do not become two 1200px slabs either. */
.lgrid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
/* CAP THE GRID, NOT THE TRACK. minmax(300px, 700px) under auto-fit decides how many columns
   fit by the MAXIMUM, so at a 984px column it fitted ONE 700px track and stacked this user's
   two leagues vertically. Capping the grid's own width leaves the tracks as 1fr, so they
   divide whatever room there is and the count comes out right at every size. */
.lgrid.n1{max-width:820px}
.lgrid.n2{max-width:1440px}
.lgrid.n3{max-width:1620px}
/* Fewer leagues means a bigger number, because the page has the room and the score is the
   point. Nine leagues keep the compact size so they all fit above the fold. */
.lgrid.n1 .lg .me,.lgrid.n2 .lg .me{font-size:36px}
.lgrid.n1 .lg .them,.lgrid.n2 .lg .them{font-size:18px}
.lgrid.n1 .lg,.lgrid.n2 .lg{padding:16px 18px}
.lg{padding:13px 15px;cursor:pointer;text-align:left;width:100%;color:inherit;
  font-family:inherit;border-left:3px solid transparent;display:block}
@media (hover:hover){
  .lg{transition:background-color .16s ease,border-color .16s ease,box-shadow .16s ease}
  .lg:hover{background-color:var(--raised);border-color:var(--line2);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 1px 2px rgba(0,0,0,.5),
               0 14px 30px -18px rgba(0,0,0,.9)}
}
/* NO transform on hover. It sticks after a tap on a touch screen, which is a live bug on
   the phone this page exists for. */
.lg:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--acc)}

/* STATE COLOUR, and the rule that fixes the 1:05pm problem: at kickoff roughly half of nine
   leagues are behind and the rest are tied at nothing, so a red spine for "losing" opened
   the dashboard as a grid of red bars before a single snap. Losing is not an emergency.
   Only winning, and only genuine urgency, earn a spine. */
.lg.win{border-left-color:var(--win)}
.lg.lose,.lg.tie{border-left-color:transparent}
/* URGENT IS AMBER, NOT THE RED-ZONE RED. Giving it --rz would recreate the exact fault this
   token was split out to fix: one colour meaning two unrelated things at once. A red spine
   must mean "somebody is inside the twenty right now" and nothing else. Amber reads as
   "this one is still in the balance", which is what it is. 8.0:1 on a card. */
.lg.urgent{border-left-color:var(--warn)}
.lg.win{--state:var(--win)} .lg.urgent{--state:var(--warn)}
.lg.win,.lg.urgent{background-image:
  linear-gradient(90deg,color-mix(in srgb,var(--state) 11%,transparent),transparent 42%),
  linear-gradient(180deg,rgba(255,255,255,.045) 0,rgba(255,255,255,0) 56px)}

.lg .nm{font-weight:600;font-size:var(--fs-title);margin-bottom:2px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;line-height:1.35;color:var(--txt)}
.lg .vs{font-size:var(--fs-micro);color:var(--dim);margin-bottom:9px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.lg .score{display:flex;align-items:baseline;gap:8px}
/* A 28/800 against a 16/600 is a deliberate 57% step, so scanning nine cards never requires
   reading the second number. */
.lg .me{font-size:var(--fs-score);font-weight:800;letter-spacing:var(--tr-display);
  line-height:1;color:var(--txt)}
.lg .them{font-size:var(--fs-2);font-weight:600;letter-spacing:var(--tr-tight);
  line-height:1.2;color:var(--dim)}
/* The margin is the only coloured text in the card, and it says the same thing three ways --
   sign, glyph and colour -- so it survives being colour-blind or being read in sunlight. */
.lg .mar{margin-left:auto;font-size:var(--fs-meta);font-weight:700}
.lg.win  .mar{color:var(--win)}
.lg.lose .mar{color:var(--lose)}
.lg.tie  .mar{color:var(--dim)}
.lg.win  .mar::before{content:"\25B2\00a0";font-size:.72em;vertical-align:.12em}
.lg.lose .mar::before{content:"\25BC\00a0";font-size:.72em;vertical-align:.12em}
.lg .meta{display:flex;gap:10px;font-size:var(--fs-micro);color:var(--dim);margin-top:9px;
  flex-wrap:wrap}
.lg .meta b{color:var(--txt);font-weight:700}
.lg .meta .rzhere{color:var(--rz);font-weight:700}

/* The right rail: real football. */
.sb{overflow:hidden;position:sticky;top:14px}
.sb h4{margin:0;padding:12px 14px;font-size:var(--fs-micro);text-transform:uppercase;
  letter-spacing:var(--tr-caps);color:var(--dim);font-weight:700;
  border-bottom:1px solid var(--line);background:var(--sunk)}
.sb .scroll{max-height:calc(100vh - 120px);overflow-y:auto;overscroll-behavior:contain}
.gm{padding:9px 14px;border-bottom:1px solid var(--hair);font-size:var(--fs-meta)}
.gm:last-child{border-bottom:0}
.gm.inplay{background:rgba(79,140,255,.05)}
.gm.rzone{background:color-mix(in srgb,var(--rz) 8%,transparent)}
.gm .row{display:flex;justify-content:space-between;align-items:center;gap:8px}
.gm .t{display:flex;justify-content:space-between;flex:1;min-width:0}
.gm .ab{font-weight:600;color:var(--dim)}
.gm .sc{color:var(--dim)}
/* .ahead, NOT .lead. `.lead` is a generic callout panel in this file -- border, 3px accent
   edge, 12px padding, rounded -- so every leading score in the rail was being drawn as a
   bordered box taller than its own row, shoving the game clock down under it. One word, two
   meanings, one stylesheet. */
.gm .sc.ahead{color:var(--txt);font-weight:700}
.gm .row:has(.sc.ahead) .ab{color:var(--txt)}
.gm .st{font-size:var(--fs-micro);color:var(--dim);margin-top:4px;display:flex;
  justify-content:space-between;gap:8px}
.gm .st .rzflag{color:var(--rz);font-weight:700}
.gm .mine{font-size:var(--fs-micro);color:var(--acc-txt);margin-top:3px}

/* Player rows inside an expanded league. */
.pl{display:grid;grid-template-columns:38px 1fr auto;gap:9px;align-items:center;
  padding:6px 0;border-top:1px solid var(--hair)}
.pl:first-child{border-top:0}
.pl .sl{font-size:var(--fs-micro);color:var(--dim);text-transform:uppercase;
  letter-spacing:.05em;font-weight:700}
.pl .who{min-width:0}
.pl .who b{font-weight:600;font-size:var(--fs-title)}
.pl .line{font-size:var(--fs-micro);color:var(--dim);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.pl .pts{font-weight:800;text-align:right;letter-spacing:var(--tr-tight)}
.pl.done .pts{color:var(--dim)}
.pl.yet .pts{color:var(--acc-txt)}
.pl .st{font-size:var(--fs-micro);color:var(--dim)}
/* .inrz, NOT .rz -- the same collision as .lead/.ahead. Bare `.rz` is the red-zone BANNER:
   display:flex, a coloured border, 13px padding and a 14px bottom margin. A player row
   carrying the same word inherited the border and the margin inside an expanded lineup. */
.pl.inrz{background:color-mix(in srgb,var(--rz) 8%,transparent);border-radius:var(--r2)}
.pl .rzhere{color:var(--rz);font-weight:700}

.hqbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.hqbar select{background:var(--card);color:var(--txt);border:1px solid var(--line2);
  border-radius:var(--r2);padding:7px 10px;font:inherit;font-size:var(--fs-meta)}
/* ONE live indicator for the page, not a badge per card: on a Sunday every league is live,
   and nine identical chips is nine units of noise. The pause control is not decoration --
   WCAG 2.2.2 requires a way to stop auto-updating content. */
.hqpill{display:inline-flex;align-items:center;gap:7px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--rp);padding:6px 12px;
  font-size:var(--fs-micro);font-weight:700;letter-spacing:var(--tr-caps);
  text-transform:uppercase;color:var(--dim)}
.hqpill .dot{width:7px;height:7px;border-radius:50%;background:var(--win);flex:0 0 auto;
  animation:rzpulse 2s cubic-bezier(.4,0,.6,1) infinite}
.hqpill.paused .dot{background:var(--dim);animation:none}
.hqpill button{background:none;border:0;color:var(--acc-txt);cursor:pointer;font:inherit;
  padding:0 2px;text-transform:none;letter-spacing:0}
.hqpill button:hover{text-decoration:underline}

/* League picker: a checklist, not a one-way hide. Every league is listed with its state
   visible, checked meaning shown, so putting one back needs no second control. */
.lpick{position:relative;display:inline-block}
.lpick > button{background:var(--card);color:var(--txt);border:1px solid var(--line2);
  border-radius:var(--r2);padding:8px 12px;font:inherit;font-size:var(--fs-meta);
  cursor:pointer;display:inline-flex;align-items:center;gap:8px}
.lpick > button:hover{border-color:var(--acc)}
.lpick > button .caret{color:var(--dim);font-size:var(--fs-micro)}
/* A popover sits one step higher than a card and carries the heavier shadow. */
.lpick .menu{position:absolute;z-index:60;top:calc(100% + 6px);left:0;min-width:300px;
  max-height:340px;overflow:auto;background:var(--pop);border:1px solid var(--line2);
  border-radius:var(--r);padding:6px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.09),0 16px 44px -12px rgba(0,0,0,.9)}
.lpick .menu.hidden{display:none}
.lpick .opt{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:var(--r2);
  cursor:pointer;font-size:var(--fs-title)}
.lpick .opt:hover{background:var(--raised)}
.lpick .opt input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer;flex:0 0 auto}
.lpick .opt .nm{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lpick .opt .pv{font-size:var(--fs-micro);color:var(--dim);text-transform:uppercase;
  letter-spacing:.06em}
.lpick .foot{border-top:1px solid var(--line);margin-top:6px;padding:8px 10px;
  font-size:var(--fs-micro);color:var(--dim)}

/* ===================== BIG PLAY FEED =====================
   The answer to "looking at the screen not sure what I am looking at". A score going up
   tells you nothing; this tells you which play, by whom, and whether it helped you.

   It now sits directly under the glance, ABOVE the league grid, because the glance says
   WHAT changed and the feed says WHY -- and the league grid is reference material while the
   feed is news.

   MOTION POLICY: only a genuinely NEW entry animates, once, for 420ms, and only the entry
   itself -- nothing already on screen moves, because content that shifts under a reader is
   worse than content that never moved. Honoured under prefers-reduced-motion. */
.feed .fp:nth-child(n+7){display:none}       /* six rows, then a disclosure */
.feed.all .fp{display:grid}
/* THE LEFT COLUMN SPLITS at wide widths: feed on the left, analysis beside it. Below this
   it is one column exactly as before. */
.hqmain{display:grid;grid-template-columns:minmax(0,1fr);gap:16px;align-items:start}
@media (min-width:1500px){
  .hqmain{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}
  .hqmain .hqfeed{margin-top:0 !important}
}
.hqside .cols3{grid-template-columns:minmax(0,1fr)}
.hqside .card{margin-bottom:12px}

/* ROWS, NOT PANELS. 100px per row for three short lines is a marketing page. The meta line
   folds together and the play text sits inline with the name, which is what it describes. */
.fp{display:grid;grid-template-columns:44px minmax(0,1fr) auto;gap:10px;align-items:baseline;
  padding:7px 2px;border-top:1px solid var(--hair)}
.fp .fpbody{min-width:0}
.fp .who .txt{font-weight:400;color:var(--dim);font-size:var(--fs-meta);margin-left:7px}
.fp .who{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fp:first-child{border-top:0}
.fp .kind{font:700 var(--fs-micro)/1.5 var(--sans);letter-spacing:.06em;text-align:center;
  padding:2px 0;border-radius:var(--r2);background:var(--raised);color:var(--dim)}
.fp .kind.TD{background:color-mix(in srgb,var(--win) 16%,transparent);color:var(--win)}
.fp .kind.FG{background:rgba(245,158,11,.15);color:#fcd34d}
.fp .kind.INT,.fp .kind.FUM,.fp .kind.SACK{
  background:color-mix(in srgb,var(--lose) 15%,transparent);color:var(--lose)}
.fp .kind.BIG{background:rgba(79,140,255,.15);color:#93c5fd}
.fp .who{font-weight:600;font-size:var(--fs-title)}
.fp .when,.fp .leagues{font-size:var(--fs-micro);color:var(--dim);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fp .net{font-weight:800;font-size:var(--fs-2);text-align:right;white-space:nowrap;
  letter-spacing:var(--tr-tight)}
.fp .net small{display:block;font:700 var(--fs-micro)/1.3 var(--sans);letter-spacing:.05em;
  color:var(--dim);text-transform:uppercase}
.fp.good .net{color:var(--win)}
.fp.bad  .net{color:var(--lose)}
.fp.mixed .net{color:var(--dim)}
/* EXPOSURE TIERS. |net| is how many of your teams the man plays for. A touchdown by someone
   on one of nine teams and a touchdown by someone on six of them are not the same news, and
   before this they were rendered identically. */
.fp.t1{opacity:.72}
.fp.t2 .net{font-size:19px}
.fp.t3 .net{font-size:22px}
.fp.t3{border-radius:var(--r2);padding-left:8px;margin-left:-8px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--win) 9%,transparent),transparent 46%)}
.fp.t3.bad{background:linear-gradient(90deg,
  color-mix(in srgb,var(--lose) 9%,transparent),transparent 46%)}
.fp.mixed .kind::after{content:"\00a0\00b1"}
.feedmore{display:block;width:100%;margin-top:10px;padding:8px;background:var(--sunk);
  border:1px solid var(--line);border-radius:var(--r2);color:var(--acc-txt);cursor:pointer;
  font:600 var(--fs-meta)/1 var(--sans)}
.feedmore:hover{border-color:var(--line2)}

.fp.isnew{animation:fpin .42s cubic-bezier(.22,1,.36,1) both}
@keyframes fpin{
  from{opacity:0;transform:translateY(-6px);background:rgba(79,140,255,.14)}
  60% {opacity:1;background:rgba(79,140,255,.10)}
  to  {opacity:1;transform:none;background:transparent}
}
.fp.isnew.good{animation-name:fpin-good}
@keyframes fpin-good{
  from{opacity:0;transform:translateY(-6px);background:color-mix(in srgb,var(--win) 20%,transparent)}
  60% {opacity:1;background:color-mix(in srgb,var(--win) 12%,transparent)}
  to  {opacity:1;transform:none;background:transparent}
}
.fp.isnew.bad{animation-name:fpin-bad}
@keyframes fpin-bad{
  from{opacity:0;transform:translateY(-6px);background:color-mix(in srgb,var(--lose) 18%,transparent)}
  60% {opacity:1;background:color-mix(in srgb,var(--lose) 10%,transparent)}
  to  {opacity:1;transform:none;background:transparent}
}

/* ONE universal reduced-motion rule, which also covers .spin -- the single animation in the
   file that had no guard of its own. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .rz .dot,.hqpill .dot{animation:none;
    box-shadow:0 0 0 3px color-mix(in srgb,var(--rz) 30%,transparent)}
  .fp.isnew,.fp.isnew.good,.fp.isnew.bad{animation:none;
    border-left:2px solid var(--acc);padding-left:6px}
}

/* ===================== THE SIX DAYS A WEEK NOTHING IS LIVE =====================
   Tuesday through Saturday the old page rendered "0-0 across 0 leagues", "+0.0 points on the
   day" and "0 of 0 games in progress" over an empty grid. The ask was to make people want to
   come back, and nobody had designed six sevenths of the week. This is a distinct state, not
   an empty version of the live one. */
.offday{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;
  margin-bottom:16px}
.offday .od{padding:15px 17px}
.offday .odl{font-size:var(--fs-micro);text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--dim);font-weight:700;margin-bottom:7px}
.offday .odv{font-size:24px;font-weight:800;letter-spacing:var(--tr-display);line-height:1;
  color:var(--txt);font-variant-numeric:tabular-nums lining-nums}
.offday .ods{font-size:var(--fs-meta);color:var(--dim);margin-top:6px;line-height:1.45}
.offday .odv.warnv{color:var(--warn)}

/* ---- classes the app emits, which used to be inline style attributes ----
   An inline colour beats every rule in this file, so while renderHQ wrote colours onto the
   margin, the glance and the exposure rows, none of the state rules above could reach them.
   Removing the inline styles is the prerequisite for every state colour on this page. */
.pnum.good{color:var(--win)}
.pnum.bad{color:var(--lose)}
.pnum.even{color:var(--dim)}

/* Start/Sit. A forced change and a worthwhile one are different sentences, so they are
   different colours: amber is "you have to", green is "you might want to". */
.alert.forced{border-color:color-mix(in srgb,var(--warn) 45%,transparent)}
.alert.worth{border-color:color-mix(in srgb,var(--win) 40%,transparent)}
.newcount{color:var(--acc-txt);font-weight:700}
.pl .who b.them{color:var(--dim)}
.fp .when .ft,.tdp .when .ft{color:var(--dim);font-weight:700}
.fp .when .ago,.tdp .when .ago{color:var(--acc-txt);font-weight:700}

/* .lg is a <button> now, and a button does not inherit type or box model from the page. */
.lg{font-size:inherit;-webkit-appearance:none;appearance:none;margin:0}

/* ---------- the touchdown feed ----------
   Every touchdown in the NFL this week, and who owns the men involved in each of the user's
   leagues. It sits under Big plays in the same column, because the league scores are the
   reason the page exists and nothing goes above them again.

   NO INLINE COLOUR REACHES THIS BLOCK. Every state below -- yours, free agent, not checked
   yet -- is a class, for the reason written at the top of this file: one style="color:" in
   the JS and none of these rules can reach the element they were written for. */

/* ROWS, NOT PANELS, like the feed above: one line per touchdown, and the ownership is a
   disclosure underneath it. Fourteen touchdowns x two players x six leagues is ~150 rows
   drawn flat, which is a wall rather than a feed. */
.tdp{border-top:1px solid var(--hair)}
.tdp:first-child{border-top:0}

/* A REAL CONTROL: a <button> with aria-expanded, not a div with an onclick, so the panel can
   be opened from the keyboard. Buttons inherit neither type nor box model from the page. */
.tdhead{
  display:grid;grid-template-columns:44px minmax(0,1fr) auto;gap:10px;align-items:baseline;
  width:100%;padding:7px 2px;text-align:left;cursor:pointer;
  background:none;border:0;border-radius:var(--r2);color:inherit;
  font:400 var(--fs-body)/1.35 var(--sans);-webkit-appearance:none;appearance:none;margin:0;
}
.tdhead:hover{background:var(--raised)}
.tdhead:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.tdp .ab{
  font:700 var(--fs-micro)/1.5 var(--sans);letter-spacing:.06em;text-align:center;
  padding:2px 0;border-radius:var(--r2);background:var(--raised);color:var(--dim);
}
.tdp .tdb{min-width:0}
.tdp .who{
  display:block;font-weight:600;font-size:var(--fs-title);color:var(--txt);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tdp .who .txt{font-weight:400;color:var(--dim);font-size:var(--fs-meta);margin-left:7px}
.tdp .when{
  display:block;font-size:var(--fs-micro);color:var(--dim);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tdp .tdt{display:flex;align-items:center;gap:8px;white-space:nowrap}
/* THE DISCLOSURE HAS TO BE VISIBLE. An 11px caret alone reads as a speck of dust and the
   collapsed rows look inert, which buries the answer the panel exists to give. The count
   beside it is both the affordance and the preview of what opening it reveals. */
.tdp .cnt{font-size:var(--fs-micro);color:var(--dim)}
/* Amber, because it is the same fact as the dashed chips and the banner: not an answer yet. */
.tdp .unck{color:var(--warn)}
.tdp .caret{color:var(--acc-txt);font-size:var(--fs-meta);line-height:1}
.tdhead:hover .cnt{color:var(--txt)}

/* THE THING THE EYE SHOULD CATCH FIRST. A touchdown that touches one of the user's teams
   gets a green spine and a green pill; everything else on the row stays grey. */
.tdp.yours{
  border-left:3px solid var(--win);padding-left:8px;margin-left:-11px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--win) 8%,transparent),transparent 42%);
}
.tdp .yrs{
  font:700 var(--fs-micro)/1.4 var(--sans);letter-spacing:var(--tr-caps);text-transform:uppercase;
  padding:2px 7px;border-radius:var(--rp);
  background:color-mix(in srgb,var(--win) 16%,transparent);color:var(--win);
}

/* The ownership panel, indented to line up under the play text rather than the badge. */
.tdo{padding:2px 2px 10px 54px}
.tdo.hidden{display:none}
.tdman{margin-top:8px}
.tdman:first-child{margin-top:2px}
.tdman .nm{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:var(--fs-meta)}
.tdman .nm b{font-weight:600;color:var(--txt)}
.tdman .role{
  font:700 var(--fs-micro)/1.4 var(--sans);letter-spacing:var(--tr-caps);
  text-transform:uppercase;color:var(--dim);
}

/* THE MAN WHO IS ON ONE OF YOUR TEAMS, marked on his own block and not only on the one chip
   out of six that is green. mine_anywhere was already being written onto this element as a
   class and no rule in the file ever claimed it, so the payload's precomputed answer styled
   nothing. On a six-league row the single green chip can wrap to a second line; the spine
   cannot. */
.tdman.yours{
  border-left:2px solid color-mix(in srgb,var(--win) 55%,transparent);
  padding-left:9px;margin-left:-11px;
}

/* ONE LEAGUE, ONE CHIP. Wrapping chips instead of a row per league: six leagues is six lines
   of prose and one line of chips. */
.tdchs{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}
.tdch{
  display:inline-flex;align-items:baseline;gap:6px;max-width:100%;
  padding:3px 8px;border-radius:var(--rp);border:1px solid transparent;
  background:var(--sunk);font-size:var(--fs-micro);line-height:1.5;
}
/* --dim, not --faint: --faint is defined at the top of this file as never being used for
   text below 13px, and .tdch sets 11px. The league name is half of the question the panel
   answers, so it was also the exact wrong thing to render at the floor of legibility. */
.tdch .lgn{color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tdch .tmn{font-weight:700;color:var(--txt);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}

/* GREEN IS THE ANSWER TO THE QUESTION ASKED: "if its their team then the user's team name is
   green". It comes from owners[].mine in the payload, never from matching the name. */
.tdch.yours{
  background:color-mix(in srgb,var(--win) 12%,transparent);
  border-color:color-mix(in srgb,var(--win) 38%,transparent);
}
.tdch.yours .tmn{color:var(--win)}
.tdch.yours .lgn{color:var(--dim)}

/* FREE AGENT and NOT CHECKED YET ARE DIFFERENT FACTS and must never look alike. We read that
   league's rosters and nobody has him -- versus we have not read that league at all. Solid
   and quiet for the first; dashed and amber, with the words on the chip, for the second. */
.tdch.free .tmn{font-weight:400;color:var(--dim)}
.tdch.unread{
  background:none;border-style:dashed;
  border-color:color-mix(in srgb,var(--warn) 55%,transparent);
}
.tdch.unread .tmn{color:var(--warn);font-weight:700}
.tdnone{font-size:var(--fs-micro);color:var(--dim)}

.tdwarn{
  margin:0 0 12px;padding:8px 10px;border-radius:var(--r2);
  font-size:var(--fs-meta);line-height:1.45;color:var(--dim);
  background:color-mix(in srgb,var(--warn) 9%,transparent);
  border:1px solid color-mix(in srgb,var(--warn) 30%,transparent);
}
.tdwarn b{color:var(--warn)}
.tdkey{color:var(--win);font-weight:700}

/* TEN ROWS, THEN A DISCLOSURE -- the same shape as the big-play feed, and for the same
   reason: renderHQ replaces the panel every 25 seconds, so a scroll box would throw the
   reader back to the top twice a minute. The count must match TD_SHOWN in app.html.
   The last rule is deliberate and load-bearing: truncation NEVER hides a touchdown that
   involves the user. Equal specificity throughout, so source order decides. */
.tdfeed .tdp:nth-child(n+11){display:none}
.tdfeed.all .tdp{display:block}
.tdfeed .tdp.yours{display:block}

/* Two cards stacked in the one feed column. */
.hqfeed .card + .card{margin-top:16px}

@media (max-width:620px){
  .tdhead{grid-template-columns:34px minmax(0,1fr) auto;gap:8px}
  .tdo{padding-left:14px}
  /* The right-hand column is nowrap, so every character it gains is taken from the play
     text. On a phone the banner at the top of the card already names the unread leagues. */
  .tdp .unck{display:none}
  .tdman.yours{margin-left:0;padding-left:7px}
}

/* ===================== COLLAPSIBLE SECTIONS =====================
 *
 * "i want each section collapsible ... there is a lot of scrolling particularly for the
 *  touchdown scorers, big plays, etc. i also want to have the option to turn on/off
 *  notifications for each section right there with a toggle."
 *
 * ONE HEADER SHAPE for every panel on the page: caret, name, and the count that has to
 * survive collapsing, then the alert switch on the right where a switch is meaningful. The
 * markup comes from one function (secCard) so there is exactly one of these to style.
 *
 * THE WHOLE HEADER IS THE CONTROL. .sectitle is a button that fills the row beside the
 * switch, so the tap target is the full width of the card rather than an 11px caret glyph --
 * which on a phone is the difference between a control and a decoration. No colour is
 * written inline anywhere in the JS that builds this; an inline colour would beat every rule
 * in this file and silently disable the on/off states below, which is the failure the first
 * assertion of test_hq_visual.js exists to catch.
 */
.sec{min-width:0}
.sec.card{padding:12px 18px 16px}
.sec.card.shut{padding:6px 18px}
.sechead{display:flex;align-items:center;gap:10px;min-width:0}
.sectitle{
  flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:9px;
  background:none;border:0;margin:0;padding:8px 0;color:var(--txt);font:inherit;
  cursor:pointer;text-align:left;border-radius:var(--r2);
}
/* The caret is the only thing on the row that says which way the section is, so it gets a
   fixed column and a real glyph rather than an 11px speck. */
.sectitle .caret{flex:0 0 auto;width:13px;text-align:center;color:var(--dim);
  font-size:var(--fs-micro);line-height:1}
.sectitle .snm{flex:0 0 auto;font-size:14.5px;font-weight:700;letter-spacing:0;
  color:var(--txt)}
/* THE COUNT, which is the whole reason a shut section is still worth having on the page.
   It ellipsises rather than wrapping, so a long one cannot push the switch off the row. */
.sectitle .scount{flex:1 1 auto;min-width:0;font-size:var(--fs-meta);color:var(--dim);
  font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sectitle:hover .caret{color:var(--acc-txt)}
.secbody{min-width:0}
.sec.shut .secbody{display:none}
/* A section with no card around it still needs its header to read as a header. */
.sec.plain > .sechead{border-bottom:1px solid var(--hair);margin-bottom:12px}
.sec.plain.shut > .sechead{margin-bottom:0;border-bottom:0}
.sec.sumsec > .sechead{margin-bottom:10px}
.sec.sumsec .glance{margin-bottom:0}
.hqhead .sec.sumsec{flex:1 1 520px;min-width:0;margin-bottom:0}
.sec.nsc{margin-top:16px}
/* The rail keeps its own sticky chrome; only its heading becomes the shared control. */
.sec.sb > .sechead{margin-bottom:0;padding:2px 14px;background:var(--sunk);
  border-bottom:1px solid var(--line)}
.sec.sb.shut > .sechead{border-bottom:0}
.sec.sb .sectitle .snm{font-size:var(--fs-micro);text-transform:uppercase;
  letter-spacing:var(--tr-caps);color:var(--dim)}

/* ---------- the notification switch, ON the section it governs ----------
 *
 * Only Big plays, Touchdowns and All plays render one, because only those three drive an
 * alert. Scoreboard, Your matchups and Exposure get a caret and nothing else: a switch that
 * changes nothing is worse than no switch, since it teaches the reader that the switches on
 * this page are decoration.
 *
 * .pend is NOT NEUTRAL STYLING FOR "OFF". It is the state before /api/telegram has answered,
 * and it is disabled and dimmed rather than drawn as off, because a switch showing the wrong
 * side leaves the user waiting for an alert that is never coming. Same reason .err exists:
 * an optimistic flip that did not reach the server goes back, visibly.
 */
.secbell{
  display:inline-flex;align-items:center;gap:8px;flex:0 0 auto;white-space:nowrap;
  background:var(--sunk);border:1px solid var(--line2);border-radius:var(--rp);
  padding:5px 11px 5px 6px;cursor:pointer;color:var(--dim);
  font:700 var(--fs-micro)/1.4 var(--sans);letter-spacing:.05em;text-transform:uppercase;
}
.secbell:hover{border-color:var(--acc);color:var(--txt)}
.secbell .track{position:relative;flex:0 0 auto;width:28px;height:16px;
  border-radius:var(--rp);background:var(--raised);border:1px solid var(--line2)}
.secbell .knob{position:absolute;top:1px;left:1px;width:12px;height:12px;border-radius:50%;
  background:var(--faint);transition:transform .14s ease,background .14s ease}
.secbell.on{color:var(--win);
  background:color-mix(in srgb,var(--win) 12%,transparent);
  border-color:color-mix(in srgb,var(--win) 45%,transparent)}
.secbell.on .track{background:color-mix(in srgb,var(--win) 30%,transparent);
  border-color:color-mix(in srgb,var(--win) 55%,transparent)}
.secbell.on .knob{transform:translateX(12px);background:var(--win)}
.secbell.pend{opacity:.5;cursor:default}
.secbell.busy{opacity:.72}
.secbell.err{color:var(--warn);
  background:color-mix(in srgb,var(--warn) 12%,transparent);
  border-color:color-mix(in srgb,var(--warn) 50%,transparent)}
.secbell.err .knob{background:var(--warn)}
@media (prefers-reduced-motion:reduce){ .secbell .knob{transition:none} }

/* ---------- every single play ----------
 * Twelve rows, then a disclosure -- the same shape as the other two feeds and for the same
 * reason: renderHQ replaces the panel every 25 seconds, so a scroll box would throw the
 * reader back to the top twice a minute. The count must match AP_SHOWN in app.html. */
.apfeed .fp:nth-child(n+13){display:none}
.apfeed.all .fp{display:grid}
/* TIER 1 IS THE NORM HERE, NOT THE EXCEPTION. In the big-play feed a single-team play is
   one row in six and dimming it ranks the page; in this one it is most of two hundred, and
   dimming it is just a wall of low-contrast 11px text. The tier still reads off the size and
   colour of the number on the right. */
.apfeed .fp.t1{opacity:1}

@media (max-width:620px){
  .sec.card{padding:10px 14px 14px}
  .sec.card.shut{padding:4px 14px}
  .sectitle{gap:7px}
  .sectitle .snm{font-size:13.5px}
  /* The switch keeps its track and loses its word before the header wraps: the track is the
     part that has to stay tappable, and the title beside it already says what it governs. */
  .secbell .bt{display:none}
  .secbell{padding:5px 6px}
}
