/* ── The official Premier League typeface ─────────────────────────────────────
   Self-hosted (79 KB, five woff2 files) rather than hotlinked, so the site does not
   depend on premierleague.com staying put. Their own CSS declares a separate FAMILY
   per weight (PremierSans-Regular / -Bold / -Light); collapsed here into one family
   with real weight ranges so `font-weight:700` just works and every existing weight in
   this stylesheet resolves sensibly. Only Light/Regular/Bold exist, so the 600-900
   range all maps to Bold — which is what the real app does too.

   Proprietary font, used here on a private site for one mini-league at the owner's
   explicit direction. Not for a commercial deployment. */
@font-face{font-family:PremierLeague;src:url(/fonts/PremierLeague-Light.woff2) format('woff2');
  font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:PremierLeague;src:url(/fonts/PremierLeague-Regular.woff2) format('woff2');
  font-weight:400 500;font-style:normal;font-display:swap}
@font-face{font-family:PremierLeague;src:url(/fonts/PremierLeague-Bold.woff2) format('woff2');
  font-weight:600 900;font-style:normal;font-display:swap}
@font-face{font-family:PremierLeague;src:url(/fonts/PremierLeague-Italic.woff2) format('woff2');
  font-weight:400 500;font-style:italic;font-display:swap}
@font-face{font-family:PremierLeague;src:url(/fonts/PremierLeague-BoldItalic.woff2) format('woff2');
  font-weight:600 900;font-style:italic;font-display:swap}

/* fantasy.temirulan.com — light and dark, with the light set as the base.
   Every text colour was picked to clear WCAG AA (4.5:1) on its own surface.

   Three states, which is what "default to the device" actually requires:
     - no data-theme attribute  -> follow the operating system
     - data-theme="light"       -> forced light, even on a dark phone
     - data-theme="dark"        -> forced dark, even on a light phone
   The dark values live in ONE block below, applied by two selectors so the explicit
   choice beats the system preference in both directions. Nothing else in this file
   should ever define a colour inside a media query. */
:root{
  color-scheme:light;
  /* ── The official Fantasy Premier League palette ──────────────────────────────
     Taken from fantasy.premierleague.com's own --ism-* design tokens rather than
     guessed. The thing I had wrong before was the GREY: FPL's neutrals are tinted
     toward the brand purple (#faf9fa, #f5f2f5, #ebe5eb), and their body text is the
     purple #37003c, not a near-black. A cool blue-grey palette reads as "some fantasy
     site"; this reads as Fantasy Premier League.                                    */

  /* brand */
  --purple:#37003c;        /* --ism-color-brand-purple, the whole identity */
  --lilac:#953bff;         /* --ism-color-brand-lilac */
  --pop:#00ff87;           /* the signature green: a FILL, never text */
  --pop-deep:#01fc7a;      /* --ism-color-difficulty-2-background */

  /* the mono ramp — every one of these is purple-tinted */
  --bg:#faf9fa;            /* mono-p2  — the page */
  --surface:#ffffff;
  --surface2:#f5f2f5;      /* mono-p5 */
  --surface3:#ebe5eb;      /* mono-p10 */
  --line:#ebe5eb;          /* mono-p10 */
  --line2:#d7ccd8;         /* mono-p20 */
  --ink:#37003c;           /* mono-p100 — body text is the brand purple */
  --ink2:#541e5d;          /* mono-p80 */
  --cap:#7d5980;           /* mono-p70 */
  --faint:#af99b1;         /* mono-p40 */

  /* accent = purple. In FPL the accent IS the brand, with green used as a fill. */
  --acc:#37003c;
  --acc-deep:#1e0021;      /* mono-p120 */
  --acc-wash:#f3ebf4;
  --acc-edge:#d7ccd8;

  /* semantics */
  --up:#1c7c47;
  --up-wash:#e3f7ec;
  --down:#e60023;          /* --ism-color-system-error */
  --down-wash:#fff2f4;     /* --ism-color-system-error-container */
  --warn:#8a5a00;
  --warn-wash:#fdf3e0;
  --gold:#8a6400;
  --info:#953bff;          /* brand lilac */
  --info-wash:#f4ecff;
  --card:var(--surface);
  --accent:var(--lilac);

  /* Text that sits ON a solid --acc or --up fill. It is NOT simply white: in dark the
     accent inverts to a light lilac, so white-on-accent drops to 1.95:1. Naming the
     pairing means every button, chip and bracket card follows the theme for free. */
  --on-acc:#ffffff;
  --on-up:#ffffff;
  --on-ink:#ffffff;           /* --ink is body text in light and a FILL in a few places */
  --on-acc-pop:#00ff87;       /* the signature green, when it sits on an accent fill */
  --on-acc-soft:#c9aecb;      /* the quieter second line on an accent fill */
  --on-up-soft:#b6ddc9;

  /* The pitch: shirts sit on a green field in both themes, but the name plate under
     each one is a surface and has to follow the theme like any other. */
  --plate:#ffffff;
  --plate-ink:#1c1c22;
  --plate-sub:#eceef2;
  --plate-sub-ink:#3d3d46;
  /* the bench: a paler strip below the turf, in whichever direction "paler" means */
  --bench-a:#cfeadd; --bench-b:#f4faf7; --bench-card:rgba(255,255,255,.42);

  /* fixture difficulty — the official five, exactly */
  --fdr1-bg:#375523; --fdr1-ink:#ffffff;
  --fdr2-bg:#01fc7a; --fdr2-ink:#37003c;
  --fdr3-bg:#e7e7e7; --fdr3-ink:#37003c;
  --fdr4-bg:#ff1751; --fdr4-ink:#000000;
  --fdr5-bg:#80072d; --fdr5-ink:#ffffff;

  /* the official radius scale (--ism-radius-*) */
  --r-tag:4px;             /* xs */
  --r-obj:8px;             /* s  */
  --r-mid:12px;            /* m  */
  --r-lift:16px;           /* l  */
  --r-pill:9999px;         /* full */
  --radius:var(--r-mid);
  --radius-sm:var(--r-obj);
  --rail:3px;
  --spot:var(--line2);

  --shadow:0 0 #0000;
  --shadow-lg:0 4px 12px rgba(55,0,60,.10), 0 24px 48px -20px rgba(55,0,60,.24);
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}


/* ── dark ────────────────────────────────────────────────────────────────────
   Not an inversion. FPL's neutrals are tinted toward the brand purple and so are
   these: the darks are purple-blacks rather than grey-blacks, which is what keeps
   the site looking like Fantasy Premier League with the lights off rather than like
   a generic dark theme. The signature green and the masthead gradient are unchanged
   — they were already dark-ground colours and they are the identity.

   The accent has to INVERT its role. In light, --acc is the brand purple used as
   dark text and dark fills; on a dark ground it has to become a light lilac or it
   disappears. Anything that reads --acc for text gets that automatically.

   Written once and applied twice: the media query for "follow the device", the
   attribute for "the reader chose". :not([data-theme="light"]) is what lets a light
   choice win on a dark phone. */
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){
  color-scheme:dark;
  --bg:#150019; --surface:#1f0725; --surface2:#2a0f31; --surface3:#3a1a42;
  --line:#331540; --line2:#4b2b54;
  --ink:#f7eff9; --ink2:#dcc9e0; --cap:#ab92b0; --faint:#7d6283;
  --acc:#cfa9ff; --acc-deep:#e8d8ff; --acc-wash:#2b1237; --acc-edge:#4b2b54;
  --up:#4ade80; --up-wash:#0e2f1d; --down:#ff7089; --down-wash:#3b101a;
  --warn:#f2bd4a; --warn-wash:#34250b; --gold:#eac94a;
  --info:#cfa9ff; --info-wash:#2b1237;
  --accent:#cfa9ff;
  --on-acc:#1b0620; --on-up:#08240f; --on-ink:#150019; --on-acc-pop:#064a24;
  --on-acc-soft:#4a2357; --on-up-soft:#12421f;
  --plate:#2a1030; --plate-ink:#f7eff9; --plate-sub:#3a1a42; --plate-sub-ink:#dcc9e0;
  --bench-a:#0e2a1c; --bench-b:#0a1c14; --bench-card:rgba(0,0,0,.28);
  --shadow-lg:0 4px 12px rgba(0,0,0,.5), 0 24px 48px -20px rgba(0,0,0,.7);
  --fdr3-bg:#3a3a3f; --fdr3-ink:#f7eff9;
} }
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#150019; --surface:#1f0725; --surface2:#2a0f31; --surface3:#3a1a42;
  --line:#331540; --line2:#4b2b54;
  --ink:#f7eff9; --ink2:#dcc9e0; --cap:#ab92b0; --faint:#7d6283;
  --acc:#cfa9ff; --acc-deep:#e8d8ff; --acc-wash:#2b1237; --acc-edge:#4b2b54;
  --up:#4ade80; --up-wash:#0e2f1d; --down:#ff7089; --down-wash:#3b101a;
  --warn:#f2bd4a; --warn-wash:#34250b; --gold:#eac94a;
  --info:#cfa9ff; --info-wash:#2b1237;
  --accent:#cfa9ff;
  --on-acc:#1b0620; --on-up:#08240f; --on-ink:#150019; --on-acc-pop:#064a24;
  --on-acc-soft:#4a2357; --on-up-soft:#12421f;
  --plate:#2a1030; --plate-ink:#f7eff9; --plate-sub:#3a1a42; --plate-sub-ink:#dcc9e0;
  --bench-a:#0e2a1c; --bench-b:#0a1c14; --bench-card:rgba(0,0,0,.28);
  --shadow-lg:0 4px 12px rgba(0,0,0,.5), 0 24px 48px -20px rgba(0,0,0,.7);
  --fdr3-bg:#3a3a3f; --fdr3-ink:#f7eff9;
}

*,*::before,*::after{box-sizing:border-box}
/* `hidden` must actually hide. The attribute's own UA rule is display:none, but ANY class
   that sets display wins on specificity — so `.whoami{display:flex}` plus `el.hidden =
   true` left the element fully visible. That silently defeated the Cup's collapsed
   manager picker and the Awards "more nominations" panel, both of which set .hidden on a
   grid or flex container. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
body{font-variant-numeric:tabular-nums;
  margin:0;min-height:100vh;background:var(--bg);color:var(--ink);
  font:15px/1.5 'Inter',system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;
;font-family:PremierLeague,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}
h1,h2,h3,h4,p{margin:0}
a{color:var(--acc-deep);text-decoration:none}
a:hover{text-decoration:underline}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--acc);outline-offset:2px;border-radius:var(--r-tag)}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.num{font-variant-numeric:tabular-nums}

/* ── header ── */
/* ── the masthead, as the official app does it ────────────────────────────────
   A purple bar with the wordmark in white and the signature green, and the nav as
   pills ON the purple rather than underlined tabs on white. This one element does
   more to make the site read as Fantasy Premier League than anything else. */
