/* ============================================================
   App shell — the part clients use every day.
   Loads after site.css and only adds what the app needs.
   ============================================================ */

body.app{display:flex; flex-direction:column; min-height:100vh}

/* ---------- top bar: channel switcher + account ---------- */
.app-top{
  display:flex; align-items:center; gap:14px; padding:11px var(--gut);
  border-bottom:1px solid var(--line); background:var(--void);
  position:sticky; top:0; z-index:50;
}
.app-top .brand{margin-right:6px}
.app-top .divider{width:1px; height:24px; background:var(--line); flex:none}

.chan{
  display:flex; align-items:center; gap:10px; background:transparent; border:1px solid transparent;
  color:var(--chalk); cursor:pointer; padding:5px 9px 5px 5px; border-radius:3px;
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; text-transform:uppercase;
  letter-spacing:.05em; font-size:17px; transition:border-color .2s;
}
.chan:hover{border-color:var(--line)}
.chan .caret{font-size:10px; color:var(--ash-dim); font-family:var(--f-body)}
.chan-wrap{position:relative}
.chan-menu{
  position:absolute; left:0; top:calc(100% + 4px); z-index:60; min-width:260px;
  background:var(--carbon-2); border:1px solid var(--line); border-radius:3px;
  box-shadow:var(--shadow); padding:5px; display:none;
}
.chan-wrap.open .chan-menu{display:block}
.chan-opt{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  background:transparent; border:0; color:var(--ash); cursor:pointer;
  padding:9px 10px; border-radius:2px; font-size:13.5px; font-family:var(--f-body);
}
.chan-opt:hover{background:color-mix(in srgb,var(--chalk) 5%, transparent); color:var(--chalk)}
.chan-opt.on{color:var(--chalk)}
.chan-opt.on::after{content:"●"; margin-left:auto; color:var(--red); font-size:9px}
.chan-opt em{font-style:normal; display:block; font-family:var(--f-mono); font-size:10px; color:var(--ash-dim); letter-spacing:.05em}

.app-user{margin-left:auto; display:flex; align-items:center; gap:10px; min-width:0}
.app-user .who{
  font-family:var(--f-mono); font-size:10.5px; color:var(--ash-dim); letter-spacing:.06em;
  text-align:right; line-height:1.4; min-width:0; overflow:hidden;
}
.app-user .who b{display:block; color:var(--ash); font-weight:400; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:24ch}
.avatar{
  width:28px; height:28px; border-radius:50%; flex:none; display:grid; place-items:center;
  background:linear-gradient(150deg, var(--red), #7a0b18); color:#fff;
  font-family:var(--f-mono); font-size:10px; font-weight:700; border:1px solid var(--line);
}
@media (max-width:720px){
  .app-user .who{display:none}
  .app-top{gap:10px}
  .chan{font-size:15px}
  .app-top .brand-name{display:none}
}

/* the public switch: the control IS the state, so it is read before the
   sentence underneath rather than after it */
.pub-switch{display:flex; align-items:center; gap:13px; margin:0 0 14px}
.tgl{
  width:46px; height:26px; flex:none; padding:0; border:0; background:none;
  cursor:pointer; border-radius:999px; line-height:0;
}
.tgl-track{
  display:block; width:100%; height:100%; border-radius:999px; position:relative;
  background:var(--carbon-2); border:1px solid var(--line);
  transition:background .18s, border-color .18s;
}
.tgl-knob{
  position:absolute; top:50%; left:3px; transform:translateY(-50%);
  width:18px; height:18px; border-radius:50%; background:var(--ash-dim);
  transition:left .18s, background .18s;
}
.tgl[aria-checked="true"] .tgl-track{background:var(--amber); border-color:var(--amber)}
.tgl[aria-checked="true"] .tgl-knob{left:calc(100% - 21px); background:var(--void)}
.tgl:disabled{opacity:.5; cursor:progress}
.tgl:focus-visible{outline:2px solid var(--red); outline-offset:3px}
.tgl-txt{font-size:13.5px; color:var(--chalk); line-height:1.4}
.tgl-txt em{
  display:block; font-style:normal; font-family:var(--f-mono); font-size:10.5px;
  letter-spacing:.06em; color:var(--ash-dim);
}
.tgl[aria-checked="true"] + .tgl-txt em{color:var(--amber)}

.pub-now{font-size:13.5px; color:var(--ash); margin:0 0 14px; max-width:64ch; line-height:1.6}
.pub-now.on{color:var(--chalk)}
.pub-now.on::before{
  content:""; display:inline-block; width:7px; height:7px; border-radius:50%;
  background:var(--amber); margin-right:9px; vertical-align:middle;
}

/* ---------- body: sidebar + view ---------- */
/* One number is the whole rail, so pulling it in is a change to --rail and
   nothing else: the track, the labels and the padding all read from it. */
body.app{--rail:196px}
body.app.rail-in{--rail:56px}
.app-body{
  display:grid; grid-template-columns:var(--rail) minmax(0,1fr); flex:1; min-height:0;
  transition:grid-template-columns .24s cubic-bezier(.2,.7,.2,1);
}
@media (max-width:860px){ .app-body{grid-template-columns:minmax(0,1fr); transition:none} }
@media (prefers-reduced-motion:reduce){ .app-body{transition:none} }

/* A column, so the one link that leaves the app can sit at the foot of
   the rail however short the page above it is. */
.side{
  border-right:1px solid var(--line); padding:16px 0; background:var(--carbon);
  align-self:start; position:sticky; top:57px;
  display:flex; flex-direction:column; min-height:calc(100vh - 57px);
  overflow-x:hidden;                       /* the label is clipped, not wrapped, on the way in */
}
.side-foot{margin-top:auto; padding-top:16px; border-top:1px solid var(--line-soft)}
.side-out{color:var(--ash-dim)}
.side-out:hover{color:var(--chalk)}
/* The word Menu and the handle that pulls the rail share a line; pulled in,
   the word goes and the handle takes the middle. Both are stated before the
   860px block, which takes the whole line away with the rail it belongs to. */
.side-grp{
  display:flex; align-items:center; gap:8px;
  font-family:var(--f-mono); font-size:9.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ash-dim); padding:14px 12px 7px 18px;
}
.side-grp-t{flex:1; min-width:0; overflow:hidden}
.side-pull{
  flex:none; width:24px; height:24px; padding:0; display:grid; place-items:center;
  background:transparent; border:1px solid transparent; border-radius:2px;
  color:var(--ash-dim); cursor:pointer; transition:color .18s, border-color .18s, background .18s;
}
.side-pull svg{width:14px; height:14px; display:block; transition:transform .24s cubic-bezier(.2,.7,.2,1)}
.side-pull:hover{color:var(--chalk); border-color:var(--line); background:var(--carbon-2)}
@media (max-width:860px){
  .side{
    position:static; border-right:0; border-bottom:1px solid var(--line);
    flex-direction:row; align-items:center; min-height:0;
    gap:4px; overflow-x:auto; padding:10px var(--gut);
  }
  /* the handle goes with it: a row across the top has no width to give back */
  .side-grp{display:none}
  .side-foot{margin-top:0; margin-left:auto; padding-top:0; border-top:0; flex:none}
}

