[data-skin="matchday"]{color-scheme:dark;--bg:#05070A;--page:var(--bg);--panel-blur:none;--page-match:var(--bg);--panel:#0E1218;--panel-2:#141A22;--well:#FFFFFF0F;--hover:#FFFFFF08;--line:#FFFFFF14;--line-2:#FFFFFF29;--fg:#F2F4F7;--mute:#FFFFFF8A;--faint:#FFFFFF52;--accent:#C8102E;--accent-ink:#FFFFFF;--ink-light:#FFFFFF;--ink-dark:#07090C;--win:#6FDBA0;--loss:#FF8C8C;--draw:#FFFFFF52;--card-yellow:#FFC93C;--card-red:#F0334A;--veil:#000000A6;--shade:#000000;--shadow:#000000AA;--cut:14deg;--bug-home:polygon(0 0,57% 0,43% 100%,0 100%);--bug-away:polygon(57% 0,100% 0,100% 100%,43% 100%);--bug-home-phone:polygon(0 0,100% 0,100% 44%,0 56%);--bug-away-phone:polygon(0 56%,100% 44%,100% 100%,0 100%);--strap:#05070AE0;--crest-clip:polygon(0 0,100% 0,100% 78%,0 100%);--pill-clip:polygon(0 0,100% 0,calc(100% - 6px) 100%,0 100%);--cta-clip:polygon(0 0,100% 0,calc(100% - 9px) 100%,0 100%);--radius:0px;--radius-sm:0px;--rule-w:3px;--panel-border:1px solid #FFFFFF14;--face-display:"Avenir Next Condensed","Roboto Condensed","Arial Narrow",Impact,sans-serif;--face-body:"Avenir Next","Helvetica Neue",system-ui,sans-serif;--face-mono:ui-monospace,"SF Mono",Menlo,monospace;--display-transform:uppercase;--display-spacing:.04em;--display-weight:700;--label-spacing:.13em;--body-size:15px;--mode-toggle:none}
[data-skin="stats"]{color-scheme:dark;--bg:#07090D;--page:var(--bg);--panel-blur:none;--page-match:var(--bg);--panel:#10131A;--panel-2:#161A23;--well:#FFFFFF12;--hover:#FFFFFF0A;--line:#FFFFFF12;--line-2:#FFFFFF1F;--fg:#F4F6FB;--mute:#98A0B0;--faint:#6B7384;--accent:#2F6DF6;--accent-ink:#FFFFFF;--ink-light:#FFFFFF;--ink-dark:#0B0F16;--win:#34D399;--loss:#F87171;--draw:#6B7384;--card-yellow:#F5C542;--card-red:#E0273A;--veil:#000000A6;--shade:#05070B;--shadow:#00000099;--cut:0deg;--bug-home:polygon(0 0,50% 0,50% 100%,0 100%);--bug-away:polygon(50% 0,100% 0,100% 100%,50% 100%);--bug-home-phone:polygon(0 0,100% 0,100% 50%,0 50%);--bug-away-phone:polygon(0 50%,100% 50%,100% 100%,0 100%);--strap:#07090DE6;--crest-clip:none;--pill-clip:none;--cta-clip:none;--radius:16px;--radius-sm:11px;--rule-w:2px;--panel-border:1px solid #FFFFFF12;--face-display:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",Roboto,system-ui,sans-serif;--face-body:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,system-ui,sans-serif;--face-mono:ui-monospace,"SF Mono",Menlo,monospace;--display-transform:none;--display-spacing:-.025em;--display-weight:700;--label-spacing:.16em;--body-size:15px;--mode-toggle:inline-flex}
[data-skin="stats"][data-mode="light"]{color-scheme:light;--bg:#F3F5F9;--panel:#FFFFFF;--panel-2:#ECEFF5;--well:#0F172A12;--hover:#0F172A0A;--line:#0F172A12;--line-2:#0F172A1F;--fg:#111824;--mute:#586172;--faint:#8B95A6;--win:#0A9D57;--loss:#E0273A;--draw:#8B95A6;--card-yellow:#E0A200;--card-red:#CC1B2E;--veil:#0F172AA6;--shade:#E6E9EF;--shadow:#0F172A1F;--strap:#F3F5F9E6;--panel-border:1px solid #0F172A12}
[data-skin="apple"]{color-scheme:dark;--bg:#05070C;--page:linear-gradient(180deg,color-mix(in srgb,var(--brand) 62%,#05070C) 0%,color-mix(in srgb,var(--brand) 24%,#05070C) 34%,transparent 100%) 0 0 / 100% 82vh no-repeat, #05070C;--panel-blur:blur(24px) saturate(150%);--page-match:linear-gradient(180deg,transparent 0%,color-mix(in srgb,#05070C 55%,transparent) 46%,#05070C 100%) 0 0 / 100% 88vh no-repeat,linear-gradient(100deg,var(--h) 0%,color-mix(in srgb,var(--h) 72%,var(--a)) 34%,color-mix(in srgb,var(--h) 50%,var(--a)) 50%,color-mix(in srgb,var(--a) 72%,var(--h)) 66%,var(--a) 100%) 0 0 / 100% 88vh no-repeat,#05070C;--panel:#00000047;--panel-2:#0000006B;--well:#FFFFFF1A;--hover:#FFFFFF0F;--line:#FFFFFF1A;--line-2:#FFFFFF33;--fg:#FFFFFF;--mute:#FFFFFF99;--faint:#FFFFFF5C;--accent:#FF453A;--accent-ink:#FFFFFF;--ink-light:#FFFFFF;--ink-dark:#05070C;--win:#30D158;--loss:#FF453A;--draw:#FFFFFF5C;--card-yellow:#FFD60A;--card-red:#FF3B30;--veil:#000000A6;--shade:#05070C;--shadow:#00000099;--cut:0deg;--bug-home:polygon(0 0,50% 0,50% 100%,0 100%);--bug-away:polygon(50% 0,100% 0,100% 100%,50% 100%);--bug-home-phone:polygon(0 0,100% 0,100% 50%,0 50%);--bug-away-phone:polygon(0 50%,100% 50%,100% 100%,0 100%);--strap:#05070CB3;--crest-clip:none;--pill-clip:none;--cta-clip:none;--radius:26px;--radius-sm:13px;--rule-w:0px;--panel-border:1px solid #FFFFFF14;--face-display:system-ui,-apple-system,BlinkMacSystemFont,"SF Pro Display","Helvetica Neue",Arial,sans-serif;--face-body:system-ui,-apple-system,BlinkMacSystemFont,"SF Pro Text","Helvetica Neue",Arial,sans-serif;--face-mono:ui-monospace,"SF Mono",Menlo,monospace;--display-transform:none;--display-spacing:-.02em;--display-weight:800;--label-spacing:.05em;--body-size:15px;--mode-toggle:none}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* ⛔ --page, NOT --bg. They are two different questions and this rule used to
   conflate them: --bg is what a card sits ON, and the PAGE is free to be
   something else entirely — Apple washes it in the client's own colour and
   fades it to black. A theme that wants flat points --page at --bg and nothing
   in the system notices. ⚠ min-height so a short page still shows the whole
   fade rather than cutting it off at the content. */
/* ⛔ THE PAGE'S BACKGROUND BELONGS TO THE ROOT, AND PUTTING --bg THERE IS WHAT
   MADE THE TOP BLACK. The last attempt painted html with the flat --bg to make
   the bottom flush, and the ROOT is exactly what paints the canvas behind the
   status bar — so the strip behind the clock went near-black above a coloured
   page. The owner: "behind it, it's black. Shouldn't be black. It should be
   whatever the page color is."
   The whole wash goes on the root instead. A root background propagates to the
   canvas, which covers the viewport edge to edge — above the status bar, below
   the URL bar, and through an overscroll — so there is one surface and nothing
   left to align. body is transparent so it cannot paint a second one over it. */
html{background:var(--page)}
html[data-page="match"]{background:var(--page-match)}
/* ⚠ 100dvh, not svh: svh is the SMALLEST viewport, so the page stopped short of
   the bottom bar exactly when the bar was hidden. */
body{margin:0;background:transparent;color:var(--fg);min-height:100dvh;
  font:var(--body-size)/1.55 var(--face-body);-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{margin:0;text-wrap:balance;font-weight:inherit}
p{margin:0}
a{color:inherit;text-decoration:none}
img{max-width:100%}
svg{display:block}
ol,ul{list-style:none;margin:0;padding:0}
table{border-collapse:collapse}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}


/* ⛔ TRACKING IS SIZE-SPECIFIC, AND ONE VALUE FOR EVERY SIZE IS WRONG SOMEWHERE.
   The theme declares ONE --display-spacing, and it was applied identically to a
   100px score and a 14px heading. Letters read too far apart as type grows, so
   large display wants NEGATIVE tracking and small display wants the positive
   value the theme sets — which for Matchday's condensed uppercase face is very
   much needed at label sizes and far too loose at hero sizes.

   ⚠ DERIVED FROM THE THEME, NOT DECLARED BESIDE IT. These are offsets from
   whatever the theme chose, so a theme that squares up to 0 still tightens as
   its type grows and no theme has to declare three values to say one thing.
   ⚠ In em, so they scale with the size they are applied to rather than needing
   a table. */
:root{
  --track-xl:calc(var(--display-spacing) - .055em);
  --track-lg:calc(var(--display-spacing) - .035em);
  --track-md:calc(var(--display-spacing) - .018em);
}
/* Apple's optical sizing point: a variable face already ships size-specific
   shapes, and asking for them costs nothing on a face that has none. */
html{font-optical-sizing:auto}
.wrap{max-width:1080px;margin:0 auto;padding:0 22px}
/* ⛔ padding-BLOCK, not the padding shorthand. .wrap and .stack sit on the
   SAME element, same specificity, and a shorthand written second resets the
   left and right padding to zero — so every page ran flush to the edge of the
   window. Nothing in the source looks wrong; you have to measure the heading. */
.stack{display:flex;flex-direction:column;gap:30px;padding-block:28px 46px}
.grid2{display:grid;grid-template-columns:1.5fr 1fr;gap:28px;align-items:start}
.grid-eq{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:start}
/* ⛔ A grid column is minmax(auto,1fr) by default, so a ten-column table
   inside one pushes the whole page wider than the window instead of shrinking.
   The page then scrolls sideways on a laptop and nobody sees the last column. */
.grid2 > *,.grid-eq > *{min-width:0}
.disp{font-family:var(--face-display);font-weight:var(--display-weight);
  letter-spacing:var(--display-spacing);text-transform:var(--display-transform)}
.lbl{font-size:10.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--faint)}
.num{font-variant-numeric:tabular-nums}
.skew{transform:skewX(calc(var(--cut) * -1))}

/* ⛔ THE CHROME IS A MATERIAL, NOT TWO BARS. The rail and the nav used to be two
   opaque strips with a hairline each, permanently consuming ~90px at the top of
   every page. As one translucent layer the page scrolls UNDERNEATH it, which is
   what a match page 2700px long needs: at any scroll position it still answers
   where am I and where can I go.
   ⚠ THE BLUR IS ON THE WRAPPER AND NOWHERE ELSE. A translucent surface stacked
   on another translucent surface is the one combination that destroys
   legibility, so the rail and nav inside are transparent and only tint. */
.chrome{position:sticky;top:0;z-index:20;
  background:color-mix(in srgb,var(--bg) 72%,transparent);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%)}
/* A SCROLL EDGE, NOT A DIVIDER. A 1px line under floating chrome reads as a
   border drawn on the page; a short fade reads as the underside of a material
   the content is passing beneath. */
.chrome::after{content:"";position:absolute;left:0;right:0;top:100%;height:14px;
  pointer-events:none;
  background:linear-gradient(color-mix(in srgb,var(--bg) 44%,transparent),transparent)}

/* THE ON-AIR RAIL — broadcast is the differentiator, so it is on every page. */
/* ⚠ A DENSER BAND, NOT A LINE UNDER IT. The comment on .top says a hairline
   would draw a divider through one material, and this rule was still drawing
   one. Material WEIGHT is how hierarchy is encoded on a translucent surface:
   the rail is the louder half of the same glass, so it is tinted rather than
   fenced off. ⚠ Mixed toward --fg rather than --shade so it darkens a dark
   theme and lightens a light one without either naming a colour. */
.rail{display:flex;align-items:center;gap:12px;padding:7px 22px;
  background:color-mix(in srgb,var(--fg) 5%,transparent);font-size:11px;
  /* ⚠ VIBRANCY: type over a blurred surface needs more weight and a touch more
     tracking than the same type on a solid one, or it dissolves into whatever
     is passing behind it. */
  font-weight:600;letter-spacing:calc(var(--label-spacing) * .85);text-transform:uppercase}
.rail .dot{width:6px;height:6px;border-radius:50%;background:var(--accent);flex:none;
  animation:beat 1.7s ease-in-out infinite}
@keyframes beat{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.8)}}
.rail-live{color:var(--accent);font-weight:800;display:flex;align-items:center;gap:6px;flex:none}
.rail-item{color:var(--mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rail-item b{color:var(--fg)}
.rail-more{margin-left:auto;color:var(--faint);flex:none}

nav/* ⚠ Shown or hidden by the THEME, never by the renderer — see --mode-toggle.
   Both themes build the same markup; only this token differs. */
.modetoggle{display:var(--mode-toggle);align-items:center;justify-content:center;
  width:30px;height:30px;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  background:none;color:var(--mute);font-size:14px;cursor:pointer;line-height:1}
.modetoggle:hover{color:var(--fg);border-color:var(--faint)}
/* ⚠ NO BORDER AND NO BACKGROUND. Both belong to .chrome now — a second
   translucent surface inside the first is the stacking the material rules
   forbid, and a hairline here would draw a divider through one material. */
.top{display:flex;align-items:center;gap:24px;padding:13px 22px}
.brand{display:flex;align-items:center;gap:10px;font-size:18px;
  letter-spacing:var(--track-md)}
.brand .m{width:26px;height:26px;background:var(--accent);flex:none;
  clip-path:var(--crest-clip);border-radius:var(--radius-sm)}
/* ⚠ A real crest is NOT clipped. The cut is our mark, and taking a corner off a
   client's own logo to apply it is the one place the theme must not reach. */
.brand img.m{background:none;clip-path:none;object-fit:contain}
nav.top .links{display:flex;gap:18px;margin-left:auto;font-size:12px;
  letter-spacing:calc(var(--label-spacing) * .7);text-transform:uppercase;color:var(--mute)}
nav.top .links a:hover{color:var(--fg)}
nav.top .links a.on{color:var(--fg);box-shadow:0 2px 0 var(--accent)}

.sec{display:flex;align-items:center;gap:12px;margin:0 0 14px}
/* ⛔ THE TRANSFORM IS THE THEME'S, AND THIS RULE WAS TAKING IT. A section
   heading carries .disp in the markup, which sets text-transform from the token
   — and this selector is one class plus one element, so it out-specified the
   token and forced UPPER CASE on every theme. Invisible until a theme that is
   sentence case existed, and then it was the first thing on the page: APPLE
   SPORTS in a design whose whole voice is sentence case. */
.sec h2{font-size:14px;letter-spacing:calc(var(--label-spacing) * 1.5);
  text-transform:var(--display-transform)}
.sec .bar{height:var(--rule-w);flex:1;transform:skewX(calc(var(--cut) * -1));
  background:linear-gradient(90deg,var(--accent) 0 24px,var(--line-2) 24px 32px,var(--line) 32px)}
/* ⚠ Truncated, and it is the ONE place a name may be. This is a note beside a
   heading — "Canadian Rugby Championship - MEN" — not the identity of a club. */
.sec .more{font-size:11px;letter-spacing:calc(var(--label-spacing) * .8);text-transform:uppercase;
  color:var(--faint);flex:none;max-width:45%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ⚠ A CARD ON A WASHED PAGE IS TRANSLUCENT AND BLURS WHAT PASSES UNDER IT; a
   card on a flat page is opaque and blurs nothing. A --panel-blur of none costs a
   theme that does not want it exactly nothing. */
.panel{background:var(--panel);border:var(--panel-border);border-radius:var(--radius);padding:18px 20px;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.panel.tight{padding:14px 16px}
.panel + .sec{margin-top:22px}
.empty{color:var(--mute);font-size:13.5px}


/* ⛔ THE SHOOT-OUT, IN THE CONVENTION EVERYBODY USES — brackets beside the
   score, never added to it. Verified against ESPN's own wire format rather than
   designed: Gremio 0(5), Independiente 0(4).
   ⛔ AND NOT ONE COLOUR IS NAMED HERE. Written first with literal hexes for the
   tick and the cross, and site/theme.test.mjs failed the build on it in seconds
   — which is the gate doing exactly its job. A shootout kick is a WIN or a LOSS,
   and this palette already has words for those.
   ⚠ NO BACKTICKS IN THIS COMMENT — one template literal, and that trap has bitten
   three times in this session already. */
.pk{font-size:.62em;font-weight:800;color:var(--accent);margin-left:.18em;vertical-align:.08em;
  font-variant-numeric:tabular-nums}
.n .pk,.sc .pk{font-size:.5em}
.pk-panel{margin:12px 0 0;border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.pk-t{border-collapse:collapse;width:100%;font-size:13px}
.pk-t td{padding:7px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
.pk-t tr:last-child td{border-bottom:0}
.pk-t td.r{text-align:right}
.pk-t td.no{text-align:center;width:30px;color:var(--mute);font-variant-numeric:tabular-nums}
.pk-t tr.sudden td{background:var(--well)}
.pk-ic{display:inline-flex;align-items:center;justify-content:center;width:19px;height:19px;border-radius:50%;
  color:var(--on-c);font-size:11px;font-weight:800;margin:0 7px}
.pk-ic.ok{background:var(--win)} .pk-ic.no{background:var(--loss)}
.pk-none{display:inline-block;width:19px;height:19px;margin:0 7px}
.pk-nm{font-weight:600} .pk-nm.dim{color:var(--mute)}
/* ⛔ APPLE'S OWN COLUMN. Its rows are numeric and right-aligned, so the brackets
   get a column rather than trailing the digit — a list of fixtures has to stay
   in line. Dims with the score it belongs to. */
.a-pk{font-weight:800;color:var(--accent);margin-left:.35em;min-width:1.9em;display:inline-block;
  text-align:right;font-variant-numeric:tabular-nums;font-size:.8em}
.a-pk.a-dim{color:var(--mute)}
.a-pens{margin:0 0 10px;font-weight:700;font-size:14px}
.a-pk-list{display:flex;flex-direction:column}
.a-pk-row{display:grid;grid-template-columns:1fr 30px 1fr;align-items:center;padding:7px 0;
  border-bottom:1px solid var(--line);font-size:13px}
.a-pk-row:last-child{border-bottom:0}
.a-pk-row.sudden{background:var(--well)}
.a-pk-side{display:flex;align-items:center;gap:7px}
.a-pk-side.r{justify-content:flex-end}
.a-pk-no{text-align:center;color:var(--mute);font-variant-numeric:tabular-nums;font-size:12px}
.a-pk-ic{display:inline-flex;align-items:center;justify-content:center;width:19px;height:19px;border-radius:50%;
  color:var(--on-c);font-size:11px;font-weight:800}
.a-pk-ic.ok{background:var(--win)} .a-pk-ic.no{background:var(--loss)}
.a-pk-none{display:inline-block;width:19px;height:19px}
.a-pk-nm{font-weight:600} .a-pk-nm.dim{color:var(--mute)}

/* ⛔ THE PENALTIES LINE, and it is deliberately NOT score-sized. A shootout
   decides who progressed; the score bug above it is the result the standings
   count. Making this look like a second score is the mistake matrix's own
   module is written to avoid — "a shootout kick is NOT a goal".
   ⚠ IT LIVES IN THE BUG BLOCK RATHER THAN ITS OWN EXPORT. Written first as its
   own PENS_CSS export, which is not in COMPONENT_CSS's join and therefore never
   reached a page at all — a dead style that renders as nothing.
   ⚠ AND NO BACKTICKS IN THIS COMMENT. The whole block is one template literal,
   so a backtick here ends it — the trap this file is named for in ledger #158,
   tripped again writing this very comment. Third time in one session. */
.pens{margin:10px 0 0;font-size:14px;font-weight:600;letter-spacing:.01em;opacity:.85}

.bug{position:relative;overflow:hidden;isolation:isolate}
.bug .fh,.bug .fa{position:absolute;inset:0;z-index:-1}
.bug .fh{background:linear-gradient(160deg,var(--h),color-mix(in srgb,var(--h) 52%,var(--shade)));
  clip-path:var(--bug-home);animation:wipeL .7s cubic-bezier(.22,1,.36,1) both}
.bug .fa{background:linear-gradient(200deg,var(--a),color-mix(in srgb,var(--a) 52%,var(--shade)));
  clip-path:var(--bug-away);animation:wipeR .7s cubic-bezier(.22,1,.36,1) both}
@keyframes wipeL{from{transform:translateX(-102%)}to{transform:none}}
@keyframes wipeR{from{transform:translateX(102%)}to{transform:none}}
.bug::after{content:"";position:absolute;inset:0;z-index:-1;
  background:radial-gradient(120% 80% at 50% 0%,transparent 40%,var(--veil))}
.bug-in{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px;
  padding:46px 22px 38px;max-width:1000px;margin:0 auto;
  animation:rise .55s .2s cubic-bezier(.22,1,.36,1) both}
@keyframes rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
/* ⚠ The ink over a team's colour field comes from the COLOUR, not the theme —
   Ottawa's primary is black and British Columbia's is a light yellow, and one
   fixed ink is unreadable on one of them. site/derive.mjs inkOn() sets --on-c. */
.side{display:flex;align-items:center;gap:14px;min-width:0;color:var(--on-c)}
.side.r{justify-content:flex-end;text-align:right}
.side .nm{min-width:0}
/* ⛔ CLUB-SAFE: long club names WRAP, they do not truncate. "Brantford
   Harlequins" cut to "Brantford Harl…" reads as a club that does not exist. */
.side .nm .t{font-size:25px;line-height:1.04;letter-spacing:var(--track-md);text-shadow:0 2px 18px var(--shadow);
  overflow-wrap:break-word}
.side .nm .s{font-size:10.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  opacity:.82;margin-top:3px}

.crest{width:56px;height:56px;flex:none;display:grid;place-items:center;background:var(--c);
  clip-path:var(--crest-clip);border-radius:var(--radius-sm);color:var(--on-c);
  font-family:var(--face-display);font-weight:700;font-size:15px;overflow:hidden;
  box-shadow:inset 0 0 0 1px var(--line-2)}
.crest img{width:100%;height:100%;object-fit:contain}

/* ⛔ The score sits across BOTH colour fields, so its ink is picked from the two
   of them together — not from the theme. On a light theme the body ink is dark,
   and dark numerals over a club's red is the least readable thing on the page. */
.score{display:flex;align-items:baseline;gap:11px;font-variant-numeric:tabular-nums;
  color:var(--on-c);text-shadow:0 4px 30px var(--shadow)}
.score .n{font-size:100px;line-height:.84;letter-spacing:var(--track-xl)}
/* The result reads before the numbers do. */
.score .n.lost{opacity:.5}
.score .x{font-size:34px;opacity:.55;font-weight:400;align-self:center}

.strap{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:10px 22px;
  background:var(--strap);border-top:1px solid var(--line);
  font-size:11px;letter-spacing:calc(var(--label-spacing) * .7);text-transform:uppercase;color:var(--mute)}
/* ⚠ THE STRAP IS SMALL CAPS AND THE THINGS SITTING IN IT ARE NOT NECESSARILY.
   Both inherit text-transform from .strap, so a theme whose voice is sentence
   case still shouted FULL TIME and WATCH THE REPLAY out of an otherwise
   sentence-case page. The competition name beside them stays upper case on
   purpose — that is a label, and Apple sets league names in caps too. */
.pill,.cta{text-transform:var(--display-transform)}
.pill{padding:4px 10px;font-weight:800;letter-spacing:calc(var(--label-spacing) * .8);flex:none;
  clip-path:var(--pill-clip);border-radius:var(--radius-sm)}
.pill.ft{background:var(--fg);color:var(--bg)}
.pill.lv{background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;gap:6px}
.pill.lv i{width:5px;height:5px;border-radius:50%;background:var(--accent-ink);animation:beat 1.7s infinite}
.pill.up{background:var(--well);color:var(--fg)}
.cta{background:var(--fg);color:var(--bg);font-weight:800;padding:8px 16px;
  letter-spacing:calc(var(--label-spacing) * .7);flex:none;border-radius:var(--radius-sm);
  clip-path:var(--cta-clip);transition:.16s}
.cta.end{margin-left:auto}
.cta:hover{background:var(--accent);color:var(--accent-ink)}
.cta.ghost{background:none;color:var(--fg);box-shadow:inset 0 0 0 1px var(--line-2)}

/* ⛔ FEEDBACK BELONGS ON THE PRESS, NOT ON THE RELEASE. Every interactive thing
   here had a :hover and nothing at all on :active — so on a phone, where there
   is no hover, tapping a match card produced no acknowledgement until the next
   page painted. On a slow connection at a ground that is a card you tap three
   times. The moment lag appears the sense of directness falls off a cliff.
   ⚠ TRANSFORM AND OPACITY ONLY — both composite, so the response cannot be
   delayed by a layout pass, which is the whole point of putting it here. */
.cta:active,.mc:active,.pl:active,.modetoggle:active,
nav.top .links a:active,.rail-item:active{
  transform:scale(.985);opacity:.9;transition:transform 100ms ease-out,opacity 100ms ease-out}


.mom{width:100%;height:auto}
.chart-key{display:flex;gap:16px;flex-wrap:wrap;font-size:10.5px;
  letter-spacing:calc(var(--label-spacing) * .8);text-transform:uppercase;color:var(--faint);margin-top:8px}
.chart-key span{display:flex;align-items:center;gap:6px}
.chart-key i{width:14px;height:5px;transform:skewX(calc(var(--cut) * -1))}
.chart-key .end{margin-left:auto}

.cmp{display:flex;flex-direction:column;gap:11px}
.cmp-r{display:grid;grid-template-columns:38px 1fr 38px;gap:10px;align-items:center;
  font-variant-numeric:tabular-nums;font-size:13px}
.cmp-r .lb{grid-column:1/-1;text-align:center;font-size:9.5px;
  letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--faint);margin-bottom:-5px}
.cmp-bar{display:flex;height:9px;background:var(--well);overflow:hidden;border-radius:var(--radius-sm)}
/* ⛔ A CLUB COLOUR KEEPS AN EDGE, for the same reason .tbl .chip does. Ottawa
   Myers Automotive's primary really is #000000: measured on the live OHF match,
   "Shots 1–3" drew the home share as a black block on a near-black track, so a
   club that had a shot read as having had none. The hairline is the only thing
   between that and a wrong number on the screen. */
.cmp-bar i{display:block;height:100%;transform:skewX(calc(var(--cut) * -1));
  box-shadow:inset 0 0 0 1px var(--line-2)}
.cmp-bar .h{background:var(--h);margin-left:auto}
.cmp-bar .a{background:var(--a)}
.cmp-r .vh{text-align:right;font-weight:700}
.cmp-r .va{font-weight:700}
.cmp-r.win-h .vh{color:var(--h)}
.cmp-r.win-a .va{color:var(--a)}
/* ⛔ A CANONICAL ROW AT 0–0 IS DRAWN AND MUTED. The owner's decision — a rugby
   page that lists Conversions 0–0 says we measure this and there were none,
   where the row missing entirely says nothing at all and reads as a page that
   failed to load. ⚠ The muting is not taste: a nil row's bar is a half-and-half
   split of NOTHING, and at full strength two even blocks of club colour read as
   a dead heat somebody fought for. The track alone carries it. */
.cmp-r.nil .vh,.cmp-r.nil .va{color:var(--faint);font-weight:400}
/* ⛔ AND A ROW WHERE FEWER IS BETTER DOES NOT GET A PROUD BAR. Every other use
   of a club colour on this page means "this club's share of a good thing" —
   momentum, the ribbon, head to head, the radar. On Red cards 1–0 the same
   colour filled the whole track for the club that had a player SENT OFF, which
   reads as an achievement. The share is still drawn, because whose it is still
   matters; it is just no longer shouted, and the winner's figure carries the
   verdict as it does everywhere else. */
.cmp-r.inv .cmp-bar i{opacity:.4}
/* ⛔ AFTER THE INVERTED RULE ABOVE, AND THE ORDER IS THE WHOLE POINT. Both
   selectors are one class on the row plus two elements, so they tie on
   specificity and the LAST one wins — with this rule written first, Penalties
   0–0 on a hockey match drew a solid half-track of club colour under two
   zeroes. Every rule was correct in isolation; only the rendered page said
   which one won. */
.cmp-r.nil .cmp-bar i{opacity:0}

.radar{width:100%;max-width:330px;margin:0 auto}

.rib{display:flex;align-items:center;gap:2px;height:38px;background:var(--well);padding:0 8px;
  position:relative;border-radius:var(--radius-sm)}
.rib::before{content:"";position:absolute;left:8px;right:8px;top:50%;height:1px;background:var(--line-2)}
.rib i{width:9px;height:9px;background:var(--c);position:relative;flex:none;
  clip-path:var(--crest-clip)}
.rib i.up{align-self:flex-start;margin-top:7px}
.rib i.dn{align-self:flex-end;margin-bottom:7px}
.rib .sp{flex:1;min-width:2px}

.h2h{display:flex;align-items:center;gap:2px;height:12px}
.h2h i{height:100%;transform:skewX(calc(var(--cut) * -1))}
.h2h-l{display:flex;justify-content:space-between;gap:10px;font-size:10.5px;
  letter-spacing:calc(var(--label-spacing) * .8);text-transform:uppercase;color:var(--faint);margin-top:8px}

.stars{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);
  border:var(--panel-border);border-radius:var(--radius);overflow:hidden;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.star{background:var(--panel);padding:14px 15px;display:flex;flex-direction:column;gap:5px}
.star .rk{font-family:var(--face-display);font-size:11px;
  letter-spacing:var(--label-spacing);color:var(--accent);font-weight:700}
.star .nm{font-size:14.5px;font-weight:600;line-height:1.2}
.star .ln{font-size:10.5px;letter-spacing:calc(var(--label-spacing) * .8);
  text-transform:uppercase;color:var(--faint)}
.star .fig{font-size:27px;margin-top:3px;letter-spacing:var(--track-lg);font-variant-numeric:tabular-nums}
.star .sub{font-size:11px;color:var(--mute)}

/* ⚠ The grouped surfaces carry the card's radius and blur too, or a theme with
   26px corners has one square block in the middle of a page of soft ones. The
   1px gaps are the group's own hairlines, so overflow:hidden is what keeps the
   corners from being cut square by the children. */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:1px;
  background:var(--line);border:var(--panel-border);border-radius:var(--radius);overflow:hidden;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.kpi{background:var(--panel);padding:14px 16px}
.kpi b{display:block;font-family:var(--face-display);font-size:29px;font-weight:var(--display-weight);
  line-height:1;letter-spacing:var(--track-lg);font-variant-numeric:tabular-nums}
.kpi span{display:block;font-size:9.5px;letter-spacing:var(--label-spacing);
  text-transform:uppercase;color:var(--faint);margin-top:6px;font-weight:600}
.kpi.bare{background:none;padding:11px 0}


/* ⛔ THESE TWO ARE SIZED BY THEIR CONTAINER, NOT BY THE WINDOW, and that is what
   makes them club-safe. A table in a sidebar and a match card in a narrow column
   are as tight as a phone is; a media query would leave both looking fine on a
   1280px laptop while "Brantford Harlequins" broke across two lines mid-word. */
.tblw,.cards{container-type:inline-size}
.tbl{width:100%;font-size:13.5px}
.tbl th{text-align:right;font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--faint);padding:0 8px 9px;font-weight:700}
.tbl th:nth-child(-n+2){text-align:left}
.tbl td{padding:10px 8px;border-top:1px solid var(--line);text-align:right;
  font-variant-numeric:tabular-nums}
.tbl td:nth-child(-n+2){text-align:left}
.tbl tbody tr:hover{background:var(--hover)}
.tbl .p{color:var(--faint);width:22px;font-family:var(--face-mono);font-size:11.5px}
.tbl .tm{display:flex;align-items:center;gap:9px}
/* ⛔ A COLOUR MARK KEEPS AN EDGE. Ottawa Myers Automotive's primary really is
   #000000, which is invisible on a dark theme and a solid block on a light one;
   a club whose mark disappears is a club a supporter cannot find in a table. */
.tbl .chip{width:6px;height:20px;background:var(--c);flex:none;clip-path:var(--crest-clip);
  box-shadow:inset 0 0 0 1px var(--line-2)}
.tbl .pt{font-family:var(--face-display);font-size:18px;font-weight:var(--display-weight);
  letter-spacing:var(--track-md)}
.tbl tr.lead td{background:var(--hover)}
.tbl tr.lead .tm{font-weight:700}
.up{color:var(--win)}
.dn{color:var(--loss)}

.frm{display:flex;gap:3px;justify-content:flex-end}
.frm i{width:13px;height:5px;display:block;transform:skewX(calc(var(--cut) * -1))}
.frm .w{background:var(--win)}
.frm .l{background:var(--loss)}
.frm .d{background:var(--draw)}

.cards{display:grid;gap:9px}
/* ⚠ overflow:hidden is load-bearing, not tidiness. The team-colour bar below is
   an absolutely-positioned block against the card's left edge, and on a theme
   with a 26px corner it painted a square through the rounding — a hard corner
   sticking out of every soft card on the page. At Matchday's 0px radius there
   was nothing to see, which is why it shipped. */
.mc{position:relative;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:12px;
  background:var(--panel);padding:13px 16px 13px 22px;border:var(--panel-border);
  border-radius:var(--radius);overflow:hidden;transition:.16s;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.mc:hover{border-color:var(--line-2);background:var(--panel-2)}
.mc::before{content:"";position:absolute;left:0;top:0;bottom:0;width:6px;
  background:linear-gradient(var(--h) 0 50%,var(--a) 50% 100%)}
.mc .t{display:flex;align-items:center;gap:9px;min-width:0}
.mc .t.r{justify-content:flex-end;text-align:right}
.mc .cr{width:24px;height:24px;flex:none;background:var(--c);clip-path:var(--crest-clip);
  border-radius:var(--radius-sm);display:grid;place-items:center;overflow:hidden;
  font-family:var(--face-display);font-size:9px;font-weight:700;color:var(--on-c);
  box-shadow:inset 0 0 0 1px var(--line-2)}
.mc .cr img{width:100%;height:100%;object-fit:contain}
/* ⛔ Club-safe again: a card name wraps to two lines rather than truncating. */
.mc .nm{font-size:13.5px;line-height:1.25;font-weight:600;overflow-wrap:break-word;min-width:0}
.mc .sc{font-family:var(--face-display);font-size:24px;font-weight:var(--display-weight);
  letter-spacing:var(--track-lg);font-variant-numeric:tabular-nums;display:flex;gap:11px;align-items:baseline;flex:none}
.mc .sc .lost{opacity:.5}
.mc .sc span + span{position:relative}
.mc .sc span + span::before{content:"";position:absolute;left:-7px;top:14%;bottom:22%;width:1px;
  background:var(--line-2);transform:skewX(calc(var(--cut) * -1))}
.mc .when{font-family:var(--face-mono);font-size:11.5px;color:var(--mute);text-align:center;
  flex:none}
.mc .meta{grid-column:1/-1;font-size:10.5px;letter-spacing:calc(var(--label-spacing) * .6);
  text-transform:uppercase;color:var(--faint);display:flex;gap:11px;flex-wrap:wrap}

.card-r{display:flex;align-items:baseline;gap:13px;padding:6px 0}
.card-r .tm{flex:1;display:flex;align-items:center;gap:11px;font-family:var(--face-display);
  font-size:23px;font-weight:var(--display-weight);letter-spacing:var(--track-md);min-width:0}
.card-r .bar{width:5px;height:22px;background:var(--c);flex:none;clip-path:var(--crest-clip);
  box-shadow:inset 0 0 0 1px var(--line-2)}
.card-r .n{font-family:var(--face-display);font-size:42px;font-weight:var(--display-weight);
  line-height:1;letter-spacing:var(--track-xl);font-variant-numeric:tabular-nums;flex:none}
.card-r .n.lost{opacity:.5}
.card-hr{height:1px;background:var(--line);margin:13px 0 4px}

/* ── the linescore ────────────────────────────────────────────────────────
   ⚠ SIZED BY ITS CONTAINER, because it sits inside the scorecard, which sits in
   a 1.5fr column on a laptop and full width on a phone — the same width in two
   different windows. A media query would be right in one of them.
   ⚠ Column widths are fluid with the team column auto: a rugby match has two
   periods and a hockey match has four plus overtime, and a fixed table lays out
   two columns across 600px like a spreadsheet somebody forgot to close. */
.lsw{container-type:inline-size;overflow-x:auto;-webkit-overflow-scrolling:touch}
.ls{width:100%;font-variant-numeric:tabular-nums;font-size:14px}
.ls th,.ls td{padding:7px 4px;text-align:center;font-weight:400}
.ls thead th{font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--faint);padding-bottom:4px}
.ls tbody tr + tr th,.ls tbody tr + tr td{border-top:1px solid var(--line)}
/* The team cell is the row's label: a colour mark and a code, left aligned, and
   it never shrinks below the code's own width. */
.ls tbody th{text-align:left;display:flex;align-items:center;gap:8px;
  font-family:var(--face-display);font-weight:var(--display-weight);
  letter-spacing:var(--track-md);text-transform:var(--display-transform);
  padding-right:10px;white-space:nowrap}
.ls tbody th i{width:4px;height:16px;background:var(--c);flex:none;clip-path:var(--crest-clip);
  border-radius:var(--radius-sm);box-shadow:inset 0 0 0 1px var(--line-2)}
.ls .t{font-family:var(--face-display);font-weight:var(--display-weight);
  letter-spacing:var(--track-md);color:var(--fg)}
.ls thead .t{font-family:var(--face-body);font-weight:700}
/* ⛔ THE LOSING ROW DIMS, exactly as the score bug and the match card already do.
   It is the one piece of Apple's language that carries the most meaning per
   pixel: the result reads before any number is parsed. */
.ls tbody tr.lost{color:var(--mute)}
.ls tbody tr.lost th{opacity:.62}

.tl li{display:grid;grid-template-columns:42px 92px 1fr auto;gap:11px;align-items:baseline;
  padding:6px 0 6px 14px;border-left:2px solid var(--line);margin-left:3px}
.tl .m{font-family:var(--face-mono);font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.tl .w{font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--mute)}
.tl .who{font-size:14px}
.tl .who em{color:var(--faint);font-style:normal}
.tl .s{font-family:var(--face-mono);font-size:12px;font-variant-numeric:tabular-nums;color:var(--mute)}
.tl li.key{border-left-color:var(--accent)}
.tl li.key .w{color:var(--accent);font-weight:800}
.tl li.key .s{color:var(--fg)}

/* ── the team sheets ──────────────────────────────────────────────────────
   ⛔ BOTH SIDES IN THE DOCUMENT. Stats hides one team behind a tab because it
   repaints panels on a poll anyway; this page arrives finished, so a supporter
   looking for one name can use the browser's own find. Two columns that become
   two stacks, and nothing is ever display:none. */
/* ⛔ THE CONTAINER IS THE OUTER ELEMENT AND THE GRID IS THE INNER ONE. A
   container query styles a container's DESCENDANTS, never the container itself,
   so container-type on the grid with a rule targeting that same grid matched
   nothing at all — clean CSS, clean build, two team sheets crushed side by side
   on a phone. See render.mjs lineupPanel(). */
.sheets{container-type:inline-size}
.sheets-in{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line);
  border:var(--panel-border);border-radius:var(--radius);overflow:hidden;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.sheet{background:var(--panel);padding:4px 0 8px;min-width:0}
.sheet-h{display:flex;align-items:center;gap:10px;padding:12px 15px 10px;
  font-family:var(--face-display);font-size:15px;font-weight:var(--display-weight);
  letter-spacing:var(--track-md);text-transform:var(--display-transform);
  border-bottom:1px solid var(--line);margin-bottom:4px}
.sheet-h .bar{width:5px;height:19px;background:var(--c);flex:none;clip-path:var(--crest-clip);
  box-shadow:inset 0 0 0 1px var(--line-2)}
.sheet-h span:not(.n){min-width:0;overflow-wrap:break-word}
.sheet-h .n{margin-left:auto;font-family:var(--face-mono);font-size:11.5px;color:var(--faint);
  flex:none;font-weight:400;letter-spacing:0;text-transform:none}
.sheet .empty{padding:10px 15px 6px}
.lu{display:grid;grid-template-columns:26px 1fr auto;gap:10px;align-items:baseline;
  padding:6px 15px}
/* ⚠ ON THE FIELD IS A LEFT EDGE, NOT A WASH. A row tinted with the club colour
   fights the crest bar above it and disappears entirely for a club whose primary
   is near the panel; a rule on the accent means the same thing in every kit. */
.lu.on{box-shadow:inset 2px 0 0 var(--accent)}
.lu .no{font-family:var(--face-display);font-size:14px;font-weight:var(--display-weight);
  color:var(--faint);font-variant-numeric:tabular-nums;text-align:right}
.lu.on .no{color:var(--accent)}
/* ⚠ min-width:0 on BOTH the cell and the name, or the auto column beside it
   never yields: at 350px "Jack Gore" and "6 CONVERSIONS" were painted on top of
   one another, which reads as a corrupted page rather than a tight one. */
.lu .id{min-width:0;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.lu .who{font-size:13.5px;line-height:1.3;overflow-wrap:break-word;min-width:0}
.lu .who em{color:var(--faint);font-style:normal;font-size:11px}
.lu .pos{font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--faint)}
/* What a player DID, and nothing where they did nothing — a column of zeroes
   down a team sheet is 26 figures nobody reads. */
.lu .did{font-size:10px;letter-spacing:calc(var(--label-spacing) * .8);text-transform:uppercase;
  color:var(--mute);text-align:right;display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.lu .did em{font-style:normal;white-space:nowrap}

/* ── the match feed — every event, not only the scoring ones ────────────── */
.feed{display:flex;flex-direction:column}
.feed li{display:grid;grid-template-columns:46px 108px 1fr auto;gap:11px;align-items:baseline;
  padding:7px 0 7px 13px;border-left:3px solid var(--c);margin-left:2px}
.feed .m{font-family:var(--face-mono);font-size:11.5px;color:var(--faint);
  font-variant-numeric:tabular-nums}
.feed .w{font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--mute)}
.feed .who{font-size:13.5px;line-height:1.3;min-width:0;overflow-wrap:break-word}
.feed .who em{color:var(--faint);font-style:normal}
.feed .s{font-family:var(--face-mono);font-size:12px;font-variant-numeric:tabular-nums;
  color:var(--mute)}
/* A play that moved the score, and a card. Everything else is the texture they
   sit in, so only these two are allowed to be loud. */
.feed li.sc .w{color:var(--fg);font-weight:800}
.feed li.sc .who{font-weight:600}
.feed li.sc .s{color:var(--fg)}
.feed li.dc .w{color:var(--loss);font-weight:800}
/* ⚠ A sin bin is not a sending-off. There is no amber token and adding one
   would make every theme declare a colour for one row of one panel, so the two
   share the loss colour and differ in weight — the red stays at full strength. */
.feed li.dc.soft .w{opacity:.74}
/* ⚠ The period marker is a boundary, not an event, so it keeps no colour stripe
   and no time — it says WHERE in the match the rows under it happened. */
.feed li.mk{grid-template-columns:1fr;border-left-color:transparent;padding:14px 0 6px 13px;
  font-size:9.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--faint)}
.feed li.mk span{display:block;border-top:1px solid var(--line);padding-top:8px}
.feed li.mk:first-child span{border-top:0;padding-top:0}

.squad{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:1px;
  background:var(--line);border:var(--panel-border);border-radius:var(--radius);overflow:hidden;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.pl{background:var(--panel);padding:11px 14px;display:flex;align-items:center;gap:11px}
.pl .no{font-family:var(--face-display);font-size:19px;font-weight:var(--display-weight);
  color:var(--faint);width:24px;font-variant-numeric:tabular-nums;flex:none}
.pl .id{display:flex;flex-direction:column;min-width:0}
.pl .who{font-size:13.5px;line-height:1.25;font-weight:600;overflow-wrap:break-word}
.pl .pos{font-size:10px;letter-spacing:calc(var(--label-spacing) * .8);text-transform:uppercase;
  color:var(--faint);margin-top:3px}
.pl .stat{margin-left:auto;font-family:var(--face-display);font-size:17px;
  font-weight:var(--display-weight);flex:none;font-variant-numeric:tabular-nums}

.hero{position:relative;padding:36px 22px 28px;overflow:hidden}
.hero::before{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(152deg,var(--c) 0%,color-mix(in srgb,var(--c) 74%,var(--shade)) 40%,
    color-mix(in srgb,var(--c) 14%,var(--bg)) 94%);
  clip-path:polygon(0 0,100% 0,100% 74%,0 100%)}
.hero .row{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.hero .big{font-size:42px;line-height:1;letter-spacing:var(--track-xl);text-shadow:0 3px 24px var(--shadow);overflow-wrap:break-word}
.hero .sub{font-size:11.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--on-c);opacity:.85;margin-top:6px}

/* ⚠ ANNOUNCED, WITH NOTHING IN IT, IS A REAL STATE. The OWL Premiership exists
   in the feed as a title and a date and nothing else. This is what that looks
   like when it is designed rather than left to fall through as an empty table. */
.soon{position:relative;overflow:hidden;background:var(--panel);border:var(--panel-border);
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur);
  border-radius:var(--radius);padding:28px 24px;display:flex;align-items:center;gap:22px;flex-wrap:wrap}
.soon::before{content:"";position:absolute;inset:0;
  background:repeating-linear-gradient(calc(90deg - var(--cut)),
    color-mix(in srgb,var(--fg) 4%,transparent) 0 2px,transparent 2px 13px)}
.soon > *{position:relative}
.soon .cd{font-family:var(--face-display);font-size:56px;font-weight:var(--display-weight);
  line-height:.9;letter-spacing:var(--track-xl);font-variant-numeric:tabular-nums}
.soon .cd span{display:block;font-family:var(--face-body);font-size:10px;
  letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--faint);
  margin-top:6px;font-weight:600}
.soon .txt{flex:1;min-width:220px}
.soon .txt h3{font-family:var(--face-display);font-size:23px;
  letter-spacing:var(--track-md);text-transform:var(--display-transform);margin-bottom:6px}
.soon .txt p{color:var(--mute);font-size:13.5px;max-width:52ch}

.foot{border-top:1px solid var(--line);padding:22px;display:flex;gap:14px;flex-wrap:wrap;
  align-items:center;font-size:11px;letter-spacing:calc(var(--label-spacing) * .7);
  text-transform:uppercase;color:var(--faint)}
.foot .end{margin-left:auto}


.a-main{max-width:960px;margin:0 auto;padding:0 clamp(12px,3.5vw,20px) 40px;
  display:flex;flex-direction:column;gap:clamp(12px,2.6vw,18px)}

/* THE HEADER — not a bar. No background, no border, not sticky: the wash IS the
   identity and a strip across the top of it hides the only thing that says
   which league this is. */
/* ⚠ viewport-fit=cover puts the page UNDER the status bar, which is what makes
   the colour flush — so the header has to add that height back itself. */
.a-hdr{max-width:960px;margin:0 auto;display:flex;align-items:center;justify-content:center;
  gap:10px;flex-wrap:wrap;
  padding:calc(clamp(12px,3.4vw,20px) + env(safe-area-inset-top))
          clamp(12px,3.5vw,20px) clamp(12px,3.4vw,20px)}
/* ⚠ The wordmark takes the row it is on; the pill centres under it. On a wide
   screen both fit one row and the pill sits right of the name. */
.a-word{flex:1 1 auto}
.a-word{display:flex;align-items:center;gap:10px;min-width:0;
  font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(19px,4.6vw,26px);letter-spacing:var(--track-lg);line-height:1.1}
.a-word img{width:clamp(26px,6vw,32px);height:clamp(26px,6vw,32px);object-fit:contain;flex:none}
/* ONE PILL holding every destination, the way the app puts one control at the
   top right. It scrolls inside itself rather than wrapping, so the pill stays a
   pill at 320px. */
/* ⛔ CENTRED AND SIZED TO ITS CONTENTS. It used to stretch with a flex basis so
   it could share a row with the light/dark button; that button is gone, so the
   pill was left filling the width with dead space after the last item — the
   owner: "there is an extra there that doesn't look nice at all". It is an
   island now: as wide as what is in it, centred when it wraps to its own row,
   and still scrolling inside itself when it cannot fit. */
.a-pill{margin:0 auto;display:flex;align-items:center;justify-content:center;gap:2px;
  flex:0 1 auto;max-width:100%;min-width:0;
  padding:4px;border-radius:999px;background:color-mix(in srgb,var(--fg) 12%,transparent);
  -webkit-backdrop-filter:blur(18px) saturate(160%);backdrop-filter:blur(18px) saturate(160%);
  /* ⛔ NO FADE. It was copied from the nav strip on the other layout, where the
     links really do overflow and the fade is the only thing telling you so.
     This pill is sized to its contents and centred, so it never overflows on
     any width measured — and a permanent fade over a strip that fits reads as
     the last item being cut off. The owner: "there is a fade out on the right
     hand side that shouldn't exist. Why is it there? remove it."
     ⚠ overflow-x stays: at a width narrow enough that five items cannot fit, it
     scrolls rather than clipping. It just does not pretend to. */
  overflow-x:auto;scrollbar-width:none}
.a-pill::-webkit-scrollbar{display:none}
.a-pill a{padding:7px 14px;border-radius:999px;white-space:nowrap;color:var(--mute);
  font-size:clamp(12px,3vw,13.5px);font-weight:600;transition:.14s}
.a-pill a.on{background:var(--fg);color:var(--bg)}
.a-pill a:active{transform:scale(.96)}
.a-mode{display:var(--mode-toggle);align-items:center;justify-content:center;flex:none;
  width:36px;height:36px;border-radius:999px;border:0;cursor:pointer;font-size:15px;
  background:color-mix(in srgb,var(--fg) 12%,transparent);color:var(--mute)}
.a-mode:active{transform:scale(.94)}

/* THE HERO — a circle back, a centred mark, the name under it. */
.a-hero{display:grid;grid-template-columns:44px 1fr 44px;align-items:center;
  gap:8px;padding:clamp(4px,2vw,14px) 0 clamp(10px,2.6vw,18px)}
.a-circ{width:44px;height:44px;border-radius:999px;display:grid;place-items:center;
  background:color-mix(in srgb,var(--fg) 12%,transparent);font-size:22px;line-height:1;
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}
.a-circ:active{transform:scale(.94)}
.a-hero-in{text-align:center;min-width:0;display:flex;flex-direction:column;
  align-items:center;gap:8px}
.a-h1{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(22px,5.6vw,32px);letter-spacing:var(--track-lg);line-height:1.08;
  overflow-wrap:break-word}
.a-sub{font-size:clamp(11.5px,3vw,13px);color:var(--mute)}

/* THE CARD — everything lives in one. */
.a-card{background:var(--panel);border:var(--panel-border);border-radius:var(--radius);
  padding:clamp(14px,3.4vw,20px);overflow:hidden;
  -webkit-backdrop-filter:var(--panel-blur);backdrop-filter:var(--panel-blur)}
.a-card.a-flush{padding:0}

.a-ct{font-size:clamp(14px,3.4vw,16px);font-weight:700;text-align:center;
  padding:clamp(13px,3vw,17px) 16px clamp(9px,2vw,12px)}
.a-card:not(.a-flush) .a-ct{padding:0 0 12px}
.a-ct-l{display:flex;align-items:center;gap:10px;padding:15px 16px;font-size:16px;font-weight:700}
.a-ct-l span{margin-left:auto;color:var(--faint);font-size:20px;line-height:1}
.a-empty{color:var(--mute);font-size:14px;text-align:center;padding:26px 16px}
.a-note{color:var(--faint);font-size:clamp(10.5px,2.7vw,11.5px)}
.a-pad{padding:0 16px 10px}
.a-sub-h{font-size:11px;font-weight:700;letter-spacing:var(--label-spacing);
  text-transform:uppercase;color:var(--faint);padding:18px 0 10px}
.a-sub-h:first-child{padding-top:4px}

/* THE SEGMENTED CONTROL — text only, the active one solid, a hairline under. */
.a-seg{display:flex;border-bottom:1px solid var(--line)}
.a-seg a{flex:1;text-align:center;padding:clamp(13px,3.2vw,16px) 6px;color:var(--faint);
  font-size:clamp(13px,3.4vw,15px);font-weight:600;transition:.14s;
  border-bottom:2px solid transparent;margin-bottom:-1px}
.a-seg a.on{color:var(--fg);font-weight:700;border-bottom-color:var(--fg)}
.a-seg a:active{transform:scale(.97)}

/* A GAME ROW — crest over name at each end, the figures inboard, state between.
   ⚠ Container query, not a media query: a row inside a card in a narrow column
   is as tight as a phone is, and the window cannot tell you that. */
.a-rows{container-type:inline-size}
.a-row{display:grid;grid-template-columns:1fr auto minmax(74px,auto) auto 1fr;
  align-items:center;gap:clamp(6px,2vw,14px);padding:clamp(12px,3vw,16px) clamp(10px,3vw,16px);
  transition:.14s}
.a-row + .a-row{border-top:1px solid var(--line)}
.a-row:active{background:var(--hover)}
.a-team{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;text-align:center}
.a-tn{font-size:clamp(11px,2.9vw,13px);font-weight:600;line-height:1.2;overflow-wrap:break-word}
/* ⛔ THE CREST WAS OVERFLOWING ITS BOX AND overflow:hidden WAS CROPPING IT.
   Measured, after the first guess was wrong: on the owner's own fixture the
   mark is 58x58 and the image inside it rendered **58x85** — 27px of shield
   hanging out of the bottom, invisible because the container clipped it. The
   rounded corner made it worse but was never the cause.

   ⛔ THE CAUSE IS min-height:auto ON A GRID ITEM, which is the classic trap and
   took two wrong guesses to find. A grid (or flex) item refuses to shrink below
   its own content size unless told to, so the image's INTRINSIC height grew the
   row past the container's fixed 58px — and height:100% then resolved against
   that overflowing row rather than against the box, giving 58x85. Swapping to
   max-height changed nothing for the same reason. min-width:0;min-height:0 is
   what actually releases it; object-fit:contain then has nothing left to do.

   ⚠ IT ONLY SHOWED ON THE CRESTS THAT MATTER. A square or circular badge came
   out square and fitted; a rugby club's SHIELD is far taller than it is wide —
   Aurora Barbarians is 1095x1264, Guelph Goats 860x1257 — so those were the
   ones losing their shoulders.

   ⚠ IT ONLY SHOWS ON THE CRESTS THAT MATTER. A circular badge has nothing in its
   corners and survives; a rugby club's SHIELD has its whole shoulder there.
   Measured on the owner's own fixture: Aurora Barbarians is 1095×1264 and lost
   both top corners, Guelph Goats the same.

   ⚠ THE ROUNDING MOVES TO THE LETTERED FALLBACK, where it belongs — that one IS
   a tile, a solid block of the club's colour, and a square one would look
   unfinished next to everything else in this layout. */
.a-mk{width:clamp(28px,7.4vw,38px);height:clamp(28px,7.4vw,38px);flex:none;display:grid;
  place-items:center}
.a-mk img{width:100%;height:100%;min-width:0;min-height:0;object-fit:contain}
.a-mk-l{background:var(--c);color:var(--on-c);font-family:var(--face-display);
  font-weight:var(--display-weight);font-size:clamp(9px,2.4vw,12px);
  overflow:hidden;border-radius:var(--radius-sm)}
.a-mk-lg{width:clamp(44px,11vw,58px);height:clamp(44px,11vw,58px)}
.a-sm{width:22px;height:22px}
.a-mk-l.a-sm{border-radius:6px}
.a-n{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(22px,6vw,30px);letter-spacing:var(--track-lg);
  font-variant-numeric:tabular-nums;line-height:1}
.a-rec{font-size:clamp(11px,2.9vw,13px);color:var(--faint);font-variant-numeric:tabular-nums}
/* ⛔ THE LOSING SIDE DIMS — crest, name and score together. It is the highest
   meaning-per-pixel in the whole design: you read who won before you have
   parsed a number. */
.a-dim{opacity:.45}
.a-mid{display:flex;flex-direction:column;align-items:center;gap:3px;text-align:center}
.a-state{font-size:clamp(12px,3.2vw,14px);font-weight:700}
.a-time{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(15px,4vw,19px);letter-spacing:var(--track-md);font-variant-numeric:tabular-nums}
.a-live{display:inline-flex;align-items:center;gap:5px;color:var(--accent);
  font-size:clamp(11px,3vw,13px);font-weight:700;white-space:nowrap}
.a-live i{width:6px;height:6px;border-radius:50%;background:var(--accent);
  animation:beat 1.7s ease-in-out infinite;flex:none}
@container (max-width:380px){
  .a-row{grid-template-columns:1fr auto minmax(58px,auto) auto 1fr;gap:5px}
  .a-tn{font-size:10.5px}
}

/* STANDINGS — division heads, then rows. The column count is data, so the grid
   is built from it rather than from a breakpoint. */
.a-st{container-type:inline-size;font-variant-numeric:tabular-nums}
.a-strow{display:grid;
  grid-template-columns:26px minmax(0,1fr) repeat(var(--cols),minmax(26px,34px)) minmax(30px,40px);
  align-items:center;gap:6px;padding:11px clamp(10px,3vw,16px);font-size:clamp(12px,3.1vw,13.5px)}
.a-strow > span:not(.a-stm){text-align:right}
.a-sthead{color:var(--faint);font-size:10.5px;font-weight:700;
  letter-spacing:var(--label-spacing);text-transform:uppercase;padding-bottom:6px}
.a-strow + .a-strow:not(.a-sthead){border-top:1px solid var(--line)}
.a-rank{color:var(--faint);text-align:left !important;font-variant-numeric:tabular-nums}
.a-stm{display:flex;align-items:center;gap:9px;min-width:0}
.a-stm b{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.a-pts{font-weight:700}
.a-strow.a-on{background:var(--hover)}
.a-strow.a-on .a-stm b{font-weight:800}
@container (max-width:330px){ .a-stm b{font-size:12px} }

/* THE MATCH SHEET — the two clubs' colours meeting down the middle. */
.a-sheet{position:relative;overflow:hidden;border-radius:var(--radius);
  border:var(--panel-border);isolation:isolate;padding-top:clamp(4px,1.6vw,8px)}
/* ⛔ ONE FIELD, THE TWO COLOURS BLEEDING INTO EACH OTHER. Two clipped halves met
   on a hard edge down the middle; the owner's screenshots show the colours
   FADING into one another and that soft seam is most of why the real thing
   looks expensive. One gradient across both stops removes the edge and there is
   nothing left to align.
   ⚠ Angled, and the stops are asymmetric on purpose: a straight 90deg blend
   reads as a swatch, and a seam exactly at 50% reads as a join somebody tried
   to hide. The mid stops sit either side of centre so the meeting drifts. */
.a-sh-field{position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(120% 90% at 8% 12%,color-mix(in srgb,var(--h) 75%,transparent),transparent 62%),
    radial-gradient(120% 90% at 92% 12%,color-mix(in srgb,var(--a) 75%,transparent),transparent 62%),
    linear-gradient(104deg,
      var(--h) 0%,
      color-mix(in srgb,var(--h) 78%,var(--shade)) 34%,
      color-mix(in srgb,var(--h) 42%,var(--a)) 50%,
      color-mix(in srgb,var(--a) 78%,var(--shade)) 66%,
      var(--a) 100%)}
.a-sheet::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(transparent 30%,var(--veil))}
/* ⚠ The share button is absolutely positioned in this corner, so the title has
   to be told to clear it — at 390px "CANADIAN RUGBY CHAMPIONSHIP - WOMEN" ran
   straight under the circle and lost its last word. Symmetric padding so the
   title stays centred on the CARD rather than on the space left over. */
.a-sh-top{text-align:center;padding:clamp(12px,3vw,16px) 56px 0;color:var(--ink-light);
  font-size:clamp(10.5px,2.8vw,12px);font-weight:700;letter-spacing:var(--label-spacing);
  text-transform:uppercase;opacity:.8}
.a-sh-in{display:grid;grid-template-columns:1fr auto 1fr;align-items:start;
  gap:clamp(8px,3vw,20px);padding:clamp(12px,3.4vw,22px) clamp(10px,3vw,20px) clamp(14px,3.4vw,20px)}
.a-sh-side{display:flex;flex-direction:column;align-items:center;gap:8px;min-width:0;
  color:var(--on-c);text-align:center}
.a-sh-n{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(40px,13vw,76px);line-height:.9;letter-spacing:var(--track-xl);
  font-variant-numeric:tabular-nums;text-shadow:0 3px 22px var(--shadow)}
.a-sh-t{font-size:clamp(12px,3.2vw,16px);font-weight:700;line-height:1.15;overflow-wrap:break-word}
.a-sh-mid{display:flex;flex-direction:column;align-items:center;gap:5px;
  color:var(--ink-light);padding-top:clamp(14px,4vw,26px);text-align:center}
.a-sh-mid .a-note{color:var(--ink-light);opacity:.75}
.a-sh-mid .a-state{font-size:clamp(12px,3.2vw,15px)}

/* THE LINESCORE, inside the sheet. */
/* ⚠ A LINESCORE IS A TIGHT BLOCK, NOT A FULL-WIDTH TABLE. With two rugby halves
   the period columns stretched to a third of the card each and the figures ended
   up under nothing — a scoreboard has its columns close together so the eye
   reads across a row rather than hunting. Capped and centred, so two halves and
   five hockey periods both look deliberate. */
.a-ls{display:flex;flex-direction:column;gap:2px;
  padding:0 clamp(10px,3vw,20px) clamp(12px,3vw,18px);
  color:var(--ink-light);font-variant-numeric:tabular-nums}
.a-ls-r{display:grid;
  grid-template-columns:minmax(34px,44px) repeat(var(--cols),minmax(26px,42px)) minmax(30px,46px);
  gap:clamp(4px,1.6vw,10px);align-items:center;justify-content:center;
  font-size:clamp(11.5px,3vw,14px);padding:4px 0;
  width:100%;max-width:min(100%,440px);margin:0 auto}
.a-ls-r > span{text-align:center}
.a-ls-h{font-size:10px;letter-spacing:var(--label-spacing);text-transform:uppercase;opacity:.65;
  border-bottom:1px solid color-mix(in srgb,var(--ink-light) 22%,transparent);padding-bottom:5px}
.a-ls-t{text-align:left !important;font-weight:700}
.a-ls-tt{font-weight:800}

/* ── THE COLLAPSED MATCH HEADER ────────────────────────────────────────────
   Slides down once the sheet has left the top, carrying the crests, the score
   and the live clock. Fixed rather than sticky: it must sit over the page rather
   than take a slot in it, or every card below shifts the moment it appears.
   ⚠ NO SHARE BUTTON. Apple's compact bar has one; the owner removed it here,
   2026-08-14 — share already sits on the scoreboard, and a second copy of it
   riding the whole page is a control competing with the score for a 50px strip.
   ⚠ THE TABS ARE NOT STUCK TO IT. That was tried and reverted the same day: it
   changed how they look and pinned two bars to the top of a phone. They stay
   exactly where they are in the page. */
:root{--mini-h:50px}
.a-mini{position:fixed;top:0;left:0;right:0;z-index:30;
  transform:translateY(-100%);transition:transform .24s cubic-bezier(.22,1,.36,1);
  will-change:transform}
.a-mini.on{transform:none}
.a-mini-f{position:absolute;inset:0;z-index:-1;opacity:.94;
  background:linear-gradient(100deg,var(--h),
    color-mix(in srgb,var(--h) 50%,var(--a)) 50%,var(--a))}
/* The underside of the material, not a border — same treatment as everywhere. */
.a-mini::after{content:"";position:absolute;left:0;right:0;top:100%;height:12px;
  pointer-events:none;
  background:linear-gradient(color-mix(in srgb,var(--bg) 66%,transparent),transparent)}
.a-mini-in{max-width:960px;margin:0 auto;min-height:var(--mini-h);
  display:flex;align-items:center;justify-content:center;gap:clamp(8px,2.6vw,16px);
  padding:8px clamp(12px,3.5vw,20px);color:var(--ink-light);
  -webkit-backdrop-filter:blur(18px) saturate(150%);backdrop-filter:blur(18px) saturate(150%)}
/* ⚠ Same cut as .a-mk, and here the rounding was doing nothing but harm: this
   variant has no background, so the 7px radius clipped a shield's corners and
   bought no shape in return. */
.a-mini-t{width:26px;height:26px;flex:none;display:grid;place-items:center}
.a-mini-t img{width:100%;height:100%;min-width:0;min-height:0;object-fit:contain}
.a-mini-t i{font-style:normal;font-size:9px;font-weight:800;opacity:.9}
.a-mini-in b{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(19px,5vw,24px);letter-spacing:var(--track-lg);line-height:1;
  font-variant-numeric:tabular-nums}
.a-mini-c{display:flex;flex-direction:column;align-items:center;line-height:1.15;
  min-width:clamp(58px,20vw,104px);text-align:center}
.a-mini-c > span{font-size:clamp(11px,3vw,12.5px);font-weight:700;white-space:nowrap}
.a-mini-c em{font-style:normal;font-size:10.5px;opacity:.72;white-space:nowrap}
/* ⚠ The live label is the one thing in here the poller rewrites, so its dot is a
   sibling of the text node rather than wrapped around it. */
.a-mini-live{display:inline-flex;align-items:center;gap:5px}
.a-mini-live i{width:5px;height:5px;border-radius:50%;background:currentColor;flex:none;
  animation:beat 1.7s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){ .a-mini{transition:none} }


/* THE MATCH PAGE'S OWN COLUMN — the wrapper that carries nothing but rhythm. */
.a-stack{display:flex;flex-direction:column;gap:clamp(12px,2.6vw,18px)}

/* SHARE — on the match and nowhere else, and only where script ran.
   ⛔ display:none by default. A button whose handler never loaded looks exactly
   like a working one, which is the defect RULE 5 names; html.js is set by the
   boot script, so without JavaScript this is absent rather than dead. */
/* The actions on a scoreboard, at its corner. Share is the only one — the match
   report was removed on 2026-08-14 because it linked out to stats.dnode.app;
   this stays a row because a second action is a matter of time. */
.a-sh-acts{position:absolute;top:clamp(10px,2.6vw,14px);right:clamp(10px,2.6vw,14px);
  z-index:2;display:flex;align-items:center;gap:8px}
/* THE SCORING TIMELINE — when the points landed. */
.a-tl{width:100%;height:auto;margin-top:2px}
.a-share{display:none}
html.js .a-share{display:grid;place-items:center;width:38px;height:38px;border:0;border-radius:999px;
  cursor:pointer;color:var(--ink-light);
  background:color-mix(in srgb,var(--ink-light) 16%,transparent);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink-light) 20%,transparent);transition:.14s}
