/* ============================================================================
   EPINOIA BROADCAST KIT — v1
   The single stylesheet for the epinoia network: scorer, league pages, embeds.

   Colourway : neon on green-black (unchanged from the epinoia scorer)
   Structure : ruled bulletin board, after The Nifty Portal
   Type      : Jersey 25 · Silkscreen · Archivo · Martian Mono (all SIL OFL,
               so they may be self-hosted — Fontshare families may not)

   Install:
     /epinoia/kit/epinoia-kit.css
     /epinoia/kit/fonts/{jersey25,silkscreen,archivo,martian}.woff2
     <link rel="stylesheet" href="/epinoia/kit/epinoia-kit.css">

   Per-page team colours (everything else derives from these):
     <div style="--team-a:#93f2bf; --team-b:#ff7ab8"> … </div>
   ============================================================================ */

/* ---------- 1. faces ---------- */
@font-face{font-family:'Jersey25';src:url('fonts/jersey25.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Silkscreen';src:url('fonts/silkscreen.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url('fonts/archivo.woff2') format('woff2');
  font-weight:100 900;font-stretch:62% 125%;font-style:normal;font-display:swap}
@font-face{font-family:'MartianMono';src:url('fonts/martian.woff2') format('woff2');
  font-weight:100 800;font-stretch:75% 112.5%;font-style:normal;font-display:swap}

/* ---------- 1b. the logotype ----------------------------------------------
   EPINOIA'S OWN FACE, and it is not the one that was supplied.

   Epinoia_Logo.ttf carries six glyphs (A E I N O P) set very loose — enough
   for the word and nothing else, with gaps you could park in. This replaces it
   with a small face derived from Archivo, which is already self-hosted here
   and is SIL OFL, pinned to one weight and width so it is static, and subset
   to the alphabet.

   THE LAMBDA IS REAL, not a substitution at the markup level. None of the four
   faces this site hosts carries U+039B — they are Latin-only subsets — so
   writing EPINOIΛ in any of them would drop the last letter into a system
   fallback matching nothing around it. So the face was given one: the V
   outline, flipped about the cap height. In a grotesque the A and the V are
   the same triangle, which makes an inverted V exactly the crossbar-less A the
   logo draws, at the same stroke weight and with the same terminals as the
   letters beside it. Built by scratchpad/buildmark.py; the recipe is in the
   font's own copyright string.

   It has the whole alphabet now, so SCORING sets in it too — but the class
   still belongs only on the brand. A league's name in the logotype would be a
   league claiming to be the platform. */
@font-face{font-family:'EpinoiaMark';
  src:url('../brand/epinoia-mark.woff2') format('woff2'),
      url('../brand/epinoia-mark.ttf') format('truetype');
  font-weight:400;font-style:normal;font-display:swap}

/* !important, which is not a habit worth having and is right here. Every page
   sets its own type on the elements this lands on — .wordmark declares
   var(--f-score) in a page-level <style> that loads after this file and wins
   on order, which is exactly what happened first time round: the class was on
   the element and the logotype never rendered. A logotype that a local rule
   can quietly override is not a logotype. */
.epinoia-mark{
  font-family:'EpinoiaMark','Archivo',system-ui,sans-serif !important;
  /* case and tracking are part of the logotype, not decoration a page may
     restyle. The scorer's own .logo sets lowercase at .42em, which is where
     the "too much space" came from — and lowercased, the lambda has no lower
     case to fall to, so it would sit as a capital in the middle of a word. */
  text-transform:uppercase !important;
  letter-spacing:.005em !important;
  font-weight:400;
}

/* SIZED BY WIDTH, NOT BY POINTS. The logotype sets at 467px per 100px against
   the scoreboard face's 298px, so a size that suited the old wordmark reads as
   a much bigger object in this one. 60px puts EPINOIΛ at about 280px, against
   the 220px the word used to occupy — prominent, which a logotype should be,
   without becoming the whole band. (The supplied face was wider still, 608px
   per 100, which is why these numbers have moved twice.) */
.wordmark.epinoia-mark{ font-size:clamp(30px,5.8vw,60px) }
.wm.epinoia-mark{ font-size:13px; padding-left:9px; padding-right:9px }

@property --ring{syntax:'<angle>';inherits:false;initial-value:0deg}

/* ---------- 2. tokens ---------- */
:root{
  /* ground — green-biased blacks, never neutral */
  --ground:#04100b; --panel:#0a1a13; --panel-2:#102419;
  /* ink — mint white; the dim steps are AA-checked against --ground */
  --ink:#e6fff1; --ink-2:rgba(230,255,241,.72); --ink-3:rgba(230,255,241,.52);
  /* structure — hairlines belong to the palette, not on top of it */
  --rule:rgba(147,242,191,.20); --rule-2:rgba(147,242,191,.44);
  /* neon */
  --lume:#93f2bf; --aqua:#8ff5ff; --amber:#ffd166; --flare:#ff5f6b; --violet:#b7a8ff;
  --team-a:var(--lume); --team-b:var(--aqua);
  --good:#63ffa0; --bad:#ff5f6b;
  /* type roles */
  --f-score:'Jersey25',ui-monospace,monospace;   /* scores, clock, headings   */
  --f-micro:'Silkscreen',ui-monospace,monospace; /* labels, ticker, badges    */
  --f-ui:'Archivo',system-ui,sans-serif;         /* names, prose, buttons     */
  --f-data:'MartianMono',ui-monospace,monospace; /* table figures             */
  /* rhythm */
  --u:8px; --ease:cubic-bezier(.22,.9,.24,1);
  color-scheme:dark;
}

/* ---------- 2b. scale --------------------------------------------------------
   EVERY PAGE THAT LOADS THIS KIT RENDERS AT 150%, which is what these screens
   were designed at and, until now, what everybody had to set by hand.

   `zoom` rather than a root font-size, because this kit sizes in px
   throughout — hairlines, table cells, the ruled grid — and rem would have
   scaled the type and left the structure behind. zoom scales the lot,
   including borders, and keeps layout intact where transform:scale would
   break fixed positioning and leave the page the wrong width.

   ZOOM DIVIDES THE LAYOUT WIDTH, which is the whole catch. At 1.5 a 1000px
   window lays out as 657px, and the sidebar rail plus a season table does not
   fit in 657px — measured, 58px of horizontal overflow. It holds at 790px and
   above. So the full 150% starts at 1200, an intermediate step covers the
   1000–1200 laptops (1.25 of 1000 is 800, the width that was proven fine),
   and below 1000 the page renders at its own size.

   MEDIA QUERIES DO NOT SEE THE ZOOM — `@media (max-width:560px)` still tests
   the real window — which is the other reason not to push this further down.
   Past a point the page would be laying out at phone widths while every
   breakpoint in the file still believed it was on a desktop.

   PAGES THAT OPT OUT. The scorer and the four embeds load neither this file
   nor anything importing it: the scorer is one self-contained document sized
   for a phone at a scorer's table, and an embed renders inside somebody
   else's page at a size they chose, so scaling it would be rude. (The embed
   GALLERY at /epinoia/embed/ is an ordinary page of ours and does scale — it
   is the four documents under it that must not.) The splash does load the kit
   and opts out here: it fills a viewport rather than being read. */
@media (min-width:1000px){ body{ zoom:1.25 } }
@media (min-width:1200px){ body{ zoom:1.5 } }
/* THE SPLASH IS NOT ZOOMED. It is a fixed composition — a pool, a title and
   four slabs sized to the viewport — not a page of type and tables that gets
   easier to read when everything grows. At 1.5 the slabs ran past the bottom
   of the screen. Both selectors for the same reason as splash.css: the splash
   is told by mode.js, the countries page opts in by class. */
.m-splash body, body.splash-body{ zoom:1 }

/* ---------- 3. base ---------- */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--ground);color:var(--ink);
  font-family:var(--f-ui);font-size:15px;line-height:1.55;
  -webkit-font-smoothing:antialiased}