.side a{
  display:flex; align-items:center; gap:10px; padding:9px 18px; font-size:13.5px;
  color:var(--ash); text-decoration:none; border-left:2px solid transparent;
  transition:all .18s; cursor:pointer; white-space:nowrap;
}
.side a:hover{color:var(--chalk); background:color-mix(in srgb,var(--chalk) 4%, transparent)}
.side a.on{color:var(--chalk); border-left-color:var(--red); background:color-mix(in srgb,var(--red) 10%, transparent)}
/* Every entry carries its own mark, because pulled in the mark is all there is */
.side a i{width:18px; height:18px; flex:none; display:block; opacity:.72}
.side a i svg{width:18px; height:18px; display:block}
.side a.on i, .side a:hover i{opacity:1}
.side a span{min-width:0; overflow:hidden; text-overflow:ellipsis}
@media (max-width:860px){
  .side a{border-left:0; border-bottom:2px solid transparent; padding:8px 12px; border-radius:2px}
  .side a.on{border-left:0; border-bottom-color:var(--red)}
}

/* ---------- the rail pulled in ----------
   Only where there is a rail to pull. Below 860px it is already a row across
   the top with no width to give back, so a state left over from a desktop
   visit must not reach it and strip the names off it. */
@media (min-width:861px){
  body.rail-in .side-grp{padding-left:0; padding-right:0; justify-content:center}
  body.rail-in .side-grp-t{display:none}
  /* the chevron points the way the rail will go next */
  body.rail-in .side-pull svg{transform:scaleX(-1)}
  /* centred rather than padded, so the mark stays on the middle of the strip
     whatever the mark's own size is */
  body.rail-in .side a{padding-left:0; padding-right:0; gap:0; justify-content:center}
  body.rail-in .side a span{display:none}
}

.view{padding:clamp(18px,2.6vw,28px) var(--gut) 64px; min-width:0}
.view-head{display:flex; align-items:flex-end; gap:16px; flex-wrap:wrap; margin-bottom:20px}
.view-head h1{
  margin:0; font-family:var(--f-display); font-stretch:87.5%; font-weight:700;
  text-transform:uppercase; letter-spacing:.03em; font-size:clamp(20px,2.4vw,26px); line-height:1.15;
  display:flex; align-items:center; gap:10px;
}
.view-head .sub{font-family:var(--f-mono); font-size:11px; color:var(--ash-dim); letter-spacing:.06em}
.view-head .right{margin-left:auto; display:flex; gap:8px; flex-wrap:wrap}
.back{
  background:none; border:0; color:var(--ash); font-size:12.5px; cursor:pointer;
  padding:0; margin-bottom:12px; display:inline-flex; align-items:center; gap:7px;
}
.back:hover{color:var(--red)}