html.js .a-share:active{transform:scale(.92)}

/* THE LINEUP'S OWN TABS — one club at a time. */
.a-lt{display:block}
.a-tbar-sm{margin:0 0 clamp(10px,2.4vw,14px)}
.a-ltp{display:none}
#lt-h:checked ~ .a-tbar label:nth-of-type(1),
#lt-a:checked ~ .a-tbar label:nth-of-type(2){background:var(--fg);color:var(--bg)}
#lt-h:checked ~ .a-ltp[data-p="lt-h"],
#lt-a:checked ~ .a-ltp[data-p="lt-a"]{display:block}
/* One club at a time means one pitch, so it gets the full width. */
.a-ltp .a-pps{grid-template-columns:1fr}

/* THE SCORERS — home left, away right, one ball between them. */
.a-sc-l{display:flex;flex-direction:column;gap:2px;
  padding:0 clamp(10px,3vw,20px) clamp(10px,2.6vw,14px);color:var(--ink-light)}
.a-sc-r{display:grid;grid-template-columns:1fr 22px 1fr;gap:6px;align-items:baseline;
  font-size:clamp(11.5px,3vw,14px)}
.a-sc-r > span{text-align:right}
.a-sc-r > span.a-r{text-align:left}
.a-sc-r i{font-style:normal;text-align:center;opacity:.85;font-size:11px}
.a-sc-r em{font-style:normal;opacity:.62;font-size:.86em}