/* CRT grain. Drop this rule on data-heavy admin screens if it distracts. */
body::after{content:"";position:fixed;inset:-50%;pointer-events:none;z-index:99;opacity:.05;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .9 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  animation:ep-grain 1s steps(4) infinite}
@keyframes ep-grain{0%{transform:translate(0,0)}25%{transform:translate(-2%,1%)}
  50%{transform:translate(2%,-1%)}75%{transform:translate(-1%,2%)}100%{transform:translate(0,0)}}
:where(a){color:var(--lume);text-underline-offset:3px}
:where(button,a,input,select,[tabindex]):focus-visible{outline:2px solid var(--lume);outline-offset:2px}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{
  animation-duration:.01ms!important;transition-duration:.01ms!important}}

/* ---------- 4. the frame: no floating cards, only ruled regions ---------- */
.ep-frame{max-width:1140px;margin:0 auto;position:relative;
  border-left:1px solid var(--rule);border-right:1px solid var(--rule)}
.ep-band{border-bottom:1px solid var(--rule);padding:calc(var(--u)*4) calc(var(--u)*3)}
.ep-band.tight{padding:calc(var(--u)*2.5) calc(var(--u)*3)}
.ep-hdr{display:flex;align-items:baseline;gap:14px;padding:calc(var(--u)*2) calc(var(--u)*3);
  border-bottom:1px solid var(--rule)}
