:root {
  --ink:#16191d; --muted:#646b78; --line:#e1e5eb;
  --page:#dde2ea; --surface:#f1f4f8; --sunk:#f8fafc; --tint:#f5f8ff;
  --head:#ffffff; --edge:#c5ccd8; --nest:#fafbfd; --lift-sm:0 1px 2px rgba(16,24,40,.12); --lift:0 1px 2px rgba(16,24,40,.06), 0 2px 8px rgba(16,24,40,.06);
  --warn:#b45309; --bad:#b91c1c; --ok:#15803d; --accent:#3b82f6; --win:#15803d; --win-ink:#ffffff;
  color-scheme: light dark;
}

/* Dark is not an afterthought here: this is an app people check late on a Sunday. Only
   the tokens change — every rule below is written against them, so nothing else needs a
   second definition. Without an explicit --page the browser paints its own dark ground
   behind our dark text, which is exactly how this was found. */
@media (prefers-color-scheme: dark) {
  :root {
    --ink:#e8eaed; --muted:#9aa3af; --line:#2c3138;
    --page:#0b0e11; --surface:#171c21; --sunk:#222830; --tint:#1e2836;
    --head:#2b333c; --edge:#3d4651; --nest:#20262d; --lift-sm:0 1px 2px rgba(0,0,0,.5); --lift:0 1px 2px rgba(0,0,0,.4), 0 2px 10px rgba(0,0,0,.3);
    --warn:#fbbf24; --bad:#f87171; --ok:#4ade80; --accent:#60a5fa; --win:#4ade80; --win-ink:#052e16;
  }
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust:100%; text-size-adjust:100%; }
body { margin:0; background:var(--page); color:var(--ink); font:15px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif; }
header { display:flex; align-items:center; gap:1rem; padding:.75rem 1.25rem; border-bottom:1px solid var(--line); }
/* The app's bar stays put while a page scrolls under it. Painted, so the page does not show
   through; over the page, under dialogs. */
.shell-bar { position:sticky; top:0; z-index:30; background:var(--surface); box-shadow:var(--lift); border-bottom-color:var(--line); padding-left:0; padding-right:0; }
/* The bar's contents in main's column: same width, same gutter, so the menu button stands
   over the left edge of the page's first card. */
.shell-row { display:flex; align-items:center; gap:1rem; width:100%; max-width:64rem; margin:0 auto; padding:0 1.25rem; min-width:0; }
.shell-row .brand { flex:none; }
/* On a phone the menu button and the league name take the first row and the tabs get a row to
   themselves, so all of them are in reach instead of two scrolled into view. */
@media (max-width: 40rem) { .shell-row { flex-wrap:wrap; row-gap:.25rem; padding:0 .9rem .35rem; }
  .shell-row > .shell-tabs { flex:1 1 100%; order:3; } .shell-row > details.shell-menu { margin:.4rem 0 0; }
  .shell-row > .brand { margin-top:.4rem; } }
.brand { display:inline-flex; align-items:center; gap:.5rem; font-weight:600; text-decoration:none; color:inherit; }
.brand-mark { width:1.5rem; height:1.5rem; border-radius:.4rem; flex:none; }
/* One row: the way around the league, and the way home. Your other leagues and your account
   are behind the button (Components/Shared/ShellMenu.razor.css) and the league's own
   destinations scroll sideways (ShellTabs), which keeps this a single line on a phone. */

/* Wide enough for the squad table to stand in full. At 46rem the column stopped short of
   the fifteen-row table's own width, so the form chips at its right-hand end were behind a
   sideways scroll on a screen with room to spare either side of them. The scroll belongs to
   the phone, where the screen really is too narrow; here the page simply gets wider. */
main { max-width:64rem; margin:0 auto; padding:1.5rem 1.25rem 4rem; }
/* A player is read as a page, not out of a box over one: while his sheet is up the rest of
   the column steps aside, so he sits in the same column, under the same bar, as everything
   else in the app. What is fixed to the screen — a toast, a question waiting to be answered
   — is not part of the column and stays. */
main:has(.player-sheet) > *:not(.player-sheet, :has(.player-sheet), .toasts, .confirm-backdrop) { display:none; }
/* Sign-in and registration: one column the width of the form itself. */
main.signed-out { max-width:24rem; }
h1 { font-size:1.35rem; margin:0 0 1rem; }
h2 { font-size:1.05rem; margin:1.75rem 0 .5rem; }
h3 { font-size:.8rem; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); margin:1rem 0 .35rem; font-weight:600; }
.muted { color:var(--muted); font-weight:400; text-transform:none; letter-spacing:0; }
.bar { display:flex; align-items:center; gap:1rem; flex-wrap:wrap; padding:.75rem 0; border-bottom:1px solid var(--line); }
.bar button { margin-left:auto; }
button, a.button { font:inherit; padding:.35rem .7rem; border:1px solid var(--line); border-radius:6px; background:var(--surface); cursor:pointer; }
button:disabled { opacity:.45; cursor:not-allowed; }
/* A link that takes you somewhere but reads as a button (LinkButton). */
a.button { display:inline-block; color:var(--ink); text-decoration:none; }
/* Three button styles, used by class everywhere. primary is the one thing a screen is for,
   secondary everything alongside it, danger takes something away. "primary danger" is the
   solid red that confirms a destructive step. */