/* THE RECORD under a club's name, and the WATCH button, which is only here when
   there is something to watch. */
.a-sh-rec{font-size:clamp(11px,2.8vw,13px);opacity:.72;font-variant-numeric:tabular-nums}
.a-watch{display:flex;align-items:center;justify-content:center;gap:9px;
  margin:0 auto clamp(14px,3vw,18px);width:fit-content;max-width:calc(100% - 32px);
  padding:12px 24px;border-radius:999px;font-size:clamp(13px,3.2vw,15px);font-weight:600;
  color:var(--ink-light);background:color-mix(in srgb,var(--ink-light) 18%,transparent);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink-light) 22%,transparent);transition:.14s}
.a-watch:active{transform:scale(.97)}
.a-play{font-size:11px}

/* THE PITCH — one box, players placed in percent, so it scales with no
   breakpoint and the markings stay where they belong. */
.a-pps{display:grid;grid-template-columns:1fr 1fr;gap:clamp(12px,3vw,22px);container-type:inline-size}
@media (max-width:720px){ .a-pps{grid-template-columns:1fr} }
.a-pp-side{min-width:0}
.a-pp-sh{margin-left:auto}
/* ⚠ 3/4, not 2/3. A real pitch is longer than this, but a lineup graphic is a
   DIAGRAM of one — at 2/3 the fifteen players floated in a column of empty
   grass and the card was twice the height it needed. */