.ep-hdr .idx{font-family:var(--f-micro);font-size:11px;color:var(--ink-3)}
.ep-hdr h2{font-family:var(--f-score);font-size:26px;font-weight:400;margin:0;text-transform:uppercase;letter-spacing:.02em}
.ep-split{display:grid;grid-template-columns:repeat(auto-fit,minmax(310px,1fr))}
.ep-split>*{border-right:1px solid var(--rule)}
.ep-split>*:last-child{border-right:none}
.ep-pad{padding:calc(var(--u)*3)}
.ep-pixrule{height:14px;border-bottom:1px solid var(--rule);background-repeat:repeat-x;background-position:center;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='14'><g fill='%2393f2bf' opacity='.30'><rect x='0' y='0' width='3.5' height='3.5'/><rect x='7' y='3.5' width='3.5' height='3.5'/><rect x='14' y='7' width='3.5' height='3.5'/><rect x='21' y='3.5' width='3.5' height='3.5'/></g></svg>")}

/* ---------- 5. type ---------- */
.ep-h1{font-family:var(--f-score);font-weight:400;font-size:clamp(46px,9vw,104px);line-height:.86;
  margin:0;text-transform:uppercase;letter-spacing:.01em;text-wrap:balance}
.ep-micro{font-family:var(--f-micro);font-size:11px;color:var(--ink-3);text-transform:uppercase}
.ep-lede{color:var(--ink-2);font-size:17px;max-width:60ch}
.ep-data{font-family:var(--f-data);font-variant-numeric:tabular-nums}
.ep-inverted{background:linear-gradient(105deg,var(--lume),var(--aqua));color:#04100b}
.ep-inverted :where(p,.ep-micro){color:rgba(4,16,11,.72)}

/* ---------- 6. ticker ---------- */
.ep-marquee{overflow:hidden;border-bottom:1px solid var(--rule);background:var(--panel);white-space:nowrap;padding:9px 0}
.ep-marquee .track{display:inline-flex;animation:ep-slide 38s linear infinite;will-change:transform}
.ep-marquee:hover .track{animation-play-state:paused}
@keyframes ep-slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.ep-tick{font-family:var(--f-micro);font-size:12px;padding:0 22px;color:var(--ink-2);
  display:inline-flex;gap:9px;align-items:center}
.ep-tick b{color:var(--ink);font-weight:400}
.ep-tick .sc{font-family:var(--f-score);font-size:17px;color:var(--team-a)}
.ep-tick .sc.b{color:var(--team-b)}
.ep-tick .fin{color:var(--ink-3)} .ep-tick .lv{color:var(--flare)}
.ep-tick::after{content:"◆";color:var(--ink-3);margin-left:22px;font-size:8px}

/* ---------- 7. scoreboard ---------- */
.ep-board{display:grid;grid-template-columns:1fr auto 1fr;align-items:stretch;border-bottom:1px solid var(--rule)}
.ep-side{padding:calc(var(--u)*3);display:flex;flex-direction:column;gap:5px;min-width:0}
.ep-side.b{align-items:flex-end;text-align:right;border-left:1px solid var(--rule)}
.ep-tnm{font-family:var(--f-ui);font-weight:800;font-size:clamp(14px,2.2vw,19px);text-transform:uppercase;
  letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ep-side.a .ep-tnm{color:var(--team-a)} .ep-side.b .ep-tnm{color:var(--team-b)}
.ep-trc{font-family:var(--f-micro);font-size:11px;color:var(--ink-3)}
.ep-scr{font-family:var(--f-score);font-size:clamp(64px,14vw,132px);line-height:.8;letter-spacing:.01em}
.ep-side.a .ep-scr{color:var(--team-a);text-shadow:0 0 50px color-mix(in oklch,var(--team-a) 45%,transparent)}
.ep-side.b .ep-scr{color:var(--team-b);text-shadow:0 0 50px color-mix(in oklch,var(--team-b) 45%,transparent)}
.ep-mid{padding:calc(var(--u)*3) calc(var(--u)*2.5);border-left:1px solid var(--rule);background:var(--panel);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px}
.ep-clk{font-family:var(--f-score);font-size:clamp(26px,4.6vw,40px);line-height:1;color:var(--ink)}
.ep-prd{font-family:var(--f-micro);font-size:11px;color:var(--ink-3)}
.ep-live{display:inline-flex;align-items:center;gap:6px;font-family:var(--f-micro);font-size:10px;
  background:var(--flare);color:#150406;padding:3px 9px 2px 4px}
.ep-live .dot{width:12px;height:12px;border-radius:50%;padding:2px;animation:ep-spin 1.5s linear infinite;
  background:conic-gradient(from var(--ring),rgba(21,4,6,.92) 0 30%,rgba(21,4,6,.18) 30%)}
.ep-live .dot i{display:block;width:100%;height:100%;border-radius:50%;background:var(--flare)}
@keyframes ep-spin{to{--ring:360deg}}
.ep-poss{display:flex;gap:4px}
.ep-poss i{width:5px;height:5px;background:var(--ink-3)}
.ep-poss i.on{background:var(--amber);box-shadow:0 0 9px var(--amber)}

/* ---------- 8. tables ---------- */
.ep-tw{overflow-x:auto}

/* ---------------------------------------------------------------------------
   SIDEWAYS SCROLLING FOR THINGS THAT ARE WIDER THAN A PHONE.

   .ep-tbl is min-width:580px on purpose — a WOWY row or a lineup row is a
   dozen numbers and squeezing them into 375px makes them unreadable rather
   than smaller. What was missing is somewhere for that width to go, so on a
   phone the columns past the fifth were simply unreachable.

   touch-action:pan-x is what makes the drag feel like a drag: without it the
   browser spends the first few pixels deciding whether the gesture belongs to
   the page's vertical scroll, and a sideways flick on a table reads as a
   stutter. overscroll-behavior stops a flick that reaches the end of a table
   from turning into a back-navigation, which on a phone is how you lose the
   page you were reading.

   The fade on the right edge is the only affordance a scroller like this gets
   — no scrollbar exists on touch — so it does the work of saying "there is
   more this way". It is painted with a background-attachment trick rather than
   a pseudo-element so it moves with the scroll and disappears at the end. */
/* The competition filter above the leaders and team-stats boards. Quiet on
   purpose: it is a lens, and a control that shouts competes with the numbers
   it is there to qualify. */
/* The shot chart and its two controls. The court keeps its aspect ratio and
   is capped so it does not swallow a phone screen on its own. */
.sc-wrap{max-width:520px;margin:0 auto}
.sc-wrap svg{width:100%;height:auto;display:block;border-radius:10px}
.sc-note{font-family:var(--f-micro);font-size:9px;letter-spacing:.06em;color:var(--ink-3);
  text-align:center;padding:calc(var(--u)*1.5) 0 0;line-height:1.8}
.sc-controls{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end}
.sc-ctl{display:flex;flex-direction:column;gap:3px}
.sc-ctl > span{font-family:var(--f-micro);font-size:8px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
.sc-ctl .ep-input{font-size:12px;padding:4px 7px;min-height:34px}

.scopebar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:0 0 calc(var(--u)*1.5)}
.scopelab{font-family:var(--f-micro);font-size:8.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
.scopesel{font-size:12px;padding:5px 8px;max-width:100%;min-height:36px}
@media (max-width:640px){ .scopesel{flex:1 1 auto;min-width:0} }

.ep-xscroll{
  overflow-x:auto; overflow-y:hidden;
  /* PAN-X ALONE STRANDS THE READER. touch-action:pan-x tells the browser this
     element handles horizontal panning AND NOTHING ELSE, so a vertical drag
     that begins on the table is discarded rather than passed up to the page.
     On a full-height stats table that means a finger anywhere over the numbers
     cannot scroll the page at all — you reach the middle of the leaders table
     and stop. It is the same trap the full statistics table had.

     Both axes named: the element takes horizontal drags, the page keeps
     vertical ones, and the browser decides by direction on the first few
     pixels. The reason to name them at all rather than leave it auto is that
     it still rules out pinch-zoom and double-tap-zoom on a data grid, which
     are the gestures that make a table jump about while you are reading it. */
  touch-action:pan-x pan-y; -webkit-overflow-scrolling:touch;
  overscroll-behavior-x:contain;
  scrollbar-width:thin;
  background:
    linear-gradient(90deg, var(--ground) 30%, transparent) left / 28px 100% no-repeat local,
    linear-gradient(90deg, transparent, var(--ground) 70%) right / 28px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.45), transparent) left / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.45), transparent) right / 14px 100% no-repeat scroll;
}
.ep-xscroll::-webkit-scrollbar{height:6px}
.ep-xscroll::-webkit-scrollbar-thumb{background:var(--rule-2);border-radius:3px}

/* A tab strip scrolls in place rather than being boxed: it is already a flex
   row and a border round it would read as a panel. Wrapping onto two lines was
   the other option and is worse — the bar changes height when you switch tabs
   and the content below it jumps. */
.ep-xtabs{
  display:flex !important; flex-wrap:nowrap !important;
  overflow-x:auto; max-width:100%;
  /* both axes, for the reason above: a tab bar spans the page and a vertical
     drag that happens to start on it must still scroll the page */
  touch-action:pan-x pan-y; -webkit-overflow-scrolling:touch;
  overscroll-behavior-x:contain;
  scrollbar-width:none;
}
.ep-xtabs::-webkit-scrollbar{display:none}
.ep-xtabs > *{flex:0 0 auto; white-space:nowrap}

/* ---------------------------------------------------------------------------
   ON A PHONE, NEITHER OF THESE IS A NATIVE SCROLLER.

   pan-x pan-y above reads correctly and does not behave: naming both axes
   leaves the browser arbitrating which one a touch belongs to, and a box with
   overflow-x:auto wins that arbitration often enough that a vertical swipe
   starting over a table strands the reader mid-table. Three attempts at
   wording touch-action, three reports back from a real phone.

   So below 640px there is nothing to arbitrate: overflow hidden on both axes
   means no scrollable surface, pan-y hands vertical to the page in as many
   words, and xscroll.js pans these sideways from pointer events — claiming
   the gesture only once it has clearly gone horizontal, and releasing it
   untouched the instant it has not.

   AFTER the base rules, not before: same specificity, so file order decides.
   --------------------------------------------------------------------------- */
@media (max-width:640px){
  .ep-xscroll, .ep-xtabs{
    overflow:hidden;
    touch-action:pan-y;
  }
  /* the edge fades are the only remaining hint that there is more sideways,
     so they stay — but the 'local' ones track scrollLeft and still work */
}
.ep-tbl{border-collapse:collapse;width:100%;min-width:580px}
.ep-tbl thead th{font-family:var(--f-micro);font-size:10px;text-align:right;padding:9px 11px;color:var(--ink-3);
  background:var(--panel);border-bottom:1px solid var(--rule-2);position:sticky;top:0}
.ep-tbl thead th:nth-child(-n+2){text-align:left}
.ep-tbl tbody td{font-family:var(--f-data);font-size:11.5px;font-variant-numeric:tabular-nums;text-align:right;
  padding:8px 11px;border-bottom:1px solid var(--rule);color:var(--ink)}
.ep-tbl tbody td:first-child{font-family:var(--f-score);font-size:15px;color:var(--ink-3);text-align:left}
.ep-tbl tbody td:nth-child(2){text-align:left;font-family:var(--f-ui);font-weight:600;font-size:13px}
.ep-tbl tbody tr:hover td{background:color-mix(in oklch,var(--team-a) 8%,transparent)}
.ep-tbl tbody tr.on td:nth-child(2){color:var(--team-a)}
.ep-tbl tfoot td{font-family:var(--f-data);font-size:11.5px;text-align:right;padding:9px 11px;
  border-top:1px solid var(--rule-2);font-weight:700}
.ep-tbl tfoot td:nth-child(2){text-align:left;font-family:var(--f-ui)}
.ep-crest{display:inline-grid;place-items:center;width:21px;height:21px;font-family:var(--f-score);
  font-size:11px;color:#04100b;margin-right:8px;vertical-align:-4px}

/* ---------- 9. bars ---------- */
.ep-bar{display:grid;grid-template-columns:92px 1fr 50px;gap:12px;align-items:center;padding:5px 0}
.ep-bar .l{font-family:var(--f-micro);font-size:10px;color:var(--ink-3)}
.ep-bar .v{font-family:var(--f-data);font-size:11.5px;text-align:right}
.ep-trk{height:9px;background:color-mix(in oklch,var(--ink) 11%,transparent);overflow:hidden}
.ep-trk i{display:block;height:100%;transition:width .7s var(--ease)}
.ep-trk i.a{background:var(--team-a)} .ep-trk i.b{background:var(--team-b)}
/* mirrored comparison — brightest where the two teams meet */
.ep-mir{display:grid;grid-template-columns:48px 1fr 48px;gap:10px;align-items:center;padding:5px 0}
.ep-mir .v{font-family:var(--f-data);font-size:11.5px;color:var(--ink-2)}
.ep-mir .v.a{text-align:right;color:var(--team-a)} .ep-mir .v.b{color:var(--team-b)}
.ep-mir .v.w{color:var(--ink);text-shadow:0 0 10px currentColor}
.ep-mb{display:flex;height:9px}
.ep-mb>div{flex:1;position:relative;background:color-mix(in oklch,var(--ink) 11%,transparent)}
.ep-mb .h i{position:absolute;right:0;height:100%;background:linear-gradient(90deg,transparent,var(--team-a))}
.ep-mb .g i{position:absolute;left:0;height:100%;background:linear-gradient(90deg,var(--team-b),transparent)}
.ep-mlb{text-align:center;font-family:var(--f-micro);font-size:9px;color:var(--ink-3);margin-top:4px}

/* ---------- 10. controls ---------- */
.ep-btn{font-family:var(--f-micro);font-size:11px;padding:11px 18px;border:1px solid var(--rule-2);
  background:transparent;color:var(--ink);cursor:pointer;text-transform:uppercase;transition:.2s var(--ease)}
.ep-btn:hover{background:var(--lume);color:#04100b;border-color:var(--lume)}
.ep-btn.pri{background:var(--lume);border-color:var(--lume);color:#0a1a12}
.ep-btn.pri:hover{filter:brightness(1.12)}
.ep-btn.dgr{color:var(--flare);border-color:color-mix(in oklch,var(--flare) 55%,transparent)}
.ep-btn.dgr:hover{background:var(--flare);color:#150406;border-color:var(--flare)}
.ep-tabs{display:inline-flex;border:1px solid var(--rule-2)}
.ep-tab{font-family:var(--f-micro);font-size:11px;padding:10px 16px;background:transparent;border:none;
  border-right:1px solid var(--rule-2);color:var(--ink-3);cursor:pointer;text-transform:uppercase;transition:.2s}
.ep-tab:last-child{border-right:none}
.ep-tab:hover{color:var(--ink)}
.ep-tab.on{background:var(--lume);color:#04100b}
.ep-chip{font-family:var(--f-micro);font-size:10px;padding:6px 11px;border:1px solid var(--rule);
  color:var(--ink-2);cursor:pointer;text-transform:uppercase;transition:.2s}
.ep-chip:hover{border-color:var(--ink-2)}
.ep-chip.on{background:color-mix(in oklch,var(--lume) 18%,transparent);border-color:var(--lume);color:var(--lume)}
.ep-input{font-family:var(--f-data);font-size:13px;padding:10px 13px;background:var(--panel);
  border:1px solid var(--rule-2);color:var(--ink);outline:none;width:100%;max-width:260px}
.ep-input:focus{border-color:var(--lume);box-shadow:0 0 0 3px color-mix(in oklch,var(--lume) 20%,transparent)}
.ep-pill{font-family:var(--f-data);font-size:10.5px;font-weight:700;padding:3px 9px;border:1px solid}
.ep-pill.up{color:var(--good);border-color:color-mix(in oklch,var(--good) 45%,transparent)}
.ep-pill.dn{color:var(--bad);border-color:color-mix(in oklch,var(--bad) 45%,transparent)}
.ep-rank{font-family:var(--f-micro);font-size:9px;background:var(--amber);color:#1a1103;padding:2px 6px}

/* ---------- 11. player card ---------- */
.ep-pc{display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center;
  padding:calc(var(--u)*3);border-bottom:1px solid var(--rule)}
.ep-pnum{font-family:var(--f-score);font-size:74px;line-height:.78;color:var(--team-a);
  text-shadow:0 0 36px color-mix(in oklch,var(--team-a) 45%,transparent)}
.ep-pnm{font-family:var(--f-ui);font-weight:800;font-size:21px;text-transform:uppercase;letter-spacing:.02em}
.ep-pln{font-family:var(--f-data);font-size:11px;color:var(--ink-2);margin-top:5px}
.ep-tiles{display:grid;grid-template-columns:repeat(3,1fr)}
.ep-tile{padding:16px 12px;text-align:center;position:relative;
  border-right:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.ep-tile:last-child{border-right:none}
.ep-tile .tv{font-family:var(--f-score);font-size:34px;line-height:1;color:var(--ink)}
.ep-tile .tl{font-family:var(--f-micro);font-size:9px;color:var(--ink-3);margin-top:7px}
.ep-tile.g .tv{color:var(--good)} .ep-tile.r .tv{color:var(--bad)}
.ep-tile .ep-rank{position:absolute;top:8px;right:8px}

/* ---------- 12. mobile ---------- */
@media (max-width:560px){
  .ep-band{padding:calc(var(--u)*3) calc(var(--u)*2)}
  .ep-hdr{padding:calc(var(--u)*1.5) calc(var(--u)*2)}
  .ep-side,.ep-pc{padding:calc(var(--u)*2)}
  .ep-bar{grid-template-columns:76px 1fr 44px;gap:9px}
}

/* ---------------------------------------------------------------------------
   .hide — THE ONE UTILITY, AND IT BELONGS HERE.

   Four pages each declared this identically in their own <style> block and two
   did not, which is not a style question: on the news page #list carried .hide
   with nothing defining it, so opening an article left the list's "Loading…"
   sitting under the finished article. The class did nothing and looked like it
   did something, which is the worst way for a rule to be missing.

   Scoped copies elsewhere (.ep-nav .hide, .sc-slab.hide, .news-ed.hide) say the
   same thing and can stay; they were the reason a grep for it looked answered.
   --------------------------------------------------------------------------- */
.hide{ display:none !important }