header{position:sticky;top:0;z-index:50;background:var(--purple);
  background-image:linear-gradient(103deg,var(--purple) 0%,#4a0b52 52%,#2b6d64 88%,#1f8f6d 100%);
  border-bottom:0;color:#fff}
.bar{max-width:1240px;margin:0 auto;padding:13px 20px;display:flex;align-items:center;gap:14px}
/* flex-shrink:0 is load-bearing: the bar is a flex row and the right-hand chips do not
   shrink, so the wordmark was being crushed to 36px while its text — which has nothing to
   clip it — kept painting at full width, straight over the chips. */
.brand{display:flex;align-items:baseline;gap:7px;font-weight:800;font-size:17px;
  letter-spacing:-.02em;color:#fff;flex-shrink:0}
/* Idea #41: "fantasy" and ".temirulan.com" are one URL, so the 7px flex gap between
   them read as a typo. Cancel it for the domain only; the emoji keeps its gap. */
.brand .dom{color:var(--pop);font-weight:700;font-size:13px;letter-spacing:0;margin-left:-7px}
.bar-right{margin-left:auto;display:flex;align-items:center;gap:9px;font-size:12px;
  color:rgba(255,255,255,.78);min-width:0}
/* A long phase label must eat into itself, never push the name chip off the screen. */
.bar-right .pill{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.livedot{width:7px;height:7px;border-radius:50%;background:var(--pop);display:inline-block;
  box-shadow:0 0 0 3px rgba(0,255,135,.28)}
/* pills in the header sit on purple, so they invert */
header .pill{border-radius:var(--r-pill);background:rgba(255,255,255,.16);color:#fff;border-color:transparent}
header .pill.down{background:rgba(0,255,135,.18);color:var(--pop)}
header .mechip{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.28);color:#fff}
header .mechip:hover,header .mechip.on{background:var(--pop);border-color:var(--pop);
  color:var(--purple)}

/* The tab strip WRAPS on a phone instead of scrolling sideways.
   Measured, not guessed: at 390px the strip was 863px wide against 485px visible, so
   League / My Team / Players / Cup / Ownership were reachable and Duel / Awards / Prices /
   Availability / Ideas were off-screen. The click data lines up almost exactly — the five
   visible tabs were opened by 8-12 of 12 people, the five hidden ones by 4-8. Half the app
   was behind a gesture nobody made. Two compact rows cost ~34px of height and nothing else. */
nav.tabs{max-width:1240px;margin:0 auto;padding:0 14px 10px;display:flex;gap:4px;
  flex-wrap:wrap;row-gap:5px}
@media (min-width:900px){ nav.tabs{flex-wrap:nowrap} }
nav.tabs button{background:rgba(255,255,255,.10);border:0;color:rgba(255,255,255,.82);
  font-weight:700;font-size:13px;padding:7px 13px;cursor:pointer;white-space:nowrap;
  border-radius:var(--r-pill);transition:background .12s ease,color .12s ease}
nav.tabs button:hover{background:rgba(255,255,255,.2);color:#fff}
/* the active tab is a solid white pill with purple text — straight from the real app */
nav.tabs button[aria-selected="true"]{background:#fff;color:var(--purple)}

main{max-width:1240px;margin:0 auto;padding:22px 20px 72px}
@media (max-width:560px){ .bar{padding:11px 14px} main{padding:16px 14px 60px} }

/* ── primitives ── */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow)}
.pad{padding:16px}
.card.pad{padding:16px}
.sec{font-size:11.5px;font-weight:800;letter-spacing:.13em;text-transform:uppercase;
  color:var(--cap);margin:0 0 8px}
/* A section label belongs to the content BENEATH it, so its spacing is asymmetric:
   pushed away from the previous block, tight to its own. This used to be repeated
   inline 23 times as margin:22px 0 8px; keyed off structure instead, a label that is a
   direct child of a view is a page-level section, one nested inside a card is not. */
.view > .sec{margin:24px 0 8px}
.view > .sec:first-child{margin-top:0}
.h1{font-size:clamp(22px,3vw,30px);font-weight:800;letter-spacing:-.025em}
.h2{font-size:18px;font-weight:750;letter-spacing:-.015em}
.lede{color:var(--ink2);max-width:62ch}

/* ── the page header, one shape for all twelve views ──────────────────────────
   Each view used to build its own, and the sizes had drifted. The title and any control
   that belongs to it share a line, because a lone chip is not worth 44px of its own row. */
.phead{margin-bottom:12px}
.phead-top{display:flex;align-items:center;justify-content:space-between;gap:10px;
  flex-wrap:wrap}
.phead .lede{margin-top:3px;line-height:1.5}
/* Two lines, then an ellipsis you can tap. These ledes explain the page once and are then
   re-read on every visit forever; the third line was pure cost. Full text on desktop,
   where the room exists. */
@media (max-width:560px){
  .clamp2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
    overflow:hidden;cursor:pointer}
}
.muted{color:var(--cap)}
.tiny{font-size:12px}
.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.spread{display:flex;align-items:center;justify-content:space-between;gap:12px}
.grid{display:grid;gap:14px}
.g2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.stack{display:flex;flex-direction:column;gap:14px}

.btn{display:inline-flex;align-items:center;gap:7px;padding:9px 15px;border-radius:var(--r-pill);
  border:1px solid var(--acc);background:var(--acc);color:var(--on-acc);font-weight:700;font-size:13.5px;
  cursor:pointer;min-height:40px}
.btn:hover{background:var(--acc-deep);border-color:var(--acc-deep);text-decoration:none}
.btn.ghost{background:var(--surface);color:var(--ink2);border-color:var(--line2)}
.btn.ghost:hover{background:var(--surface2);color:var(--ink)}
.btn:disabled{opacity:.55;cursor:default}
.chip{display:inline-flex;align-items:center;gap:6px;padding:6px 11px;border-radius:var(--r-pill);
  background:var(--surface);border:1px solid var(--line2);color:var(--ink2);font-size:12.5px;
  font-weight:650;cursor:pointer;min-height:34px}
.chip:hover{background:var(--surface2);color:var(--ink)}
.chip[aria-pressed="true"]{background:var(--acc);border-color:var(--acc);color:var(--on-acc)}
.pill{border-radius:var(--r-pill);display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:var(--r-pill);
  font-size:11px;font-weight:750;letter-spacing:.02em;background:var(--surface2);color:var(--ink2)}
.pill.up{background:var(--up-wash);color:var(--up)}
.pill.down{background:var(--down-wash);color:var(--down)}
.pill.warn{background:var(--warn-wash);color:var(--warn)}
.pill.info{background:var(--info-wash);color:var(--info)}
.pill.acc{background:var(--acc-wash);color:var(--acc-deep)}
input[type=text],input[type=search],input[type=number],select,textarea{
  background:var(--surface);border:1px solid var(--line2);border-radius:var(--radius-sm);
  padding:9px 11px;min-height:40px;color:var(--ink);outline:none;width:100%}
input:focus,select:focus,textarea:focus{border-color:var(--acc)}
label.f{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:650;color:var(--cap)}
label.f select,label.f input{width:auto;min-width:96px}

/* ── tables ── */
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:0;
  border:0;border-top:2px solid var(--ink);background:none;box-shadow:none;
  position:relative}
/* A clipped column looks broken; a fading edge looks swipeable. `has-more` is set by
   table() only when the table really is wider than its box, and cleared once you have
   scrolled to the end, so a table that fits carries no decoration at all.
   Masking the container beats a positioned pseudo-element: a sticky ::after inside a
   scroll box that contains a table does not reliably paint, and a mask needs no layout
   participation at all. */
.tscroll.has-more{
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 30px),transparent);
  mask-image:linear-gradient(to right,#000 calc(100% - 30px),transparent)}
.tscroll.has-more.at-end{-webkit-mask-image:none;mask-image:none}
table{border-collapse:separate;border-spacing:0;width:100%;font-size:13.5px}
thead th{position:sticky;top:0;z-index:2;background:var(--bg);color:var(--cap);
  font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  padding:10px 12px;text-align:right;white-space:nowrap;border-bottom:1px solid var(--line);border-bottom:1px solid var(--line2)}
thead th.l{text-align:left}
thead th.sortable{cursor:pointer;user-select:none}
thead th.sortable:hover{color:var(--ink)}
thead th[aria-sort]{color:var(--acc-deep)}
tbody td{padding:9px 12px;text-align:right;border-bottom:1px solid var(--line);
  white-space:nowrap;font-variant-numeric:tabular-nums}
tbody td.l{text-align:left;font-variant-numeric:normal}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--surface2)}
tbody tr:last-child td{border-bottom:2px solid var(--ink)}
tbody tr.me{background:var(--acc-wash)}
tbody tr.me:hover{background:#daeee4}
.stick{position:sticky;left:0;background:var(--surface);z-index:1}
tbody tr:hover .stick{background:var(--surface2)}
thead th.stick{z-index:3;background:var(--bg)}
/* Every row tint needs a matching .stick rule or the sticky first column shows the
   wrong colour mid-scroll — on the exact device everyone here uses. tr.mine was
   missing one. */
tbody tr.mine .stick{background:var(--info-wash)}
tbody tr.mine:hover .stick{background:var(--info-wash)}
td.big{font-weight:750;color:var(--ink)}

/* ── position + FDR ── */
.pos{display:inline-block;min-width:34px;text-align:center;font-size:10px;font-weight:800;
  padding:3px 5px;border-radius:var(--r-tag);letter-spacing:.04em}
.pos.GKP{background:#fdf0d6;color:#7a5600}
.pos.DEF{background:#e2ecfd;color:#1c4a8f}
.pos.MID{background:#d9f2e5;color:#0a5c38}
.pos.FWD{background:#fde0e6;color:#8f1d3c}
.fdr{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
  min-width:34px;padding:3px 4px;border-radius:var(--r-tag);font-size:10px;font-weight:750;line-height:1.25}
.fdr b{font-size:10.5px;font-weight:800;letter-spacing:.01em}
.fdr u{text-decoration:none;font-size:8.5px;font-weight:800;opacity:.85}
.fdr i{font-style:normal;font-size:8.5px;opacity:.8}
.fdr.d1{background:var(--fdr1-bg);color:var(--fdr1-ink)}
.fdr.d2{background:var(--fdr2-bg);color:var(--fdr2-ink)}
.fdr.d3{background:var(--fdr3-bg);color:var(--fdr3-ink)}
.fdr.d4{background:var(--fdr4-bg);color:var(--fdr4-ink)}
.fdr.d5{background:var(--fdr5-bg);color:var(--fdr5-ink)}
.strip{display:inline-flex;gap:3px}

/* availability — icon + text, never colour alone */
.flag{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;
  padding:2px 8px;border-radius:var(--r-pill)}
.flag.ok{background:var(--acc-wash);color:var(--acc-deep)}
.flag.d75{background:var(--warn-wash);color:var(--warn)}
.flag.d50{background:#fde8d4;color:#8a4a06}
.flag.d25{background:var(--down-wash);color:var(--down)}
.flag.out{background:#f3e3e1;color:#7a1c14}
.flag.susp{background:#ece4f7;color:#59328f}

/* deltas */
.delta{font-weight:750;font-variant-numeric:tabular-nums}
.delta.up{color:var(--up)} .delta.down{color:var(--down)} .delta.flat{color:var(--cap)}

/* sparkline / bars */
.spark{display:block}
.spark path{fill:none;stroke:var(--acc);stroke-width:1.6;vector-effect:non-scaling-stroke}
.spark .area{fill:var(--acc-wash);stroke:none}
.meter{display:block;height:7px;border-radius:var(--r-pill);background:var(--surface3);overflow:hidden}
.meter>i{display:block;height:100%;border-radius:var(--r-pill);background:var(--acc)}
.meter.down>i{background:var(--down)}

/* stat tiles */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px}
.tile{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-obj);
  padding:12px 14px}
.tile b{display:block;font-size:22px;font-weight:800;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.tile span{display:block;margin-top:2px;font-size:10.5px;font-weight:750;letter-spacing:.1em;
  text-transform:uppercase;color:var(--cap)}
.tile.acc b{color:var(--acc-deep)}

/* empty / pre-season states are first-class: the site launches before GW1 */
.empty{padding:40px 22px;text-align:center;color:var(--cap);background:var(--surface);
  border:1px dashed var(--line2);border-radius:var(--radius)}
.empty b{display:block;color:var(--ink);font-size:15.5px;font-weight:750;margin-bottom:5px}
.empty .btn{margin-top:14px}
.skel{padding:34px;text-align:center;color:var(--cap)}

/* countdown */
.cd{display:flex;align-items:baseline}
.cd div{background:none;border:0;border-right:1px solid var(--line);border-radius:0;
  padding:0 16px;text-align:left;min-width:0;flex:0 0 auto}
.cd div:last-child{border-right:0}
.cd div:first-child{padding-left:0}
.cd b{display:block;font-size:clamp(24px,7vw,32px);font-weight:800;letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:var(--ink)}
.cd span{font-size:9.5px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;color:var(--cap)}

/* award cards */
/* A gameweek's verdict is ONE ROW you swipe, not a column you scroll past. Stacked, a
   single gameweek filled most of a phone and the season before it was invisible; laid
   sideways the page reads down as a season instead of down as one week. */
/* A wrapping grid, never a swipe. Awards sit side by side — the point of going
   horizontal was to stop one gameweek being eight full-width rows — but a strip you have
   to drag sideways hides half of them behind a gesture nobody makes. Two up on a phone,
   more as the screen allows, and the whole gameweek is on screen at once. */
.awards{display:grid;gap:7px;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));
  padding:0 0 2px;align-items:stretch}
.award{position:relative;
  background:var(--surface);border:1px solid var(--line);border-left:0;
  border-radius:0 var(--r-obj) var(--r-obj) 0;
  padding:8px 9px 9px 10px;box-shadow:none;display:flex;
  flex-direction:column;gap:3px;--spot:var(--line2);min-width:0}
.award::before{content:'';position:absolute;left:0;top:0;bottom:0;
  width:var(--rail);background:var(--spot);border-radius:1px 0 0 1px}
/* the emoji rides beside the label instead of costing a line of its own */
.award .em{position:absolute;right:8px;top:7px;opacity:.85}
@media (min-width:640px){
  .awards{gap:9px;grid-template-columns:repeat(auto-fill,minmax(196px,1fr))}
  .award{padding:11px 12px 12px 13px;gap:5px}
}
.award.good{--spot:var(--acc)}
.award.bad{--spot:var(--down)}
.award .em{font-size:15px;line-height:1}
.award .lab{font-size:9px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--cap);padding-right:18px;line-height:1.25}
.award .who{font-size:13px;font-weight:780;letter-spacing:-.015em;line-height:1.25;
  overflow-wrap:anywhere}
.award .det{font-size:11px;line-height:1.3}
.award .tiny{font-size:10px;line-height:1.3}
.award .pill{font-size:9.5px;padding:2px 6px;align-self:flex-start}
@media (min-width:640px){
  .award .em{font-size:20px}
  .award .lab{font-size:11px;letter-spacing:.1em;padding-right:22px}
  .award .who{font-size:16px}
  .award .det{font-size:12.5px}
  .award .tiny{font-size:11px}
}
/* the winner's name opens that manager — the most-tapped dead element in the whole app */
.award .wholink{cursor:pointer;text-decoration:underline;text-decoration-style:dotted;
  text-underline-offset:3px}
.award .det{color:var(--ink2)}
.award.bad{border-color:#f0cfcb}
.award.good{border-color:var(--acc-edge)}

/* ownership grid */
.ogrid{overflow:auto;max-height:74vh}
.ogrid table{font-size:12px}
.ogrid td,.ogrid th{padding:6px 7px}
.ogrid .own{text-align:center;color:var(--cap)}
.ogrid .own.has{background:var(--acc-wash);color:var(--acc-deep);font-weight:750}
.ogrid .own.cap{background:#fdf0d6;color:#7a5600;font-weight:800}
.ogrid .own.uniq{outline:2px solid var(--info);outline-offset:-2px}

/* misc */
.feed{display:flex;flex-direction:column;gap:8px}
.feeditem{display:flex;gap:10px;align-items:flex-start;padding:11px 0;background:none;
  border:0;border-bottom:1px solid var(--line);border-radius:0;font-size:13px}
.feeditem .when{margin-left:auto;color:var(--cap);font-size:11.5px;white-space:nowrap}
.modal{position:fixed;inset:0;z-index:100;background:rgba(15,21,34,.42);display:none;
  align-items:center;justify-content:center;padding:18px}
.modal.open{display:flex}
.sheet{background:var(--surface);border-radius:var(--r-lift);box-shadow:var(--shadow-lg);
  max-width:660px;width:100%;max-height:88vh;overflow:auto;padding:22px;position:relative}
.closer{position:absolute;top:12px;right:14px;font-size:22px;color:var(--cap);cursor:pointer;
  background:none;border:0;line-height:1;padding:4px 8px;border-radius:var(--r-obj)}
.closer:hover{background:var(--surface2);color:var(--ink)}

/* the header has three things competing for one line; on a phone the brand wins */
@media (max-width:560px){
  .bar{gap:8px;flex-wrap:nowrap}
  .brand{font-size:15px;white-space:nowrap;min-width:0}
  .brand .dom{display:none}
  .bar-right{gap:7px;font-size:11.5px;flex:none}
  #freshness{display:none}
  /* auto-fit left a ragged 3+1 whenever a tile's value was a long name; a fixed pair of
     columns is a clean 2x2 and reads as deliberate. */
  .tiles{grid-template-columns:1fr 1fr;gap:8px}
  .tile{padding:10px 11px} .tile b{font-size:19px}
  /* .awards is a horizontal strip now; a single-column override would undo it */
  .g2,.g3{grid-template-columns:1fr}
  thead th,tbody td{padding:8px 9px}
}

/* rows and cards that open a modal are real controls: they must show focus */
tr[tabindex]:focus-visible,[role="button"]:focus-visible{
  outline:2px solid var(--acc);outline-offset:-2px}
tr[tabindex]{cursor:pointer}

/* ── A–D grade badge. Letter + colour, and the letter is the primary signal so it
   survives monochrome. Grades are ranked WITHIN a position, never across. ── */
.gr{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:22px;
  padding:0 6px;border-radius:var(--r-tag);font-size:11.5px;font-weight:800;letter-spacing:.01em}
.gr.a{background:#cdefdd;color:#08512f}
.gr.b{background:#e2f0d4;color:#3c6114}
.gr.c{background:#fdeecf;color:#7a5000}
.gr.d{background:#fbd8d2;color:#8a2318}
.gr.nr{background:var(--surface3);color:var(--cap);font-weight:700}
.gr.big{min-width:46px;height:34px;font-size:17px;border-radius:9px}

/* grade explainer rows */
.gbars{display:flex;flex-direction:column;gap:7px;margin-top:8px}
.gbar{display:grid;grid-template-columns:118px 1fr 58px;gap:9px;align-items:center;font-size:12.5px}
.gbar .lbl{color:var(--ink2);font-weight:650}
.gbar .val{color:var(--cap);text-align:right;font-variant-numeric:tabular-nums}
.gbar .w{color:var(--faint);font-size:10px}

/* screenshot dropzone */
.drop{border:2px dashed var(--line2);border-radius:var(--radius);padding:30px 20px;
  text-align:center;background:var(--surface);cursor:pointer;transition:border-color .15s,background .15s}
.drop:hover,.drop.over{border-color:var(--acc);background:var(--acc-wash)}
.drop b{display:block;font-size:15.5px;margin-bottom:4px}
.shot{max-width:100%;border-radius:var(--radius-sm);border:1px solid var(--line);display:block}
.verdict{display:flex;gap:11px;align-items:flex-start;padding:12px 14px;border-radius:var(--radius-sm);
  border:1px solid var(--line);background:var(--surface)}
.verdict .ic{font-size:16px;line-height:1.2;flex:none}
.verdict.risk{border-color:#f0cbc5;background:#fdf4f2}
.verdict.warn{border-color:#f3e0bd;background:#fdf9ef}
.verdict.good{border-color:var(--acc-edge);background:var(--acc-wash)}
.verdict.info{border-color:#c9dcf5;background:#f2f7fe}
.verdict .t{font-weight:750;font-size:13.5px}
.verdict .d{font-size:12.5px;color:var(--ink2);margin-top:2px}
.unmatched{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:9px 11px;
  border:1px dashed #e6b8b0;border-radius:var(--radius-sm);background:#fdf5f3;font-size:13px}
.spin{display:inline-block;width:14px;height:14px;border:2px solid var(--acc-edge);
  border-top-color:var(--acc);border-radius:50%;animation:sp .8s linear infinite;vertical-align:-2px}
@keyframes sp{to{transform:rotate(360deg)}}

/* ── the cup: fixtures, form and the season run ───────────────────────────── */
.fxlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:8px}
.fxr{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;
  padding:11px 13px;border:1px solid var(--line);border-radius:var(--r-obj);background:var(--card)}
.fxr.solo{max-width:430px}
.fxr.mine{border-color:var(--accent);box-shadow:0 0 0 2px var(--info-wash)}
.fxr .side{display:flex;flex-direction:column;gap:1px;min-width:0}
.fxr .side.a{text-align:right;align-items:flex-end}
.fxr .side b{font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.fxr .side span{font-size:11px;color:var(--cap);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;max-width:100%}
.fxr .sc{display:flex;align-items:center;gap:7px;font-variant-numeric:tabular-nums;
  font-weight:800;font-size:16px}
.fxr .sc em{font-style:normal;min-width:30px;text-align:center;padding:3px 6px;border-radius:var(--r-tag);
  background:var(--surface3);color:var(--ink)}
.fxr .sc em.won{background:#cdefdd;color:#08512f}
.fxr .sc em.lost{background:var(--surface3);color:var(--cap)}
.fxr .sc .v{color:var(--cap);font-weight:600;font-size:12px}
.fxr .sc.pend em{background:transparent;color:var(--cap);font-weight:600;font-size:12.5px;min-width:0}
.frm{display:inline-flex;gap:3px}
.frm i{width:17px;height:17px;border-radius:var(--r-tag);font-style:normal;font-size:10.5px;font-weight:800;
  display:inline-flex;align-items:center;justify-content:center}
.frm i.W{background:#cdefdd;color:#08512f}
.frm i.D{background:#fde9c8;color:#7a4a05}
.frm i.L{background:#fbd5d5;color:#7d1414}
tr.mine td{background:var(--info-wash)}
.run{display:flex;flex-wrap:wrap;gap:4px}
.run a{display:flex;flex-direction:column;align-items:center;gap:2px;text-decoration:none;
  min-width:46px;padding:5px 4px;border:1px solid var(--line);border-radius:var(--r-obj);background:var(--card)}
.run a:hover{border-color:var(--accent)}
.run a u{font-style:normal;text-decoration:none;font-size:9.5px;color:var(--cap);letter-spacing:.03em}
.run a b{font-size:11.5px;max-width:56px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.run a i{font-style:normal;font-size:10px;font-weight:800;border-radius:var(--r-tag);padding:0 4px}
.run a i.W{background:#cdefdd;color:#08512f}
.run a i.D{background:#fde9c8;color:#7a4a05}
.run a i.L{background:#fbd5d5;color:#7d1414}
.run a.next{border-color:var(--accent);background:var(--info-wash)}
.whoami{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.rnav{display:flex;align-items:center;gap:8px;margin:14px 0 9px}
.rnav b{font-size:15px;min-width:130px;text-align:center}
.rnav button{padding:5px 11px}

/* ── share cards ───────────────────────────────────────────────────────────── */
.share{display:inline-flex;gap:6px;align-items:center;margin-top:9px}
.share button{font-size:11.5px;padding:4px 9px;border-radius:var(--r-tag);border:1px solid var(--line);
  background:var(--card);color:var(--cap);cursor:pointer;font-weight:600}
.share button:hover{border-color:var(--accent);color:var(--accent)}
.share button:disabled{opacity:.5;cursor:default}
.share .said{font-size:11.5px;color:#08512f;font-weight:600}

.projmark{color:var(--accent);font-weight:800;font-size:12px;vertical-align:middle}

/* ── "this is me" identity chip + personal panel ──────────────────────────── */
.mechip{font:inherit;font-size:11.5px;font-weight:700;padding:4px 10px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--card);color:var(--cap);cursor:pointer;
  white-space:nowrap;max-width:44vw;overflow:hidden;text-overflow:ellipsis}
.mechip:hover{border-color:var(--accent);color:var(--accent)}
.mechip.on{background:var(--info-wash);border-color:var(--accent);color:var(--accent)}
.mepanel{border:1px solid var(--accent);border-radius:var(--r-obj);background:var(--info-wash);
  padding:14px;margin-bottom:16px}
.mepanel .top{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:11px}
.mepanel .top b{font-size:17px}
.mestat{display:grid;grid-template-columns:repeat(auto-fit,minmax(74px,1fr));gap:8px}
.mestat div{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-obj);
  padding:8px 10px}
.mestat b{display:block;font-size:18px;font-variant-numeric:tabular-nums;line-height:1.15}
/* One line, always. A single label that wraps sets the height of all five tiles, so the
   labels are kept short AND clipped rather than allowed to reflow the row. */
.mestat span{font-size:10.5px;color:var(--cap);letter-spacing:.02em;text-transform:uppercase;
  display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.melist{display:flex;flex-wrap:wrap;gap:5px;margin-top:11px}
.melist a{display:inline-flex;align-items:center;gap:4px;text-decoration:none;font-size:11.5px;
  padding:3px 8px;border-radius:var(--r-pill);border:1px solid var(--line);background:var(--card);
  color:var(--ink)}
.melist a i{font-style:normal;font-weight:800;font-variant-numeric:tabular-nums}
.melist a.played{border-color:#a9dcc0;background:#eefaf3}
.melist a.live{border-color:var(--accent);background:var(--info-wash)}
.melist a.yet{color:var(--cap)}
.mepick{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}

/* ═══ the pitch — modelled on the official FPL "Pick Team" view ═══════════════
   Mow stripes as a repeating gradient, markings drawn with borders (no images), and
   the club shirts are the official assets mirrored into /shirts so the view is
   self-contained and cannot break if premierleague.com changes a path. */
.pitchwrap{border-radius:12px;overflow:hidden;border:1px solid var(--line);
  background:#0b7a3b;margin:4px 0 0}
.pitch{position:relative;padding:16px 6px 20px;
  background:
    repeating-linear-gradient(180deg,#12a04f 0 46px,#0f9748 46px 92px);
  overflow:hidden}
/* centre circle + halfway line */
.pitch::before{content:'';position:absolute;left:0;right:0;top:50%;height:2px;
  background:rgba(255,255,255,.55)}
.pitch::after{content:'';position:absolute;left:50%;top:50%;width:104px;height:104px;
  transform:translate(-50%,-50%);border:2px solid rgba(255,255,255,.55);border-radius:50%}
/* the 18-yard box at the top, in the same flattened perspective the official app uses */
.pitch .box{position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:56%;height:74px;border:2px solid rgba(255,255,255,.6);border-top:0;
  border-radius:0 0 4px 4px}
.pitch .box6{position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:26%;height:34px;border:2px solid rgba(255,255,255,.6);border-top:0;
  border-radius:0 0 3px 3px}
.prow{position:relative;z-index:2;display:flex;justify-content:center;align-items:flex-start;
  gap:6px;margin:0 0 16px;flex-wrap:nowrap}
.prow:last-child{margin-bottom:0}

.pcard{position:relative;flex:1 1 0;min-width:0;max-width:82px;border-radius:6px;
  background:rgba(0,50,20,.30);padding:5px 3px 0;text-align:center}
.pcard.bench{background:var(--bench-card)}
.pcard img{display:block;width:100%;max-width:52px;height:auto;margin:0 auto 4px;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.25))}
.pcard .plate{background:var(--plate);border-radius:4px;overflow:hidden;
  box-shadow:0 1px 2px rgba(0,0,0,.18)}
.pcard .pname{font-size:11px;font-weight:700;color:var(--plate-ink);padding:3px 2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.25}
.pcard .pfix{font-size:10.5px;font-weight:600;color:var(--plate-sub-ink);background:var(--plate-sub);
  padding:2px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pcard .pfix.pts{background:#37003c;color:#fff;font-weight:800;font-size:11.5px}
.pcard .pfix.live{background:#00ff87;color:#37003c;font-weight:800}
/* captain / vice armband, top-left, exactly where the official app puts it */
.parm{position:absolute;top:-4px;left:-4px;width:18px;height:18px;border-radius:50%;
  background:#37003c;color:#fff;font-size:10px;font-weight:800;display:flex;
  align-items:center;justify-content:center;z-index:3;
  box-shadow:0 1px 3px rgba(0,0,0,.35)}
.parm.v{background:#fff;color:#37003c;border:1px solid #37003c}
/* Idea #48: the triple captain is a different thing from a captain and should look it.
   Signature green on the brand purple — the same pairing the masthead uses — and a little
   wider, because "3x" needs the room a single letter does not. */
.parm.tri{width:auto;min-width:22px;padding:0 4px;border-radius:9px;
  background:var(--pop);color:var(--purple);border:1px solid var(--purple);
  font-size:9.5px;letter-spacing:-.02em}
.pcard.out .plate{opacity:.62}
.pcard .flagdot{position:absolute;top:-4px;right:-4px;width:16px;height:16px;
  border-radius:50%;background:#e03131;color:#fff;font-size:10px;font-weight:800;
  display:flex;align-items:center;justify-content:center;z-index:3}

/* the bench strip, its own panel below the pitch like the official view */
.benchwrap{background:linear-gradient(180deg,var(--bench-a),var(--bench-b));padding:9px 6px 11px}
.benchhead{display:flex;justify-content:center;gap:6px;margin-bottom:5px}
.benchhead span{flex:1 1 0;max-width:82px;text-align:center;font-size:10px;font-weight:800;
  letter-spacing:.06em;color:#37003c}
.pitchfoot{display:flex;flex-wrap:wrap;gap:8px;align-items:center;
  padding:9px 11px;background:var(--surface3);font-size:11.5px;color:var(--cap)}
.pitchfoot b{color:var(--ink)}
@media (max-width:400px){
  .pcard{max-width:70px;padding:4px 2px 0}
  .pcard img{max-width:44px}
  .pcard .pname{font-size:10px}
  .pcard .pfix{font-size:9.5px}
  .benchhead span{max-width:70px}
}
/* the pitch wants width — let the sheet grow when one is inside it */
/* the panel, not the inner content div, is what carries max-width */
.sheet:has(.pitchwrap){max-width:720px}

/* The duel picker: two selects and a "v" on ONE row at every width.
   It used to stack below 520px and cost three rows plus a tray's padding — about 200px
   spent on two dropdowns. Now the options carry the manager's name only, which is short
   enough that two selects and a separator fit a 360px phone side by side. */
.duelpick{display:grid;grid-template-columns:1fr auto 1fr;gap:7px;align-items:center}
.duelpick select{width:100%;min-width:0;text-overflow:ellipsis}
.duelpick .vs{font-size:11px;font-weight:800;color:var(--cap);text-align:center}
@media (max-width:560px){
  .duelpick{gap:5px}
  .duelpick select{padding-left:8px;padding-right:16px;font-size:12.5px}
}

/* ═══════════════════════════ MATCHDAY LEDGER ═══════════════════════════════════
 * A tier system, because 26 cards were doing five different jobs in one identical
 * white 14px box — which is what "un-llm the design" was asking about.
 *
 * The organising idea is print: content is set ON the page and separated by RULES,
 * not floated above it in boxes. Only a verdict earns paper. That inverts what was
 * here before, where everything was elevated — and when everything is elevated,
 * nothing is.
 *
 * THE LAW, so the next person doesn't have to ask:
 *   pick the tier that matches the card's state — transient/notice -> .n-note,
 *   counting -> .n-strap, a figure -> .n-ledger, repeated rows -> .n-rack,
 *   controls -> .n-tray, a verdict -> .n-leader. If you can't decide, write nothing
 *   and you get .n-sheet. To make something louder, add RULE WEIGHT — never a
 *   shadow, never a second hue.
 *
 * Rule weights are the whole elevation language:
 *   1px --line   hairline inside a region
 *   1px --line2  boundary between regions
 *   2-3px ink/spot  outer edge of a region
 *
 * Deliberately NOT done: no inverted near-black panels (the site is light-only by
 * request), no translateY hover lift (13-card grids become a hover storm, and it is
 * dead on a touchscreen anyway), no radial gradient washes — that IS the templated
 * gesture this is trying to get away from.
 */

:root{
  /* Radius law: sharpness = how printed-on-the-page a thing is. Replaces
     4,5,6,7,8,9,10,11,13,16px scattered across ~20 rules. */
  --r-tag:4px;      /* inline type swatches */
  --r-obj:8px;      /* things that read as objects */
  --r-lift:14px;    /* only what genuinely floats */
  --r-pill:999px;   /* reserved for things you tap */
  --rail:3px;
  --spot:var(--line2);   /* every tier's accent comes from this one variable */
}

/* ── tier 1 · printed note — transient + state notices ───────────────────────
   No surface, no border, no radius. A rail and the words. */
.n-note{position:relative;padding:3px 0 3px 13px;font-size:13px;color:var(--ink2);
  line-height:1.45}
.n-note::before{content:'';position:absolute;left:0;top:2px;bottom:2px;
  width:var(--rail);background:var(--spot);border-radius:1px}
.n-note b,.n-note strong{color:var(--ink);font-weight:700}
.n-note.live{--spot:var(--down)}
.n-note.warn{--spot:var(--warn)}
.n-note.good{--spot:var(--acc)}
.n-note.info{--spot:var(--accent)}
/* the spinner card, replaced: a segment travels down the rail */
.n-note.working::before{background:linear-gradient(var(--line2) 0 38%,var(--acc) 38% 62%,
  var(--line2) 62% 100%);background-size:100% 260%;animation:railrun 1.5s linear infinite}
@keyframes railrun{from{background-position:0 100%}to{background-position:0 -100%}}
@media (prefers-reduced-motion:reduce){
  .n-note.working::before{animation:none;background:var(--acc)}
}

/* ── tier 2 · strap — the schedule. The one loud thing. ──────────────────── */
.n-strap{border-top:3px solid var(--spot);border-bottom:1px solid var(--line2);
  padding:12px 0 14px;background:none;border-radius:0;--spot:var(--ink)}
.n-strap.live{--spot:var(--down)}

/* ── tier 3 · ledger — a figure is top-and-tailed, not boxed ─────────────── */
.n-ledger{border:0;border-top:2px solid var(--ink);background:none;
  border-radius:0;overflow-x:auto}

/* ── tier 4 · rack — repeated rows, ruled not boxed. THE complaint. ──────── */
.n-rack{display:block}
.n-rack > *{padding:13px 0;border-bottom:1px solid var(--line);break-inside:avoid}
.n-rack > *:last-child{border-bottom:0}
/* activatable rows grow a rail instead of lifting — works on touch, no shadow */
.n-rack > *[tabindex]{position:relative;padding-left:0;
  transition:padding-left .12s ease}
.n-rack > *[tabindex]::before{content:'';position:absolute;left:0;top:8px;bottom:8px;
  width:0;background:var(--acc);transition:width .12s ease}
.n-rack > *[tabindex]:hover,.n-rack > *[tabindex]:focus-visible{padding-left:11px}
.n-rack > *[tabindex]:hover::before,.n-rack > *[tabindex]:focus-visible::before{
  width:var(--rail)}
@media (min-width:720px){
  .n-rack.two{columns:2;column-gap:32px;column-rule:1px solid var(--line)}
}

/* ── tier 5 · tray — controls. Grey means you can change it. ─────────────── */
.n-tray{background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-mid);
  padding:12px 14px;box-shadow:inset 0 1px 0 #fff}

/* ── tier 6 · leader — the only tier that earns paper ────────────────────────
   Square shoulders under a heavy rule, soft bottom. That asymmetry is the signature. */
.n-leader{background:var(--surface);border:1px solid var(--line);
  border-top:var(--rail) solid var(--spot);border-radius:0 0 var(--r-obj) var(--r-obj);
  padding:16px;box-shadow:none;--spot:var(--acc)}
.n-leader.you{--spot:var(--accent)}
@media (max-width:560px){ .n-leader{padding:13px} }

/* ── guardrail · .card survives as a quiet, valid tier ───────────────────────
   After migration nothing on the site uses it. It exists so that a naive `card pad`
   written next month renders as something correct and calm rather than as unpadded
   floating text — which is the extensibility hole this direction would otherwise have. */
.n-sheet,.card{background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-mid);box-shadow:none}

/* ── desktop layout: stop stretching a phone design across 1240px ─────────────
   The League view was one column of full-width blocks: on a 1440px screen the table
   ran 1200px wide with its last three columns mostly empty, and everything else was
   a stretched band. Two columns on wide screens, untouched on mobile. */
.lg-grid{display:grid;gap:20px;align-items:start}
.lg-main{min-width:0}
.lg-rail{min-width:0;display:flex;flex-direction:column;gap:16px}
@media (min-width:1000px){
  .lg-grid{grid-template-columns:minmax(0,1.75fr) minmax(290px,0.85fr);gap:28px}
  /* the rail's side-competition grid becomes a single stack in a narrow column */
  .lg-rail .grid.g3,.lg-rail .grid.g2{grid-template-columns:1fr}
  /* and the page itself does not need to be as wide as a spreadsheet */
  main{max-width:1180px}
}

/* ── the ownership grid on a phone ────────────────────────────────────────────
   Requests #14 and #15, and the measurements were worse than reported: at 390px the
   sticky name column was 266px — 68% of the screen — and with the 66px "Own" column
   beside it that left 58px for fourteen 78px manager columns. ZERO of 14 were visible.
   A sticky column is only useful if there is something left to scroll past it. */
@media (max-width:560px){
  .ogrid td.stick,.ogrid th.stick{max-width:112px;min-width:112px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ogrid .gmeta{display:none}            /* club, price and the template pill */
  .ogrid td.stick .pos{padding:1px 4px;font-size:9px}
  .ogrid td,.ogrid th{padding:7px 5px}
  .ogrid td.own,.ogrid th:not(.stick){min-width:40px}
  .ogrid .meter{display:none}            /* the little ownership bar, redundant next to N/M */
}

/* Request #16: on a phone the league table's team-name column is the widest thing that
   carries no information the manager's own name does not already give you, so it goes.
   Same utility is reused anywhere a column is nice-to-have rather than load-bearing. */
/* The mirror of hide-phone: something that only earns its space on a narrow screen,
   because it is standing in for a column that got dropped there. */
.only-phone{display:none}
@media (max-width:560px){
  .hide-phone{display:none}
  .only-phone{display:inline-flex;vertical-align:middle}
}

/* A header can carry a short alternative for narrow screens: "To leader" becomes "Gap"
   and "To next" becomes "±", which is 80px of a 390px table recovered without dropping
   the two columns that are the entire point of a gap board. */
.lbl-abbr{display:none}
@media (max-width:560px){
  .lbl-full{display:none}
  .lbl-abbr{display:inline}
}

/* Tighter cells on a phone. After hiding the team column the league table measured 385px
   against 362px of usable width — 23px over, which is one padding step. */
@media (max-width:560px){
  thead th,tbody td{padding-left:5px;padding-right:5px}
  tbody td:first-child,thead th:first-child{padding-left:2px}
  tbody td:last-child,thead th:last-child{padding-right:2px}
}

/* ── the duel, rebuilt ────────────────────────────────────────────────────────
   Previously two separate cards listing only each manager's unique players, with the
   shared block collapsed to a bare count. You could not see what you had in common, the
   two lists were not aligned to each other, and nothing said how many players were
   actually scoring — which is wrong precisely when someone plays a bench boost and the
   answer is 15 rather than 11.

   Now: one scoreline, differentials facing each other across a centre line, and the
   shared players listed ONCE down the middle instead of twice. */
.duel-head{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;
  padding:13px 4px;border-top:2px solid var(--ink);border-bottom:1px solid var(--line2)}
.duel-head .side{display:flex;flex-direction:column;min-width:0}
.duel-head .side.a{text-align:right;align-items:flex-end}
.duel-head .side b{font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  max-width:100%}
.duel-head .side span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.duel-head .score{display:flex;align-items:center;gap:8px;font-variant-numeric:tabular-nums}
.duel-head .score em{font-style:normal;font-weight:800;font-size:26px;min-width:34px;
  text-align:center;color:var(--cap)}
.duel-head .score em.won{color:var(--ink)}
.duel-head .score .v{font-size:11px;font-weight:700;color:var(--faint)}

/* differentials: a column each, mirrored so they read toward the centre */
.duel-cols{display:grid;grid-template-columns:1fr 1fr;gap:0}
.dcol{min-width:0}
.drow{display:flex;align-items:center;gap:6px;padding:7px 8px;
  border-bottom:1px solid var(--line);font-size:12.5px;min-width:0}
.drow.ra{flex-direction:row-reverse;text-align:right}
.drow .p{display:flex;align-items:center;gap:4px;min-width:0;flex:1}
.drow.ra .p{flex-direction:row-reverse}
.drow .p b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.drow .n{font-weight:800;font-variant-numeric:tabular-nums;color:var(--faint);
  min-width:22px;text-align:center}
.drow .n.hot{color:var(--ink)}
.dcol:first-child .drow{border-right:1px solid var(--line2)}
.duel-sub{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:8px;
  padding:9px 8px;border-bottom:2px solid var(--ink)}
.duel-sub b{font-size:17px;font-variant-numeric:tabular-nums}
.duel-sub b:first-child{text-align:right}

/* shared: one row per player, centred, both sides only when they differ */
.duel-shared .srow{display:grid;grid-template-columns:34px 1fr 34px;align-items:center;
  gap:8px;padding:7px 4px;border-bottom:1px solid var(--line);font-size:12.5px}
.duel-shared .srow .p{display:flex;align-items:center;gap:5px;justify-content:center;
  min-width:0}
.duel-shared .srow .p b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.duel-shared .srow .n{font-weight:800;font-variant-numeric:tabular-nums;text-align:center;
  color:var(--faint)}
.duel-shared .srow .n.hot{color:var(--ink)}
.duel-shared .srow.split{background:var(--warn-wash)}
@media (max-width:400px){
  .duel-head .score em{font-size:22px;min-width:28px}
  .drow{padding:6px 5px;font-size:12px;gap:4px}
  .drow .n{min-width:18px}
}

/* ── matches: the real football ───────────────────────────────────────────────── */
.mrow{position:relative;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  gap:8px;padding:11px 6px;border-bottom:1px solid var(--line)}
.mrow:first-of-type{border-top:1px solid var(--line2)}
.mrow.live{background:var(--warn-wash)}
.mrow .side{display:flex;align-items:center;gap:6px;min-width:0}
.mrow .side.a{justify-content:flex-end}
.mrow .side b{font-size:14px;letter-spacing:-.01em;white-space:nowrap}
.mrow .sc{display:flex;align-items:center;gap:6px;min-width:66px;justify-content:center;
  font-variant-numeric:tabular-nums}
.mrow .sc em{font-style:normal;font-weight:800;font-size:19px;color:var(--cap)}
.mrow .sc em.won{color:var(--ink)}
.mrow .sc .dash{color:var(--faint);font-size:12px}
.mrow .sc.ko span{font-size:13px;font-weight:700;color:var(--cap)}
.mrow .mstate{position:absolute;right:4px;top:2px;font-size:9px;font-weight:800;
  letter-spacing:.08em;color:var(--faint)}
.mrow .mlive{position:absolute;right:4px;top:2px;display:flex;align-items:center;gap:4px;
  font-size:9.5px;font-weight:800;color:var(--down)}
@media (max-width:400px){
  .mrow{padding:10px 2px;gap:5px}
  .mrow .side b{font-size:13px}
  .mrow .sc{min-width:56px}
  .mrow .sc em{font-size:17px}
}

/* ── versions ─────────────────────────────────────────────────────────────────── */
.vrow{padding:13px 0;border-bottom:1px solid var(--line)}
.vrow:first-of-type{border-top:2px solid var(--ink)}
.vrow.now .vhead b{color:var(--acc)}
.vhead{display:flex;align-items:baseline;gap:9px;margin-bottom:6px}
.vhead b{font-size:16px;letter-spacing:-.01em}
.vlist{margin:0;padding-left:17px;display:flex;flex-direction:column;gap:4px}
.vlist li{font-size:13px;color:var(--ink2);line-height:1.45}

/* ── transfer suggestions ─────────────────────────────────────────────────────── */
.sug{display:grid;grid-template-columns:1fr auto 1fr;gap:8px;align-items:start;
  padding:12px 0;border-bottom:1px solid var(--line)}
.sug:first-of-type{border-top:1px solid var(--line2)}
.sug-side{position:relative;min-width:0;display:flex;flex-direction:column;gap:3px}
.sug-side .lab{font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint)}
.sug-side.out .lab{color:var(--down)}
.sug-side.in .lab{color:var(--up)}
.sug-side .who{display:flex;align-items:center;gap:5px;min-width:0;flex-wrap:wrap}
.sug-side .who b{font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sug-side .nums{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.sug-side .nope{margin-top:5px;align-self:flex-start;font:inherit;font-size:10.5px;
  font-weight:700;padding:2px 8px;border-radius:var(--r-pill);border:1px solid var(--line2);
  background:var(--surface);color:var(--cap);cursor:pointer}
.sug-side .nope:hover{border-color:var(--down);color:var(--down)}
.sug-mid{display:flex;flex-direction:column;align-items:center;gap:1px;padding-top:14px}
.sug-mid .arrow{font-size:16px;color:var(--faint)}
.sug-mid .gain{font-size:14px;font-weight:800;color:var(--up);font-variant-numeric:tabular-nums}
.sug-why{grid-column:1 / -1;font-size:12.5px;color:var(--ink2);line-height:1.45;
  padding:7px 10px;background:var(--surface2);border-radius:var(--r-obj);margin-top:4px}
@media (max-width:520px){
  .sug{grid-template-columns:1fr;gap:4px}
  .sug-mid{flex-direction:row;gap:6px;padding:2px 0}
  .sug-side.in{padding-top:6px;border-top:1px dashed var(--line)}
}

/* ── squad chat ───────────────────────────────────────────────────────────────── */
.chatlog{display:flex;flex-direction:column;gap:8px;max-height:340px;overflow-y:auto;
  padding:2px}
.bub{max-width:88%;padding:9px 12px;border-radius:var(--r-mid);font-size:13px;
  line-height:1.5;white-space:pre-wrap}
.bub.me{align-self:flex-end;background:var(--purple);color:#fff;
  border-bottom-right-radius:var(--r-tag)}
.bub.ai{align-self:flex-start;background:var(--surface2);color:var(--ink);
  border-bottom-left-radius:var(--r-tag)}
.bub.pending{color:var(--faint);font-style:italic}
/* What the answer was actually built from. Quiet enough to ignore, present enough that a
   sceptical reader can tell a lookup from a guess. */
.grounded{display:block;margin-top:7px;padding-top:6px;font-size:10.5px;
  letter-spacing:.02em;color:var(--faint);border-top:1px solid var(--line)}
.chatbar{display:flex;gap:7px;margin-top:10px}
.chatbar input{flex:1;min-width:0}

/* My Team's low-priority verdicts collapse to a chip strip; risks and warnings stay open.
   Four full-width cards plus a banner plus the table pushed everything actionable below
   the fold on a phone. */
.vchips{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 10px}
.vchip{font:inherit;font-size:11.5px;font-weight:700;display:inline-flex;align-items:center;
  gap:5px;padding:5px 10px;border-radius:var(--r-pill);border:1px solid var(--line);
  background:var(--surface);color:var(--ink2);cursor:pointer}
.vchip.open{border-color:var(--acc);background:var(--acc-wash)}
.vchip.good{border-color:var(--acc-edge)}
.vbody{font-size:12.5px;color:var(--ink2);line-height:1.5;padding:9px 11px;
  background:var(--surface2);border-radius:var(--r-obj);margin:0 0 9px}

/* ═══════════════════════════ PHONE DENSITY PASS ═══════════════════════════════
 * Measured before this block, on a 390px phone: 107px of tab bar, 156px of header and
 * nav together, and 754px on the League tab before the first row of the table. Nearly a
 * fifth of the screen was spent on furniture on every single page.
 *
 * Everything here is spacing and type scale — no element is hidden and no information is
 * dropped. It lives in one block, keyed off structure, so the density of the whole site is
 * one thing to tune rather than twelve.
 */
@media (max-width:560px){
  /* Twelve tabs wrapped to THREE rows. They wrap rather than scroll on purpose — a
     scrolling bar is what hid half of them before — so the saving has to come from the
     pills themselves: at this size the same twelve fit two rows. */
  nav.tabs{padding:0 10px 7px;gap:2px;row-gap:3px}
  nav.tabs button{font-size:11.5px;padding:6px 8px;font-weight:800;letter-spacing:-.01em}

  .bar{padding:9px 12px}
  main{padding:13px 12px 56px}

  /* A page title does not need to be 22px when the content under it is 13px. */
  .h1{font-size:20px;letter-spacing:-.02em}
  .phead{margin-bottom:9px}
  .h2{font-size:16.5px}

  /* the asymmetric section rhythm survives, just tighter */
  .view > .sec{margin:15px 0 7px}
  .sec{font-size:11px;letter-spacing:.11em}

  .verdict{padding:10px 11px;gap:9px}
  .verdict .t{font-size:13px}
  .verdict .d{font-size:12px}
  .pad,.card.pad{padding:12px}
  .grid{gap:10px}

  /* the ledger tiers, one notch tighter — the rhythm is unchanged, only the leading */
  .n-strap{padding:9px 0 10px}
  .n-rack > *{padding:11px 0}
  .n-tray{padding:10px 11px}
  .n-leader{padding:11px}
  .awards{gap:8px}

  /* Five personal stats at a 74px floor fit four per row, so the fifth wrapped and the
     block cost two rows. A 62px floor fits all five on one line at 390px. */
  /* The modal is where the pitch lives, and 18px of scrim padding plus 22px of sheet
     padding was 80px of a 390px screen spent on white space around a formation that
     wants every pixel. */
  .modal{padding:9px}
  .sheet{padding:14px;max-height:92vh}
  .closer{top:6px;right:8px}

  .mepanel{padding:11px;margin-bottom:12px}
  .mepanel .top{margin-bottom:9px}
  .mestat{grid-template-columns:repeat(auto-fit,minmax(62px,1fr));gap:6px}
  .mestat div{padding:6px 7px}
  .mestat b{font-size:16px}
  .mestat span{font-size:9.5px}
  .melist{margin-top:9px}
}

/* A change arrived while you were reading. Repainting a view rebuilds it from scratch and
   would throw away your scroll position, an open chat or a half-typed search — so when it
   is not safe to do silently, this offers instead. Fixed to the bottom because that is
   where a thumb already is, and it must never cover the tab bar at the top. */
.freshbar{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:60;
  border:0;border-radius:var(--r-pill);cursor:pointer;
  background:var(--purple);color:#fff;font-weight:800;font-size:12.5px;
  padding:10px 18px;box-shadow:var(--shadow-lg);white-space:nowrap;max-width:calc(100vw - 24px);
  animation:freshin .18s ease-out}
.freshbar::before{content:'';display:inline-block;width:7px;height:7px;border-radius:50%;
  background:var(--pop);margin-right:7px;vertical-align:1px}
.freshbar:hover{background:var(--acc-deep)}
@keyframes freshin{from{opacity:0;transform:translate(-50%,8px)}
                   to{opacity:1;transform:translate(-50%,0)}}

/* ═══════════════════════════ THE PLAYER, AS A FOOTBALLER ══════════════════════════
   The sheet used to be a grade and a price chart. These are the parts that say what he
   actually did on a pitch. */

/* Headshot. Falls back to the club shirt, which is a different aspect ratio, hence the
   two treatments. */
.face{display:flex;justify-content:center;margin:0 0 12px}
.face img{height:112px;width:auto;object-fit:contain;
  border-radius:var(--r-mid);background:var(--surface2)}
.face.isshirt img{height:84px;background:none}

.statgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:7px}
.statgrid > div{background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-obj);padding:8px 9px;text-align:center}
.statgrid b{display:block;font-size:17px;font-weight:800;line-height:1.15;
  font-variant-numeric:tabular-nums}
.statgrid span{display:block;margin-top:1px;font-size:9.5px;font-weight:750;
  letter-spacing:.06em;text-transform:uppercase;color:var(--cap);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* The match log is a ledger, not a table: a row per game and a line of reasons under it. */
.mlog{border-top:2px solid var(--ink)}
.mlrow{display:flex;align-items:baseline;gap:9px;padding:9px 0 3px}
.mlrow .gw{font-size:10.5px;font-weight:800;letter-spacing:.06em;color:var(--cap);
  width:38px;flex:none}
.mlrow .opp{flex:1;min-width:0;font-size:13.5px}
.mlrow .min{width:42px;text-align:right;flex:none}
.mlrow .pts{width:32px;text-align:right;flex:none;font-size:16px;font-weight:800;
  font-variant-numeric:tabular-nums}
.mlrow.haul .pts{color:var(--up)}
.mlwhy{display:flex;flex-wrap:wrap;gap:4px;padding:0 0 9px 47px;
  border-bottom:1px solid var(--line)}
.why{font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:var(--r-pill);
  background:var(--acc-wash);color:var(--ink2);white-space:nowrap}
.why.bad{background:var(--down-wash);color:var(--down)}

/* The gameweek chip only glows while something is actually being played. It used to be
   permanently "live" because FPL keeps is_current on a gameweek until it finalises it. */
#gwBadge.hot{background:var(--pop);color:var(--purple);font-weight:800}

/* Your own row in the league table. A star rather than a tinted row: at fourteen rows a
   full-width highlight shouts, and all you actually want is to find yourself. */
.youstar{color:var(--accent);font-weight:800}
td.stick.mine{font-weight:800}

/* ── My Team's gameweek buttons ────────────────────────────────────────────────
   Buttons, not a slider: a dozen discrete steps is the wrong job for a range input — you
   cannot see where you are going and on a phone you cannot land on one. Each carries its
   score, and the next gameweek shows locked rather than silently missing. */
.gwbar{margin:0 0 10px}
.gwchips{display:flex;gap:5px;flex-wrap:wrap}
.gwchip{font:inherit;font-size:12px;font-weight:800;display:inline-flex;align-items:center;
  gap:5px;padding:5px 10px;border-radius:var(--r-pill);border:1px solid var(--line);
  background:var(--surface);color:var(--ink2);cursor:pointer}
.gwchip i{font-style:normal;font-weight:800;font-size:11px;color:var(--cap);
  font-variant-numeric:tabular-nums}
.gwchip.on{background:var(--ink);border-color:var(--ink);color:var(--on-ink)}
.gwchip.on i{color:var(--on-acc-pop)}
.gwchip.locked{opacity:.5;cursor:not-allowed}

/* Opponent and price under the score on a pitch card. */
.pmeta{font-size:9px;color:var(--cap);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;padding:0 2px 1px}

/* Club crests in the fixture list. Three letters told you which club; the crest is what
   people actually recognise at a glance. */
.crest{width:18px;height:18px;object-fit:contain;flex:none;vertical-align:-3px}
.mrow .side{display:flex;align-items:center;gap:6px}

/* A match, opened out. */
.fxhead{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.fxside{flex:1;min-width:0;display:flex;align-items:center;gap:7px;font-size:14px}
.fxside.r{justify-content:flex-end;text-align:right}
.fxside .crest{width:26px;height:26px}
.fxsc{font-size:22px;font-weight:800;letter-spacing:-.02em;flex:none;
  font-variant-numeric:tabular-nums}
.why.own{background:var(--info-wash);color:var(--info)}

/* ── the cup knockout ─────────────────────────────────────────────────────────
   Two brackets side by side down the page, one gameweek at a time, so the DROP —
   losing in the Premier and reappearing in the Championship — is visible as a thing that
   happens between them rather than something you have to be told about. */
.koweek{display:flex;align-items:baseline;gap:8px;margin:14px 0 5px;
  border-top:1px solid var(--line2);padding-top:8px}
.koweek b{font-size:12px;letter-spacing:.06em}
.kobox{border-left:3px solid var(--line2);padding-left:9px;margin-bottom:7px}
.kobox.premier{border-left-color:var(--acc)}
.kobox.champ{border-left-color:var(--up)}
.kotie{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-obj);
  margin-bottom:5px;overflow:hidden}
.koside{display:flex;align-items:center;gap:8px;padding:6px 9px;font-size:13px;
  cursor:pointer}
.koside + .koside{border-top:1px solid var(--line)}
.koside .kon{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.koside .kop{font-weight:800;font-variant-numeric:tabular-nums;flex:none}
.koside.won{background:var(--acc-wash)}
.koside.won .kon{font-weight:800}
.koside.tbd{color:var(--faint);cursor:default;font-style:italic}

/* ═══════════════════════════ HOW THE APERTURA WORKS ═══════════════════════════
   Designed in Paper, rebuilt here on the site's tokens. Two lanes running left to right
   through the gameweeks, with the drop drawn as arrows falling from one into the other —
   the whole format in a single picture. It scrolls horizontally on a phone rather than
   reflowing, because a bracket that wraps stops being a bracket. */
.apex{margin:0 0 18px}
.apex-kicker{font-size:10.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cap)}
.apex-h{font-size:clamp(20px,3.4vw,30px);font-weight:800;letter-spacing:-.03em;
  line-height:1.1;margin:4px 0 6px;color:var(--ink)}
.apex-lede{font-size:13px;line-height:1.5;color:var(--ink2);max-width:62ch;
  margin-bottom:14px}

/* It FITS. The whole point of a diagram is to be taken in at a glance, and one you have
   to drag sideways is a diagram you never see the end of. So the grid is fluid: the lane
   label is a fixed narrow column and the five gameweeks share whatever is left. */
.apex-scroll{overflow:visible}
.apex-grid{display:flex;flex-direction:column;gap:0;width:100%}
.apex-row{display:flex;align-items:stretch;gap:3px}
/* "Championship" is one 12-character word and was breaking mid-syllable at 74px. */
.apex-lane{width:82px;flex:none;display:flex;flex-direction:column;gap:1px;
  overflow-wrap:normal;hyphens:none;
  justify-content:center;padding-right:6px}
.apex-lane b{font-size:11px;letter-spacing:-.03em;line-height:1.1;
  overflow-wrap:anywhere}
.apex-lane b.p{color:var(--acc)}
.apex-lane b.c{color:var(--up)}
.apex-lane span{font-size:9.5px;color:var(--cap);line-height:1.25}
.apex-cell{flex:1 1 0;min-width:0;display:flex;align-items:stretch;padding:3px 0}
.apex-ruler .apex-cell{padding:0 0 5px;font-size:9.5px;font-weight:800;
  letter-spacing:.06em;color:var(--cap);align-items:flex-end}

.apex-card{flex:1;min-width:0;padding:7px 7px;border-radius:var(--r-obj);display:flex;
  flex-direction:column;gap:2px;justify-content:center}
.apex-card b{font-size:11px;font-weight:800;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis}
.apex-card span{font-size:9px;line-height:1.25;overflow:hidden;text-overflow:ellipsis}
.apex-card.prem{background:var(--acc)}
.apex-card.prem b{color:var(--on-acc)}
.apex-card.prem span{color:var(--on-acc-soft)}
.apex-card.prem.win{border:2px solid var(--pop)}
.apex-card.prem.win span{color:var(--on-acc-pop);font-weight:700}
.apex-card.champ{background:var(--up-wash);border:1px solid var(--up)}
.apex-card.champ b{color:var(--up)}
.apex-card.champ span{color:var(--ink2)}
.apex-card.champ.win{background:var(--up);border-color:var(--up)}
.apex-card.champ.win b{color:var(--on-up)}
.apex-card.champ.win span{color:var(--on-up-soft);font-weight:700}
.apex-rest{font-size:9.5px;color:var(--faint);font-style:italic;align-self:center;
  width:100%;text-align:center}

.apex-drop .apex-cell{padding:1px 0}
.apex-arrow{display:flex;align-items:center;gap:3px;justify-content:center;width:100%}
.apex-arrow .ar{font-size:13px;line-height:1;color:var(--down)}
.apex-arrow .lb{font-size:9px;font-weight:800;color:var(--down);line-height:1.2;
  white-space:nowrap}

.apex-notes{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:12px;margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
.apex-note{display:flex;flex-direction:column;gap:3px}
.apex-note b{font-size:12.5px;font-weight:800}
.apex-note span{font-size:12px;color:var(--ink2);line-height:1.5}

/* On a real screen the diagram can breathe again. */
@media (min-width:720px){
  .apex-lane{width:120px;padding-right:12px}
  .apex-lane b{font-size:14px}
  .apex-lane span{font-size:11px}
  .apex-row{gap:8px}
  .apex-card{padding:12px;border-radius:var(--r-mid);gap:3px}
  .apex-card b{font-size:13px}
  .apex-card span{font-size:10.5px}
  .apex-ruler .apex-cell{font-size:10.5px;letter-spacing:.1em}
  .apex-rest{font-size:11.5px}
  .apex-arrow .ar{font-size:17px}
  .apex-arrow .lb{font-size:10.5px}
}

/* ── The pitch, made compact on a phone ──────────────────────────────────────
   At 390px the eleven ran well past a screen and a half: a 52px shirt plus a three-line
   plate is ~110px per card, so two rows filled the viewport and you scrolled to see your
   own forwards. Shirts shrink hardest because they are decoration — the name, the score
   and the opponent are the content, and they stay legible. */
@media (max-width:560px){
  .pitch{padding:9px 3px 11px}
  .prow{margin-bottom:6px}
  .pcard{max-width:70px;padding:3px 2px 0;border-radius:5px}
  .pcard img{max-width:34px;margin-bottom:2px}
  .pcard .pname{font-size:9.5px;padding:2px 1px;font-weight:800}
  .pcard .pfix{font-size:9px;padding:1px}
  .pcard .pfix.pts{font-size:10px}
  .pmeta{font-size:8px;padding:0 1px 1px}
  .parm{width:15px;height:15px;font-size:9px;top:-3px;left:-3px}
  .pcard .flagdot{width:13px;height:13px;font-size:9px;top:-3px;right:-3px}
  .benchhead span{font-size:9px}
  .pitchfoot{padding:7px 9px;font-size:10.5px}
}

/* Narrowing the ownership grid to a few managers. Fourteen columns is a reference table;
   two or three is a question — "what do we own between us?" */
.ownsel{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 10px}
.ownsel .chip{font-size:11.5px;padding:4px 10px}

/* ── #25 · this gameweek's arrivals ───────────────────────────────────────────
   A squad is fifteen familiar names and the two you changed are the only news in it. */
.pcard.newin{box-shadow:0 0 0 2px #ffd43b;border-radius:6px}
.pcard .newtag{position:absolute;top:-5px;right:-4px;z-index:4;
  background:#ffd43b;color:#37003c;font-size:8.5px;font-weight:800;letter-spacing:.04em;
  padding:1px 4px;border-radius:var(--r-pill);box-shadow:0 1px 2px rgba(0,0,0,.3)}
/* the flag dot already owns the top-right, so an arriving player who is ALSO flagged
   pushes his tag left rather than stacking the two on top of each other */
.pcard.out .newtag,.pcard:has(.flagdot) .newtag{right:14px}

/* ── #26 · the manager sheet's stat tiles, on a phone ─────────────────────────
   Four tiles at two per row was ~140px before the pitch even started, and the pitch is
   what you opened the sheet for. One row of four, sized to fit. */
@media (max-width:560px){
  .sheet .tiles{grid-template-columns:repeat(4,1fr);gap:5px}
  .sheet .tile{padding:6px 4px;text-align:center}
  .sheet .tile b{font-size:14px}
  .sheet .tile span{font-size:8px;letter-spacing:.04em;white-space:normal;line-height:1.2}
}

/* ── #27 · what shows behind a rubber-band pull ───────────────────────────────
   iOS paints the overscroll area from the HTML element, not the body, so pulling the
   sticky purple masthead down revealed the pale page ground behind it. The document
   carries the header colour now and the body keeps the page ground, so a pull just
   stretches the header. */
html{background:var(--purple)}
body{background:var(--bg)}

/* ── where the Apertura table splits ─────────────────────────────────────────
   You could read all fourteen rows and not learn that 8th and 9th go to different
   competitions. A rule under 8th and a dot on every row saying which way it is heading. */
tr.cutline td{border-bottom:2px solid var(--ink)}
.qmark{display:inline-block;width:6px;height:6px;border-radius:50%;margin-left:6px;
  vertical-align:middle}
.qmark.p{background:var(--acc)}
.qmark.c{background:var(--up)}
i.qmark{margin:0 5px 0 0}
.cutkey{display:flex;gap:14px;flex-wrap:wrap;margin-top:8px;font-size:11px;
  color:var(--ink2);align-items:center}
.cutkey .muted{color:var(--cap)}

/* Two readings of one match: what FPL paid him, and what he actually did. */
.modebar{display:flex;gap:4px;flex:none}
.modebar .chip{font-size:11px;padding:3px 9px}
.why.key{background:var(--acc);color:var(--on-acc)}
.why.good{background:var(--up-wash);color:var(--up)}

/* Each gameweek's heading above its strip. */
.gwhead{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  margin:20px 0 8px;padding-top:10px;border-top:2px solid var(--ink)}
.gwhead b{font-size:15px;letter-spacing:-.02em}

/* ── Coach of the month ──────────────────────────────────────────────────────
   Fixed lanes, so three months read down the page as a sequence rather than as three
   loose cards. A month is a different unit from a gameweek and gets its own shape. */
.months{border-top:2px solid var(--ink)}
.mrow2{display:flex;align-items:center;gap:10px;padding:10px 0;
  border-bottom:1px solid var(--line);cursor:pointer}
.mrow2 .mmedal{width:22px;flex:none;font-size:16px;line-height:1}
.mrow2 .mmonth{width:74px;flex:none;font-size:11px;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--cap)}
.mrow2 .mwho{flex:1;min-width:0;font-size:14px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.mrow2 .mpts{flex:none;font-size:17px;font-weight:800;font-variant-numeric:tabular-nums}
.mrow2 .mflag{flex:none}
.mrow2.running{background:var(--warn-wash)}

/* ── +1 on an idea ────────────────────────────────────────────────────────── */
.idearow{display:flex;gap:10px;align-items:flex-start}
.ideatext{flex:1;min-width:0}
.plus1{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:1px;
  min-width:40px;padding:5px 6px 4px;border:1px solid var(--line);border-radius:var(--r-obj);
  background:var(--card);color:var(--cap);cursor:pointer;font:inherit;line-height:1;
  transition:background .12s,border-color .12s,color .12s}
.plus1:hover{border-color:var(--accent);color:var(--accent)}
.plus1 .plus1i{font-size:10px}
.plus1 .plus1n{font-size:12.5px;font-weight:800;min-height:13px}
.plus1.on{background:var(--acc-wash);border-color:var(--acc);color:var(--acc-deep)}

/* a late joiner, explained where the field is described */
.apex-note{margin:8px 0 0;font-size:12.5px;line-height:1.45;color:var(--ink2);
  border-left:3px solid var(--acc-edge);padding-left:10px}

/* the "show earlier gameweeks" fold on Awards */
.btn.ghost.wide{width:100%;margin-top:12px;background:var(--card);border:1px dashed var(--line2);
  color:var(--cap);font-weight:700}
.btn.ghost.wide:hover{border-color:var(--accent);color:var(--accent)}

/* the score on a shirt is its own tap target: it opens that gameweek's breakdown */
.pfix.tapscore{cursor:pointer}
.pfix.tapscore:hover{text-decoration:underline;text-decoration-style:dotted;
  text-underline-offset:2px}
.mlrow.focus{background:var(--acc-wash);border-radius:var(--r-obj)}

/* Idea #40: the Apertura's sticky name column was 78% of a phone screen, which left
   nothing to scroll the rest of the table past it — a sticky column is only useful if
   something can move behind it. Capped, with the team name dropped on phones. */
.cupname{max-width:132px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (min-width:560px){ .cupname{max-width:none} }

/* the diagram's sub-lines carry their own line breaks */
.apex-card span{white-space:pre-line}

/* ── the theme button ──────────────────────────────────────────────────────
   Sits in the masthead where the freshness stamp goes, which is already hidden on
   phones — so it costs no width on the screen that had none to give. */
.themebtn{flex:0 0 auto;width:28px;height:28px;padding:0;border-radius:var(--r-pill);
  border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.10);
  color:#fff;cursor:pointer;font-size:14px;line-height:1;display:inline-flex;
  align-items:center;justify-content:center;transition:background .12s,border-color .12s}
.themebtn:hover{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.5)}

/* an award nobody won: present, greyed, and saying why */
.award.none{--spot:var(--line2);opacity:.72}
.award.none .who.nowin{color:var(--cap);font-weight:700;font-size:13px}
@media (min-width:640px){ .award.none .who.nowin{font-size:14px} }

/* Idea #43: ideas and replies keep the line breaks they were written with. The text is
   stored with newlines already (see _clean); it was only the render that flattened them.
   pre-wrap, not pre, so long lines still wrap to the card rather than overflowing it. */
.ideatext{white-space:pre-wrap;overflow-wrap:anywhere}

/* ── idea replies: a thread, owner and members (idea #42) ─────────────────────── */
.irep{border-left:3px solid var(--line2);padding:6px 0 4px 10px;margin-top:8px}
.irep.admin{border-left-color:var(--acc-edge)}
.irep.nested{margin-left:16px}
.irep .ideatext{margin:2px 0 3px}
.irep .linkbtn{margin-top:2px}
.replybox{margin:8px 0 2px;padding:8px;border:1px solid var(--line);border-radius:var(--r-obj);
  background:var(--surface2)}
.replybox textarea,.replybox input{width:100%;padding:7px 9px;border:1px solid var(--line2);
  border-radius:var(--r-obj);background:var(--surface);color:var(--ink)}
.replybox .row{gap:8px;align-items:center;margin-top:6px}
.replybox input{max-width:200px}
.linkbtn{background:none;border:0;padding:2px 0;color:var(--accent);cursor:pointer;
  font-weight:700}
.linkbtn:hover{text-decoration:underline}
.btn.sm{padding:6px 13px;font-size:13px}

/* Idea #52: the league-position chart opens large in the modal, with a legend so a line
   traces back to a name. */
.card.tappable{cursor:pointer}
.card.tappable:hover{border-color:var(--accent)}
.bumplegend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:12px}
.bumplegend .blg{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--ink2)}
.bumplegend .blg i{width:11px;height:11px;border-radius:3px;flex:0 0 auto}

/* Idea #53: shared row reads name-left, the two scores adjacent, so comparing them needs
   no eye travel across the row. */
.duel-shared .srow{grid-template-columns:1fr auto;gap:10px}
.duel-shared .srow .p{justify-content:flex-start}
.duel-shared .srow .nn{display:flex;gap:12px}
.duel-shared .srow .nn .n{min-width:22px;text-align:right}

/* the benched, tucked below the comparison */
.benchbox{margin-top:12px;border-top:1px solid var(--line);padding-top:8px}
.benchbox summary{cursor:pointer;color:var(--cap);font-weight:700;list-style:none}
.benchbox summary::-webkit-details-marker{display:none}
.benchbox summary::before{content:'▸ ';color:var(--faint)}
.benchbox[open] summary::before{content:'▾ '}
.benchlist{margin-top:6px;display:flex;flex-direction:column;gap:2px}
.benchrow{display:grid;grid-template-columns:1fr auto auto;align-items:center;gap:8px;
  padding:4px 2px;font-size:12px}
.benchrow .p{display:flex;align-items:center;gap:5px;min-width:0}
.benchrow .p b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.benchrow .n{font-weight:800;min-width:20px;text-align:right}

/* Idea #59: a faint club tag in the shirt corner — present for disambiguation, quiet
   enough not to read as primary information. */
.pcard{position:relative}
.pcard .pclub{position:absolute;top:2px;left:3px;font-size:8px;font-weight:800;
  letter-spacing:.02em;color:var(--cap);opacity:.6;pointer-events:none;
  text-shadow:0 1px 1px var(--surface)}
.pcard .pclub.shift{left:19px}   /* past a C / V / 3x armband */

/* Idea #55: a small C beside a shared player's score marking who captained him. */
.duel-shared .srow .nn .n{display:inline-flex;align-items:baseline;gap:2px;justify-content:flex-end}
.capdot{font-size:8px;font-weight:800;color:var(--warn);opacity:.85}
.fxr.tap{cursor:pointer}
.fxr.tap:hover{background:var(--acc-wash)}

/* Idea #64: captaincy and boosters shown boldly in Compare, not as faint text. */
.chipbadge{display:inline-block;margin-top:3px;padding:1px 6px;border-radius:var(--r-pill);
  background:var(--warn);color:#fff;font-size:8.5px;font-weight:800;letter-spacing:.04em}
.duel-shared .srow .nn .n .cbadge{background:var(--warn);color:#fff;font-size:8px;
  font-weight:800;border-radius:3px;padding:0 3px;margin-right:3px;vertical-align:middle}
.duel-shared .srow .nn .n .cbadge.tri{background:var(--acc);}

/* Idea #62: league-vs-global averages card */
.avgrow{display:flex;align-items:baseline;gap:10px;padding:6px 0;border-bottom:1px solid var(--line)}
.avgrow:last-of-type{border-bottom:0}
.avglbl{flex:1;font-weight:700;font-size:13px}
.avgours{font-size:18px;font-weight:800;font-variant-numeric:tabular-nums}
.avgvs{flex:0 0 auto}
.avgdelta{font-size:12px;font-weight:800;font-variant-numeric:tabular-nums}
.avgdelta.up{color:var(--up)} .avgdelta.down{color:var(--down)}

/* Idea #60: chips a manager has played, in their sheet */
.chiprow{display:flex;flex-wrap:wrap;gap:6px}
.chiptag{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;border-radius:var(--r-pill);
  background:var(--acc-wash);border:1px solid var(--acc-edge);font-size:12px;font-weight:700}
.chiptag .muted{font-weight:600}