.a-pp{position:relative;width:100%;aspect-ratio:3/4;margin:4px 0 6px;
  border-radius:var(--radius-sm);overflow:hidden;
  background:linear-gradient(180deg,color-mix(in srgb,var(--c) 26%,transparent),
    color-mix(in srgb,var(--c) 9%,transparent))}
.a-pp-g{position:absolute;inset:0;width:100%;height:100%;opacity:.5}
.a-pp-p{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;
  align-items:center;gap:2px;width:clamp(46px,13cqw,74px)}
.a-pp-s{position:relative;width:clamp(22px,6cqw,30px);height:clamp(22px,6cqw,30px);
  border-radius:50%;display:grid;place-items:center;background:var(--c);color:var(--on-c);
  font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(10px,2.6cqw,13px);font-variant-numeric:tabular-nums;
  box-shadow:0 2px 8px var(--shadow)}
.a-pp-b{position:absolute;right:-5px;top:-4px;width:14px;height:14px;border-radius:50%;
  background:var(--accent);color:var(--accent-ink);font-size:9px;font-style:normal;
  display:grid;place-items:center;font-weight:700}
.a-pp-n{font-size:clamp(8.5px,2.2cqw,11px);font-weight:600;line-height:1.1;text-align:center;
  overflow-wrap:anywhere}