button.primary, a.button.primary { background:var(--accent); border-color:var(--accent); color:#fff; font-weight:600; }
button.primary:hover:not(:disabled), a.button.primary:hover { filter:brightness(1.1); }
button.secondary, a.button.secondary { background:var(--surface); border-color:var(--line); color:var(--ink); }
button.secondary:hover:not(:disabled), a.button.secondary:hover { background:var(--sunk); }
button.danger { background:var(--surface); border-color:var(--bad); color:var(--bad); font-weight:600; }
button.danger:hover:not(:disabled) { background:var(--sunk); }
button.primary.danger { background:var(--bad); color:#fff; }
/* The small size of any of them: a card header's action or a button inside a row. */
button.compact, a.button.compact { padding:.1rem .5rem; font-size:.8rem; }
/* Roles, decided once: primary = the one thing a screen is for; secondary = everything
   alongside it, and a card header's "see more" (a.button.secondary.compact); danger = takes
   something away, whether it is Drop, Remove or Revoke; link = quiet text inside a table. */
button.link { border:0; background:none; color:var(--muted); text-decoration:underline; padding:0; }
select, input { font:inherit; padding:.3rem .4rem; border:1px solid var(--line); border-radius:6px; }
label { display:inline-flex; gap:.4rem; align-items:center; }
.row { display:flex; align-items:center; gap:.75rem; padding:.45rem .6rem; border:1px solid var(--line); border-radius:8px; margin-bottom:.3rem; }
.row .name { font-weight:500; }
/* A name that opens the player sheet, drawn as the name rather than as a button. */
.row button.name, .drafting button.name { background:none; border:0; padding:0; font:inherit; font-weight:500; color:inherit; text-align:left; cursor:pointer; }
.row .when { margin-left:auto; color:var(--muted); font-size:.85rem; }
/* Locked players read as settled, not broken — the point is that nothing is wrong. */
.row.locked { background:var(--sunk); border-style:dashed; }
.row.locked .name { color:var(--muted); }
.row.empty { color:var(--warn); border-style:dashed; justify-content:center; }
.warn { color:var(--warn); }
.error { color:var(--bad); }
.ok { color:var(--ok); }
.notice { color:var(--muted); }
.archived-notice { margin:0 0 1rem; padding:.5rem .75rem; border-left:3px solid var(--muted); }
.card { display:flex; flex-direction:column; gap:.75rem; max-width:20rem; }
/* Inside a card the box sets the width and the form fills it. Left to its own 20rem the form
   sat in the left half of a box drawn twice as wide, which reads as a broken layout rather
   than as a narrow form. */
.card-box .card { max-width:none; }
.card label { flex-direction:column; align-items:stretch; gap:.25rem; }
ul.leagues { list-style:none; padding:0; }
ul.leagues li { display:flex; gap:.75rem; align-items:center; padding:.6rem; border:1px solid var(--line); border-radius:8px; margin-bottom:.4rem; }
ul.leagues .team { color:var(--muted); }
ul.leagues a { margin-left:.75rem; }
ul.leagues a:first-of-type, ul.leagues .muted { margin-left:auto; }

table.standings { width:100%; border-collapse:collapse; margin:.5rem 0 1.5rem; }
.flush table.standings { margin-top:0; }
/* The header band's end cells follow the card's rounded corners. */
.players-card.flush table thead th:first-child { border-top-left-radius:.7rem; }
.players-card.flush table thead th:last-child { border-top-right-radius:.7rem; }
table.standings th { text-align:left; text-transform:capitalize; font-size:.8rem;
  letter-spacing:0; color:var(--ink); font-weight:700; padding:.5rem .5rem;
  background:var(--head); border-bottom:1px solid var(--edge); }
table.standings td { padding:.45rem .5rem; border-bottom:1px solid var(--line); }
table.standings .num { text-align:right; font-variant-numeric:tabular-nums; }
table.standings .strong { font-weight:600; }
/* Your own row: in a twelve-team table the first thing you look for is yourself. */
table.standings tr.me td { background:var(--tint); }
table.standings tr.me td:first-child { box-shadow:inset 3px 0 0 var(--accent); }

ol.feed { list-style:none; padding:0; margin:0; }

/* A live draft: the clock across the top, then the queue beside the rounds. */
.draft { display:grid; grid-template-columns:repeat(auto-fit, minmax(22rem, 1fr)); gap:1rem; align-items:start; margin-bottom:1rem; }
@media (max-width:44rem) { .draft { grid-template-columns:1fr; } }
.drafting .clock { display:flex; justify-content:space-between; align-items:center; gap:1rem; flex-wrap:wrap;
  border:1px solid var(--line); border-radius:.5rem; background:var(--surface); padding:.75rem 1rem; margin:1rem 0; }
.drafting .clock h2 { margin:.1rem 0; font-size:1.25rem; }
.drafting .clock.mine { border-color:var(--accent); background:var(--tint); }
.drafting .clock .shape { color:var(--muted); font-size:.85rem; margin:0; }
.drafting .clock.urgent .left { color:var(--bad); font-weight:600; }
.drafting .clock .until { display:flex; flex-direction:column; align-items:center; min-width:6rem; padding:.4rem .9rem; border:1px solid var(--accent); border-radius:.6rem; background:var(--tint); }
.drafting .clock .until .count { font-size:2.2rem; font-weight:700; line-height:1; font-variant-numeric:tabular-nums; color:var(--ink); }
.drafting .clock .until .caption { font-size:.75rem; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; margin-top:.2rem; }
.drafting .clock ol.next { list-style:none; display:flex; gap:.4rem; flex-wrap:wrap; padding:0; margin:0; }
.drafting .clock ol.next li { border:1px solid var(--line); border-radius:999px; padding:.15rem .6rem; font-size:.8rem; color:var(--muted); }
.drafting .clock ol.next li.mine { border-color:var(--accent); color:var(--ink); font-weight:600; }
.drafting .clock ol.next .overall { font-variant-numeric:tabular-nums; margin-right:.2rem; }
.results.drafting ol.picks.queue li { grid-template-columns:1.25rem auto 1.5rem minmax(0,1fr) auto; align-items:center; }
/* The crest has a cell of its own even when a player has no club, so the columns after it
   never slide left. */
.results.drafting ol.picks.queue .crest-slot { display:flex; align-items:center; justify-content:center; }
/* The name and its fitness mark share one grid cell, so the mark sits against the name
   rather than being flung to the far side of the row (#279). */
.results.drafting ol.picks.queue .named { display:flex; align-items:center; gap:.35rem; min-width:0; }
.results.drafting ol.picks.queue .named .name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Every control on a queue row is the same box, and they sit together at the right. */
.drafting ol.queue .own { display:flex; align-items:center; justify-content:flex-end; gap:.3rem; }
.drafting ol.queue .order { display:flex; gap:.3rem; }
.drafting ol.queue .own button { padding:0; width:2.75rem; min-width:2.75rem; height:2.25rem; display:inline-flex; align-items:center; justify-content:center; }
/* On a phone the controls take less, and the name wraps instead of trimming, so the surname
   is always whole (#512). */
@media (max-width:40rem) {
  .drafting ol.queue .own button { width:2.25rem; min-width:2.25rem; font-size:.85rem; }
  .drafting ol.queue .own, .drafting ol.queue .order { gap:.2rem; }
  .results.drafting ol.picks.queue li { gap:.35rem; }
  .results.drafting ol.picks.queue .named { flex-wrap:wrap; }
  .results.drafting ol.picks.queue .named .name { white-space:normal; overflow:visible; text-align:left; }
}
.results.drafting ol.picks.suggested li { opacity:.75; }
.results.drafting ol.picks.suggested .own button { width:auto; min-width:3.5rem; padding:0 .6rem; }
.drafting .team-card .then { margin-top:.75rem; }
.drafting .draft-players .filters { display:flex; gap:.4rem; flex-wrap:wrap; margin:.5rem 0; }
.drafting .draft-players .search { flex:1 1 10rem; min-width:0; }
@media (max-width: 40rem) {
  .drafting .draft-players .search { flex-basis:100%; }
  /* The list scrolls inside its card, so the filters above it never leave the screen. */
  .drafting .draft-players .table-scroll { max-height:65dvh; overflow-y:auto; }
  .drafting .draft-players thead th { position:sticky; top:0; z-index:3; background:var(--head); }
  /* The frozen heads are frozen both ways and stay over every other cell as it passes under. */
  .drafting table.squad.available.players thead th.pos, .drafting table.squad.available.players thead th.crest-col,
  .drafting table.squad.available.players thead th.who, .drafting table.squad.available.players thead th.act { z-index:4; }
  .drafting .draft-players .filter-row { display:flex; flex:1 1 100%; flex-wrap:nowrap; justify-content:space-between; }
}
/* The list is the Players page's table (frozen identity columns, a scroller of its own), so
   it takes that page's rules; what is the draft's is the buttons, frozen at the right edge
   where Queue and Pick stay in reach however far the numbers have scrolled (#514). */
.drafting .draft-players .table-scroll { overflow-x:auto; position:relative; }
.drafting table.squad.available { width:100%; }
.drafting table.squad.available th.act, .drafting table.squad.available td.act { position:sticky; right:0; z-index:1;
  background:var(--surface); box-shadow:-1px 0 0 var(--line); }
.drafting table.squad.available thead th.act { background:var(--head); }
.drafting table.squad.available tr.opens:hover > td.act { background:var(--sunk); }
.drafting table.squad.available .acts { display:flex; gap:.35rem; align-items:center; justify-content:flex-end; white-space:nowrap; }
.drafting table.squad.available tbody th.who { max-width:12rem; }
/* Queued stands in the Queue button's own box, so the row does not shift when it changes. */
.drafting table.squad.available .queue { box-sizing:border-box; min-width:4.6rem; text-align:center; }
.drafting table.squad.available .queued { display:inline-block; padding:.35rem .7rem; border:1px solid transparent; color:var(--muted); }
/* The board: teams across, rounds down. Position tints reuse the badge colours, mixed into
   the surface so names stay readable in light and dark alike. It scrolls sideways inside
   its card rather than squeezing twelve teams into a phone. */
/* The players card gets the room its table needs (about 34rem of columns plus padding), the
   queue the rest. Below that the two stack, and on a phone the form run goes so the numbers
   and buttons still fit without scrolling. */
.drafting .draft.roomy { width:max(100%, min(76rem, 100vw - 3rem)); grid-template-columns:minmax(22rem, 1fr) minmax(37rem, 1.35fr); }
/* A grid item is never narrower than its content unless told: without this the players table
   stretches its card past the screen instead of scrolling inside it. */
.drafting .draft.roomy > *, .drafting .draft-players { min-width:0; }
@media (max-width: 65rem) {
  .drafting .draft.roomy { grid-template-columns:minmax(0, 1fr); }
}
@media (max-width: 40rem) {
  .drafting .draft-players .table-scroll.snaps { scroll-snap-type:x mandatory; scroll-padding-left:var(--pinned); }
  .drafting table.squad.available thead th:not(.pos, .crest-col, .who, .act) { scroll-snap-align:start; }
  .drafting table.squad.available .acts { flex-direction:column; align-items:stretch; gap:.25rem; }
  .drafting table.squad.available .acts button, .drafting table.squad.available .queued { font-size:.72rem; padding:.2rem .3rem; min-height:0; line-height:1.2; }
  .drafting table.squad.available .queue { min-width:0; width:100%; }
  .drafting table.squad.available td.act, .drafting table.squad.available th.act { width:3.2rem; min-width:3.2rem; padding-left:.2rem; padding-right:.2rem; }
}
/* Never narrower than the column it breaks out of: a three-team board would otherwise sit
   off to one side of the clock card above it (#446). */
.drafting .board.roomy { width:max(100%, min(max(43.5rem, var(--teams) * 9rem + 2rem), 100vw - 3rem)); margin-bottom:1rem; }
.draft-grid { display:grid; grid-template-columns:repeat(var(--teams), minmax(8.5rem, 1fr)); gap:3px; overflow-x:auto; }
.draft-grid .head { font-size:.8rem; font-weight:600; padding:.35rem .5rem; background:var(--sunk);
  border-radius:6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.draft-grid .head.mine { box-shadow:inset 0 -2px var(--accent); }
.draft-grid .cell { position:relative; padding-right:2.4rem !important; display:flex; flex-direction:column; min-width:0; padding:.3rem .5rem; border-radius:6px;
  line-height:1.2; background:var(--sunk); --tint-of:transparent;
  background:color-mix(in srgb, var(--tint-of) 28%, var(--surface)); border-left:3px solid var(--tint-of); }
.draft-grid .cell.gk { --tint-of:#f0a12f; }
.draft-grid .cell.def { --tint-of:#3b9ae8; }
.draft-grid .cell.mid { --tint-of:#4caf3f; }
.draft-grid .cell.fwd { --tint-of:#ef3b30; }
.draft-grid .cell .crest { position:absolute; right:.4rem; top:50%; transform:translateY(-50%); }
.draft-grid .cell.pending { background:transparent; border:1px dashed var(--line); }
.draft-grid .cell.current { border:2px solid var(--accent); background:var(--tint); }
.draft-grid .no { font-size:.7rem; color:var(--muted); font-variant-numeric:tabular-nums; }
.draft-grid .who { font-weight:600; font-size:.85rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-height:1.02rem; }
.draft-grid .club { font-size:.7rem; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* An unmade pick is quiet: most of a board is empty for most of a draft. The one on the
   clock is not, and your own picks-to-come are marked so you can see them coming. */
.results ol.picks li.pending { opacity:.55; }
.results ol.picks li.pending.current { opacity:1; background:var(--tint); }
.results ol.picks li.pending.mine .name { color:var(--accent); }

/* A finished draft: every squad as it came out, a card a team, in first-round order. */
.results .views { display:flex; gap:.4rem; margin-bottom:1rem; }
.results .views button.on { background:color-mix(in srgb, var(--accent) 16%, transparent); color:var(--accent); border-color:var(--accent); font-weight:700; }
.results .teams { display:grid; grid-template-columns:repeat(auto-fill, minmax(17rem, 1fr)); gap:1rem; }
.results .teams.by-round { grid-template-columns:repeat(2, minmax(0, 1fr)); }
@media (max-width: 48rem) { .results .teams.by-round { grid-template-columns:minmax(0, 1fr); } }
.results ol.picks .name.with-owner { display:flex; align-items:center; gap:.5rem; }
.results ol.picks .name.with-owner .player { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; }
.results ol.picks .name.with-owner .owner-chip { flex:none; }
.results .team-card { border:1px solid var(--line); border-radius:.5rem; background:var(--surface); padding:.75rem; min-width:0; }
.results .team-card.mine { border-color:var(--accent); }
.results .team-card h3 { margin:0; font-size:1rem; }
.results .team-card .shape { color:var(--muted); font-size:.8rem; margin:.1rem 0 .5rem; }
.results ol.picks { list-style:none; padding:0; margin:0; }
.results ol.picks li { display:grid; grid-template-columns:2rem auto minmax(0,1fr) auto; gap:.5rem; align-items:center;
  padding:.3rem 0; border-top:1px solid var(--line); }
.results ol.picks .overall { color:var(--muted); font-variant-numeric:tabular-nums; font-size:.8rem; }
.results ol.picks .name { font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.results .auto { color:var(--warn); font-size:.7rem; text-transform:uppercase; letter-spacing:.04em; }

.two-up { display:grid; grid-template-columns:1fr 1fr; gap:2rem; margin-top:2rem; }
@media (max-width:40rem) { .two-up { grid-template-columns:1fr; } }
/* The join code is the invitation, so it reads as something to copy and say aloud. */
p.code { font-size:1.6rem; font-weight:600; letter-spacing:.18em; font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  background:var(--tint); border:1px solid var(--line); border-radius:8px; padding:.5rem .9rem; display:inline-block; margin:.25rem 0; }
.bar a { margin-right:1rem; }

ol.rounds { list-style:none; padding:0; margin:.5rem 0 2rem; }
ol.rounds li { display:flex; align-items:center; gap:.75rem; padding:.45rem .5rem;
  border-bottom:1px solid var(--line); }
ol.rounds .pos { color:var(--muted); min-width:1.8rem; font-variant-numeric:tabular-nums; }
ol.rounds .team { min-width:10rem; }
/* The arithmetic reads as secondary to the total, but it is the reason the row exists. */
ol.rounds .why { margin-left:auto; color:var(--muted); font-size:.85rem; }
ol.rounds .num { min-width:3rem; text-align:right; font-variant-numeric:tabular-nums; }
ol.rounds li.pending { opacity:.55; }

/* A round being fetched, with the last one still on screen. Dimmed rather than removed:
   what is there is a moment out of date, which is worth saying, and saying it by taking
   the page away and putting it back reads as a reload. Clicks are held off so nothing is
   pressed on figures that are about to change. */
.busy { opacity:.45; pointer-events:none; transition:opacity .12s ease-in; }
/* Put on the pitch, the table and the matches rather than on the whole column: the
   round picker is how you got here and how you leave, and a manager paging through a
   season should not have to wait out each round before the arrow works again. */

/* A round's matches, drawn as scoreboards rather than as a list: home, the result, away.
   The crest each side will one day carry goes on the outside of the name, which is why the
   names are pushed to the edges rather than centred with the score. */
/* Two abreast where there is room — a round is ten matches, and ten scoreboards in a
   single column is a scroll rather than a glance. Two and no more: a round has an even
   number of matches, so two columns come out level, and a third leaves a short row
   dangling with a gap beside it. Back to one column when a card would have to squeeze. */
ol.matches { list-style:none; padding:0; margin:.5rem 0 1.5rem; display:grid;
  grid-template-columns:repeat(2, minmax(0, 1fr)); gap:.4rem; }
/* On the rounds screen the list is the grid's last row, edge to edge under pitch and table. */
.round-layout > ol.round-matches { grid-column:1 / -1; margin:0; }
/* Its two columns are the grid's own, so the left cards are the pitch's width and the right
   ones the table's, with the same gap between: every edge lines up with a card above. */
.round-layout > ol.round-matches { grid-template-columns:subgrid; column-gap:1.5rem; }
@media (max-width:46rem) { ol.matches { grid-template-columns:1fr; } }
ol.matches .match { display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
  gap:.5rem; box-sizing:border-box; width:100%; padding:.4rem .6rem; border:1px solid var(--line);
  border-radius:8px; background:var(--nest); border-color:var(--edge); box-shadow:var(--lift-sm);
  font-size:.88rem; }
/* A card that opens its line-ups: a button that still looks like the card, lifting its
   edge under the cursor rather than turning into a grey form control. */
ol.matches button.match { font:inherit; font-size:.88rem; color:inherit; text-align:left;
  cursor:pointer; }
ol.matches button.match:hover { border-color:var(--muted); }
ol.matches button.match:focus-visible { outline:2px solid var(--accent, #3b9ae8); outline-offset:1px; }
/* The crest on the outside of the name, so the two clubs read outward from the score. */
ol.matches .side { min-width:0; display:flex; align-items:center; gap:.4rem; }
ol.matches .side.away { justify-content:flex-end; text-align:right; }
ol.matches .side .crest { width:1.4rem; height:1.4rem; }
ol.matches .side span.crest { font-size:.5rem; }
ol.matches .club { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
ol.matches .result { display:flex; align-items:center; justify-content:center; }
ol.matches .when { display:flex; flex-direction:column; align-items:center; line-height:1.15;
  font-size:.72rem; color:var(--muted); white-space:nowrap; }
ol.matches .when b { font-size:.8rem; color:var(--fg, inherit); font-weight:600; }
ol.matches .goals { display:flex; gap:.2rem; }
ol.matches .goals b { display:flex; align-items:center; justify-content:center;
  min-width:1.6rem; height:1.6rem; border-radius:5px; font-size:.95rem; font-weight:700;
  font-variant-numeric:tabular-nums; background:var(--head); color:var(--ink); border:1px solid var(--edge); }
/* A result is told by its side: the win is a solid green box and a bold club, the loss a
   faded box and a muted club, a draw the plain neutral box with both clubs as normal. */
ol.matches .goals b.won { background:var(--win); border-color:var(--win); color:var(--win-ink); }
ol.matches .goals b.lost { background:var(--sunk); border-color:var(--line); color:var(--muted); font-weight:500; }
ol.matches .side.won .club { font-weight:700; color:var(--ink); }
ol.matches .side.lost .club { color:var(--muted); }

@media (max-width:520px) {
  ol.matches .match { gap:.35rem; padding:.4rem .5rem; }
}

/* Waivers. The preference number is the mechanic — processing stops at your first
   success — so it reads as a rank rather than a bullet. */
.row .pref { width:1.5rem; color:var(--muted); font-variant-numeric:tabular-nums; }
.row.picked { border-color:var(--accent); background:var(--tint); }
button.on { border-color:var(--accent); background:var(--tint); }
/* The pool switch is a segmented control, not the bar's trailing action, so it opts out
   of the rule that pushes a lone button to the right. */
.bar .pools { display:flex; gap:.4rem; }
.bar .pools button { margin-left:0; }
.pill { display:inline-block; border:1px solid var(--line); border-radius:999px; padding:.05rem .5rem; margin-right:.4rem; color:var(--ink); }

/* The picker rides on top of the table as its header: pick a round, read the round. Its own
   look is its own (Components/Shared/RoundPicker.razor.css); this is only the column. */
.table-side { display:flex; flex-direction:column; gap:.5rem; min-width:0; }

/* Something being played: a match row, a match popup's heading and a round whose points are
   a running total all wear this one blue chip. */
.live-badge {
  display:inline-block; font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  color:var(--accent, #3b9ae8); border:1px solid currentColor; border-radius:999px;
  padding:.15rem .5rem; white-space:nowrap;
}

/* A round not yet started: when, in the same quiet size as the live label. */
.starts { color:var(--muted); font-size:.72rem; line-height:1.2; }

/* The team name picks its pitch up, so it is a button — but it is still the row's name,
   and it should read like the rest of the column, with no underline pretending it leads
   somewhere. The row's own tint is what says it can be pressed. */
table.standings td button.link { color:inherit; text-decoration:none; font:inherit; cursor:pointer; text-align:left; }
/* Said only to a screen reader: a column whose heading is obvious to anyone looking at it
   still needs a name for anyone who is not. */
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; border:0; }

/* The place a manager is in, drawn as a chip so it reads as a standing rather than as a
   fourth number in a row of numbers. The arrow under it is the round's own news: it is the
   only thing in the table that says which way someone is going. */
table.standings td.place, table.standings th.place { width:1%; padding-right:.5rem;
  white-space:nowrap; vertical-align:middle; }
/* Chip over arrow, both centred on the same axis and the column the same width in every
   row, so the places read as one straight line down the table. */
table.standings td.place > .stack { display:flex; flex-direction:column; align-items:center;
  justify-content:center; }
/* A spacer the height of the arrow line above the chip, so the chip itself sits on the
   row's middle, level with the team name, rather than lifted by the line under it. */
table.standings td.place > .stack::before { content:""; height:.9rem; }
/* Reserved whether or not there is an arrow in it. */
table.standings td.place .moved { display:flex; align-items:center; justify-content:center;
  height:.9rem; font-size:.65rem; font-weight:700; letter-spacing:-.02em; }
table.standings td.place .moved.up { color:var(--ok); }
table.standings td.place .moved.down { color:var(--bad); }

/* One line a team, however long the name: a row is read across, and a name that wraps
   takes its own points down the table with it. What will not fit is cut, and the whole
   name is on the row itself for anyone who wants it. */
/* The name column takes whatever the numbers leave: width:100% claims the slack,
   max-width:0 is what lets the ellipsis happen inside a table cell at all. */
table.standings td.team { width:100%; max-width:0; }
table.standings td.team button.link, table.standings td.team > span { display:block; max-width:100%;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* The picture, and beside it the name with when its manager was last here under it (#151).
   The muted line belongs under the name rather than under the circle, so the two words are
   their own block and the row stays one line tall per thing it says. min-width:0 is what
   keeps the ellipsis working once the name is inside a flex child. */
/* Tall enough for a name with a "seen" line under it, whether or not this row has one:
   rows that differ in height by whoever happens to have logged in read as two tables. */
table.standings td.team .named { display:flex; align-items:center; gap:.4rem; min-height:2.25rem; }
table.standings td.team .stacked { display:flex; flex-direction:column; min-width:0; }
table.standings td.team .stacked > * { max-width:100%; white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
table.standings td.team .runs { font-size:.8rem; line-height:1; flex:none; opacity:.8; }

/* Last season's podium, beside the name (#269). The colour is the whole message — one
   drawing, three metals — so it is set here rather than in the glyph, which paints itself
   in whatever colour it is given. */
table.standings td.team .medal { font-size:.9rem; flex:none; }
/* The metals themselves are unscoped: the same three colours say the same three places
   wherever a medal is drawn — beside a name in the table, and against a finished season
   in a manager's achievements (#269). */
.medal.gold { color:#d4a017; }
.medal.silver { color:#9aa3ab; }
.medal.bronze { color:#b06a3b; }
/* A Survival's cups (#299) in the same gold and silver: won outright, and shared in a draw. */
.cup.gold { color:#d4a017; }
.cup.silver { color:#9aa3ab; }
/* The Diamond Cup (#304), held by one member at a time for the longest Survival won. */
.cup.diamond { color:#4fb3d9; }
table.standings td.team .seen { color:var(--muted); font-size:.72rem; line-height:1.2; }

/* The row is the target, not the word in it. The name keeps its button so the table is
   still walkable by keyboard, but a mouse can land anywhere on the line. */
table.standings tr.pick { cursor:pointer; }
table.standings tr.pick:hover td { background:var(--sunk); }
/* Your own row keeps its tint under the cursor: hovering it must not make it stop being
   yours. */
table.standings tr.pick.me:hover td { background:var(--tint); }
/* Which team the pitch above is showing. Quieter than the tint on your own row: one says
   "this is you", the other only says "this is what you are looking at". */
table.standings tr.picked td { box-shadow:inset 0 -2px 0 var(--accent); }

/* One look for every standings table, wherever it is read. These rules stay global rather
   than moving into StandingsTable.razor.css because half of what the component draws is the
   page's own columns, and an isolated stylesheet would have to reach every one of them
   through ::deep to say the same thing. The casing is the same everywhere: a column is
   named, not shouted. */
/* A sortable heading is a button, but it is still a heading — it inherits the header's
   own weight and colour and only the caret says which one the table is ordered by. */
table.standings th button.link, table.squad th.sortable button.link { color:inherit; font:inherit; padding:0;
  background:none; border:0; cursor:pointer; text-decoration:none; white-space:nowrap; }
table.standings th button.link:hover, table.squad th.sortable button.link:hover { text-decoration:underline; }
/* The arithmetic behind a total, on the rows that have any: under the number it explains,
   and small enough that the column still scans as one figure a row. */
table.standings td.num .muted { display:block; font-size:.75rem; font-weight:400; }

/* Pitch beside table on a wide screen, stacked on a narrow one — the pitch first either
   way, because it is the thing being read and the table is how you change it. */
/* A screen wide enough to be let out of the column the rest of the app is read in — the
   draft board, which is a row per pick and a column per team. Centred on the viewport
   rather than on the text column, and never wider than the window it is in. */
.roomy { width:max(100%, min(76rem, 100vw - 3rem)); margin-inline:auto;
  position:relative; left:50%; transform:translateX(-50%); }
/* On a phone it is the column's own width, so the centring is a no-op there — and a transform
   makes a box the containing block of everything fixed inside it, which put every filter
   sheet at the foot of this whole tall screen instead of the foot of the glass. */
@media (max-width:40rem) { .roomy { left:0; transform:none; } }
/* The rounds screen is not one of them. A pitch and a table side by side are 53.5rem, which
   the page's own 64rem column holds with room to spare — and breaking out of it put the
   whole screen a few centimetres right of the menu button and the bar above it, so the one
   page a manager spends the season on was the one page that did not line up. Started rather
   than centred for the same reason: its left edge is the column's left edge. */
.round-layout { display:grid; gap:1.5rem; align-items:start;
  /* Two equal columns, each the pitch's own width: the table and the matches under it are
     drawn to the pitch, so every card on the screen is one size. */
  grid-template-columns:minmax(18rem, 26rem) minmax(18rem, 26rem); justify-content:start; }
/* The pitch column is the pitch's own 26rem and the table fills its column, so the matches
   under them run from the pitch's left edge to the table's right one rather than past both. */
.round-layout .standings-card { max-width:none; }
.round-layout > * { min-width:0; }
/* minmax(0, …) rather than a bare 1fr: a bare fr column will not shrink below its content,
   so a team with five long-named midfielders pushed the pitch wider than a team with four,
   and the whole sheet grew as you went from one manager to the next. */
@media (max-width:62rem) { .round-layout { grid-template-columns:minmax(0, 26rem) minmax(0, 26rem); } }
@media (max-width:46rem) { .round-layout { grid-template-columns:1fr; } }

/* The card, the pitch and the bench are one team sheet, so they share one width: the
   pitch's own cap. Left to the column, the card stretched past a pitch that stops
   growing, and on a wide window the two stopped lining up. */
.pitch-side { width:100%; max-width:25.5rem; margin-inline:auto; }

/* The header above the pitch: the team on top, and under it the three figures anyone
   asks for first, each a number over its own word so the column reads as one thing. */
.scoreline { padding:.6rem .75rem; border:1px solid var(--line); border-radius:.75rem .75rem 0 0;
  background:var(--sunk); text-align:center; }
.scoreline > strong { display:block; font-size:1.05rem; margin-bottom:.5rem; }
.scoreline .figures { display:flex; align-items:stretch; }
/* Hairlines between the figures rather than around them: they are one row of numbers,
   not three boxes. */
.scoreline .figure + .figure { border-left:1px solid var(--line); }
.scoreline .figure { flex:1 1 0; min-width:0; padding:0 .25rem; }
.scoreline .figure b { display:block; font-size:1.1rem; font-variant-numeric:tabular-nums; }
.scoreline .figure span { display:block; font-size:.75rem; color:var(--muted); }
.scoreline .figure button.link { display:block; width:100%; color:inherit; font:inherit;
  text-decoration:none; cursor:pointer; padding:0; }
.scoreline .figure button.link:hover span { color:var(--ink); }
/* The breakdown, when it is open: the same row of figures a size down, ruled off from the
   three above so it reads as detail rather than as more headline. */
.scoreline .figures.detail { margin-top:.6rem; padding-top:.6rem; border-top:1px solid var(--line); }
.scoreline .figures.detail b { font-size:.95rem; }

/* The lineup card, on the rounds screen, for every manager alike. Your own eleven was in a
   card and everyone else's was a bare pitch under the scoreline, so the pitch changed both
   its width and its height down the page as you stepped through the league — a difference
   the eye reads as a different screen, not as a team you cannot edit. One card for all of
   them, carrying nothing of its own but a header: the grass runs to the card's edges and
   the card runs on from the scoreline above it, so only the men on it change. */
.pitch-side .card-box.pitch-card { border-top:0; border-radius:0 0 .75rem .75rem; overflow:hidden; }
/* The header keeps one height whichever it is holding. A menu is taller than the words it
   would have said, and left to itself it pushed the grass eleven pixels further down the
   page on your own team than on anybody else's — the last of the movement this was for. */
.card-box.pitch-card > .card-head { height:2.6rem; align-items:center; border-radius:0; }
/* What his formation is, where yours has the menu to change it. Said in the header's own
   quiet voice rather than dressed as a control he could press. */
.pitch-card .formation { font-size:.85rem; color:var(--muted); font-variant-numeric:tabular-nums; }

/* Stepping between weeks, on the same centre line as everything under it: the picker is
   the pitch's own header, so it is held to the pitch's width rather than the page's. */

/* The team sheet: the pitch in a card with the formation menu in its header, as wide as the
   pitch so the menu sits at the pitch's own right edge rather than a far margin. */
/* The pitch's own cap, said again here as a width. fit-content looked like it would settle
   on the pitch, but a pitch is width:100% of whatever holds it and so has no width of its
   own to shrink to: the card came out as narrow as the widest player chip, about 13rem, and
   drew the pitch that size with it. Naming the width makes the card the one that decides
   and the pitch the one that fills it, which is the way round it was always meant to be. */
.team-sheet { width:25.5rem; max-width:100%; margin-left:auto; margin-right:auto; }
/* What became of the last gesture, in the header of whichever pitch is writing itself —
   the team sheet and a live round's lineup say it the same way, so the rule is not tied to
   either of them. */
.save-state { font-size:.8rem; color:var(--muted); font-weight:400; }


/* --- The squad table, wherever it is drawn -----------------------------------

   Shared between the Team page's squad and the Players page's league-wide list. One
   table read two ways: the eleven you are picking, and everyone you might pick from.
   SquadTable's own sheet adds only what picking needs on top of this. */
/* The Players page grows to its table, so everything above the list shares its edges. */
.players-page { width:max-content; min-width:100%; }
/* The claims above take the table's width rather than setting it: opened, their own rows
   would otherwise widen the page. */
.players-page .pending-claims { width:0; min-width:100%; }
/* On a phone the page keeps the screen's width and the table scrolls inside its card (the
   card's flush body does that), rather than the page growing to the table and being shrunk
   to fit, which left the bar half-width and the text inflated. */
@media (max-width:40rem) { .players-page { width:auto; min-width:0; } }

.squad { width:100%; border-collapse:collapse; font-size:.85rem; }

.squad th, .squad td { padding:.3rem .4rem; text-align:right; white-space:nowrap; }
.squad th.who, .squad td.who { text-align:left; }
/* Position and club lead every player table, each a narrow fixed column: the chip is one
   letter and the club is its crest alone, so the names start on one line down the table. */
.squad th.pos, .squad td.pos, .squad th.crest-col, .squad td.crest-col, .squad th.watch-col, .squad td.watch-col {
  width:2.4rem; min-width:2.4rem; max-width:2.4rem; padding-left:.3rem; padding-right:.3rem; text-align:center; }
.squad td.pos .badge { margin:0 auto; }
.squad td.crest-col .crest { display:block; margin:0 auto; }
/* The opponent is a crest too, centred under its heading. */
.squad th.opp, .squad td.opp { text-align:center; }
.squad td.opp .crest { display:block; margin:0 auto; }

.squad thead th { font-size:.72rem; text-transform:capitalize; letter-spacing:.04em;
  color:var(--ink); font-weight:700; background:var(--head); border-bottom:1px solid var(--edge); }

.squad tbody td, .squad tbody th { border-bottom:1px solid var(--line); }

.squad .name { font-weight:500; overflow:hidden; text-overflow:ellipsis; }

/* The same disc as the pitch, at the size a row of text allows. */
.squad .badge, .results .badge { flex:none; display:inline-grid; place-items:center;
  min-width:1.35rem; height:1.1rem; padding:0 .2rem; border-radius:.55rem;
  font-size:.62rem; font-weight:700; color:#fff; }
.squad .badge.gk, .results .badge.gk { background:#f0a12f; }
.squad .badge.def, .results .badge.def { background:#3b9ae8; }
.squad .badge.mid, .results .badge.mid { background:#4caf3f; }
.squad .badge.fwd, .results .badge.fwd { background:#ef3b30; }
.squad .badge.great { background:#3b9ae8; }
.squad .badge.good { background:#4caf3f; }
.squad .badge.low { background:#f0a12f; }
.squad .badge.nil { background:#9ca3af; }
.squad .badge.poor { background:#ef3b30; }
.squad .badge.soon { background:#64748b; }
.squad .badge.none, .squad .badge.gap { background:#4b5563; }

.squad .num { font-variant-numeric:tabular-nums; }
.squad .num.strong { font-weight:700; }
/* The one pair of columns that is centred rather than ranged right. Everywhere else a
   number is a column you read down and compare, so its digits line up on the right; these
   two are a total with its own average stacked beneath, and the pair reads as one small
   block about one side of the season. Centred, the two lines sit over each other. */
.squad .split { line-height:1.05; text-align:center; }
/* The total is the number, the average is the footnote under it. Two lines nearly the same
   size read as two facts of equal weight and the eye has to stop and work out which is
   which; a clear step down says which one the column is for at a glance. */
.squad .split span { font-weight:600; }
.squad .split small { display:block; font-size:.62rem; line-height:1.2; color:var(--muted); }
.squad .side { font-weight:600; }

/* The run of weeks lines up under the heading; the chips themselves are FormRun's. */
.squad td.run { text-align:right; }

/* Nothing is dropped on a phone. The splits' averages and the older weeks are what the
   squad is read for, so the table scrolls sideways inside its own box (SquadTable's sheet)
   rather than quietly losing columns. */


/* --- The Players page --------------------------------------------------------

   A box and a button, and behind the button two rows of chips and a dropdown. Chips where
   the answers are few and worth seeing at once — which filter is on is the state of the
   page, and a closed <select> hides it behind a click. The clubs are the exception: twenty
   of them is more than a row of buttons can hold, and it is a list you already know the
   name of your answer in. */
.filters { display:flex; align-items:center; flex-wrap:wrap; gap:.25rem .5rem;
  padding:.75rem 0; }
/* Wide enough for a name and no wider: a box the width of the table invites a sentence. */
.filters .search { flex:0 1 16rem; min-width:8rem; margin-right:.25rem; }
/* The menus are one group so a phone can show them together; elsewhere the group adds nothing. */
.filters .filter-row { display:contents; }

/* A player's row opens his sheet wherever it is pressed, the same in every list of players:
   the Players page, the draft's available list and its queue. The name stays a button, so
   the keyboard has something to land on; the controls on the row do their own thing. */
tr.opens, li.opens { cursor:pointer; }
tr.opens:hover > *, li.opens:hover { background:var(--sunk); }
/* Holds a row's own controls without a box of its own, so a grid row keeps its columns. */
.own { display:contents; }

/* The name opens the player sheet, and reads as the row rather than as a control: the
   whole line is what the eye follows, and a button outline round every name in a list of
   twenty is a page of boxes. */
table.players th.who button { display:flex; align-items:center; gap:.45rem; width:100%;
  background:none; border:0; padding:0; font:inherit; color:inherit; text-align:left;
  cursor:pointer; }
table.players th.who small { color:var(--muted); font-size:.72rem; }

/* Whether you can have him, in one chip. Green for a man anyone can claim tonight, amber
   for one held until his waiver runs out, and nothing at all for one already owned — a
   rival's squad is a fact rather than an opportunity, and colouring it would make the
   page look like most of the league were available. */
/* Status is a fixed width whatever team owns the man, so the columns hold still between
   pages; the full name is in the pill's title. */
table.players .pill .short { display:none; }
table.players .status { width:7rem; min-width:7rem; max-width:7rem; text-align:center; }
/* The name is capped too, cut short with an ellipsis, so one long name cannot push the
   table past the page. */
table.players tbody th.who { max-width:10rem; }
table.players th.who button { min-width:0; }
table.players th.who .last { display:none; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
table.players th.who .name, table.players th.who small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }

table.players .pill { margin-right:0; font-size:.72rem; max-width:100%; box-sizing:border-box;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; vertical-align:middle; }
table.players .pill.free { color:var(--ok); border-color:currentColor; }
table.players .pill.held { color:var(--warn); border-color:currentColor; }
table.players .pill.owned { color:var(--muted); }
/* A player already in your claims is yours-in-waiting, not an opportunity: filled in the
   accent the page uses for you, so it cannot be mistaken for the green chip that opens a claim. */
/* The owner chip, shrunk to the column: the chip's own sizes are for the sheet's header. */
table.players .owner-chip { font-size:.72rem; vertical-align:middle; }
table.players .pill.mine { color:var(--accent); background:var(--tint); border-color:currentColor; font-weight:600; }

/* Only the table scrolls sideways: the legend and the pager under it belong to the card and
   stay in view, so the card's own body does not scroll. */
.card-box.players-card.flush .card-body { overflow-x:visible; }
.players-card .table-scroll { overflow-x:auto; position:relative; }
/* The claim panel opens in a row as wide as the table: pinned to the left edge and as wide as
   what is on screen, so it is never cut off or scrolled away with the numbers. */
.players-card .table-scroll { container-type:inline-size; }
table.players tr.claiming > td { padding:0; }
table.players tr.claiming > td > * { position:sticky; left:0; box-sizing:border-box; width:100cqw; }
/* The hidden headings are absolutely placed: without a positioned box around them they sit
   at the page's edge and make the whole page scroll. */
.squad-scroll { position:relative; }

/* Position, club and name stay put while the numbers scroll under them, so a row is never
   read without whose it is. Each cell is painted, or what scrolls would show through, and
   each sits after the widths of the ones before it. */
table.players td.pos, table.players th.pos, table.players td.crest-col, table.players th.crest-col,
table.players td.watch-col, table.players th.watch-col,
table.players tbody th.who, table.players thead th.who:not(.status),
.squad-scroll table.squad td.pos, .squad-scroll table.squad th.pos,
.squad-scroll table.squad td.crest-col, .squad-scroll table.squad th.crest-col,
.squad-scroll table.squad tbody th.who, .squad-scroll table.squad thead th.who {
  position:sticky; background:var(--surface); z-index:1; }
/* The pinned header cells are the header band, not the card, or they read as a dark block. */
table.players thead th.pos, table.players thead th.crest-col, table.players thead th.watch-col, table.players thead th.who:not(.status),
.squad-scroll table.squad thead th.pos, .squad-scroll table.squad thead th.crest-col, .squad-scroll table.squad thead th.who {
  background:var(--head); }
table.players .pos, .squad-scroll table.squad .pos { left:0; }
table.players .crest-col, .squad-scroll table.squad .crest-col { left:2.4rem; }
table.players .watch-col { left:2.4rem; }
table.players.watching .crest-col { left:4.8rem; }
table.players.watching th.who:not(.status) { left:7.2rem; }
table.players th.who:not(.status), .squad-scroll table.squad th.who { left:4.8rem; box-shadow:1px 0 0 var(--line); }
/* Where the frozen columns end, a soft shadow (a gradient, as a cell's own box-shadow is not drawn on body rows) rather than a hard cut: it appears once the
   numbers have scrolled under them (pinned-scroll.js sets data-scrolled), so a column going
   out of sight reads as "more this way" and at rest nothing is drawn over the first column. */
.pinned-scroll[data-scrolled] table.players thead th.who:not(.status)::after, .pinned-scroll[data-scrolled] table.players tbody th.who::after,
.pinned-scroll[data-scrolled] table.squad thead th.who:not(.status)::after, .pinned-scroll[data-scrolled] table.squad tbody th.who::after {
  content:""; position:absolute; top:0; bottom:0; left:100%; width:.6rem; pointer-events:none;
  background:linear-gradient(to right, rgba(0,0,0,.22), transparent); }
table.players tr.opens:hover > .pos, table.players tr.opens:hover > .watch-col, table.players tr.opens:hover > .crest-col,
table.players tr.opens:hover > th.who { background:var(--sunk); }
/* The squad's marked rows are translucent washes; a frozen cell has to be opaque, so the
   wash is laid over the surface. */
.squad-scroll table.squad tr.out > .pos, .squad-scroll table.squad tr.out > .crest-col,
.squad-scroll table.squad tr.out > th.who { background:linear-gradient(var(--tint), var(--tint)), var(--surface); }
.squad-scroll table.squad tr.picked > .pos, .squad-scroll table.squad tr.picked > .crest-col,
.squad-scroll table.squad tr.picked > th.who, .squad-scroll table.squad tr.pick:hover > .pos,
.squad-scroll table.squad tr.pick:hover > .crest-col, .squad-scroll table.squad tr.pick:hover > th.who { background:var(--sunk); }
.squad-scroll table.squad th.who .last { display:none; }
@media (max-width:40rem) {
  .squad-scroll table.squad th.who .name { display:none; }
  .squad-scroll table.squad th.who .last { display:inline; font-weight:500; overflow:hidden; text-overflow:ellipsis; min-width:0; }
}

/* A page at a time, forwards or back. The count is between the arrows because it is the
   thing that tells you whether pressing one is worth it. */
.pager { display:flex; align-items:center; justify-content:center; gap:1rem;
  padding:.75rem 0; color:var(--muted); font-size:.85rem; }
.pager button, .pager .step { padding:.15rem .6rem; }
.pager a.step { color:inherit; text-decoration:none; }
.pager span.step { opacity:.4; }

/* A read in flight fades the table rather than replacing it with a notice: the rows about
   to arrive are the rows already there, give or take a filter, and blanking the screen
   between them makes a page turn look like a page load. */
table.players.busy { opacity:.55; }

/* On a phone the club under the name is the first thing to go — the name and the badge
   already say who he is, and the column has to fit beside a status and three numbers. */
@media (max-width: 40rem) {
  table.players th.who small { display:none; }
  /* Status is FA, WW or an avatar here, so the column shrinks and the Player column keeps the room. */
  table.players .status { width:3.4rem; min-width:3.4rem; max-width:3.4rem; }
  table.players .pill .long { display:none; }
  table.players .pill .short { display:inline; }
  /* Surname only: the full name is still in the sheet the row opens. */
  table.players th.who .name { display:none; }
  table.players th.who .last { display:block; }
  /* The frozen name is one width on every row, which is what lets the scroll stop at its
     edge: each column that scrolls snaps to the frozen part's right side, so none is left
     half under the name at rest. */
  /* Position and club shrink to their badge and crest, which is what gives the numbers room. */
  table.players td.pos, table.players th.pos, table.players td.crest-col, table.players th.crest-col, table.players td.watch-col, table.players th.watch-col {
    box-sizing:border-box; padding-left:.1rem; padding-right:.1rem; }
  table.players td.pos, table.players th.pos { width:var(--pos-w); min-width:var(--pos-w); max-width:var(--pos-w); }
  table.players td.watch-col, table.players th.watch-col { width:var(--watch-w); min-width:var(--watch-w); max-width:var(--watch-w); left:var(--pos-w); }
  table.players td.crest-col, table.players th.crest-col { width:var(--club-w); min-width:var(--club-w); max-width:var(--club-w); }
  /* Each offset is set where the desktop one is, `.watching` included, or the desktop rem
     offsets win and leave a gap between the pinned columns. */
  table.players .crest-col, table.players.watching .crest-col { left:var(--club-left); }
  table.players th.who:not(.status), table.players.watching th.who:not(.status) { left:var(--name-left); }
  table.players tbody th.who, table.players thead th.who:not(.status) {
    width:var(--name-w); min-width:var(--name-w); max-width:var(--name-w); box-sizing:border-box; }
  .players-card .table-scroll.snaps { scroll-snap-type:x mandatory; scroll-padding-left:var(--pinned); }
  table.players thead th:not(.pos, .watch-col, .crest-col, .who:not(.status)) { scroll-snap-align:start; }
  .filters .search { flex:1 1 100%; margin-right:0; }
  /* Shown once the search box has been used; one line, small. */
  .filters .filter-row { display:flex; flex:1 1 100%; flex-wrap:nowrap; justify-content:space-between; }
  .filters .filter-row:not(.shown) { display:none; }
  .filters { gap:.25rem; padding:.5rem 0; }
}

/* The claim column on the Players page: a button on unowned rows, and the form it opens
   laid under the row as a line of its own. */
table.players button.pill { font:inherit; font-size:.72rem; background:none; cursor:pointer; }
table.players button.pill:hover { background:var(--sunk); }
/* The row whose claim form is open: the chip fills in with its own colour. */
table.players button.pill.chosen { background:var(--tint); box-shadow:inset 0 0 0 1px currentColor; }
table.players tr.claiming > td { padding:0; }

/* Another manager's team: back to the table, and whose squad this is. */

/* A club crest, or a circle with the club's code when we have no crest for it. */
.crest { display:inline-grid; place-items:center; flex:none; width:1.7rem; height:1.7rem; border-radius:50%;
  background:var(--surface); border:1px solid var(--line); color:var(--muted);
  font-size:.55rem; font-weight:700; letter-spacing:.02em; }
img.crest { object-fit:contain; border:0; border-radius:0; background:none; }
.crested { display:inline-flex; align-items:center; gap:.4rem; min-width:0; }
.crested > .crest { width:1.2rem; height:1.2rem; }
.crested > span.crest { font-size:.45rem; }
.crested > .name { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* A manager's picture, or a circle with their team's initial when they have not set one
   (#150). One rule for both so the two never differ in size or shape, and a size modifier
   rather than a per-page override: the same circle appears on a profile card, in the
   standings and beside a line of the feed, and only how big it is changes. */
.team-avatar { --avatar:1.7rem; display:inline-grid; place-items:center; flex:none;
  width:var(--avatar); height:var(--avatar); border-radius:50%; background:var(--tint);
  color:var(--accent); font-size:calc(var(--avatar) * .45); font-weight:700; }
img.team-avatar { object-fit:cover; }
.team-avatar.lg { --avatar:3rem; }
.team-avatar.sm { --avatar:1.15rem; }

/* Your own circle is a button: pressing it is how a picture is replaced (#150). It adds
   nothing but the press — the circle inside keeps its own size and shape. */
.avatar-button { display:inline-grid; place-items:center; padding:0; border:0; background:none;
  border-radius:50%; cursor:pointer; line-height:0; }
.avatar-button:hover .team-avatar, .avatar-button:focus-visible .team-avatar {
  outline:2px solid var(--accent); outline-offset:2px; }
.avatar-button:focus { outline:none; }

/* A team named beside its picture, in a table cell that may be narrower than the name. */
.standings td.team .named { display:flex; align-items:center; gap:.45rem; min-width:0; }
.standings td.team .named > .link, .standings td.team .named > .name {
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* A table or list drawn edge to edge in a card lines its first and last columns up with the
   card's heading, and ends at the card's bottom edge rather than a row's border. */
.card-body > table { margin:0; }
.card-body > table th:first-child, .card-body > table td:first-child { padding-left:1rem; }
.card-body > table th:last-child, .card-body > table td:last-child { padding-right:1rem; }
.card-body > table tbody tr:last-child > * { border-bottom:0; }

/* The members list: team, manager, and the role as a chip pushed to the right. Your own row
   carries the accent so it is found at a glance. */
ul.leagues li.member { flex-wrap:wrap; }
ul.leagues li.member .manager { color:var(--muted); }
ul.leagues li.member .role { margin-left:auto; font-size:.8rem; padding:.1rem .6rem; border-radius:999px;
  border:1px solid var(--line); color:var(--muted); }
ul.leagues li.member .role ~ .role { margin-left:0; }
ul.leagues li.member.me { border-color:var(--accent); background:var(--tint); }
ul.leagues li.member button { font-size:.8rem; padding:.15rem .6rem; }
ul.leagues li.member .you { font-size:.8rem; font-weight:600; color:var(--accent); }

/* League settings (#204): the four cards, then one save for all of them. */
.settings .per-position { flex-direction:row; align-items:center; gap:.3rem; font-size:.85rem; }
.settings .per-position input { width:3.5rem; }
.settings label.inline { flex-direction:row; align-items:center; gap:.4rem; }
.settings-save { display:flex; justify-content:flex-end; margin-top:.75rem; }

/* Every standings table, the league's and the round's, in one compact card: read at a
   glance, one line a row, and no wider than its four or five columns need. The movement
   arrow sits beside the chip rather than under it, which is what keeps a row one line. */
.standings-card { max-width:34rem; }

/* The league's page above the activity: the table at its own width, the fixtures filling
   what is left, and the pair ending level with the activity card under them. One column
   under this, where two would leave each too narrow to read. */
.league-top { display:grid; grid-template-columns:minmax(0, 28rem) minmax(0, 1fr);
  align-items:start; gap:1.5rem; margin-bottom:1rem; }
@media (max-width: 60rem) { .league-top { grid-template-columns:minmax(0, 1fr); } }
.league-top .standings-card { max-width:none; }
/* The heading and the season beside it, on the line the era menu sits on: the page's own
   h2 margin would drop the heading below the menu. */
.standings-head { display:flex; align-items:center; gap:.5rem; min-width:0; flex:1; }
.standings-head h2 { margin:0 auto 0 0; }
/* Beside the table there is room for one scoreboard a row, not two. */
.league-top ol.matches { grid-template-columns:minmax(0, 1fr); margin:0; }
/* Match cards inside a flush card keep a gutter, so they do not touch its edges. */
.flush ol.matches { margin:0; padding:.6rem .65rem; }
/* The round picker as a card's heading: across the whole head, and a size down from the
   page title it used to be, so it reads as this card's title. */
.round-card .card-head { padding:.4rem .75rem; }

.standings-card table.standings { margin:0; font-size:.92rem; }
.standings-card table.standings th { padding:.3rem .45rem; font-size:.76rem; }
.standings-card table.standings td { padding:.3rem .45rem; }
.standings-card table.standings td.place > .stack { flex-direction:row; gap:.2rem; }
.standings-card table.standings td.place > .stack::before { content:none; }
.standings-card table.standings td.place .moved { height:auto; min-width:1.4rem; justify-content:flex-start; }
.standings-card table.standings .rank { min-width:1.9rem; height:1.3rem; font-size:.74rem; }

/* A phone gives the team name what the numbers leave: the standing, the avatar and the
   figures are all packed tight, the arrow sits under the chip, and the table is never wider
   than the card it is in. */
@media (max-width:40rem) {
  .standings-card table.standings { font-size:.85rem; }
  .standings-card table.standings th { padding:.3rem .25rem; font-size:.7rem; }
  .standings-card table.standings td { padding:.3rem .25rem; }
  .standings-card table.standings td.place > .stack { flex-direction:column; gap:0; }
  .standings-card table.standings td.place .moved { min-width:0; justify-content:center; font-size:.6rem; }
  .standings-card table.standings .rank { min-width:1.5rem; height:1.2rem; font-size:.7rem; }
  .standings-card table.standings td.team .named { gap:.3rem; }
  .standings-card table.standings td.num .muted { font-size:.68rem; }
}

/* The invite code and the league name, when a page puts them in the card. ::deep: it is the
   page's markup, so these are global rules. Each is a label over one line: the code with its Reset button beside it, the
   name input filling the row with Rename beside it. */
.commissioner-card .invite { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem .6rem; margin-bottom:1rem; }
.commissioner-card .invite-label { flex:1 0 100%; font-size:.8rem; text-transform:uppercase; letter-spacing:.05em; opacity:.7; }
.commissioner-card .invite p.code { margin:0; }
.commissioner-card .invite button { margin:0; }
.commissioner-card .rename { display:flex; flex-wrap:wrap; gap:.4rem .6rem; align-items:flex-end; margin-bottom:1rem; }
.commissioner-card .rename label { flex:1 1 14rem; min-width:0; display:flex; flex-direction:column; align-items:stretch; gap:.25rem; }
.commissioner-card .rename input { width:100%; box-sizing:border-box; min-width:0; }
.commissioner-card .rename button { flex:none; }
.commissioner-card .rename .error { flex-basis:100%; margin:0; order:3; }
/* The re-draft button and its kin sit on their own line under the fields. */
.commissioner-card .commissioner-actions { margin-top:.25rem; }
@media (max-width:40rem) {
  .commissioner-card .invite p.code { font-size:1.2rem; padding:.35rem .6rem; letter-spacing:.14em; }
  .commissioner-card .rename label { flex-basis:100%; }
  .commissioner-card .rename button { width:100%; }
  .commissioner-card .commissioner-actions button { flex:1 1 100%; }
}

/* Choosing the drop for a claim (#487): a row that cannot be the drop is marked rather than hidden. */
.squad th.pick, .squad td.pick { width:1%; white-space:nowrap; text-align:center; }
.squad td.pick .no-drop { color:var(--muted); cursor:help; }

/* The Watchlist (#497): a star per player, a filter button, and a list on a manager's page. */
.watch-toggle { background:none; border:0; padding:0; margin:0 0 0 .25rem; min-width:2.25rem; min-height:2.25rem;
  font-size:1.2rem; line-height:1; cursor:pointer; color:var(--muted); vertical-align:middle; }
.watch-toggle.on { color:var(--accent); }
.watch-toggle:disabled { opacity:.5; cursor:default; }
td.watch-col .watch-toggle { display:block; margin:0 auto; min-width:2rem; min-height:2rem; }
.watchlist-filter { border:0; background:none; color:inherit; font:inherit; font-weight:600; font-size:.9rem;
  padding:.3rem .4rem; white-space:nowrap; cursor:pointer; }
.watchlist-filter.on { color:var(--accent); }
@media (max-width: 40rem) { .watchlist-filter { font-size:.9rem; padding:.3rem .3rem; } .watchlist-filter .watchlist-word { display:none; } }
.watchlist { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.4rem; }
.watchlist li { display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; }
.watchlist .name { background:none; border:0; padding:0; color:var(--ink); cursor:pointer; text-align:left; }

/* The league home's draft card (#513): above the table, the accent when the pick is yours. */
.draft-card { margin-bottom:1rem; }
.draft-card.your-turn { border-color:var(--accent); background:color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.draft-card-line { display:flex; align-items:center; gap:.5rem; margin:0 0 .5rem; font-weight:600; }
.draft-card-line .live-dot { width:.6rem; height:.6rem; border-radius:50%; background:var(--accent); flex:none; }

/* A player the squad can't take: greyed, with the reason in a few words (#521). */
.drafting .why { display:block; font-size:.7rem; color:var(--muted, #6b7280); line-height:1.1; text-align:right; }
.drafting ol.queue li.blocked .named .name { opacity:.55; text-decoration:line-through; }
.drafting ol.queue li.blocked .named .why { color:var(--danger, #b91c1c); text-align:left; white-space:nowrap; }
.draft-players td.act .acts { flex-wrap:wrap; justify-content:flex-end; }

/* The draft selector sits above the results or the clock, one compact button (#523). */
.draft-picker { margin:.25rem 0 .5rem; }

/* The bar Blazor reveals when the connection's circuit fails; hidden until it does. */
#blazor-error-ui { display:none; position:fixed; left:0; right:0; bottom:0; z-index:1000;
  padding:.75rem 1rem; background:var(--surface); color:var(--ink); border-top:2px solid var(--bad);
  box-shadow:0 -2px 8px rgb(0 0 0 / .15); }
#blazor-error-ui .reload { margin-left:.5rem; font-weight:600; }
#blazor-error-ui .dismiss { position:absolute; right:.75rem; top:.5rem; background:none; border:0;
  color:inherit; font-size:1.25rem; cursor:pointer; }

/* The server error page (Errors/ErrorPageHtml.cs), which has no component to style it. */
.error-page { text-align:center; }
.error-page .error-actions { display:flex; gap:.75rem; justify-content:center; flex-wrap:wrap; }
.error-page code { user-select:all; }
.error-page .error-detail { text-align:left; white-space:pre-wrap; overflow-wrap:anywhere; font-size:.75rem; }