/* ---------- match list ---------- */
.mlist{display:flex; flex-direction:column}
/* Date, home, score, away, result — five columns, so a scoreline sits under
   the words that name it and each side can be read straight down.

   The five read as a mirror about the score: date and result are the same
   track, home and away are the same track. That is what puts the scoreline on
   the middle of the row rather than 143px right of it, which is where a fixed
   92px result column left it — and with the fixture off centre, the void after
   the date came out half as wide again as the one before the result. */
.mlist-h,.mrow{
  --m-cols:minmax(150px,1.1fr) minmax(140px,1.3fr) 96px minmax(140px,1.3fr) minmax(150px,1.1fr);
}
.mlist-h{
  display:grid; grid-template-columns:var(--m-cols);
  gap:14px; padding:0 4px 10px; border-bottom:1px solid var(--line);
  font-family:var(--f-mono); font-size:9.5px; letter-spacing:.16em; text-transform:uppercase; color:var(--ash-dim);
}
.mrow{
  display:grid; grid-template-columns:var(--m-cols);
  gap:14px; align-items:center; padding:14px 4px; border-bottom:1px solid var(--line-soft);
  cursor:pointer; transition:background .18s; text-align:left; width:100%;
  background:transparent; border-left:0; border-right:0; border-top:0; color:inherit; font:inherit;
}
.mrow:hover{background:color-mix(in srgb,var(--chalk) 4%, transparent)}
.mrow:last-child{border-bottom:0}
.m-date{font-size:13px; color:var(--chalk); line-height:1.45}
.m-date em{display:block; font-style:normal; font-family:var(--f-mono); font-size:10.5px; color:var(--ash-dim); letter-spacing:.06em}
.m-team{display:flex; align-items:center; gap:9px; min-width:0; font-size:13.5px}
.m-team .tn{color:var(--ash); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.m-team .tn.us{color:var(--chalk); font-weight:600}
/* The home name reads right, into the score; the away name reads left, out of
   it, so the fixture is balanced either side of the scoreline. Left-aligning
   both put the home name a column's width away from the score and the away
   name right against it. */
.m-home{justify-content:flex-end; text-align:right}
.m-away{justify-content:flex-start; text-align:left}
.m-sc{display:flex; align-items:center; justify-content:center}
.m-score{
  font-family:var(--f-mono); font-variant-numeric:tabular-nums; font-weight:700; font-size:13px;
  background:var(--carbon-2); border:1px solid var(--line); border-radius:2px; padding:3px 10px;
  color:var(--chalk); letter-spacing:.06em; white-space:nowrap;
}
.m-end{display:flex; align-items:center; justify-content:flex-end; gap:10px}
.m-open{
  width:24px; height:24px; border-radius:50%; border:1px solid var(--line); background:transparent;
  display:grid; place-items:center; color:var(--ash); flex:none; transition:all .2s;
}
.mrow:hover .m-open{border-color:var(--red); color:var(--red)}
/* Narrow: the date and the result keep the top line to themselves and the
   fixture folds under them, still reading home · score · away. */
@media (max-width:820px){
  .mlist-h{display:none}
  .mrow{
    grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
    grid-template-areas:"date date end" "home score away";
    row-gap:10px; column-gap:10px;
  }
  .m-date{grid-area:date}
  .m-end{grid-area:end}
  /* the score is the middle column of three, so the two names lean into it
     here exactly as they do on the wide row */
  .m-home{grid-area:home}
  .m-sc{grid-area:score}
  .m-away{grid-area:away}
}

/* ---------- roster / contributor cards ---------- */
.people{display:grid; gap:12px; grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.person{
  border:1px solid var(--line); border-radius:3px; background:var(--carbon-2);
  padding:14px 16px; display:grid; gap:8px;
}
.person .top{display:flex; align-items:center; gap:10px}
.person .nm{font-size:15px; color:var(--chalk); font-weight:600}
.person .ct{margin-left:auto; font-family:var(--f-mono); font-size:11px; color:var(--ash-dim)}
.person .dt{font-size:12.5px; color:var(--ash); line-height:1.5}
.person .gz{display:flex; gap:14px; font-family:var(--f-mono); font-size:11px; color:var(--ash-dim)}
.person .gz b{color:var(--red); font-size:15px; font-family:var(--f-display); font-stretch:87.5%}

/* ---------- generic states ---------- */
.state{
  border:1px dashed var(--line); border-radius:3px; padding:clamp(26px,4vw,46px);
  text-align:center; color:var(--ash); background:var(--carbon);
}
.state b{
  display:block; font-family:var(--f-display); font-stretch:87.5%; text-transform:uppercase;
  letter-spacing:.04em; color:var(--chalk); font-size:18px; margin-bottom:10px;
}
.state p{margin:0 auto; max-width:56ch; font-size:14px}
.state .btn{margin-top:18px}

.spinner{
  width:22px; height:22px; border-radius:50%; border:2px solid var(--line);
  border-top-color:var(--red); animation:spin .8s linear infinite; margin:0 auto 14px;
}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------- Data: Overview / Team Data ----------
   The top bar is a rule with the live section sitting on it, so the two
   sections read as two states of one page and not as two pages. */
.dtabs{display:flex; gap:4px; margin:0 0 22px; border-bottom:1px solid var(--line)}
.dtab{
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; font-size:14px; color:var(--ash-dim); background:transparent;
  border:0; border-bottom:2px solid transparent; margin-bottom:-1px;
  padding:10px 18px; cursor:pointer; transition:color .16s, border-color .16s;
}
.dtab:hover{color:var(--chalk)}
.dtab.on{color:var(--chalk); border-bottom-color:var(--red)}
.dsubs{display:flex; flex-wrap:wrap; gap:7px; margin:0 0 16px}
.dbody{min-width:0}
/* six tiles, so they wrap 6 / 3 / 2 and never leave a part-empty row —
   auto-fit sized them by the widest label and stranded the last one */
.kpis.six{grid-template-columns:repeat(6,minmax(0,1fr))}
@media (max-width:1100px){ .kpis.six{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:560px){ .kpis.six{grid-template-columns:repeat(2,minmax(0,1fr))} }

/* ---------- Data: team stats and recent results ----------
   .dcol is the Channel view's stack of cards; the Data view had one too,
   beside a pitch, and both went when the formation card did. */
.dcol{display:flex; flex-direction:column; gap:14px; min-width:0}

.stat-card{margin-bottom:14px}
/* Both rows are the same four columns, so Average goals scored sits under Total
   and every value below reads down a column. The second row asked for three and
   nothing in it lined up with anything above it. */
.tstats{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:0 22px}
.tstats.sec{margin-top:18px}
.tstat{padding:2px 0 0; min-width:0}
/* The rule belongs to the label, not to the cell: it stops at the column it
   measures rather than running the width of the card. */
.ts-l{
  display:block; font-size:12px; color:var(--ash); line-height:1.5;
  padding-bottom:7px; margin-bottom:9px; border-bottom:1px solid var(--line);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.ts-v{
  display:block; font-family:var(--f-display); font-stretch:87.5%; font-weight:700;
  font-size:26px; line-height:1; font-variant-numeric:tabular-nums; color:var(--chalk);
}
@media (max-width:520px){
  .tstats{grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:18px}
  .tstats.sec{margin-top:18px}
}

/* one row per result: how it went, who played whom, what it finished, when.
   The home side reads left-to-right into the score and the away side out of
   it, so a column can be read down for every home team or every scoreline. */
.res-card{margin-bottom:20px}
.rlist{display:flex; flex-direction:column}
/* The two end cells are the same width — the result on one, the date and the
   chevron on the other — so the pair of scores lands on the middle of the row
   and the fixture reads as one block centred on it, whatever the date says. */
.rrow{
  display:grid; grid-template-columns:92px minmax(0,1fr) 26px 26px minmax(0,1fr) 92px;
  gap:9px; align-items:center; width:100%; text-align:left; cursor:pointer;
  background:transparent; border:0; border-bottom:1px solid var(--line-soft);
  color:inherit; font:inherit; padding:10px 2px; transition:background .16s;
}
.rrow:last-child{border-bottom:0}
.rrow:hover{background:color-mix(in srgb,var(--chalk) 4%, transparent)}
.rrow .rres{display:flex; align-items:center}
.rrow .rend{display:flex; align-items:center; justify-content:flex-end; gap:8px; min-width:0}
/* min-width:0 is what lets a long club name ellipsis rather than push the
   scoreline off the middle of the row */
.rrow .rn{font-size:13px; color:var(--ash); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.rrow .rn.us{color:var(--chalk); font-weight:600}
/* home reads right, into the score; away reads left, out of it */
.rrow .rn-h{text-align:right}
.rrow .rn-a{text-align:left}
.rrow .rsc{
  font-family:var(--f-mono); font-variant-numeric:tabular-nums; font-weight:700; font-size:12.5px;
  background:var(--carbon); border:1px solid var(--line); border-radius:2px;
  padding:2px 0; text-align:center; color:var(--chalk);
}
.rrow .rd{font-family:var(--f-mono); font-size:10px; color:var(--ash-dim); white-space:nowrap; letter-spacing:.04em}
.rrow .m-open{opacity:0; flex:none; transition:opacity .16s, border-color .16s, color .16s}
.rrow:hover .m-open{opacity:1; border-color:var(--red); color:var(--red)}
@media (max-width:640px){
  /* the date goes, and with it the reason the end cells were 92px — they stay
     equal to each other, which is what keeps the score centred */
  .rrow{grid-template-columns:24px minmax(0,1fr) 24px 24px minmax(0,1fr) 24px; gap:7px}
  .rrow .rd{display:none}
}

/* ---------- Data: key players ----------
   The three questions a club asks first, one card each. The shirt number
   stands in for the portrait these cards carry elsewhere — this site holds
   no photographs of anybody. */
/* three, always three — auto-fit would drop to two at laptop width and
   leave the third stranded under a hole */
.kp-grid{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; margin-bottom:20px}
@media (max-width:820px){ .kp-grid{grid-template-columns:minmax(0,1fr)} }
.kp{
  border:1px solid var(--line); border-radius:3px; background:var(--carbon-2);
  min-width:0; overflow:hidden;
}
.kp-h{
  display:flex; align-items:center; gap:8px; margin:0; padding:12px 14px;
  border-bottom:1px solid var(--line-soft);
  font-family:var(--f-mono); font-size:9.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ash-dim);
}
.kp-b{display:flex; align-items:center; gap:12px; padding:15px 14px}
.kp-av{
  width:42px; height:42px; flex:none; border-radius:50%; display:grid; place-items:center;
  background:linear-gradient(155deg,var(--red),#7C0A1B); color:#fff;
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; font-size:16px;
  font-variant-numeric:tabular-nums; box-shadow:0 0 0 1px rgba(255,255,255,.08);
}
.kp-n{font-size:14.5px; color:var(--chalk); min-width:0; overflow:hidden}
.kp-n em{
  display:block; font-style:normal; margin-top:4px;
  font-family:var(--f-mono); font-size:9.5px; letter-spacing:.07em; color:var(--ash-dim);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.kp-v{
  margin-left:auto; padding-left:8px; color:var(--red);
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; font-size:30px;
  line-height:1; font-variant-numeric:tabular-nums;
}
.kp.none .kp-av{background:var(--carbon); color:var(--ash-dim); box-shadow:0 0 0 1px var(--line)}
.kp.none .kp-n{color:var(--ash)}
.kp.none .kp-v{color:var(--ash-dim); font-size:24px}

/* ---------- Data: the per-match table ----------
   Wide on purpose — a category is a lot of columns — so it scrolls sideways
   inside its own frame and the two columns that say WHICH match this is stay
   put while it does. */
.stbl-wrap{
  overflow-x:auto; border:1px solid var(--line); border-radius:3px;
  background:var(--carbon-2); margin-bottom:14px;
}
table.stbl{border-collapse:separate; border-spacing:0; width:100%; font-size:12.5px; font-variant-numeric:tabular-nums}
table.stbl th{
  font-family:var(--f-mono); font-size:9px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ash-dim); font-weight:400; white-space:nowrap; text-align:right;
  vertical-align:bottom; padding:11px 12px; background:var(--carbon);
  border-bottom:1px solid var(--line);
}
/* a header that spans a run of columns: centred over them, and boxed off so
   the run reads as one thing */
table.stbl th.gh{
  text-align:center; color:var(--ash); letter-spacing:.16em; padding-bottom:7px;
  border-bottom:1px solid var(--line-soft);
  border-left:1px solid var(--line-soft); border-right:1px solid var(--line-soft);
}
table.stbl td{
  padding:12px; text-align:right; white-space:nowrap; color:var(--ash);
  border-bottom:1px solid var(--line-soft);
}
table.stbl tbody tr:hover td{background:color-mix(in srgb,var(--chalk) 4%, transparent)}
table.stbl tbody tr[data-go]{cursor:pointer}

table.stbl .c-date{
  position:sticky; left:0; z-index:2; text-align:left; width:104px; min-width:104px;
  font-family:var(--f-mono); font-size:11px; letter-spacing:.02em; color:var(--ash-dim);
}
table.stbl .c-opp{position:sticky; left:104px; z-index:2; text-align:left; min-width:178px}
table.stbl thead .c-date, table.stbl thead .c-opp{z-index:4}
table.stbl tbody .c-date, table.stbl tbody .c-opp{background:var(--carbon-2)}
table.stbl tbody tr:hover .c-date, table.stbl tbody tr:hover .c-opp{background:#1A1516}
/* the edge of the frozen block, so scrolled columns pass behind something */
table.stbl .c-opp::after{content:""; position:absolute; top:0; right:0; bottom:0; width:1px; background:var(--line)}
.stbl .cop{display:flex; align-items:center; gap:9px; min-width:0}
.stbl .cop b{font-weight:600; color:var(--chalk); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.stbl .cop em{
  flex:none; font-style:normal; font-family:var(--f-mono); font-size:9px; letter-spacing:.1em;
  color:var(--ash-dim); border:1px solid var(--line); border-radius:2px; padding:1px 5px;
}
table.stbl .c-res{text-align:center}
table.stbl td.c-res .res{margin:0 auto}
table.stbl .c-sc{
  text-align:center; color:var(--chalk);
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; font-size:14.5px;
}
table.stbl thead .c-sc{
  font-family:var(--f-mono); font-size:9px; font-weight:400; color:var(--ash-dim);
}
table.stbl tbody tr:last-child td{border-bottom:0}

/* Player Data's list freezes the same way, on the one column that says whose
   row you are reading — his name. There is no shirt column beside it: a number
   belongs to a match, not to a man, and a squad is renumbered between windows. */
table.stbl .c-pl{position:sticky; left:0; z-index:2; text-align:left; min-width:184px}
table.stbl thead .c-pl{z-index:4}
table.stbl tbody .c-pl{background:var(--carbon-2)}
table.stbl tbody tr:hover .c-pl{background:#1A1516}
table.stbl .c-pl::after{content:""; position:absolute; top:0; right:0; bottom:0; width:1px; background:var(--line)}
table.stbl .c-pl b{font-weight:600; color:var(--chalk)}
table.stbl tbody tr[data-who]{cursor:pointer}

/* what the campaign came to, under the matches it came from */
table.stbl tfoot td{
  padding:12px; text-align:right; white-space:nowrap; color:var(--chalk);
  background:var(--carbon); border-top:1px solid var(--line);
  font-family:var(--f-mono); font-size:11.5px;
}
table.stbl tfoot .c-date{
  position:sticky; left:0; z-index:2; text-align:left; background:var(--carbon);
  letter-spacing:.1em; text-transform:uppercase; font-size:9px; color:var(--ash-dim);
}
table.stbl tfoot .c-opp{position:sticky; left:104px; z-index:2; text-align:left; background:var(--carbon)}
/* on a phone there is not enough width left over to freeze two columns in —
   true of the match table's date and opponent, and of the player list's
   shirt and name alike */
@media (max-width:720px){
  table.stbl .c-date, table.stbl .c-opp{position:static}
  table.stbl .c-pl{position:static}
  table.stbl tfoot .c-date, table.stbl tfoot .c-opp{position:static}
  table.stbl .c-opp::after, table.stbl .c-pl::after{display:none}
}

/* the two halves of the list, each under its own heading */
.pl-sec{margin-bottom:20px}
.pl-sec .card-h{margin-bottom:9px}

/* ---------- one player ---------- */
.pl-head{margin-bottom:14px}
.pl-id{display:flex; align-items:center; gap:13px; flex-wrap:wrap}
/* the one thing about a player that does not change from week to week — his
   number does, which is why there is no badge carrying one */
.pl-role{
  flex:none; font-family:var(--f-mono); font-size:9.5px; letter-spacing:.14em;
  color:var(--amber); border:1px solid var(--amber); border-radius:2px; padding:2px 6px;
}
.pl-role.sm{font-size:8.5px; padding:1px 4px; letter-spacing:.1em; margin-left:6px}
.pl-nm{
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; font-size:23px;
  color:var(--chalk); letter-spacing:-.01em; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.pl-id .menu-wrap{margin-left:auto}
.pl-id .menu{max-height:52vh; overflow-y:auto}
.pl-id .menu-opt.on{color:var(--chalk)}
.pl-id .menu-opt.on::after{content:"●"; float:right; color:var(--red); font-size:9px}
.pl-meta{
  margin:12px 0 0; font-family:var(--f-mono); font-size:10.5px; letter-spacing:.06em;
  color:var(--ash-dim);
}

/* ---------- one match ---------- */
/* The mounted Stats view brings its own stylesheet (Stats/stats-view.css) and
   the tagging app's tokens with it. Both are class-scoped, so all this has to
   do is give them somewhere to sit. */
.pt-stats{min-width:0}
.pt-stats-bar{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding-bottom:14px; margin-bottom:14px; border-bottom:1px solid var(--line);
}
.pt-stats-bar .pt-exports{margin-left:auto}
.pt-stats .stats-wrap{max-height:none}

/* ---------- the shooting map on a match page ---------- */
.shot-card{margin-top:16px}
.sm-wrap{display:grid; grid-template-columns:minmax(0,1.15fr) minmax(230px,.85fr); gap:20px; align-items:start}
@media (max-width:820px){ .sm-wrap{grid-template-columns:minmax(0,1fr)} }
.sm-pitch{background:#142b18; border:1px solid var(--line); border-radius:2px; padding:6px 6px 2px}
.sm-pitch svg{width:100%; height:auto; display:block; max-height:60vh}
.sm-pitch .lines{fill:none; stroke:rgba(255,255,255,.85); stroke-width:3}
.sm-pitch .lines .spot{fill:#fff; stroke:none}
.sm-pitch .lines .goal{fill:rgba(255,255,255,.18)}
.sm-dirn{
  margin:6px 0 4px; text-align:center; font-family:var(--f-mono); font-size:9.5px;
  color:var(--ash-dim); letter-spacing:.06em;
}
.sm-side{display:flex; flex-direction:column; gap:12px; min-width:0}
.sm-legend{display:flex; flex-direction:column; gap:7px; font-size:12px; color:var(--ash)}
.sm-legend span{display:flex; align-items:center; gap:8px}
.sm-legend i, .sl-o i{width:10px; height:10px; border-radius:50%; flex:none; display:inline-block}
.sl{display:flex; flex-direction:column; max-height:44vh; overflow:auto; border-top:1px solid var(--line-soft)}
.sl-row{
  display:grid; grid-template-columns:26px 34px auto minmax(0,1fr); gap:8px; align-items:center;
  padding:7px 2px; border-bottom:1px solid var(--line-soft); font-size:12.5px;
}
.sl-row:last-child{border-bottom:0}
.sl-i{font-family:var(--f-mono); font-size:10px; color:var(--ash-dim); text-align:right}
.sl-t{font-family:var(--f-mono); font-size:11px; color:var(--ash); font-variant-numeric:tabular-nums}
.sl-row .shirt{margin-right:0}
.sl-o{display:flex; align-items:center; gap:7px; color:var(--ash); min-width:0}

/* ---------- Channel: the list, its members, the new-channel form ---------- */
.clist{display:flex; flex-direction:column; border-top:1px solid var(--line-soft)}
.crow{
  display:flex; align-items:center; gap:12px; width:100%; text-align:left; cursor:pointer;
  background:transparent; border:0; border-bottom:1px solid var(--line-soft);
  color:inherit; font:inherit; padding:14px 4px; transition:background .16s;
}
.crow:hover{background:color-mix(in srgb,var(--chalk) 4%, transparent)}
.crow .cn{font-size:15px; color:var(--chalk); min-width:0}
.crow .cn em{
  display:block; font-style:normal; font-family:var(--f-mono); font-size:10px;
  color:var(--ash-dim); letter-spacing:.06em; margin-top:3px;
}
.crow .cgo{margin-left:auto; color:var(--ash-dim); font-size:19px; line-height:1}
.crow:hover .cgo{color:var(--red)}

.tag-you{
  font-family:var(--f-mono); font-size:9px; letter-spacing:.1em; text-transform:uppercase;
  border:1px solid var(--line); border-radius:2px; padding:2px 6px; color:var(--ash-dim); margin-left:6px;
}
.rsel, .inv-form select{
  background:var(--void); border:1px solid var(--line); border-radius:2px; color:var(--chalk);
  padding:5px 7px; font-family:var(--f-body); font-size:12px; cursor:pointer;
}
.rsel:focus, .inv-form select:focus, .inv-form input:focus{outline:none; border-color:var(--red)}
.lnk-rm{
  background:none; border:0; padding:0; cursor:pointer; color:var(--ash-dim);
  font-family:var(--f-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
}
.lnk-rm:hover{color:var(--red)}
.lnk-rm[disabled]{opacity:.5; cursor:not-allowed}

.inv-form{display:flex; gap:8px; flex-wrap:wrap}
.inv-form input[type=email]{
  flex:1; min-width:180px; background:var(--void); border:1px solid var(--line); border-radius:2px;
  color:var(--chalk); padding:9px 11px; font-size:13.5px; font-family:var(--f-body);
}
.invs{display:flex; flex-direction:column; margin-top:6px; border-top:1px solid var(--line-soft)}
.inv{display:flex; align-items:center; gap:12px; padding:9px 2px; border-bottom:1px solid var(--line-soft); font-size:12.5px}
.inv:last-child{border-bottom:0}
.inv .inv-r{margin-left:auto; font-family:var(--f-mono); font-size:10px; color:var(--ash-dim); letter-spacing:.08em; text-transform:uppercase}

.form-card{max-width:640px}
.form-card .f2{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:0 14px; align-items:start}
/* a .field is itself a grid, so a stretched one shares the extra height out
   among its rows — which grew the Monogram box to match the Team code box
   plus the note underneath it */
.form-card .f2 .field{align-content:start}
@media (max-width:560px){ .form-card .f2{grid-template-columns:minmax(0,1fr)} }
.form-card .field label .opt{color:var(--ash-dim); letter-spacing:.06em; text-transform:none; opacity:.75}
.form-card select{
  background:var(--void); border:1px solid var(--line); border-radius:2px; color:var(--chalk);
  padding:11px 12px; font-size:14px; font-family:var(--f-body); width:100%; cursor:pointer;
}
.form-card select:focus{outline:none; border-color:var(--red)}
/* ---------- Settings menu on a channel ----------
   The top bar's channel switcher is the same idea; it is not reused because
   that one is wired to #chanWrap by id and there is only ever one of it. */
.menu-wrap{position:relative; display:inline-flex}
.menu-btn .caret{font-size:9px; margin-left:7px; color:var(--ash-dim); font-family:var(--f-body)}
.menu{
  display:none; position:absolute; top:calc(100% + 6px); right:0; z-index:30;
  min-width:250px; padding:5px; background:var(--carbon); border:1px solid var(--line);
  border-radius:3px; box-shadow:var(--shadow);
}
.menu-wrap.open .menu{display:block}
.menu-opt{
  display:block; width:100%; text-align:left; padding:9px 11px; border:0; border-radius:2px;
  background:transparent; color:var(--ash); font:inherit; font-size:13.5px; cursor:pointer;
}
.menu-opt em{
  display:block; font-style:normal; margin-top:3px;
  font-family:var(--f-mono); font-size:9.5px; letter-spacing:.05em; color:var(--ash-dim);
}
.menu-opt:hover{background:color-mix(in srgb,var(--chalk) 6%, transparent); color:var(--chalk)}
.menu-opt.danger:hover{background:color-mix(in srgb,var(--red) 14%, transparent); color:var(--red)}
.menu-opt.danger:hover em{color:var(--red)}

.form-end{display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:8px}
.form-msg{font-family:var(--f-mono); font-size:11px; color:var(--ash-dim); letter-spacing:.04em}
.form-msg.err{color:var(--red)}
.note.err{color:var(--red)}

/* ---------- sign-in page ---------- */
body.auth-page{display:grid; place-items:center; min-height:100vh; padding:24px}
.auth-card{
  width:min(420px,100%); border:1px solid var(--line); border-radius:4px;
  background:var(--carbon); padding:clamp(26px,4vw,38px); box-shadow:var(--shadow);
}
.auth-card .brand{justify-content:flex-start; margin-bottom:26px}
.auth-card h1{
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; text-transform:uppercase;
  letter-spacing:.03em; font-size:26px; margin:0 0 8px; line-height:1.1;
}
.auth-card p.intro{color:var(--ash); font-size:14px; margin:0 0 22px}
/* Sign in / Sign up. A segmented control rather than the rule-and-underline
   the app uses for its own sections: this is a choice between two forms, not
   a place in a page. */
.auth-tabs{
  display:grid; grid-template-columns:1fr 1fr; gap:2px; margin:0 0 24px;
  border:1px solid var(--line); border-radius:3px; padding:2px; background:var(--void);
}
.auth-tabs button{
  font-family:var(--f-display); font-stretch:87.5%; font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; font-size:12.5px; color:var(--ash-dim);
  background:transparent; border:0; border-radius:2px; padding:10px 0; cursor:pointer;
  transition:background .16s, color .16s;
}
.auth-tabs button:hover{color:var(--chalk)}
.auth-tabs button.on{background:var(--red); color:#fff}
.field{display:grid; gap:7px; margin-bottom:16px}
.field label{font-family:var(--f-mono); font-size:10px; letter-spacing:.16em; text-transform:uppercase; color:var(--ash-dim)}
.field input{
  background:var(--void); border:1px solid var(--line); border-radius:2px; color:var(--chalk);
  padding:11px 12px; font-size:14px; font-family:var(--f-body); width:100%;
}
.field input:focus{outline:none; border-color:var(--red)}
/* what a box wants, stated under it rather than only on rejection — the
   password rules on the sign-in page, the team a code resolved to on the
   channel form */
.field-note{margin:0; font-family:var(--f-mono); font-size:10px; line-height:1.7; color:var(--ash-dim)}
.field-note.ok{color:var(--green)}
.field-note.err{color:var(--red)}
.auth-card .btn{width:100%; justify-content:center; margin-top:6px}
.msg{
  margin-top:16px; font-size:13px; padding:11px 13px; border-radius:2px;
  border:1px solid var(--line); background:var(--carbon-2); color:var(--ash);
}
.msg.err{border-color:var(--red); color:var(--chalk)}
.auth-alt{margin-top:22px; font-size:13px; color:var(--ash-dim); text-align:center}
.auth-alt a{color:var(--ash)}
.auth-alt a:hover{color:var(--red)}