.a-pp-r{font-size:clamp(7.5px,2cqw,9px);color:var(--faint);letter-spacing:var(--label-spacing)}
.a-pp-none{color:var(--mute);font-size:12.5px;padding:10px 0 4px;line-height:1.45}
.a-pp-b-h{font-size:10.5px;font-weight:700;letter-spacing:var(--label-spacing);
  text-transform:uppercase;color:var(--faint);padding:10px 0 4px}
.a-pp-list{display:flex;flex-direction:column}

/* THE TABS — a hidden radio, a styled label, every panel in the document. */
.a-tabs{display:block}
.a-tin{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.a-tbar{display:flex;gap:4px;padding:6px;margin:clamp(10px,2.6vw,14px);
  border-radius:999px;background:color-mix(in srgb,var(--fg) 10%,transparent)}
/* ⚠ min-width:0 so four labels shrink instead of pushing the pill wider than
   its card. "Play-by-play" and "Tournament" together are wider than a phone. */
.a-tbar label{flex:1 1 0;min-width:0;text-align:center;padding:9px 6px;border-radius:999px;
  cursor:pointer;font-size:clamp(11px,2.9vw,14px);font-weight:600;color:var(--mute);
  transition:.14s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.a-tbar label:active{transform:scale(.97)}
.a-tp{display:none;padding:0 clamp(14px,3.4vw,20px) clamp(16px,3.4vw,22px)}
#mt-stats:checked ~ .a-tbar label:nth-of-type(1){background:var(--fg);color:var(--bg)}
#mt-stats:checked ~ .a-tp[data-p="mt-stats"]{display:block}
#mt-pbp:checked ~ .a-tbar label:nth-of-type(2){background:var(--fg);color:var(--bg)}
#mt-pbp:checked ~ .a-tp[data-p="mt-pbp"]{display:block}
#mt-lineup:checked ~ .a-tbar label:nth-of-type(3){background:var(--fg);color:var(--bg)}
#mt-lineup:checked ~ .a-tp[data-p="mt-lineup"]{display:block}
#mt-tour:checked ~ .a-tbar label:nth-of-type(4){background:var(--fg);color:var(--bg)}
#mt-tour:checked ~ .a-tp[data-p="mt-tour"]{display:block}

/* A SUB-CONTROL INSIDE A TAB — All plays / Key plays, and one club at a time on
   Previous matches. Quieter than the tab bar above it: the same pill, smaller,
   and it never competes for the eye with the control that chose the panel.
   ⚠ Two of these appear on one page, so each has its own radio NAME and its own
   pair of rules. Generated rather than written twice, because two hand-written
   copies of one selector is how the second one stops matching. */
#pbp-all:checked ~ .a-tbar label:nth-of-type(1){background:var(--fg);color:var(--bg)}
#pbp-all:checked ~ .a-subp[data-p="pbp-all"]{display:block}
#pbp-key:checked ~ .a-tbar label:nth-of-type(2){background:var(--fg);color:var(--bg)}
#pbp-key:checked ~ .a-subp[data-p="pbp-key"]{display:block}
#pm-h:checked ~ .a-tbar label:nth-of-type(1){background:var(--fg);color:var(--bg)}
#pm-h:checked ~ .a-subp[data-p="pm-h"]{display:block}
#pm-a:checked ~ .a-tbar label:nth-of-type(2){background:var(--fg);color:var(--bg)}
#pm-a:checked ~ .a-subp[data-p="pm-a"]{display:block}
.a-sub{display:block}
.a-subp{display:none}
/* ⚠ The sub-bar sits under a heading, so it gets less air above than below. */
.a-sub .a-tbar-sm{margin:2px 0 clamp(10px,2.4vw,14px)}
.a-sub .a-tbar-sm label{font-size:clamp(11.5px,3vw,13px);padding:8px}

/* TEAM STATS — a figure each end, the label between, the share underneath. */
.a-ts{display:flex;flex-direction:column;gap:clamp(11px,2.6vw,15px)}
.a-ts-r{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:8px;
  font-variant-numeric:tabular-nums}
.a-ts-v{font-size:clamp(14px,3.6vw,17px);font-weight:700;min-width:34px}
.a-ts-v.a-r{text-align:right}
.a-ts-l{text-align:center;font-size:clamp(11px,2.9vw,12.5px);color:var(--mute)}
.a-ts-bar{grid-column:1/-1;display:flex;height:5px;border-radius:999px;overflow:hidden;
  background:var(--well)}
.a-ts-bar i{display:block;height:100%;background:var(--h)}
.a-ts-bar i.a-r{background:var(--a)}
.a-ts-r.a-nil{opacity:.45}

/* PLAY BY PLAY — every event, newest first. */
.a-pbp{display:flex;flex-direction:column}
.a-pbp-m{font-size:10.5px;font-weight:700;letter-spacing:var(--label-spacing);
  text-transform:uppercase;color:var(--faint);padding:16px 0 8px;text-align:center}
.a-pbp-r{display:grid;grid-template-columns:auto auto 1fr auto;gap:9px;align-items:baseline;
  padding:10px 0 10px 11px;border-left:3px solid var(--c)}
.a-pbp-r + .a-pbp-r{border-top:1px solid var(--line)}
.a-pbp-c{font-family:var(--face-mono);font-size:11.5px;color:var(--faint);
  font-variant-numeric:tabular-nums}

/* THE GLYPH BESIDE THE PLAY.
   ⚠ NOT BASELINE-ALIGNED. An inline SVG's baseline is its bottom edge, so a
   row aligned on one drops every icon a few pixels below its own label and the
   column reads as a mistake. It is aligned to the TOP of the row and given the
   label's own line box to sit in, so it centres on the words next to it
   whatever the clamp resolves the type to.
   ⛔ AND THE COLOUR IS THE ROW'S, so a scoring play's mark is as bright as its
   label and a set piece's is as faint. The only glyphs that override it are the
   four below — the two cards and the two substitution arrows — because those
   are what a supporter scans a match for. */
.a-pbp-i{align-self:start;display:grid;place-items:center;width:17px;
  font-size:clamp(12.5px,3.2vw,14px);height:1.4em;color:var(--faint)}
.a-pbp-r.a-sc .a-pbp-i{color:var(--fg)}
.a-ic-yc{fill:var(--card-yellow);stroke:none}
.a-ic-rc{fill:var(--card-red);stroke:none}
.a-ic-on{stroke:var(--win)}
.a-ic-off{stroke:var(--loss)}
.a-ic-f{fill:currentColor;stroke:none}

.a-pbp-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.a-pbp-t{font-size:clamp(12.5px,3.2vw,14px);font-weight:600}
.a-pbp-r.a-sc .a-pbp-t{color:var(--fg);font-weight:800}
.a-pbp-t em{font-style:normal;color:var(--faint);font-weight:400}
.a-pbp-w{font-size:clamp(11.5px,3vw,13px);color:var(--mute);overflow-wrap:break-word}
.a-pbp-w em{font-style:normal;color:var(--faint)}
.a-pbp-s{font-family:var(--face-mono);font-size:12px;color:var(--mute);
  font-variant-numeric:tabular-nums}

/* TEAM SHEETS — side by side, stacked when there is not room for two. */
.a-lus{display:grid;grid-template-columns:1fr 1fr;gap:clamp(10px,2.6vw,18px)}
@media (max-width:640px){ .a-lus{grid-template-columns:1fr} }
.a-lu{min-width:0}
.a-lu-h{display:flex;align-items:center;gap:9px;padding:0 0 10px;font-size:14px}
/* ⚠ minmax(0,1fr) on the name and a CAP on the marks. With a bare 1fr and an
   auto third column, "3× penalty goal" beside a long French-Canadian surname
   pushed the marks past the card's edge and the label was clipped to "3×" —
   which reads as a broken number rather than as a statistic. */
.a-lu-r{display:grid;grid-template-columns:24px minmax(0,1fr) auto;gap:8px;align-items:baseline;
  padding:7px 0;border-top:1px solid var(--line);font-size:clamp(12px,3vw,13.5px)}
.a-lu-r.a-on{background:var(--hover)}
.a-lu-no{color:var(--faint);font-variant-numeric:tabular-nums;font-size:11.5px}
.a-lu-n{min-width:0;overflow-wrap:break-word}
.a-lu-n em,.a-lu-p{font-style:normal;color:var(--faint);font-size:11px}
.a-lu-p{display:block}
.a-lu-m{color:var(--accent);font-size:11px;font-weight:600;text-align:right;
  max-width:42%;overflow-wrap:break-word;line-height:1.3}

/* THREE STARS, HEAD TO HEAD, FORM, KPIS */
.a-stars{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.a-star{display:flex;flex-direction:column;gap:3px;padding:13px 14px;border-radius:var(--radius-sm);
  background:var(--well)}
.a-star-r{color:var(--accent);font-size:12px}
.a-star b{font-size:14px}
.a-star-f{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:19px;letter-spacing:var(--track-md);margin-top:3px}
.a-h2h-b{display:flex;height:9px;border-radius:999px;overflow:hidden;gap:2px}
.a-h2h-l{display:flex;justify-content:space-between;gap:10px;margin-top:8px;
  font-size:11.5px;color:var(--mute)}
.a-form{display:flex;gap:5px;flex-wrap:wrap}
.a-form i{width:26px;height:7px;border-radius:999px;display:block}
.a-w{background:var(--win)}.a-l{background:var(--loss)}.a-d{background:var(--draw)}
/* The --cols value is a COUNT the renderer works out from how many figures
   there actually are, so the last row is always full. auto-fit left nine
   figures as 4 + 4 + 1 with a hole three cells wide beside the last one. */
.a-kpis{display:grid;grid-template-columns:repeat(var(--cols,4),1fr);gap:1px;
  background:var(--line)}
.a-kpis > div{background:var(--panel);padding:14px 12px;text-align:center}
.a-kpis b{display:block;font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(20px,5.2vw,26px);letter-spacing:var(--track-lg);font-variant-numeric:tabular-nums}
.a-kpis span{display:block;font-size:10px;letter-spacing:var(--label-spacing);
  text-transform:uppercase;color:var(--faint);margin-top:5px}
/* The line under the form strip — last ten on the left, streak on the right. */
.a-form-l{display:flex;justify-content:space-between;gap:10px;margin-top:10px;
  font-size:11.5px;color:var(--mute)}

/* THE COMPETITION SWITCH — a club in a men's AND a women's championship.
   ⚠ Links rather than a tab: each one is a different kind=team payload and
   already a different URL. It scrolls on a phone, because a league is free to
   enter one club in five competitions and a wrapped row of pills pushes the
   whole page down. */
/* ⛔ A PILL IS NEVER LEFT HALF OFF THE SCREEN. The owner sent a screenshot of
   both of them cut mid-word at each edge. Three things together, and all three
   are needed: the LABELS are shortened to what differs (in the renderer, which
   is what actually made them fit); scroll-snap so a drag can only ever come to
   rest with a pill flush against an edge; and scroll-padding matching the
   container's own padding, so "flush" means flush with the page margin rather
   than with the viewport. Without the last one a snapped pill sits hard against
   the glass and reads as cut off anyway. */
.a-cswitch{display:flex;gap:7px;overflow-x:auto;padding:0 clamp(10px,3vw,16px) 2px;
  margin:0 0 clamp(12px,2.6vw,18px);scrollbar-width:none;
  scroll-snap-type:x proximity;scroll-padding-inline:clamp(10px,3vw,16px)}
.a-cswitch::-webkit-scrollbar{display:none}
.a-cswitch a{flex:0 0 auto;padding:8px 14px;border-radius:999px;font-size:12.5px;font-weight:600;
  color:var(--mute);background:var(--well);text-decoration:none;white-space:nowrap;
  scroll-snap-align:start}
.a-cswitch a:last-child{scroll-snap-align:end}
.a-cswitch a.on{background:var(--fg);color:var(--bg)}

/* THE SEASON KEY — which colour is this club and which is everybody else.
   ⚠ It names the CLUB rather than saying "For", because "For / Against" is the
   language of a scoreboard and this is a whole season against many opponents. */
.a-ts-key{display:flex;justify-content:space-between;gap:10px;padding-bottom:10px;
  margin-bottom:2px;border-bottom:1px solid var(--line);
  font-size:11px;letter-spacing:var(--label-spacing);text-transform:uppercase;color:var(--faint)}
.a-ts-key span{display:flex;align-items:center;gap:6px;min-width:0}
.a-ts-key i{width:10px;height:10px;border-radius:3px;background:var(--h);flex:0 0 auto}
.a-ts-key i.a-r{background:var(--a)}

/* THE SQUAD — a name, then one column per stat the sport counts.
   ⛔ The --cols value IS A COUNT, set by the renderer, because rugby keeps eight columns
   and hockey five. A grid built from a breakpoint instead would be wrong for one
   of them at every width. */
.a-sq{display:flex;flex-direction:column;font-variant-numeric:tabular-nums}
.a-sq-r{display:grid;grid-template-columns:26px minmax(0,1fr) repeat(var(--cols),minmax(26px,auto));
  gap:6px;align-items:center;padding:9px clamp(10px,3vw,16px)}
/* ⚠ No shirt-number column when no player in the squad has one — an empty 26px
   column down thirty rows reads as data that failed to load. */
.a-sq-nn .a-sq-r{grid-template-columns:minmax(0,1fr) repeat(var(--cols),minmax(26px,auto))}
.a-sq-r + .a-sq-r{border-top:1px solid var(--line)}
.a-sq-r > span:not(.a-sq-n):not(.a-sq-no){text-align:right;font-family:var(--face-mono);
  font-size:12px}
/* ⛔ NOT STICKY, AND THAT IS LEDGER #169, NOT AN OMISSION. The first version
   pinned this header with position:sticky — which does nothing here, silently,
   because .a-card sets overflow:hidden to hold its corners and an overflow
   ancestor kills sticky in every descendant. A rule that cannot fire is worse
   than no rule: it reads as a working feature to the next person. */
.a-sq-h{font-size:10px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--faint)}
.a-sq-h > span:not(.a-sq-n):not(.a-sq-no){font-family:inherit;font-size:10px}
.a-sq-no{font-family:var(--face-mono);font-size:11.5px;color:var(--faint);text-align:center}
.a-sq-n{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.a-sq-n em{font-style:normal;color:var(--faint);font-weight:400}
/* ⚠ A zero is DIMMED rather than blanked. An empty cell reads as missing data;
   a faint 0 reads as "none", which is what it means. */
.a-nilv{color:var(--faint)}

/* CLUBS, GAME INFORMATION, THE ANNOUNCED STATE, THE FOOTER */
.a-clubs{container-type:inline-size}
.a-club{display:flex;align-items:center;gap:12px;padding:12px clamp(10px,3vw,16px)}
.a-club + .a-club{border-top:1px solid var(--line)}
.a-club:active{background:var(--hover)}
.a-club-n{display:flex;flex-direction:column;gap:2px;min-width:0}
.a-club-n b{font-size:14.5px;font-weight:600;overflow-wrap:break-word}
.a-chev{margin-left:auto;color:var(--faint);font-size:20px;line-height:1;flex:none}
.a-info{display:flex;flex-direction:column;gap:10px}
.a-info > div{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
.a-info dt{color:var(--faint);font-size:12px;min-width:88px}
.a-info dd{margin:0;font-size:13.5px}
.a-soon{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.a-soon b{font-family:var(--face-display);font-weight:var(--display-weight);
  font-size:clamp(30px,8vw,44px);line-height:1;letter-spacing:var(--track-xl)}
.a-soon span{font-size:10.5px;letter-spacing:var(--label-spacing);text-transform:uppercase;
  color:var(--faint);display:block}
.a-soon p{color:var(--mute);font-size:13.5px;flex:1;min-width:200px}
.a-mom{width:100%;height:auto}
.a-radar{width:100%;max-width:300px;margin:0 auto}
.a-key{display:flex;justify-content:space-between;gap:10px;margin-top:6px;
  font-size:11px;color:var(--faint)}
/* ⚠ NO BACKGROUND. It briefly had one, to hide the fact that the wash's base
   colour was bright and had not faded out by the time the footer arrived on a
   short page. The base is black again, so the footer needs nothing — and the
   owner's note about it was the same note as the coloured bars: stop painting
   things the page is not. */
.a-foot{max-width:960px;margin:0 auto;
  padding:26px clamp(12px,3.5vw,20px) calc(40px + env(safe-area-inset-bottom));
  display:flex;gap:14px;flex-wrap:wrap;font-size:11.5px;color:var(--faint)}


@media (max-width:720px){
  .wrap{padding:0 14px}
  .stack{gap:22px;padding-block:18px 30px}
  .grid2,.grid-eq{grid-template-columns:1fr;gap:18px}
  /* The brand keeps a line of its own and the links scroll under it. Squeezed
     onto one row, "Rugby Ontario" broke across two lines and the last nav item
     sat off the edge with nothing to say it was there. */
  nav.top{padding:11px 14px;gap:9px;flex-wrap:wrap}
  /* ⛔ A STRIP THAT SCROLLS WITH NOTHING TO SAY SO IS A LINK NOBODY FINDS.
     Measured at 320px on a real phone width: the nav overflows and hides its
     LAST item — which on a league with an OTT is "Watch", the one link that
     takes a supporter to the thing we are paid for. The scrollbar is hidden on
     purpose (it is ugly and on iOS it is invisible anyway), so the fade is the
     only affordance left. Ledger C32 is this exact failure on the console's
     actions column: reachable by scrolling, and nothing to suggest scrolling.
     ⚠ The mask is applied ONLY while it actually overflows — a permanent fade
     over a strip that fits reads as a rendering fault. */
  nav.top .links{margin-left:0;gap:15px;width:100%;overflow-x:auto;scrollbar-width:none;
    /* ⛔ THE MASK STOP IS AN ALPHA, NOT A COLOUR, AND IT HAS TO BE OPAQUE.
       A mask reads only the alpha channel, so the keyword white means KEEP; it is
       not a theme decision and it is why the no-colour-literals gate does not
       see a keyword. ⚠ currentColor was tried first and was worse than the bug:
       it inherits the nav's muted ink, which is #FFFFFF8A, so the mask resolved
       to alpha 0.54 and faded the ENTIRE strip to half opacity. Measured in a
       browser at 320px, not read. A test asserts the stop stays opaque.
       ⚠ AND NO BACKTICKS IN THIS FILE'S COMMENTS — the whole stylesheet is one
       template literal, so a backtick in a comment ends it. */
    -webkit-mask-image:linear-gradient(to right,white calc(100% - 26px),transparent 100%);
    mask-image:linear-gradient(to right,white calc(100% - 26px),transparent 100%);
    /* the last item needs room to clear the fade when it IS scrolled to */
    padding-right:14px}
  nav.top .links::-webkit-scrollbar{display:none}
  nav.top .links a{white-space:nowrap}
  .brand{font-size:16px;white-space:nowrap}
  .rail{padding:6px 14px;gap:9px;font-size:10px}
  .rail-more{display:none}

  /* THE BUG, RETHOUGHT. Side by side at 375px gives each club about 120px and
     truncates every club name; stacked, the score leads and the names get the
     whole width. The diagonal becomes horizontal so the two colour fields still
     read as two sides. */
  .bug .fh{clip-path:var(--bug-home-phone)}
  .bug .fa{clip-path:var(--bug-away-phone)}
  .bug-in{grid-template-columns:1fr;gap:12px;padding:22px 14px 20px;text-align:center}
  .side{flex-direction:row;justify-content:center;gap:11px;text-align:left}
  /* ⚠ justify-content is re-stated, not inherited. .side.r carries flex-end
     from the desktop rule and under row-reverse flex-end means the LEFT edge —
     so the away club sat hard left while the home club was centred. */
  .side.r{flex-direction:row-reverse;justify-content:center;text-align:right}
  .side .nm .t{font-size:19px}
  .side .nm .s{font-size:9.5px}
  .crest{width:40px;height:40px;font-size:12px}
  .score{justify-content:center;order:-1}
  .score .n{font-size:62px}
  .score .x{font-size:20px}
  .strap{padding:9px 14px;gap:9px;font-size:10px}
  .cta.end{margin-left:0}
  .cta{width:100%;text-align:center;padding:11px 16px}

  .sec h2{font-size:12.5px}
  .panel{padding:14px 15px}
  .stars{grid-template-columns:1fr}
  .kpis{grid-template-columns:repeat(2,1fr)}
  .squad{grid-template-columns:1fr}

  .card-r .tm{font-size:18px}
  .card-r .n{font-size:32px}
  .tl li{grid-template-columns:38px 1fr;gap:2px 9px;padding-left:11px}
  .tl .w{grid-column:2}
  .tl .who{grid-column:2;grid-row:2}
  .tl .s{grid-column:1;grid-row:2;font-size:11px}
  /* Same two-line fold as the scorecard above, so the two lists that describe
     the same match read the same way on a phone. */
  .feed li{grid-template-columns:42px 1fr;gap:2px 9px;padding-left:10px}
  .feed .w{grid-column:2}
  .feed .who{grid-column:2;grid-row:2}
  .feed .s{grid-column:1;grid-row:2;font-size:11px}
  .feed li.mk{grid-template-columns:1fr;padding-left:10px}
  .hero{padding:24px 14px 20px}
  .hero .big{font-size:28px}
  .soon{padding:20px 16px;gap:16px}
  .soon .cd{font-size:42px}
  .cmp-r{grid-template-columns:32px 1fr 32px;font-size:12px}
  .foot{padding:18px 14px}
}
/* A wide table does not fit a narrow column, wherever that column is. It becomes
   a row per club: position, name and points on one line, and every other figure
   as one quiet labelled line underneath — rather than a sideways scroll nobody
   discovers, or a "Pts" column pushed off the edge of a laptop. */
@container (max-width:560px){
  .tbl thead{display:none}
  .tbl,.tbl tbody{display:block;width:100%}
  /* ⛔ FLEX-WRAP, NOT A GRID. Each figure is its own <td> and there is nowhere to
     put a wrapper around them, so under a grid every one of them landed on a row
     of its own — nine stacked lines per club on a phone. Wrapping flex lets the
     first line be position / club / points and the rest flow into one quiet line
     underneath, which is what a supporter actually reads. */
  .tbl tr{display:flex;flex-wrap:wrap;align-items:center;gap:3px 11px;
    padding:10px 0;border-top:1px solid var(--line);width:100%}
  .tbl td{display:block;border:0;padding:0;text-align:left;width:auto}
  .tbl td.p{width:20px;order:1}
  .tbl td.tmc{order:2;flex:1;min-width:0}
  .tbl td.ptc{order:3;margin-left:auto;font-family:var(--face-display);font-size:18px}
  .tbl td[data-k]{order:4;font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums}
  .tbl td[data-k]::before{content:attr(data-k) " ";letter-spacing:var(--label-spacing);
    text-transform:uppercase}
  .tbl td.frmc{order:5;width:100%}
  .tbl .frm{justify-content:flex-start}
}
/* ⛔ TWO TEAM SHEETS DO NOT FIT SIDE BY SIDE ON A PHONE, and squeezing them is
   worse than stacking: at 375px each column gets ~170px, which breaks "Mickael
   Tissier" across two lines under a shirt number and puts what he did on a third.
   Sized by the CONTAINER, so a sheet in a narrow column on a laptop folds too. */
@container (max-width:520px){
  .sheets-in{grid-template-columns:1fr}
  .lu{grid-template-columns:26px 1fr;gap:2px 10px}
  .lu .did{grid-column:2;justify-content:flex-start;text-align:left}
}
/* ⛔ CLUB-SAFE. Below this the two clubs stack rather than share the width, so
   "Brantford Harlequins" gets a line of its own instead of breaking mid-word. */
@container (max-width:430px){
  .mc{grid-template-columns:1fr auto;gap:8px;padding:11px 13px 11px 19px}
  .mc .t.r{grid-column:1;justify-content:flex-start;text-align:left}
  .mc .sc{grid-row:1/3;grid-column:2;flex-direction:column;gap:2px;align-items:flex-end;font-size:20px}
  .mc .sc span + span::before{display:none}
  .mc .when{grid-row:1/3;grid-column:2;text-align:right;align-self:center}
  .mc .meta{font-size:9.5px}
}
/* ⛔ REDUCED MOTION IS NOT NO FEEDBACK. Killing every transition also killed the
   press response added above, so the one signal a phone user gets that a tap
   landed would have disappeared for exactly the people least able to infer it
   from movement. The transform goes; the opacity change stays, instantly. */
@media (prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important}
  .cta:active,.mc:active,.pl:active,.modetoggle:active,
  nav.top .links a:active,.rail-item:active{transform:none;opacity:.82}
}

/* ⛔ TRANSLUCENCY IS A PREFERENCE, AND THE SHEET HAD NO ANSWER FOR IT. A blurred
   bar over moving content is exactly what somebody turns this off to avoid, and
   without this block they got it anyway. Frostier and solid, no blur — and the
   hairline comes back, because with the material gone the edge has to be drawn
   rather than implied. */
@media (prefers-reduced-transparency:reduce){
  .chrome{background:var(--bg);-webkit-backdrop-filter:none;backdrop-filter:none;
    border-bottom:1px solid var(--line)}
  .chrome::after{display:none}
}

/* ⛔ AND HIGH CONTRAST GETS SOLID SURFACES WITH DEFINED EDGES. A panel separated
   from the page by a 8%-alpha hairline is a panel somebody has told us they
   cannot see. */
@media (prefers-contrast:more){
  .chrome{background:var(--bg);-webkit-backdrop-filter:none;backdrop-filter:none;
    border-bottom:1px solid var(--fg)}
  .chrome::after{display:none}
  .panel,.kpis,.stars,.squad,.sheets-in{border:1px solid var(--fg)}
  .cmp-bar,.rib,.h2h{box-shadow:inset 0 0 0 1px var(--fg)}
  .tbl td{border-top-color:var(--mute)}
}
