/* ============================================================
   Suwalska Liga Bowlingowa - główny arkusz stylów
   ------------------------------------------------------------
   Charakter: PŁASKI. Estetyka sportowej tablicy wyników -
   ostre krawędzie, małe promienie, grube nagłówki, mocny kontrast.
   Czerwień punktowo, czerń dla sekcji ciemnych, biel jako podstawa.
   „Cienie" to płaskie obwódki i offsetowe bloki koloru; box-shadow
   z rozmyciem zarezerwowany wyłącznie dla warstw unoszących się
   nad treścią (przyklejony nagłówek, menu, modale).

   SPIS SEKCJI
     01. Fonty (self-hosted)
     02. Zmienne (:root)
     03. Reset i baza + zabezpieczenie przed przewijaniem w bok
     04. Typografia
     05. Narzędzia i układ (container, section, siatki,
         klasy porządkowe .mt-* .mb-* .is-* .fw-*)
     06. Przyciski (.btn)
     07. Etykiety (.chip, .badge-*)
     08. Karty (.card, .stat)
     09. Tabele (.tbl, .tbl--standings, .pos, .team-cell)
     10. Mecz (.match)
     11. Nawigacja kolejek (.round-nav)
     12. Aktualności (.news-card)
     13. Zawodnicy i rankingi (.player-card, .rank-row)
     14. Okruszki, paginacja, stany (.crumbs, .pagination, .flash,
         .empty, .is-loading, .skeleton)
     15. Pasek górny (.topbar)
     16. Nagłówek strony (.nav)
     17. Hero (.hero)
     18. Pasek wyników (.ticker)
     19. Karuzela partnerów (.partners)
     20. Stopka (.foot)
     21. Pasek cookies (.cookie-bar)
     22. Formularze
     23. Drobne komponenty pomocnicze
     23a. Wykres formy zawodnika (.form-chart)
     24. Animacje wejścia ([data-reveal])
     25. Responsywność (1180 / 980 / 760 / 560 / 400)
     26. Druk
     27. prefers-reduced-motion: reduce
   ============================================================ */


/* ============================================================
   01. FONTY - self-hosted, rozbite na latin / latin-ext,
       żeby przeglądarka ściągała wyłącznie potrzebny zakres.
   ============================================================ */
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-latin-ext-normal.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-latin-normal.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-latin-ext-italic.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-latin-italic.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/assets/fonts/jbmono-latin-ext-normal.woff2') format('woff2');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/assets/fonts/jbmono-latin-normal.woff2') format('woff2');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Caveat';
  src: url('/assets/fonts/caveat-latin-ext.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Caveat';
  src: url('/assets/fonts/caveat-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ============================================================
   02. ZMIENNE - nazwy są kontraktem (SPEC §6.2). Nie zmieniać.
   ============================================================ */
:root{
  --red:#d7332b;          /* główny */
  --red-600:#b8271f;      /* hover/active */
  --red-700:#96201a;
  --red-050:#fdeceb;      /* tło delikatne */
  --black:#010202;        /* główny ciemny */
  --ink:#101112;          /* tekst na jasnym */
  --ink-2:#3a3d40;
  --ink-3:#6c7176;        /* tekst pomocniczy, >=4.5:1 na białym */
  --white:#ffffff;
  --paper:#ffffff;
  --paper-2:#f5f6f7;      /* przeplatane sekcje */
  --paper-3:#eceef0;
  --line:rgba(1,2,2,.12);
  --line-2:rgba(1,2,2,.06);
  --on-dark:rgba(255,255,255,.72);
  --on-dark-2:rgba(255,255,255,.5);
  --line-dark:rgba(255,255,255,.14);
  --ok:#1f8a4c; --warn:#c8791a; --err:#d7332b;
  /* PROMIEŃ - jeden na cały serwis. --r-2 jest aliasem zgodnościowym:
     nazwa została, bo używa jej kilkanaście reguł i markup innych stron,
     ale wartość jest ta sama, więc karta, pole i przycisk mają identycznie
     ścięty narożnik. Udokumentowane wyjątki (2px): mikro-znaczki, które przy
     4px wyglądają na krzywe - .form-strip__i, .lane, .news-card__tag,
     .match--featured::before, .share__done. */
  --r:4px;
  --r-2:var(--r);
  --container:1240px;
  --pad-x:max(clamp(18px,4vw,44px),env(safe-area-inset-left),env(safe-area-inset-right));

  /* RYTM PIONOWY - trzy poziomy, nic pomiędzy (patrz §05):
     --sec-y-tight  zwarty  - bloki dopisane do poprzedniej sekcji
                             (tabela + jej legenda, lista + paginacja),
     --sec-y        normalny- domyślny odstęp między sekcjami strony,
     --sec-y-loose  luźny   - otwarcie i zamknięcie strony (hero, wezwanie
                             do zgłoszenia drużyny).
     Klasy: .section--tight / .section / .section--loose. */
  --sec-y-tight:clamp(1.9rem,4.2vw,3.2rem);
  --sec-y:clamp(2.9rem,6vw,5.4rem);
  --sec-y-loose:clamp(4rem,8vw,7.2rem);

  /* SKALA ODSTĘPÓW WEWNĄTRZ KOMPONENTÓW - osiem stopni i nic pomiędzy.
     Wcześniej wartości były pisane „na oko" (.35rem, .42rem, .55rem, 3px,
     .85rem, 1.25rem…), przez co dwie karty obok siebie miały inne wcięcia,
     a ten sam odstęp między ikoną a tekstem wypadał raz na 5px, raz na 7px.
     Teraz każdy padding, gap i margin komponentu bierze wartość STĄD.

     Na dużym ekranie skala to czysta czwórka: 2 4 8 12 16 24 32 48 px.

       --gap-0  2px    mikro - tylko wewnątrz znaczków (.lane, .badge-hdcp),
                       gdzie 4px już rozpycha etykietę,
       --gap-1  4px    ikona przy tekście, wiersze wewnątrz jednego bloku,
       --gap-2  8px    elementy tego samego rzędu (chipy, przyciski w grupie),
       --gap-3  12px   wcięcie komórki tabeli, wnętrze małego pola,
       --gap-4  16px   odstęp między blokami wewnątrz karty,
       --gap-5  24px   wcięcie karty, przerwa w siatce treści,
       --gap-6  32px   odstęp między grupami w sekcji,
       --gap-7  48px   największy odstęp WEWNĄTRZ sekcji (rytm MIĘDZY
                       sekcjami niosą --sec-y-*, nie ta skala).

     Stopnie 0-2 są STAŁE: to odstępy optyczne, związane z wielkością
     litery i ikony - skalowanie ich do szerokości ekranu tylko zamazuje
     relacje. Stopnie 3-7 są PŁYNNE (clamp): to odstępy przestrzenne
     i na telefonie mają maleć proporcjonalnie, a nie zostawać desktopowe.
     Przy 320px skala schodzi do: 2 4 8 10 14 18 22 30 px. */
  --gap-0:.125rem;
  --gap-1:.25rem;
  --gap-2:.5rem;
  --gap-3:clamp(.65rem,1.6vw,.75rem);
  --gap-4:clamp(.85rem,2vw,1rem);
  --gap-5:clamp(1.1rem,2.2vw,1.5rem);
  --gap-6:clamp(1.4rem,3vw,2rem);
  --gap-7:clamp(1.9rem,4.4vw,3rem);

  /* Odstęp nagłówka sekcji od jej treści - jeden dla wszystkich sekcji. */
  --head-gap:var(--gap-6);

  /* SKALA NAGŁÓWKÓW - kolejne poziomy dzieli wyraźny skok (~1,5×),
     żeby hierarchia była czytelna bez dodatkowych ozdobników.
     .section__title jest tym samym rozmiarem co h2 - bez osobnego wariantu. */
  --fs-h1:clamp(2.2rem,5.6vw,4rem);
  --fs-h2:clamp(1.7rem,3.6vw,2.6rem);
  --fs-h3:clamp(1.25rem,2.4vw,1.7rem);
  --fs-h4:clamp(1.05rem,1.6vw,1.22rem);

  /* KARTY - jedno obramowanie i jeden odstęp wewnętrzny dla wszystkich
     pojemników (.card, .stat, .tile, .match, .empty, .news-card__body). */
  --card-pad:var(--gap-5);
  --card-pad-sm:var(--gap-4);
  /* Komórka tabeli - ten sam odstęp w nagłówku, ciele i stopce tabeli.
     Poziomo i pionowo tyle samo: wiersz wyników czyta się jako siatka,
     a nie jako pasek z przypadkowym wcięciem. */
  --cell-y:var(--gap-3);
  --cell-x:var(--gap-3);

  /* Nagłówek: 70px na desktopie, 66/62 na węższych ekranach (§24).
     Powyżej 80px pasek zaczyna zjadać pierwszy ekran wyników. */
  --nav-h:70px;
  --topbar-h:0px;

  /* KRZYWE - dwie, obie własne. Wbudowane słowa kluczowe (ease, ease-in)
     są w interfejsie zakazane: ease-in rusza wolno i sprawia, że całość
     wydaje się ociężała.
       --ease-out    - wszystko, co użytkownik wywołał (reakcja na klik,
                       rozwinięcie, wejście elementu). Szybki start, miękkie
                       dojście.
       --ease-in-out - ruch ciągły i pętle (pulsowanie stanu „na żywo"),
                       gdzie nie ma wyraźnego początku ani końca.
     CZASY: reakcja przycisku 100-160ms, rozwijane 150-250ms,
     modale i panele 200-350ms. Wyjście zawsze szybsze niż wejście. */
  --ease-out:cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out:cubic-bezier(0.77, 0, 0.175, 1);
  --font:'Archivo',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'JetBrains Mono',ui-monospace,monospace;
}


/* ============================================================
   03. RESET I BAZA
   ------------------------------------------------------------
   Blok „ochrony przed przewijaniem w bok" jest obowiązkowy
   (SPEC §6.4): overflow-x:clip zamiast hidden, bo hidden na
   <html> psuje position:sticky w nagłówku i w tabelach.
   ============================================================ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
[hidden]{display:none !important}

html,body{max-width:100%;overflow-x:clip}

/* Zapas dla Safari ≤15 (iOS 15) - tam `clip` jest wartością nieprawidłową,
   więc cała deklaracja overflow-x wyżej jest odrzucana i strona przewija się
   w bok. Blokadę zakładamy wyłącznie na <body>: overflow z body propaguje się
   do viewportu, a samo body nie staje się kontenerem przewijania, więc
   position:sticky w nagłówku i w tabelach działa dalej (SPEC §6.4). */
@supports not (overflow-x: clip){
  html{overflow-x:visible}
  body{overflow-x:hidden}
}

body{overflow-wrap:break-word}
img,svg,video,canvas{max-width:100%;height:auto;display:block}
/* <iframe> celowo bez height:auto - element zastępowany bez własnych proporcji
   dostałby wtedy domyślne 150px wysokości i spłaszczył osadzone wideo. */
iframe{max-width:100%;display:block}
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  /* Odsunięcie kotwic o wysokość przyklejonego nagłówka - inaczej
     nagłówek zasłania początek sekcji po kliknięciu w link #hash. */
  scroll-padding-top:calc(var(--nav-h) + var(--topbar-h) + var(--gap-3));
  scrollbar-color:var(--ink-3) var(--paper-3);
  scrollbar-width:thin;
}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:var(--paper-3)}
::-webkit-scrollbar-thumb{background:var(--ink-3);border:3px solid var(--paper-3);background-clip:padding-box}
@media (hover:hover) and (pointer:fine){
  ::-webkit-scrollbar-thumb:hover{background:var(--ink);background-clip:padding-box}
}

::-webkit-scrollbar-corner{background:var(--paper-3)}

body{
  font-family:var(--font);
  font-size:1.0625rem;
  line-height:1.6;
  color:var(--ink);
  background:var(--paper);
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  /* Miejsce na wcięcie ekranu (notch) w orientacji poziomej. */
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
}

/* Blokada przewijania tła przy otwartym menu / modalu.
   Pozycja przywracana skryptem, dlatego tylko fixed + szerokość. */
body.is-locked{position:fixed;width:100%;overflow:hidden}

a{color:inherit;text-decoration:none}
@media (hover:hover) and (pointer:fine){
  a:hover{color:var(--red-600)}
}

button,input,select,textarea{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
ul,ol{list-style:none}
table{border-collapse:collapse;border-spacing:0;width:100%}
::selection{background:var(--red);color:var(--white)}

/* Fokus klawiaturowy - jednolity w całym serwisie (SPEC §6.7).
   Reguła obejmuje wszystko, co da się sfokusować: linki, przyciski,
   pola formularzy, elementy z tabindex, wiersze tabel z data-href
   i pojemniki przewijane (te dostają fokus, gdy da się je przewinąć). */
:focus{outline:none}
:focus-visible,
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[contenteditable]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.table-scroll:focus-visible,
.tbl tr.is-clickable:focus-visible{
  outline:2px solid var(--red);
  outline-offset:3px;
  border-radius:2px;
}
/* Na ciemnym tle czerwony obrys ginie - tam pierścień jest biały. */
.section--dark :focus-visible,
.hero--dark :focus-visible,
.foot :focus-visible,
.topbar :focus-visible,
.cookie-bar :focus-visible,
.nav__menu :focus-visible{outline-color:var(--white)}
/* Element z własnym obrysem (przycisk, kafel) nie może chować pierścienia
   pod sąsiadem - offset zostaje, ale nie wychodzi poza pole kliknięcia. */
.btn:focus-visible,
.btn-icon:focus-visible,
.chip:focus-visible,
.pagination a:focus-visible{outline-offset:2px}

.skip-link{
  position:absolute;left:8px;top:-100px;z-index:2000;
  display:inline-block;padding:var(--gap-3) var(--gap-4);
  background:var(--black);color:var(--white);
  font-weight:700;letter-spacing:.02em;border-radius:var(--r);
  transition:top .18s var(--ease-out);
}
/* Zwykły :focus, nie :focus-visible - link musi się pokazać także wtedy,
   gdy fokus ustawia skrypt (powrót na górę strony). */
.skip-link:focus,
.skip-link:focus-visible{top:8px;color:var(--white);outline-color:var(--white)}

/* Kotwica startu strony - punkt docelowy linku „do góry". Bez własnej
   wysokości, żeby nie wpływała na układ. */
#top{display:block;height:0;overflow:hidden}

.visually-hidden{
  position:absolute !important;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* Wspólny „rytm" pionowy dla bloków tekstowych z bazy (Quill). */
.prose>*+*{margin-top:var(--gap-4)}
.prose h2{margin-top:var(--gap-6);font-size:clamp(1.35rem,2.4vw,1.75rem)}
.prose h3{margin-top:var(--gap-5);font-size:clamp(1.15rem,2vw,1.35rem)}
.prose ul,.prose ol{padding-left:var(--gap-5)}
.prose ul li{list-style:disc}
.prose ol li{list-style:decimal}
.prose li+li{margin-top:var(--gap-1)}
.prose a{color:var(--red-700);text-decoration:underline;text-underline-offset:.18em}
@media (hover:hover) and (pointer:fine){
  .prose a:hover{color:var(--red-600)}
}

.prose img{margin:var(--gap-6) 0;border-radius:var(--r-2);border:1px solid var(--line)}
/* Osadzone wideo (YouTube/Vimeo dopuszczone przez sanitize_html) - proporcja
   16:9 zamiast atrybutów width/height z kodu osadzenia. */
.prose iframe{
  width:100%;max-width:100%;aspect-ratio:16/9;height:auto;
  margin:var(--gap-6) 0;border:0;border-radius:var(--r-2);
}
.prose blockquote{
  border-left:4px solid var(--red);
  padding:var(--gap-1) 0 var(--gap-1) var(--gap-4);
  color:var(--ink-2);font-size:1.08em;
}
.prose hr{border:0;border-top:1px solid var(--line);margin:var(--gap-6) 0}
.prose table{margin:var(--gap-5) 0;font-size:.95em}
.prose th,.prose td{border:1px solid var(--line);padding:var(--gap-2) var(--gap-3);text-align:left}
.prose th{background:var(--paper-2);font-weight:700}


/* ============================================================
   04. TYPOGRAFIA
   ------------------------------------------------------------
   Wszystkie liczby idą monospace z tabular-nums - bez tego
   kolumny wyników „tańczą" przy każdej zmianie cyfry.
   ============================================================ */
h1,h2,h3,h4,h5,h6{
  font-weight:800;
  line-height:1.08;
  letter-spacing:-.03em;
  text-wrap:balance;
}
h1{font-size:var(--fs-h1)}
h2{font-size:var(--fs-h2)}
h3{font-size:var(--fs-h3)}
h4{font-size:var(--fs-h4);letter-spacing:-.02em}
h5,h6{font-size:1rem;letter-spacing:-.01em}

p{text-wrap:pretty}
strong,b{font-weight:700}
small{font-size:.8125rem}

.num,
.is-num,
[data-count],
.stat__val,
.tbl--standings td,
.match__score,
.rank-row__score{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
}

.lead{
  font-size:clamp(1.0625rem,1.6vw,1.25rem);
  line-height:1.55;
  color:var(--ink-2);
}
.muted{color:var(--ink-3)}
.upper{text-transform:uppercase;letter-spacing:.1em}
/* --- .eyebrow - mała wersalikowa etykieta nad nagłówkiem ------
   LIMIT: najwyżej RAZ NA TRZY SEKCJE na stronie. Hero liczy się jako
   jedno użycie. Nadtytuł nad każdym nagłówkiem przestaje cokolwiek
   zapowiadać i zamienia stronę w spis treści - w większości miejsc
   sam nagłówek sekcji wystarcza. Przed oddaniem strony policz je.
   ZAKAZ numerowania („01 / TABELA") - nadtytuł nazywa temat, nie
   porządkuje sekcji.
   Kolor: tekst neutralny, czerwona zostaje sama kreska. Nadtytuł
   w czerwieni migotałby przez całą stronę i zabierał uwagę temu
   jednemu akcentowi, który ma ją dostać. Wariant .eyebrow--red to
   wyjątek na jedno miejsce w serwisie. --------------------------- */
.eyebrow{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  font-size:.75rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.16em;
  color:var(--ink-3);
}
.eyebrow--red{color:var(--red-700)}
.eyebrow--dark{color:var(--white)}
.eyebrow::before{
  content:'';width:22px;height:2px;background:var(--red);flex:none;
}
.eyebrow--red::before,.eyebrow--dark::before{background:currentColor}
.handwritten{font-family:'Caveat',cursive;font-size:1.5em;line-height:1.2}

/* Akcent czerwony wewnątrz nagłówka - pojedyncze słowo, nie całe zdanie. */
.accent{color:var(--red)}
.section--dark .accent,
.hero--dark .accent{color:var(--red)}

/* Podkreślenie „markerem": płaski blok koloru pod tekstem. */
.mark-red{
  background:linear-gradient(var(--red),var(--red)) no-repeat left bottom / 100% .28em;
  padding:0 .06em;
}


/* ============================================================
   05. UKŁAD - kontener, sekcje, siatki
   ============================================================ */
.container{
  width:100%;
  max-width:var(--container);
  margin-inline:auto;
  padding-inline:var(--pad-x);
}
.container--narrow{max-width:820px}
.container--wide{max-width:1440px}

/* --- Rytm pionowy -------------------------------------------
   Trzy poziomy odstępu i nic pomiędzy - jedna klasa na sekcję:
     .section--tight  zwarty   - blok dopisany do poprzedniego
                                 (legenda pod tabelą, paginacja pod listą),
     .section         normalny - domyślny odstęp między tematami,
     .section--loose  luźny    - otwarcie i zamknięcie strony.
   Tło (--tint / --tint2 / --dark) i linia (--line) są niezależne od
   rytmu: odstęp mówi „jak daleko", tło mówi „to inny temat".
   Zasada przeplotu: dwie sąsiadujące sekcje nigdy nie mają tego samego
   tła bez .section--line między nimi. ------------------------- */
.section{padding-block:var(--sec-y);position:relative}
.section--tight{padding-block:var(--sec-y-tight)}
.section--loose{padding-block:var(--sec-y-loose)}
.section--tint{background:var(--paper-2)}
.section--tint2{background:var(--paper-3)}
/* BLOKADA MOTYWU: serwis ma jeden motyw - jasny. Sekcja ciemna jest
   świadomym zabiegiem kompozycyjnym i wolno jej wystąpić RAZ NA STRONĘ
   (hero ciemne liczy się jako to jedno wystąpienie). Naprzemienne
   jasne-ciemne-jasne czyta się jak sklejka z dwóch projektów.
   Agenci budujący podstrony: sprawdźcie, czy strona już nie ma
   .hero--dark, zanim dołożycie .section--dark. */
.section--dark{background:var(--black);color:var(--white)}
.section--dark .lead,
.section--dark .section__desc{color:var(--on-dark)}
.section--dark .muted{color:var(--on-dark-2)}
@media (hover:hover) and (pointer:fine){
  .section--dark a:hover{color:var(--white)}
}

/* Cienka linia rozdzielająca sekcje na tym samym tle. */
.section--line{border-top:1px solid var(--line)}
.section--dark.section--line{border-top-color:var(--line-dark)}

/* --- Nagłówek sekcji ----------------------------------------
   Jeden układ wszędzie: [nadtytuł → tytuł → opis] po lewej,
   link „zobacz wszystko" po prawej. Jedyny wariant to --center
   (nagłówek nad siatką wyśrodkowaną). Rozmiar tytułu = h2. --- */
.section__head{
  display:flex;flex-wrap:wrap;align-items:flex-end;
  justify-content:space-between;gap:var(--gap-4) var(--gap-6);
  margin-bottom:var(--head-gap);
}
.section__head--center{
  flex-direction:column;align-items:center;text-align:center;
}
.section__head--center .section__desc{margin-inline:auto}
.section__head-main{max-width:64ch;min-width:0}
.section__head .eyebrow{margin-bottom:var(--gap-2)}
.section__title{
  font-size:var(--fs-h2);
  letter-spacing:-.035em;
}
.section__title .accent{color:var(--red)}
/* Bezpiecznik rytmu: gdy zaraz po nagłówku sekcji stoi element z własnym
   marginesem górnym (np. .prose), odstęp sumowałby się z --head-gap i ta
   jedna sekcja odjeżdżałaby od reszty strony. */
.section__head+*{margin-top:0}
.section__desc{
  margin-top:var(--gap-3);
  color:var(--ink-2);
  font-size:clamp(.98rem,1.3vw,1.09rem);
  max-width:62ch;
}
/* Link boczny jest neutralny - czerwień zostaje dla jednego akcentu
   w sekcji. Kolor pojawia się dopiero pod kursorem, w podkreśleniu. */
.section__link{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  font-weight:700;font-size:.94rem;
  color:var(--ink);
  border-bottom:2px solid var(--line);
  padding-bottom:2px;
  transition:border-color .18s var(--ease-out),color .18s var(--ease-out);
}
.section__link svg{width:16px;height:16px;flex:none}
@media (hover:hover) and (pointer:fine){
  .section__link:hover{color:var(--red-600);border-bottom-color:var(--red)}
}

.section--dark .section__link{color:var(--white);border-bottom-color:var(--line-dark)}
@media (hover:hover) and (pointer:fine){
  .section--dark .section__link:hover{color:var(--white);border-bottom-color:var(--red)}
}

/* --- Siatki uniwersalne -------------------------------------
   auto-fit + minmax: bez media queries kolumny same się układają,
   a min() chroni przed rozpychaniem układu przy 320px. --------- */
/* Przerwa w siatce treści (karty, kafle wpisów) to --gap-5; siatki gęste,
   złożone z małych elementów (.stat-row, .form-grid), schodzą o stopień
   niżej, do --gap-4. Innych wartości gap w siatkach nie ma.
   LICZBA KOLUMN jest schodkowa i jawna (§25): powyżej 760px auto-fit
   dobiera kolumny sam, 561-760px dokładnie DWIE, od 560px w dół JEDNA.
   Udokumentowany wyjątek: .grid--4 niesie kafle liczbowe (.stat) i jak
   .stat-row zostaje przy dwóch kolumnach także na telefonie. .grid--5
   (drobne kafle) zostaje na auto-fit na każdej szerokości. */
.grid{display:grid;gap:var(--gap-5)}
.grid--2{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}
.grid--3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.grid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.grid--5{grid-template-columns:repeat(auto-fit,minmax(min(100%,170px),1fr))}
/* Układ „treść + kolumna boczna"; poniżej 980px spada do jednej kolumny. */
.grid--side{grid-template-columns:minmax(0,1fr)}
@media (min-width:981px){
  .grid--side{grid-template-columns:minmax(0,1fr) 340px;align-items:start}
  .grid--side-left{grid-template-columns:320px minmax(0,1fr)}
}

.stack{display:flex;flex-direction:column;gap:var(--gap-5)}
.row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--gap-3)}
.row--between{justify-content:space-between}
.row--end{justify-content:flex-end}
.row--center{justify-content:center}

/* --- Klasy porządkowe -----------------------------------------
   Kilkanaście klas do SPRZĄTANIA stylów inline ze stron (profil
   zawodnika, drużyny, mecz, rankingi) - to nie jest system klas
   narzędziowych i nie ma się rozrastać. Zakres użycia:
     .mt-* / .mb-*   odstęp między dwoma blokami, które nie mają
                     wspólnego komponentu (np. .stat-row pod nagłówkiem
                     profilu, akapit „to jedyne spotkanie" pod tabelą);
                     wartości WYŁĄCZNIE ze skali --gap-*. Margines dolny
                     kończy się na stopniu 4, bo większy odstęp POD
                     blokiem to już rytm sekcji (--sec-y-*),
     .is-center / .is-right / .is-nowrap   wyrównanie pojedynczej
                     komórki lub akapitu (w .tbl istnieje też para
                     th/td.is-center - ta sama nazwa, ten sam skutek),
     .fw-bold / .fw-heavy   pogrubienie wiersza z wynikiem >= 200
                     albo komórki nagłówkowej „K7" w tabeli gier,
     .is-num         liczby monospace + tabular-nums poza tabelą
                     (w tabeli robi to .tbl td.is-num); definicja stoi
                     w §04 w grupie .num.
   Gdy ten sam zestaw powtarza się w trzech miejscach, należy mu się
   prawdziwa klasa komponentu, nie kolejna klasa porządkowa. --------- */
.mt-2{margin-top:var(--gap-2)}
.mt-3{margin-top:var(--gap-3)}
.mt-4{margin-top:var(--gap-4)}
.mt-5{margin-top:var(--gap-5)}
.mt-6{margin-top:var(--gap-6)}
.mb-2{margin-bottom:var(--gap-2)}
.mb-3{margin-bottom:var(--gap-3)}
.mb-4{margin-bottom:var(--gap-4)}
.is-center{text-align:center}
.is-right{text-align:right}
.is-nowrap{white-space:nowrap}
.fw-bold{font-weight:700}
.fw-heavy{font-weight:800}

/* Pasek akcji nad tabelą/listą: filtry z lewej, przyciski z prawej. */
.toolbar{
  display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:var(--gap-3) var(--gap-5);
  margin-bottom:var(--gap-4);
}
.toolbar__group{display:flex;flex-wrap:wrap;align-items:center;gap:var(--gap-2)}
/* Pole filtra nie może rozpychać paska szerokością najdłuższej opcji listy
   (nazwa drużyny to VARCHAR(120)) - dolna granica zamiast rozmiaru min-content. */
.toolbar .field{min-width:min(100%,240px)}

/* Płaska linia dzieląca; nigdy cień. */
.rule{border:0;border-top:1px solid var(--line);margin-block:var(--gap-6)}
.section--dark .rule{border-top-color:var(--line-dark)}

/* Sticky boks w kolumnie bocznej (np. mini-tabela obok terminarza). */
.sticky-col{position:sticky;top:calc(var(--nav-h) + var(--topbar-h) + var(--gap-4))}


/* ============================================================
   06. PRZYCISKI
   ------------------------------------------------------------
   Wariant podstawowy = ciemny.
   POTWIERDZENIE KLIKNIĘCIA: każdy przycisk kurczy się do
   scale(.97) na :active. Reakcja jest natychmiastowa i wraca
   w 160ms - użytkownik widzi, że system przyjął kliknięcie,
   zanim zdąży się cokolwiek przeładować.
   Transition zawsze na konkretnych własnościach (nigdy „all”),
   a ruch wyłącznie na transform i opacity - te dwie omijają
   layout i paint, więc idą na GPU.
   ============================================================ */
.btn{
  --btn-bg:var(--ink);
  --btn-fg:var(--white);
  --btn-line:var(--ink);
  display:inline-flex;align-items:center;justify-content:center;gap:var(--gap-2);
  padding:var(--gap-3) var(--gap-5);
  min-height:46px;
  background:var(--btn-bg);
  color:var(--btn-fg);
  border:2px solid var(--btn-line);
  border-radius:var(--r);
  font-weight:800;
  font-size:.9375rem;
  letter-spacing:.01em;
  text-align:center;
  cursor:pointer;
  white-space:nowrap;
  transition:background-color .16s var(--ease-out),
             border-color .16s var(--ease-out),
             color .16s var(--ease-out),
             transform .16s var(--ease-out);
}
.btn svg{width:18px;height:18px;flex:none}
@media (hover:hover) and (pointer:fine){
  .btn:hover{color:var(--btn-fg)}
}

.btn:active{transform:scale(.97)}

.btn--red{--btn-bg:var(--red);--btn-line:var(--red);--btn-fg:var(--white)}
@media (hover:hover) and (pointer:fine){
  .btn--red:hover{--btn-bg:var(--red-600);--btn-line:var(--red-600)}
}

.btn--red:active{--btn-bg:var(--red-700);--btn-line:var(--red-700)}

.btn--dark{--btn-bg:var(--black);--btn-line:var(--black);--btn-fg:var(--white)}
@media (hover:hover) and (pointer:fine){
  .btn--dark:hover{--btn-bg:var(--ink);--btn-line:var(--ink)}
}

/* Obrys - na jasnym tle czarny, na ciemnym biały (dziedziczy currentColor). */
.btn--line{
  --btn-bg:transparent;
  --btn-fg:var(--ink);
  --btn-line:var(--ink);
}
@media (hover:hover) and (pointer:fine){
  .btn--line:hover{--btn-bg:var(--ink);--btn-fg:var(--white)}
}

.section--dark .btn--line,
.hero--dark .btn--line,
.foot .btn--line{--btn-fg:var(--white);--btn-line:var(--white)}
@media (hover:hover) and (pointer:fine){
  .section--dark .btn--line:hover,.hero--dark .btn--line:hover,.foot .btn--line:hover{--btn-bg:var(--white);--btn-fg:var(--black)}
}

.btn--ghost{
  --btn-bg:transparent;
  --btn-fg:var(--ink-2);
  --btn-line:transparent;
  padding-inline:var(--gap-3);
}
@media (hover:hover) and (pointer:fine){
  .btn--ghost:hover{--btn-bg:var(--paper-2);--btn-fg:var(--ink)}
}

.section--dark .btn--ghost,
.foot .btn--ghost{--btn-fg:var(--on-dark)}
@media (hover:hover) and (pointer:fine){
  .section--dark .btn--ghost:hover,.foot .btn--ghost:hover{--btn-bg:rgba(255,255,255,.08);--btn-fg:var(--white)}
}

.btn--sm{padding:var(--gap-2) var(--gap-3);min-height:36px;font-size:.8125rem;border-width:1px}
.btn--sm svg{width:15px;height:15px}
.btn--lg{padding:var(--gap-4) var(--gap-6);min-height:56px;font-size:1.0625rem}
.btn--block{display:flex;width:100%}

.btn[disabled],
.btn[aria-disabled="true"]{
  opacity:.45;
  cursor:not-allowed;
  pointer-events:none;
}

/* Przycisk ikonowy - kwadrat, do pasków narzędzi i strzałek. */
.btn-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:42px;height:42px;flex:none;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
  color:var(--ink-2);
  transition:background-color .16s var(--ease-out),color .16s var(--ease-out),
             border-color .16s var(--ease-out),transform .16s var(--ease-out);
}
.btn-icon:active{transform:scale(.97)}
.btn-icon svg{width:19px;height:19px}
@media (hover:hover) and (pointer:fine){
  .btn-icon:hover{background:var(--ink);border-color:var(--ink);color:var(--white)}
}

.btn-icon[disabled]{opacity:.35;pointer-events:none}
.section--dark .btn-icon,
.foot .btn-icon{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
@media (hover:hover) and (pointer:fine){
  .section--dark .btn-icon:hover,.foot .btn-icon:hover{background:var(--white);border-color:var(--white);color:var(--black)}
}


/* ============================================================
   07. ETYKIETY - .chip, .badge-mvp, .badge-hdcp
   ============================================================ */
.chip{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  padding:var(--gap-1) var(--gap-3);
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
  color:var(--ink-2);
  font-size:.75rem;
  font-weight:700;
  letter-spacing:.05em;
  text-transform:uppercase;
  line-height:1.35;
  white-space:nowrap;
}
.chip svg{width:14px;height:14px;flex:none}
.chip--red{background:var(--red-050);border-color:rgba(215,51,43,.3);color:var(--red-700)}
.chip--dark{background:var(--black);border-color:var(--black);color:var(--white)}
.chip--ok{background:rgba(31,138,76,.1);border-color:rgba(31,138,76,.32);color:#166a3a}
.chip--warn{background:rgba(200,121,26,.12);border-color:rgba(200,121,26,.34);color:#8f560f}
/* Chip „na żywo" - czerwone tło pod białym tekstem, bo sam czerwony
   tekst na ciemnym tle nie wyrabia kontrastu (SPEC §6.7). */
.chip--live{
  background:var(--red);border-color:var(--red);color:var(--white);
}
.chip--live::before{
  content:'';width:7px;height:7px;border-radius:50%;
  background:var(--white);flex:none;
  animation:pulse-dot 1.6s var(--ease-in-out) infinite;
}
.section--dark .chip,
.foot .chip{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
.section--dark .chip--red{background:var(--red);border-color:var(--red);color:var(--white)}
.section--dark .chip--dark{background:var(--white);border-color:var(--white);color:var(--black)}

/* Klikalny chip (filtr) - te same wymiary, inne stany. */
@media (hover:hover) and (pointer:fine){
  a.chip:hover,button.chip:hover{border-color:var(--ink);color:var(--ink)}
}

.chip.is-active{background:var(--ink);border-color:var(--ink);color:var(--white)}
@media (hover:hover) and (pointer:fine){
  .chip.is-active:hover{color:var(--white)}
}

@keyframes pulse-dot{
  0%,100%{opacity:1;transform:scale(1)}
  50%{opacity:.35;transform:scale(.7)}
}

/* Plakietka MVP - mocna, czerwona, zawsze biały tekst. */
.badge-mvp{
  display:inline-flex;align-items:center;gap:var(--gap-1);
  padding:var(--gap-1) var(--gap-2);
  background:var(--red);
  color:var(--white);
  border-radius:var(--r);
  font-size:.6875rem;
  font-weight:800;
  letter-spacing:.1em;
  text-transform:uppercase;
  line-height:1.3;
  white-space:nowrap;
}
.badge-mvp svg{width:13px;height:13px;flex:none}

/* HDCP - neutralna, monospace, bo obok zawsze stoi liczba. */
.badge-hdcp{
  display:inline-flex;align-items:center;gap:var(--gap-1);
  padding:var(--gap-0) var(--gap-2);
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper-2);
  color:var(--ink-2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.75rem;
  font-weight:600;
  line-height:1.35;
  white-space:nowrap;
}
.badge-hdcp--zero{color:var(--ink-3);opacity:.75}
.badge-hdcp--waived{
  border-style:dashed;color:var(--ink-3);
  text-decoration:line-through;text-decoration-thickness:1px;
}
.section--dark .badge-hdcp,
.foot .badge-hdcp{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}

/* Strzałka trendu w tabeli (pozycja w górę / w dół). */
.trend{display:inline-flex;align-items:center;width:14px;height:14px}
.trend svg{width:14px;height:14px}
.trend--up{color:var(--ok)}
.trend--down{color:var(--red)}
.trend--same{color:var(--ink-3)}
.trend--new{color:var(--red-700)}


/* ============================================================
   08. KARTY I KAFLE LICZBOWE
   ------------------------------------------------------------
   Jeden styl pojemnika w całym serwisie: tło --paper, obwódka
   1px --line, promień --r-2 i odstęp wewnętrzny --card-pad.
   Ten sam zestaw obowiązuje .card, .stat, .tile, .match,
   .news-card, .player-card i .empty - dzięki temu karty z różnych
   sekcji stoją obok siebie bez różnicy grubości i wcięć.
   Grubsza obwódka (2px) i czerwień są zarezerwowane dla jednego
   wyróżnionego elementu w sekcji (.card--red, .match--featured).
   ============================================================ */
.card{
  display:flex;flex-direction:column;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  overflow:hidden;
  transition:border-color .18s var(--ease-out),translate .18s var(--ease-out);
}
.card--flat{border-radius:0}
.card--tint{background:var(--paper-2)}
.card--dark{background:var(--black);border-color:var(--black);color:var(--white)}
.card--dark .card__head{border-bottom-color:var(--line-dark)}
.card--dark .card__foot{border-top-color:var(--line-dark);background:transparent}
.card--red{border-color:var(--red);border-width:2px}
/* Karta jako link - obwódka ciemnieje, całość unosi się o 2px. */
@media (hover:hover) and (pointer:fine){
  a.card:hover,.card--link:hover{border-color:var(--ink);translate:0 -2px}
}

.card__head{
  display:flex;align-items:center;justify-content:space-between;gap:var(--gap-3);
  padding:var(--card-pad-sm) var(--card-pad);
  border-bottom:1px solid var(--line);
}
.card__head h2,.card__head h3{font-size:1.05rem;letter-spacing:-.02em}
.card__body{padding:var(--card-pad);flex:1 1 auto}
.card__body--tight{padding:var(--card-pad-sm)}
.card__foot{
  padding:var(--card-pad-sm) var(--card-pad);
  border-top:1px solid var(--line);
  background:var(--paper-2);
  display:flex;align-items:center;justify-content:space-between;gap:var(--gap-3);
  font-size:.875rem;
}

/* Kafel liczbowy - wielka liczba monospace nad etykietą. */
.stat{
  display:flex;flex-direction:column;gap:var(--gap-1);
  padding:var(--card-pad);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  min-width:0;
}
.stat__val{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-weight:700;
  font-size:clamp(1.9rem,4.6vw,2.9rem);
  line-height:1;
  letter-spacing:-.045em;
  color:var(--ink);
  /* Liczba nigdy nie zawija - przy skrajnie wąskim ekranie skaluje się w dół. */
  white-space:nowrap;
}
.stat__val sup,.stat__unit{
  font-size:.42em;font-weight:600;letter-spacing:0;
  color:var(--ink-3);margin-left:.15em;vertical-align:super;
}
.stat__label{
  font-size:.75rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.12em;
  color:var(--ink-3);
}
.stat__note{font-size:.8125rem;color:var(--ink-3);margin-top:var(--gap-0)}
.stat--red .stat__val{color:var(--red)}
.stat--dark{background:var(--black);border-color:var(--black)}
.stat--dark .stat__val{color:var(--white)}
.stat--dark .stat__label{color:var(--on-dark-2)}
/* Wariant „paskowy": czerwony blok koloru z boku zamiast cienia. */
.stat--bar{border-left:4px solid var(--red);border-radius:0 var(--r-2) var(--r-2) 0}
.section--dark .stat{background:transparent;border-color:var(--line-dark)}
.section--dark .stat__val{color:var(--white)}
.section--dark .stat__label{color:var(--on-dark-2)}

/* Rząd kafli statystyk - na mobile 2 kolumny, nie jedna,
   bo liczby są krótkie i pion marnowałby ekran. */
.stat-row{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr));
  gap:var(--gap-4);
}


/* ============================================================
   09. TABELE
   ------------------------------------------------------------
   Każda tabela MUSI stać w .table-scroll (SPEC §6.4) - dopiero
   wtedy sticky kolumny mają względem czego się przykleić,
   a strona nie rozpycha się w bok.
   ============================================================ */
.table-scroll{
  position:relative;
  border:1px solid var(--line);
  border-radius:var(--r-2);
  background:var(--paper);
}
/* Wariant bez ramki - gdy tabela stoi już wewnątrz .card. */
.table-scroll--bare{border:0;border-radius:0;background:transparent}
.table-scroll--dark{background:var(--black);border-color:var(--line-dark)}

.tbl{
  width:100%;
  min-width:520px;              /* poniżej tej szerokości kolumny robią się nieczytelne */
  font-size:.9375rem;
  background:var(--paper);
}
.tbl caption{
  caption-side:top;
  text-align:left;
  padding:var(--gap-4) var(--cell-x);
  font-weight:800;
  letter-spacing:-.02em;
  color:var(--ink);
}
.tbl thead th{
  padding:var(--cell-y) var(--cell-x);
  background:var(--paper-2);
  border-bottom:2px solid var(--ink);
  font-size:.6875rem;
  font-weight:800;
  text-transform:uppercase;
  letter-spacing:.1em;
  color:var(--ink-2);
  text-align:left;
  white-space:nowrap;
  vertical-align:middle;
}
.tbl tbody td{
  padding:var(--cell-y) var(--cell-x);
  border-bottom:1px solid var(--line-2);
  vertical-align:middle;
}
.tbl tbody tr:last-child td{border-bottom:0}
@media (hover:hover) and (pointer:fine){
  .tbl tbody tr:hover{background:var(--paper-2)}
}

.tbl th.is-num,.tbl td.is-num,
.tbl th.num,.tbl td.num{
  text-align:right;
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
}
.tbl th.is-center,.tbl td.is-center{text-align:center}
.tbl tfoot td{
  padding:var(--cell-y) var(--cell-x);
  border-top:2px solid var(--ink);
  font-weight:700;
  background:var(--paper-2);
}
.tbl--compact{font-size:.875rem;min-width:420px;--cell-y:var(--gap-2);--cell-x:var(--gap-2)}
.tbl--fixed{table-layout:fixed}

/* Wiersz-link: cała linia klikalna, ale bez zagnieżdżania <a> w <a>. */
.tbl tbody tr.is-clickable{cursor:pointer}
@media (hover:hover) and (pointer:fine){
  .tbl tbody tr.is-clickable:hover{background:var(--red-050)}
}

.tbl tbody tr.is-muted td{color:var(--ink-3)}
.tbl tbody tr.is-highlight{background:var(--red-050)}
@media (hover:hover) and (pointer:fine){
  .tbl tbody tr.is-highlight:hover{background:#fbdedc}
}

/* Sortowanie po stronie klienta ([data-sort] w <th>, SPEC §6.6.8). */
.tbl th[data-sort]{cursor:pointer;user-select:none;position:relative;padding-right:var(--gap-5)}
@media (hover:hover) and (pointer:fine){
  .tbl th[data-sort]:hover{color:var(--ink)}
}

.tbl th[data-sort]::after{
  content:'';
  position:absolute;right:.5rem;top:50%;
  width:0;height:0;
  border-left:4px solid transparent;
  border-right:4px solid transparent;
  border-top:5px solid currentColor;
  opacity:.28;
  translate:0 -50%;
}
.tbl th[aria-sort="ascending"]::after{
  border-top:0;border-bottom:5px solid var(--red);opacity:1;
}
.tbl th[aria-sort="descending"]::after{border-top-color:var(--red);opacity:1}

/* --- Tabela ligowa ------------------------------------------
   Kolumny: poz. | drużyna | M | Z | R | P | pkt | małe pkt | HDCP | forma
   Dwie pierwsze kolumny są przyklejone przy przewijaniu w poziomie -
   bez własnego tła prześwitywałyby przez przesuwane liczby. -- */
.tbl--standings{
  --pos-w:52px;
  min-width:760px;
}
.tbl--standings td{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
}
.tbl--standings thead th{font-family:var(--font)}

.tbl--standings th:first-child,
.tbl--standings td:first-child{
  position:sticky;left:0;z-index:2;
  width:var(--pos-w);min-width:var(--pos-w);
  padding-inline:var(--gap-2);
  text-align:center;
  background:var(--paper);
}
.tbl--standings thead th:first-child{background:var(--paper-2)}
.tbl--standings th:nth-child(2),
.tbl--standings td:nth-child(2){
  position:sticky;left:var(--pos-w);z-index:2;
  min-width:190px;
  background:var(--paper);
  /* Płaska krawędź zamiast cienia - sygnalizuje odcięcie od przewijanej reszty. */
  border-right:1px solid var(--line);
  font-family:var(--font);
}
.tbl--standings thead th:nth-child(2){background:var(--paper-2)}
/* Podświetlenie wiersza musi objąć także kolumny przyklejone. */
@media (hover:hover) and (pointer:fine){
  .tbl--standings tbody tr:hover td:first-child,.tbl--standings tbody tr:hover td:nth-child(2){background:var(--paper-2)}
}

.tbl--standings tbody tr.is-highlight td:first-child,
.tbl--standings tbody tr.is-highlight td:nth-child(2){background:var(--red-050)}

.tbl--standings td.is-pts{
  font-weight:800;
  font-size:1.0625rem;
  color:var(--ink);
}
.tbl--standings td.is-pins{color:var(--ink-2)}
.tbl--standings td.is-hdcp{color:var(--ink-3)}
.tbl--standings .is-form{width:1%;white-space:nowrap;padding-left:var(--gap-4)}

/* Kreska strefy: linia pod ostatnią drużyną z „górnej" części tabeli. */
.tbl--standings tbody tr.is-cut td{border-bottom:2px dashed var(--line)}

/* --- Numer pozycji ------------------------------------------
   Kwadrat z liczbą. Miejsca 1-3 dostają płaskie bloki koloru. */
.pos{
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;
  border-radius:var(--r);
  background:var(--paper-2);
  border:1px solid var(--line);
  color:var(--ink-2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-weight:700;
  font-size:.875rem;
  line-height:1;
}
.pos--1{background:var(--red);border-color:var(--red);color:var(--white)}
.pos--2{background:var(--black);border-color:var(--black);color:var(--white)}
.pos--3{background:var(--ink-3);border-color:var(--ink-3);color:var(--white)}
.pos--lg{width:40px;height:40px;font-size:1.05rem;border-radius:var(--r-2)}
.pos--sm{width:24px;height:24px;font-size:.75rem}

/* --- Komórka drużyny ---------------------------------------- */
.team-cell{
  display:flex;align-items:center;gap:var(--gap-3);
  min-width:0;
}
.team-cell__logo{
  width:30px;height:30px;flex:none;
  border-radius:var(--r);
  object-fit:contain;
  background:var(--paper-2);
  border:1px solid var(--line-2);
}
/* Zastępnik loga: inicjał na kolorze drużyny (ustawianym inline). */
.team-cell__logo--initial{
  display:flex;align-items:center;justify-content:center;
  background:var(--black);color:var(--white);
  font-weight:800;font-size:.8125rem;line-height:1;
  border-color:transparent;
}
.team-cell__name{
  font-weight:700;
  letter-spacing:-.01em;
  color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  min-width:0;
}
@media (hover:hover) and (pointer:fine){
  a.team-cell:hover .team-cell__name{color:var(--red-600)}
}

.team-cell__sub{
  display:block;
  font-family:var(--font);
  font-size:.75rem;font-weight:600;
  color:var(--ink-3);
  letter-spacing:0;
}
/* Skrót nazwy - widoczny dopiero na wąskich ekranach (patrz §23). */
.team-cell__short{display:none}

/* --- Forma (ostatnie 5 meczów) ------------------------------ */
.form-strip{display:inline-flex;gap:var(--gap-0);align-items:center}
.form-strip__i{
  display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;flex:none;
  border-radius:2px;
  font-family:var(--font);
  font-size:.6875rem;font-weight:800;line-height:1;
  color:var(--white);
  background:var(--ink-3);
}
.form-strip__i--w{background:var(--ok)}
.form-strip__i--d{background:var(--ink-3)}
.form-strip__i--l{background:var(--red)}
.form-strip__i--n{background:var(--paper-3);color:var(--ink-3)}

/* Kolumny drugorzędne (R, P, małe pkt, HDCP) - na wąskich ekranach
   znikają w media query z §23. Tu tylko wyrównanie liczb. */
.tbl__col--opt{text-align:right}

/* Podpowiedź o przewijaniu w bok. Domyślnie ukryta - moduł 18 skryptu dokłada
   klasę .is-scrollable tylko tym tabelom, które naprawdę wystają poza kontener,
   i zdejmuje ją po pierwszym przesunięciu. */
.table-hint{
  display:none;
  align-items:center;gap:var(--gap-2);
  margin-top:var(--gap-2);
  font-size:.75rem;color:var(--ink-3);
}
.table-hint svg{width:14px;height:14px}


/* ============================================================
   10. MECZ - karta wyniku
   ------------------------------------------------------------
   Siatka [drużyna][wynik][drużyna]. Kolumna środkowa ma stałą,
   wąską szerokość, boczne minmax(0,1fr) - dzięki temu długie
   nazwy skracają się wielokropkiem zamiast rozpychać kartę.
   ============================================================ */
.match{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
  align-items:center;
  /* Kolumna środkowa (wynik) musi zostać wąska także przy 320px, dlatego
     dolna granica schodzi tu o dwa stopnie niżej niż wcięcie karty. */
  gap:clamp(var(--gap-2),2vw,var(--gap-5));
  padding:var(--card-pad);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  position:relative;
  transition:border-color .18s var(--ease-out),translate .18s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  a.match:hover,.match--link:hover{border-color:var(--ink);translate:0 -2px}
}

/* Pasek nad siatką: kolejka, data, tor, status. */
.match__meta{
  grid-column:1 / -1;
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--gap-2) var(--gap-3);
  margin-bottom:var(--gap-1);
  font-size:.75rem;
  font-weight:700;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--ink-3);
  min-width:0;
}
.match__meta time{font-family:var(--mono);letter-spacing:0;text-transform:none}
.match__meta-sep{opacity:.4}

.match__team{
  display:flex;align-items:center;gap:var(--gap-3);
  min-width:0;
}
/* Gospodarze wyrównani do lewej, goście lustrzanie do prawej. */
.match__team--away{flex-direction:row-reverse;text-align:right}
.match__logo{
  width:44px;height:44px;flex:none;
  object-fit:contain;
  border-radius:var(--r);
  background:var(--paper-2);
  border:1px solid var(--line-2);
}
.match__logo--initial{
  display:flex;align-items:center;justify-content:center;
  background:var(--black);color:var(--white);
  font-weight:800;font-size:1rem;line-height:1;border-color:transparent;
}
.match__name{
  font-weight:800;
  font-size:clamp(.9375rem,1.6vw,1.0625rem);
  letter-spacing:-.02em;
  line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  min-width:0;
}
.match__hdcp{
  display:block;
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.75rem;font-weight:600;
  color:var(--ink-3);
  letter-spacing:0;
}
/* Zwycięzca wyróżniony grubością, nie kolorem - kolor rezerwujemy dla statusu. */
.match__team.is-winner .match__name{color:var(--ink)}
.match__team:not(.is-winner) .match__name{color:var(--ink-2)}
.match--played .match__team:not(.is-winner){opacity:.72}

.match__score{
  display:flex;align-items:center;justify-content:center;
  gap:var(--gap-1);
  padding:var(--gap-1) var(--gap-2);
  min-width:96px;
  border:2px solid var(--ink);
  border-radius:var(--r);
  background:var(--paper);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-weight:700;
  font-size:clamp(1.1rem,2.6vw,1.5rem);
  line-height:1.1;
  letter-spacing:-.03em;
  white-space:nowrap;
}
.match__score-sep{color:var(--ink-3);font-weight:400}
.match__score-side.is-winner{color:var(--red)}
/* Mecz jeszcze nierozegrany - zamiast wyniku godzina rozpoczęcia. */
.match__score--soon{
  border-color:var(--line);
  font-size:1.0625rem;
  color:var(--ink-2);
  font-weight:600;
}
.match__score--wo{border-color:var(--warn);font-size:.9375rem}

/* Rozbicie wyniku pod kreską: surowe + HDCP + bonus − kara. */
.match__detail{
  grid-column:1 / -1;
  margin-top:var(--gap-3);padding-top:var(--gap-3);
  border-top:1px solid var(--line-2);
  display:flex;flex-wrap:wrap;gap:var(--gap-1) var(--gap-4);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.75rem;
  color:var(--ink-3);
}
.match__detail b{color:var(--ink-2);font-weight:700}

/* --- Warianty stanu ---------------------------------------- */
.match--live{border-color:var(--red);border-width:2px}
.match--live .match__score{border-color:var(--red);color:var(--red)}
/* Pulsujący punkt „na żywo" w rogu karty. */
.match--live::after{
  content:'';
  position:absolute;top:var(--gap-3);right:var(--gap-3);
  width:9px;height:9px;border-radius:50%;
  background:var(--red);
  animation:pulse-dot 1.6s var(--ease-in-out) infinite;
}

.match--featured{
  border:2px solid var(--red);
  padding-top:calc(var(--card-pad) + var(--gap-2));
}
/* Etykieta „MECZ KOLEJKI" wchodzi w górną krawędź ramki. */
.match--featured::before{
  content:'Mecz kolejki';
  position:absolute;top:0;left:var(--card-pad);
  translate:0 -50%;
  padding:var(--gap-0) var(--gap-2);
  background:var(--red);
  color:var(--white);
  font-size:.625rem;
  font-weight:800;
  letter-spacing:.14em;
  text-transform:uppercase;
  line-height:1.4;
  border-radius:2px;
}
.match--postponed{border-style:dashed}
.match--postponed .match__score{border-style:dashed;color:var(--ink-3)}
.match--dark{background:var(--black);border-color:var(--line-dark);color:var(--white)}
.match--dark .match__score{background:transparent;border-color:var(--white);color:var(--white)}
.match--dark .match__meta,.match--dark .match__hdcp{color:var(--on-dark-2)}
.match--dark .match__team:not(.is-winner) .match__name{color:var(--on-dark)}

/* Lista meczów w kolejce. */
.match-list{display:grid;gap:var(--gap-3)}
/* Pauza w kolejce (nieparzysta liczba drużyn). */
.match--bye{
  grid-template-columns:1fr;
  justify-items:center;text-align:center;
  border-style:dashed;color:var(--ink-3);
}
.match--bye .match__team{justify-content:center}


/* ============================================================
   11. NAWIGACJA KOLEJEK (.round-nav)
   ------------------------------------------------------------
   Poziomy pasek przewijalny ze scroll-snapem. Strzałki po bokach
   są elementami rodzeństwa, żeby nie jechały razem z taśmą.
   ============================================================ */
.round-nav-wrap{
  position:relative;
  display:flex;align-items:center;gap:var(--gap-2);
  margin-bottom:var(--gap-5);
}
.round-nav{
  display:flex;
  gap:var(--gap-2);
  flex:1 1 auto;
  min-width:0;
  overflow-x:auto;
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;
  scroll-padding-inline:var(--gap-2);
  padding:var(--gap-1);
  scrollbar-width:thin;
}
.round-nav::-webkit-scrollbar{height:6px}
.round-nav::-webkit-scrollbar-thumb{background:var(--line);border:0}
.round-nav::-webkit-scrollbar-track{background:transparent}

.round-nav__item{
  display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--gap-0);
  flex:none;
  min-width:66px;
  padding:var(--gap-2) var(--gap-3);
  scroll-snap-align:center;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
  color:var(--ink-2);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-weight:700;
  font-size:.9375rem;
  line-height:1.15;
  white-space:nowrap;
  transition:background-color .16s var(--ease-out),border-color .16s var(--ease-out),color .16s var(--ease-out);
}
.round-nav__item small{
  font-family:var(--font);
  font-size:.625rem;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);
}
@media (hover:hover) and (pointer:fine){
  .round-nav__item:hover{border-color:var(--ink);color:var(--ink)}
}

.round-nav__item.is-active{
  background:var(--red);border-color:var(--red);color:var(--white);
}
.round-nav__item.is-active small{color:rgba(255,255,255,.78)}
.round-nav__item.is-done{background:var(--paper-2)}
.round-nav__item.is-live{border-color:var(--red);color:var(--red)}
.round-nav__item[aria-disabled="true"]{opacity:.4;pointer-events:none}

.round-nav__arrow{
  flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
  color:var(--ink-2);
  transition:background-color .16s var(--ease-out),color .16s var(--ease-out),
             border-color .16s var(--ease-out),transform .16s var(--ease-out);
}
.round-nav__arrow:active{transform:scale(.97)}
.round-nav__arrow svg{width:18px;height:18px}
@media (hover:hover) and (pointer:fine){
  .round-nav__arrow:hover{background:var(--ink);border-color:var(--ink);color:var(--white)}
}

.round-nav__arrow[disabled]{opacity:.3;pointer-events:none}

.section--dark .round-nav__item,
.section--dark .round-nav__arrow{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
.section--dark .round-nav__item.is-active{background:var(--red);border-color:var(--red);color:var(--white)}


/* ============================================================
   12. AKTUALNOŚCI (.news-card)
   ============================================================ */
.news-card{
  display:flex;flex-direction:column;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  overflow:hidden;
  min-width:0;
  transition:border-color .18s var(--ease-out),translate .18s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .news-card:hover{border-color:var(--ink);translate:0 -2px}
}

.news-card__img{
  position:relative;
  aspect-ratio:16/9;
  background:var(--paper-3);
  overflow:hidden;
  border-bottom:1px solid var(--line);
}
.news-card__img img{
  width:100%;height:100%;
  object-fit:cover;
  transition:scale .5s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .news-card:hover .news-card__img img{scale:1.03}
}

/* Zastępnik, gdy wpis nie ma okładki - płaski wzór torów. */
.news-card__img--empty{
  background:
    repeating-linear-gradient(90deg,var(--paper-3) 0 14px,var(--paper-2) 14px 28px);
}
/* Etykieta kategorii jest czarna, nie czerwona: w siatce wpisów czerwone
   plakietki zapalałyby się przy każdej karcie naraz. Czerwony wariant
   (.news-card__tag--red) zostaje dla jednego wyróżnionego wpisu. */
.news-card__tag{
  position:absolute;left:var(--gap-3);top:var(--gap-3);
  padding:var(--gap-0) var(--gap-2);
  background:var(--black);color:var(--white);
  font-size:.625rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;
  border-radius:2px;
}
.news-card__tag--red{background:var(--red)}
.news-card__body{
  display:flex;flex-direction:column;gap:var(--gap-2);
  padding:var(--card-pad);
  flex:1 1 auto;
}
.news-card__date{
  font-family:var(--mono);
  font-size:.75rem;font-weight:600;
  color:var(--ink-3);
  letter-spacing:.02em;
}
.news-card__title{
  font-size:1.125rem;
  font-weight:800;
  line-height:1.22;
  letter-spacing:-.025em;
}
@media (hover:hover) and (pointer:fine){
  .news-card:hover .news-card__title{color:var(--red-600)}
}

.news-card__excerpt{
  font-size:.9375rem;
  color:var(--ink-2);
  line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
  overflow:hidden;
}
/* „Czytaj dalej" powtarza się przy każdej karcie - neutralne, czerwień
   dopiero pod kursorem. */
.news-card__more{
  margin-top:auto;padding-top:var(--gap-3);
  display:inline-flex;align-items:center;gap:var(--gap-2);
  font-size:.8125rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-2);
  transition:color .16s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .news-card:hover .news-card__more{color:var(--red-700)}
}

.news-card__more svg{width:15px;height:15px}

/* Wariant poziomy - wpis przypięty na stronie głównej. */
.news-card--wide{flex-direction:row}
.news-card--wide .news-card__img{
  flex:0 0 46%;aspect-ratio:auto;border-bottom:0;border-right:1px solid var(--line);
}
.news-card--wide .news-card__body{padding:var(--gap-6)}
.news-card--wide .news-card__title{font-size:clamp(1.25rem,2.4vw,1.75rem)}
@media (max-width:760px){
  .news-card--wide{flex-direction:column}
  .news-card--wide .news-card__img{
    flex:none;aspect-ratio:16/9;border-right:0;border-bottom:1px solid var(--line);
  }
}


/* ============================================================
   13. ZAWODNICY I RANKINGI
   ============================================================ */
.player-card{
  display:flex;flex-direction:column;align-items:center;
  gap:var(--gap-2);
  padding:var(--card-pad);
  text-align:center;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  min-width:0;
  transition:border-color .18s var(--ease-out),translate .18s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .player-card:hover{border-color:var(--ink);translate:0 -2px}
}

.player-card__photo{
  width:84px;height:84px;flex:none;
  border-radius:50%;
  object-fit:cover;
  background:var(--paper-2);
  border:2px solid var(--line);
}
.player-card__photo--initial{
  display:flex;align-items:center;justify-content:center;
  background:var(--black);color:var(--white);
  border-color:var(--black);
  font-weight:800;font-size:1.5rem;letter-spacing:-.02em;line-height:1;
}
@media (hover:hover) and (pointer:fine){
  .player-card:hover .player-card__photo{border-color:var(--ink)}
}

.player-card__name{
  font-weight:800;font-size:1.0625rem;
  letter-spacing:-.02em;line-height:1.2;
}
.player-card__nick{
  font-family:'Caveat',cursive;
  font-size:1.15rem;line-height:1;
  color:var(--ink-2);
}
.player-card__team{
  font-size:.8125rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);
}
.player-card__stats{
  display:flex;flex-wrap:wrap;justify-content:center;gap:var(--gap-1) var(--gap-4);
  margin-top:var(--gap-1);padding-top:var(--gap-3);
  border-top:1px solid var(--line-2);
  width:100%;
}
.player-card__stat{
  display:flex;flex-direction:column;align-items:center;line-height:1.15;
}
.player-card__stat b{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:1.05rem;font-weight:700;
}
.player-card__stat span{
  font-size:.625rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3);
}
.player-card--dark{background:var(--black);border-color:var(--black);color:var(--white)}
.player-card--dark .player-card__team{color:var(--on-dark-2)}
.player-card--dark .player-card__stats{border-top-color:var(--line-dark)}

/* --- Wiersz rankingu ---------------------------------------- */
.rank-row{
  display:grid;
  grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;
  gap:var(--gap-3);
  padding:var(--gap-3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r);
  min-width:0;
  transition:border-color .16s var(--ease-out),background-color .16s var(--ease-out);
}
.rank-row+.rank-row{margin-top:var(--gap-2)}
@media (hover:hover) and (pointer:fine){
  a.rank-row:hover{border-color:var(--ink);background:var(--paper-2)}
}

.rank-row__pos{
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;flex:none;
  border-radius:var(--r);
  background:var(--paper-2);
  border:1px solid var(--line);
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;font-size:.875rem;line-height:1;
  color:var(--ink-2);
}
.rank-row:first-child .rank-row__pos,
.rank-row__pos.pos--1{background:var(--red);border-color:var(--red);color:var(--white)}
.rank-row__main{min-width:0}
.rank-row__name{
  font-weight:700;letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.rank-row__sub{
  font-size:.75rem;color:var(--ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.rank-row__score{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;font-size:1.15rem;
  letter-spacing:-.03em;
  text-align:right;
  white-space:nowrap;
}
.rank-row__score small{
  display:block;
  font-family:var(--font);
  font-size:.625rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);
}
.rank-row--dark{background:transparent;border-color:var(--line-dark);color:var(--white)}
.rank-row--dark .rank-row__pos{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
.rank-row--dark .rank-row__sub{color:var(--on-dark-2)}

/* Zakładki rankingów (role="tablist"). */
.tabs{
  display:flex;gap:var(--gap-1);
  overflow-x:auto;overscroll-behavior-x:contain;
  border-bottom:1px solid var(--line);
  margin-bottom:var(--gap-5);
  scrollbar-width:none;
}
.tabs::-webkit-scrollbar{display:none}
.tabs__btn{
  flex:none;
  padding:var(--gap-3) var(--gap-4);
  border-bottom:3px solid transparent;
  font-weight:700;font-size:.9375rem;
  color:var(--ink-3);
  white-space:nowrap;
  transition:color .16s var(--ease-out),border-color .16s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .tabs__btn:hover{color:var(--ink)}
}

.tabs__btn[aria-selected="true"]{color:var(--ink);border-bottom-color:var(--red)}
.tabs__panel[hidden]{display:none}
.section--dark .tabs{border-bottom-color:var(--line-dark)}
.section--dark .tabs__btn{color:var(--on-dark-2)}
.section--dark .tabs__btn[aria-selected="true"]{color:var(--white)}


/* ============================================================
   14. OKRUSZKI, PAGINACJA, KOMUNIKATY
   ============================================================ */
.crumbs{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--gap-1) var(--gap-2);
  padding-block:var(--gap-3);
  font-size:.8125rem;
  color:var(--ink-3);
}
.crumbs ol{display:contents}
.crumbs li{display:inline-flex;align-items:center;gap:var(--gap-2);min-width:0}
.crumbs li+li::before{
  content:'';
  width:5px;height:5px;flex:none;
  border-top:1px solid currentColor;
  border-right:1px solid currentColor;
  rotate:45deg;
  opacity:.55;
}
.crumbs a{font-weight:600;color:var(--ink-2)}
@media (hover:hover) and (pointer:fine){
  .crumbs a:hover{color:var(--red-600)}
}

.crumbs [aria-current="page"]{
  color:var(--ink);font-weight:700;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44ch;
}
.crumbs--dark{color:var(--on-dark-2)}
.crumbs--dark a{color:var(--on-dark)}
@media (hover:hover) and (pointer:fine){
  .crumbs--dark a:hover{color:var(--white)}
}

.crumbs--dark [aria-current="page"]{color:var(--white)}

.pagination{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:var(--gap-1);
  margin-top:var(--gap-7);
}
.pagination a,.pagination span{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:42px;height:42px;
  padding-inline:var(--gap-3);
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;font-size:.9375rem;
  color:var(--ink-2);
  transition:background-color .16s var(--ease-out),border-color .16s var(--ease-out),
             color .16s var(--ease-out),transform .16s var(--ease-out);
}
.pagination a:active{transform:scale(.97)}
@media (hover:hover) and (pointer:fine){
  .pagination a:hover{background:var(--ink);border-color:var(--ink);color:var(--white)}
}

.pagination [aria-current="page"]{
  background:var(--red);border-color:var(--red);color:var(--white);
}
.pagination .is-gap{
  border-color:transparent;background:transparent;color:var(--ink-3);min-width:26px;
}
.pagination .is-nav{font-family:var(--font);letter-spacing:.02em}
.pagination .is-disabled{opacity:.35;pointer-events:none}

/* --- Komunikaty ---------------------------------------------
   Płaski blok koloru z lewej zamiast tła całego paska. -------- */
.flash{
  display:flex;align-items:flex-start;gap:var(--gap-3);
  padding:var(--gap-3) var(--gap-4);
  border:1px solid var(--line);
  border-left:4px solid var(--ink-3);
  border-radius:0 var(--r) var(--r) 0;
  background:var(--paper-2);
  font-size:.9375rem;
  line-height:1.5;
  margin-bottom:var(--gap-4);
}
.flash svg{width:19px;height:19px;flex:none;margin-top:var(--gap-0)}
.flash strong{display:block;font-weight:800;letter-spacing:-.01em}
.flash--ok{border-left-color:var(--ok);background:rgba(31,138,76,.07);color:#14522d}
.flash--err{border-left-color:var(--err);background:var(--red-050);color:var(--red-700)}
.flash--info{border-left-color:var(--ink);background:var(--paper-2);color:var(--ink-2)}
.flash--warn{border-left-color:var(--warn);background:rgba(200,121,26,.09);color:#7d4c0d}
.flash__close{
  margin-left:auto;flex:none;
  width:26px;height:26px;
  display:inline-flex;align-items:center;justify-content:center;
  color:inherit;opacity:.6;
}
@media (hover:hover) and (pointer:fine){
  .flash__close:hover{opacity:1}
}

/* --- Stan pusty ---------------------------------------------
   Zawsze te same trzy elementy w tej samej kolejności:
     ikona (w kwadracie) → tytuł → jedno zdanie wyjaśniające,
   opcjonalnie .empty__actions z jednym przyciskiem.
   Przerywana ramka, nie karta - brak treści nie ma udawać treści.
   Markup:
     <div class="empty">
       <span class="empty__ico">SVG</span>
       <p class="empty__title">Brak wyników</p>
       <p>Kolejka jeszcze się nie odbyła. Wyniki pojawią się…</p>
       <div class="empty__actions"><a class="btn btn--line btn--sm">…</a></div>
     </div>
   ------------------------------------------------------------ */
.empty{
  display:flex;flex-direction:column;align-items:center;
  gap:var(--gap-2);
  padding:var(--gap-7) var(--card-pad);
  text-align:center;
  border:1px dashed var(--line);
  border-radius:var(--r-2);
  background:var(--paper-2);
  color:var(--ink-3);
}
/* Ikona w kwadracie - ten sam znak wielkości w każdym pustym stanie.
   Sam <svg> bez opakowania też działa (starsze fragmenty markupu). */
.empty__ico{
  display:inline-flex;align-items:center;justify-content:center;
  width:46px;height:46px;flex:none;
  margin-bottom:var(--gap-0);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  background:var(--paper);
  color:var(--ink-3);
}
.empty__ico svg{width:22px;height:22px;opacity:1}
.empty>svg{width:30px;height:30px;opacity:.45}
.empty__title{
  font-size:1.0625rem;font-weight:800;
  letter-spacing:-.02em;color:var(--ink);
}
.empty p{max-width:52ch;font-size:.9375rem;line-height:1.5}
.empty__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--gap-2);margin-top:var(--gap-2)}
.empty--sm{padding:var(--gap-6) var(--card-pad-sm);gap:var(--gap-1)}
.empty--sm .empty__ico{width:36px;height:36px}
.empty--sm .empty__ico svg{width:18px;height:18px}
.empty--sm .empty__title{font-size:.9375rem}
.section--dark .empty,
.card--dark .empty{background:transparent;border-color:var(--line-dark);color:var(--on-dark-2)}
.section--dark .empty__ico{background:transparent;border-color:var(--line-dark);color:var(--on-dark-2)}
.section--dark .empty__title{color:var(--white)}

/* --- Stan ładowania -----------------------------------------
   .is-loading zakłada się na pojemnik, który czeka na dane
   (tabela, lista, kafle). Treść pod spodem zostaje na miejscu -
   przygasza się i przestaje przyjmować kliknięcia, żeby układ nie
   skoczył w chwili podmiany. aria-busy="true" na tym samym
   elemencie mówi to samo czytnikowi ekranu.
   ------------------------------------------------------------ */
.is-loading{
  position:relative;
  pointer-events:none;
  user-select:none;
}
.is-loading>*{opacity:.45;transition:opacity .2s var(--ease-out)}
/* Cienki pasek postępu na górnej krawędzi - jedyny ruch w tym stanie.
   Kręcące się kółko nic nie mówi o tym, co się ładuje; pasek na
   krawędzi pojemnika pokazuje przynajmniej GDZIE pojawi się treść. */
.is-loading::after{
  content:'';
  position:absolute;left:0;right:0;top:0;height:2px;
  background:var(--red);
  transform-origin:0 50%;
  animation:load-bar 1.1s var(--ease-in-out) infinite;
}
@keyframes load-bar{
  0%{transform:scaleX(0)}
  50%{transform:scaleX(1)}
  100%{transform:scaleX(0);transform-origin:100% 50%}
}

/* --- Szkielet treści ----------------------------------------
   .skeleton ma ODWZOROWAĆ docelowy układ, a nie go zastąpić: tyle
   samo wierszy, ta sama wysokość, te same szerokości kolumn. Dzięki
   temu podmiana danych nie przesuwa niczego na ekranie.
   Markup:
     <div class="skeleton-list" aria-hidden="true">
       <span class="skeleton skeleton--row"></span>  (× tyle, ile wierszy)
     </div>
   Blok jest dekoracją stanu, więc zawsze aria-hidden="true";
   komunikat dla czytnika niesie aria-busy na pojemniku.
   ------------------------------------------------------------ */
.skeleton{
  display:block;
  background:var(--paper-3);
  border-radius:2px;
  /* Pulsuje sama przezroczystość - bez przesuwanego połysku, który
     na liście dwudziestu wierszy robi z ekranu stroboskop. */
  animation:skeleton-pulse 1.4s var(--ease-in-out) infinite;
}
@keyframes skeleton-pulse{
  0%,100%{opacity:1}
  50%{opacity:.45}
}
.skeleton--line{height:.85rem;margin-block:var(--gap-1)}
.skeleton--line-sm{height:.7rem;width:45%}
.skeleton--title{height:1.4rem;width:60%;margin-bottom:var(--gap-3)}
/* Wiersz tabeli/listy - wysokość zgodna z .tbl tbody td i .rank-row. */
.skeleton--row{height:44px;margin-bottom:1px}
.skeleton--cell{height:1rem}
/* Kafel liczbowy i karta - proporcje jak w .stat i .card. */
.skeleton--stat{height:104px;border-radius:var(--r-2)}
.skeleton--card{height:190px;border-radius:var(--r-2)}
.skeleton--avatar{width:84px;height:84px;border-radius:50%}
.skeleton--thumb{aspect-ratio:16/9;border-radius:var(--r-2)}
.skeleton-list{display:block}
.skeleton-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));
  gap:var(--gap-5);
}
.section--dark .skeleton,
.card--dark .skeleton{background:rgba(255,255,255,.12)}


/* ============================================================
   15. PASEK GÓRNY (.topbar)
   ------------------------------------------------------------
   Wysokość podaje layout w --topbar-h; nagłówek i scroll-padding
   liczą ją razem z --nav-h, więc nie wolno jej „zaszyć" tutaj.
   ============================================================ */
.topbar{
  position:relative;z-index:60;
  background:var(--black);
  color:var(--white);
  font-size:.8125rem;
  border-bottom:1px solid var(--line-dark);
}
.topbar__inner{
  display:flex;align-items:center;justify-content:center;
  gap:var(--gap-2) var(--gap-4);
  min-height:var(--topbar-h);
  padding-block:var(--gap-2);
  text-align:center;
  flex-wrap:wrap;
}
.topbar__text{color:var(--on-dark);font-weight:600}
.topbar__text b,.topbar__text strong{color:var(--white);font-weight:800}
.topbar__link{
  display:inline-flex;align-items:center;gap:var(--gap-1);
  font-weight:800;
  letter-spacing:.04em;
  text-transform:uppercase;
  font-size:.75rem;
  color:var(--white);
  border-bottom:2px solid var(--red);
  padding-bottom:1px;
}
@media (hover:hover) and (pointer:fine){
  .topbar__link:hover{color:var(--white);border-bottom-color:var(--white)}
}

.topbar__link svg{width:14px;height:14px}
.topbar__close{
  position:absolute;right:var(--gap-2);top:50%;translate:0 -50%;
  width:28px;height:28px;
  display:inline-flex;align-items:center;justify-content:center;
  color:var(--on-dark-2);
}
.topbar__close svg{width:15px;height:15px}
@media (hover:hover) and (pointer:fine){
  .topbar__close:hover{color:var(--white)}
}


/* ============================================================
   16. NAGŁÓWEK (.nav)
   ------------------------------------------------------------
   Domyślnie biały pasek z dolną linią. Wariant .nav--over jest
   przezroczysty (leży na ciemnym hero) i dopiero po przewinięciu
   dostaje .is-scrolled - wtedy staje się biały.
   Jedyny box-shadow z rozmyciem w całym arkuszu poza modalami:
   przyklejony pasek musi wizualnie oddzielić się od treści.

   UKŁAD: [logotyp] … [pasek: 5 pozycji] [przycisk] [hamburger]
   Znakiem serwisu jest wyłącznie logotyp - bez nazwy obok, bez skrótu.
   W pasku stoi pięć tras: Tabela, Terminarz, Rankingi, Drużyny,
   Aktualności. Regulamin zszedł do stopki i menu mobilnego, „Start"
   zastępuje logotyp, a „Kontakt" zastępuje przycisk „Zgłoś drużynę"
   (ten sam adres, ta sama intencja).
   Czerwień w nagłówku jest JEDNA - przycisk; dlatego aktywna pozycja
   menu jest podkreślona czernią, nie czerwienią.
   ============================================================ */
.nav{
  position:sticky;top:0;z-index:100;
  background:var(--paper);
  border-bottom:1px solid var(--line);
  transition:background-color .25s var(--ease-out),
             border-color .25s var(--ease-out),
             box-shadow .25s var(--ease-out);
}
.nav__inner{
  display:flex;align-items:center;gap:var(--gap-4);
  min-height:var(--nav-h);
  width:100%;
  max-width:var(--container);
  margin-inline:auto;
  padding-inline:var(--pad-x);
}

/* Znak firmowy - sam logotyp, bez nazwy obok. Prowadzi na stronę
   główną, więc pozycja „Start" w pasku byłaby tym samym linkiem. */
.nav__brand{
  display:inline-flex;align-items:center;
  flex:none;
  margin-right:auto;
  padding:2px;                      /* miejsce na pierścień fokusu */
  border-radius:var(--r);
  min-width:0;
}
/* Wysokość ustala CSS, proporcję - atrybuty width/height w markupie
   (rzeczywiste 1054×946). Logotyp jest biało-czerwony z czarnym
   konturem: czyta się i na białym pasku, i nad ciemnym hero, więc
   nie podkładamy pod niego tła ani nie ruszamy go filtrami. */
.nav__logo{
  height:44px;width:auto;flex:none;
  transition:height .22s var(--ease-out);
}

/* --- Znak wskakujący do paska --------------------------------------
   Na stronach ze znakiem w hero pasek startuje BEZ logotypu - dwa te same
   znaki jeden nad drugim to powtórzenie. Logotyp wjeżdża do paska dopiero
   w chwili, gdy znak z hero wyjeżdża z pola widzenia, i wraca na miejsce
   przy przewijaniu w górę.

   Klasę .nav--logo-defer nadaje skrypt, więc bez JavaScriptu logotyp jest
   widoczny od razu - to jest stan domyślny, nie awaria.

   Miejsce po znaku zostaje zarezerwowane (visibility zamiast display),
   dzięki czemu pozycje pozostałych elementów paska ani drgną.
   visibility, a nie samo opacity: niewidoczny odnośnik nie może zostać
   punktem zatrzymania tabulatora. */
.nav--logo-defer .nav__brand{
  opacity:0;
  visibility:hidden;
  transform:translateY(-10px) scale(.82);
  transform-origin:left center;
  pointer-events:none;
  /* Wyjście szybsze niż wejście; visibility przełącza się dopiero po ruchu. */
  transition:opacity .16s var(--ease-out),
             transform .16s var(--ease-out),
             visibility 0s linear .16s;
}
.nav--logo-defer.nav--logo-in .nav__brand{
  opacity:1;
  visibility:visible;
  transform:none;
  pointer-events:auto;
  transition:opacity .26s var(--ease-out),
             transform .26s var(--ease-out),
             visibility 0s;
}

/* Ruch znika, sam pokaz i ukrycie zostają - tak jak przy pozostałych
   animacjach serwisu. */
@media (prefers-reduced-motion:reduce){
  .nav--logo-defer .nav__brand,
  .nav--logo-defer.nav--logo-in .nav__brand{
    transform:none;
    transition:opacity .2s linear, visibility 0s;
  }
}

/* --- Menu na dużych ekranach -------------------------------- */
.nav__links{display:flex;align-items:center;gap:var(--gap-0);min-width:0}
.nav__link{
  position:relative;
  display:inline-flex;align-items:center;
  padding:var(--gap-2) var(--gap-3);
  border-radius:var(--r);
  font-weight:700;
  font-size:.9375rem;
  letter-spacing:-.01em;
  color:var(--ink-2);
  white-space:nowrap;
  transition:color .16s var(--ease-out),background-color .16s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .nav__link:hover{color:var(--ink);background:var(--paper-2)}
}

/* Aktywna pozycja: płaska kreska pod tekstem, w kolorze tekstu -
   czerwień w nagłówku należy do przycisku „Zgłoś drużynę". */
.nav__link.is-active{color:var(--ink)}
.nav__link.is-active::after{
  content:'';
  position:absolute;left:var(--gap-3);right:var(--gap-3);bottom:var(--gap-0);
  height:2px;background:currentColor;
}

/* --- Prawa strefa: przycisk i hamburger ---------------------- */
.nav__actions{display:flex;align-items:center;gap:var(--gap-2);flex:none}
/* Etykieta przycisku nie może się złamać na dwie linie - stąd
   white-space:nowrap w .btn i krótka nazwa „Zgłoś drużynę". */
/* Aktywna trasa „kontakt" - przycisk jest jej jedyną reprezentacją
   w serwisie, więc to on niesie zaznaczenie (ciemniejsza czerwień). */
.nav__cta.is-active{--btn-bg:var(--red-700);--btn-line:var(--red-700)}
@media (hover:hover) and (pointer:fine){
  .nav__cta.is-active:hover{--btn-bg:var(--red-600);--btn-line:var(--red-600)}
}

/* --- Wariant nad hero --------------------------------------- */
.nav--over{
  background:transparent;
  border-bottom-color:transparent;
  /* Nagłówek leży NA hero - hero rekompensuje to własnym padding-top. */
  position:fixed;left:0;right:0;top:var(--topbar-h);
}
.nav--over .nav__link{color:var(--on-dark)}
@media (hover:hover) and (pointer:fine){
  .nav--over .nav__link:hover{color:var(--white);background:rgba(255,255,255,.1)}
}

.nav--over .nav__link.is-active{color:var(--white)}
.nav--over .nav__burger span{background:var(--white)}
.nav--over .btn--line{--btn-fg:var(--white);--btn-line:var(--white)}
@media (hover:hover) and (pointer:fine){
  .nav--over .btn--line:hover{--btn-bg:var(--white);--btn-fg:var(--black)}
}

/* --- Po przewinięciu ----------------------------------------
   Zmieniamy wyłącznie wygląd, nie sposób pozycjonowania -
   przełączenie sticky→fixed w trakcie przewijania szarpnęłoby
   treścią o wysokość paska. Wyjątkiem jest .nav--over, które
   jest fixed od początku i po prostu wjeżdża pod górną krawędź. */
.nav.is-scrolled{
  background:var(--paper);
  border-bottom-color:var(--line);
  box-shadow:0 1px 14px rgba(1,2,2,.10);
}
.nav--over.is-scrolled{top:0}
.nav.is-scrolled .nav__link{color:var(--ink-2)}
@media (hover:hover) and (pointer:fine){
  .nav.is-scrolled .nav__link:hover{color:var(--ink);background:var(--paper-2)}
}

.nav.is-scrolled .nav__link.is-active{color:var(--ink)}
.nav.is-scrolled .nav__burger span{background:var(--ink)}
.nav.is-scrolled .nav__logo{height:36px}
.nav.is-scrolled .btn--line{--btn-fg:var(--ink);--btn-line:var(--ink)}
@media (hover:hover) and (pointer:fine){
  .nav.is-scrolled .btn--line:hover{--btn-bg:var(--ink);--btn-fg:var(--white)}
}

/* --- Przycisk hamburgera ------------------------------------ */
.nav__burger{
  display:none;
  position:relative;
  width:44px;height:44px;flex:none;
  align-items:center;justify-content:center;
  border:1px solid transparent;
  border-radius:var(--r);
}
.nav__burger span{
  position:absolute;left:11px;
  width:22px;height:2px;
  background:var(--ink);
  transition:translate .22s var(--ease-out),rotate .22s var(--ease-out),opacity .12s linear;
}
.nav__burger span:nth-child(1){translate:0 -6px}
.nav__burger span:nth-child(2){translate:0 0}
.nav__burger span:nth-child(3){translate:0 6px}
.nav__burger{transition:transform .16s var(--ease-out),border-color .16s var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .nav__burger:hover{border-color:var(--line)}
}

.nav__burger:active{transform:scale(.97)}
/* Stan otwarty: górna i dolna kreska tworzą krzyżyk, środkowa znika. */
.nav__burger[aria-expanded="true"] span{background:var(--white)}
.nav__burger[aria-expanded="true"] span:nth-child(1){translate:0 0;rotate:45deg}
.nav__burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav__burger[aria-expanded="true"] span:nth-child(3){translate:0 0;rotate:-45deg}

/* --- Menu mobilne (panel pełnoekranowy) ---------------------- */
.nav__menu{
  position:fixed;inset:0;z-index:95;
  display:flex;flex-direction:column;
  padding:calc(var(--nav-h) + var(--topbar-h) + var(--gap-5)) var(--pad-x) var(--gap-6);
  background:var(--black);
  color:var(--white);
  overflow-y:auto;
  overscroll-behavior:contain;
  opacity:0;
  visibility:hidden;
  translate:0 -12px;
  /* Wyjście szybsze niż wejście: zamknięcie ma zejść z drogi, nie
     odgrywać się jeszcze raz od tyłu. */
  transition:opacity .18s var(--ease-out),translate .18s var(--ease-out),visibility 0s linear .18s;
}
.nav__menu.is-open{
  opacity:1;visibility:visible;translate:0 0;
  transition:opacity .24s var(--ease-out),translate .24s var(--ease-out),visibility 0s linear 0s;
}
.nav__menu-links{display:flex;flex-direction:column}
.nav__menu-link{
  display:flex;align-items:center;justify-content:space-between;gap:var(--gap-4);
  padding:var(--gap-3) 0;
  border-bottom:1px solid var(--line-dark);
  font-size:clamp(1.35rem,6vw,1.85rem);
  font-weight:800;
  letter-spacing:-.035em;
  color:var(--white);
}
@media (hover:hover) and (pointer:fine){
  .nav__menu-link:hover{color:var(--white)}
}

.nav__menu-link svg{width:20px;height:20px;flex:none;opacity:.4}
.nav__menu-link.is-active{color:var(--red)}
.nav__menu-link.is-active svg{opacity:1;color:var(--red)}
/* Pozycje menu nie są numerowane: „01 / TABELA" udaje porządek,
   którego w menu nie ma - kolejność niesie już sama lista. */
.nav__menu-foot{
  margin-top:auto;padding-top:var(--gap-6);
  display:flex;flex-direction:column;gap:var(--gap-3);
}
/* Przycisk zastępuje w menu pozycję „Kontakt", więc niesie jej
   zaznaczenie - tak samo jak .nav__cta w pasku. */
.nav__menu-foot .btn.is-active{--btn-bg:var(--red-700);--btn-line:var(--red-700)}
.nav__menu-meta{
  display:flex;flex-wrap:wrap;gap:var(--gap-1) var(--gap-5);
  font-size:.875rem;
  color:var(--on-dark);
}
@media (hover:hover) and (pointer:fine){
  .nav__menu-meta a:hover{color:var(--white);text-decoration:underline}
}

.nav__menu-secondary{
  display:flex;flex-wrap:wrap;gap:var(--gap-1) var(--gap-4);
  font-size:.8125rem;
  color:var(--on-dark-2);
}


/* ============================================================
   17. HERO
   ------------------------------------------------------------
   Wariant ciemny dostaje płaski wzór torów: powtarzalne pionowe
   pasy o bardzo niskim kontraście. Żadnych gradientów ozdobnych -
   repeating-linear-gradient użyty tu jako wzór, nie jako przejście.
   ============================================================ */
.hero{
  position:relative;
  background:var(--paper);
  border-bottom:1px solid var(--line);
  overflow:hidden;
}

/* --- Tło hero: wnętrze kręgielni ------------------------------------
   Zdjęcie leży pod treścią jako osobna warstwa, nie jako tło sekcji -
   dzięki temu opacity i maska działają wyłącznie na fotografii, a tekst
   i logotyp zachowują pełny kontrast.

   Kompozycja: kadr jest zakotwiczony u dołu i wygaszany maską ku górze.
   Tory zbiegają się w perspektywie i prowadzą wzrok w stronę treści,
   a górna część hero (logotyp, nagłówek) zostaje na czystej bieli.

   Krycie 16% na białym tle daje najciemniejszym partiom zdjęcia około
   #e0e0e0 - tekst #101112 ma na tym ponad 12:1, więc kontrast WCAG
   zostaje z zapasem. */
.hero::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
  /* Zapas dla przeglądarek bez image-set: zwykły JPEG. */
  background-image:url('/assets/img/kregielnia-1280.jpg');
  background-image:-webkit-image-set(
    url('/assets/img/kregielnia-1280.webp') 1x,
    url('/assets/img/kregielnia-1920.webp') 2x);
  background-image:image-set(
    url('/assets/img/kregielnia-1280.webp') type('image/webp') 1x,
    url('/assets/img/kregielnia-1920.webp') type('image/webp') 2x);
  background-size:cover;
  background-position:50% 42%;
  background-repeat:no-repeat;
  opacity:.16;
  /* Lekkie odbarwienie stapia fotografię z płaską identyfikacją serwisu -
     czerwień na stronie ma pochodzić z akcentów, nie z tła. */
  filter:grayscale(.4) contrast(1.04);
  -webkit-mask-image:linear-gradient(to top,#000 0%,#000 30%,rgba(0,0,0,.55) 62%,transparent 94%);
  mask-image:linear-gradient(to top,#000 0%,#000 30%,rgba(0,0,0,.55) 62%,transparent 94%);
}

/* Na wąskich ekranach wystarczy lżejszy plik; kadr przesuwamy tak,
   żeby zbieg torów nie uciekł poza widoczny obszar. */
@media (max-width:760px){
  .hero::before{
    background-image:url('/assets/img/kregielnia-800.webp');
    background-position:52% 46%;
    opacity:.13;
  }
}

/* Hero w wariancie ciemnym: na czerni zdjęcie może być wyraźniejsze,
   bo nie walczy z czytelnością czarnego tekstu. */

/* Użytkownik prosił system o wyższy kontrast - fotografia schodzi z drogi. */
@media (prefers-contrast:more){
  .hero::before{opacity:.07}
}
@media print{
  .hero::before{display:none}
}
.hero__inner{
  position:relative;z-index:1;
  width:100%;max-width:var(--container);
  margin-inline:auto;
  /* Hero oddycha tym samym rytmem co sekcje strony - wcześniej miało
     własne, przypadkowe wartości i pierwszy ekran nie zgrywał się
     z resztą kolumny. */
  padding:var(--sec-y) var(--pad-x);
}
/* Hero pod przezroczystym nagłówkiem musi zrobić miejsce na pasek. */
.hero--over .hero__inner{
  padding-top:calc(var(--nav-h) + var(--topbar-h) + var(--sec-y));
}
/* --- Logotyp w hero ----------------------------------------
   Znak firmowy otwiera pierwszy ekran i jest ZNACZNIE większy niż
   ten w pasku nawigacji (44px): 112-208px wysokości. Szerokość
   zostaje auto, więc proporcja 1054x946 (1,114:1) trzyma się sama.
   Żadnych filtrów CSS - znak jest biało-czerwony z czarnym obrysem
   i czyta się zarówno na papierowym tle, jak i na czarnym wariancie
   hero (biały napis „Bowling" i czerwony pierścień niosą kształt,
   obrys tylko go domyka).

   BUDŻET PIERWSZEGO EKRANU (okno 700px i 800px):
   hero na stronie głównej to wariant „dark sm over", więc jego
   wysokość to nav 70px + 2x --sec-y-tight + treść. Sam logotyp
   dokłada 208px + odstęp, czego przy oknie 700px nie dało się
   zmieścić razem z tytułem, leadem i przyciskami. Zmniejszone
   zostały ODSTĘPY HERO, nie logotyp: .hero--logo skraca dolny
   padding do --gap-7, a nad znakiem zostawia tylko wysokość
   paska nawigacji + --gap-5. Dolna granica clamp została nietknięta,
   bo to ona ratuje czytelność znaku na telefonach. */
.hero__logo-box{
  display:block;
  /* Odstęp ze skali: znak jest osobną grupą nad blokiem tekstu. */
  margin-bottom:var(--gap-5);
}
.hero__logo{
  display:block;
  height:clamp(112px,17vw,208px);
  width:auto;
}
/* Wejście znaku: sama przezroczystość i krótkie dojście z góry,
   bez skalowania od zera. Cały blok stoi w „no-preference", więc
   przy prośbie o ciszę ruchową logotyp jest po prostu od razu
   widoczny - zostaje zmiana przezroczystości, znika ruch. */
@media (prefers-reduced-motion: no-preference){
  .hero__logo{animation:hero-logo-in .52s var(--ease-out) both}
}
@keyframes hero-logo-in{
  from{opacity:0;transform:translate3d(0,-12px,0)}
  to{opacity:1;transform:translate3d(0,0,0)}
}

/* Nadtytuł hero - jak .eyebrow: neutralny tekst, czerwona kreska.
   Na pierwszym ekranie akcentem ma być przycisk, nie nagłówek nad tytułem. */
.hero__eyebrow{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  font-size:.75rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.18em;
  color:var(--ink-2);
  /* Rytm pierwszego ekranu rośnie schodkowo: nadtytuł 12px pod tytułem,
     lead 24px, przyciski 32px, metadane 48px. Każdy kolejny element
     jest dalej niż poprzedni, więc grupy czytają się same. */
  margin-bottom:var(--gap-3);
}
.hero__eyebrow::before{content:'';width:26px;height:2px;background:var(--red);flex:none}
.hero__title{
  font-size:clamp(2.3rem,6.6vw,4.6rem);
  font-weight:800;
  line-height:1.02;
  letter-spacing:-.04em;
  max-width:20ch;
}
.hero__title .accent{color:var(--red)}
.hero__lead{
  margin-top:var(--gap-5);
  font-size:clamp(1rem,1.7vw,1.25rem);
  line-height:1.55;
  color:var(--ink-2);
  max-width:58ch;
}
.hero__actions{
  display:flex;flex-wrap:wrap;gap:var(--gap-3);
  margin-top:var(--gap-6);
}
.hero__meta{
  display:flex;flex-wrap:wrap;gap:var(--gap-3) var(--gap-6);
  margin-top:var(--gap-7);
  padding-top:var(--gap-5);
  border-top:1px solid var(--line);
  font-size:.875rem;
  color:var(--ink-3);
}
.hero__meta-item{display:inline-flex;align-items:center;gap:var(--gap-2);min-width:0}
/* Długi e-mail/telefon jako element flex nie skurczy się przy samym
   break-word - dopiero `anywhere` obniża rozmiar min-content i pozwala
   złamać adres zamiast wypychać go poza viewport. */
.hero__meta-item a{min-width:0;overflow-wrap:anywhere}
/* Ikony metadanych stoją po kilka w rzędzie - neutralne. */
.hero__meta-item svg{width:17px;height:17px;flex:none;color:var(--ink-3)}
.hero__meta-item b{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;color:var(--ink);
}

/* --- Wariant ciemny ----------------------------------------- */
.hero--dark{
  background:var(--black);
  color:var(--white);
  border-bottom-color:var(--black);
}
.hero--dark .hero__eyebrow{color:var(--white)}
.hero--dark .hero__lead{color:var(--on-dark)}
.hero--dark .hero__meta{border-top-color:var(--line-dark);color:var(--on-dark-2)}
.hero--dark .hero__meta-item b{color:var(--white)}
/* Wzór torów rysowany CSS-em został usunięty: ten sam ::before niesie teraz
   fotografię wnętrza kręgielni (patrz „Tło hero" wyżej). Rysowanie pasów tutaj
   ustawiało własność background i kasowało zdjęcie, bo ta reguła stoi w arkuszu
   niżej niż warstwa fotografii. */
/* Czerwony blok w prawym górnym rogu - akcent, nie tło sekcji. */
.hero--dark::after{
  content:'';
  position:absolute;top:0;right:0;z-index:0;
  width:clamp(60px,12vw,150px);height:6px;
  background:var(--red);
  pointer-events:none;
}
/* Hero ciemne: na czerni fotografia może być wyraźniejsza, bo nie walczy
   z czytelnością czarnego tekstu. Reguła stoi celowo za wszystkimi innymi
   deklaracjami .hero--dark - wcześniej wzór pasów rysowany niżej w arkuszu
   nadpisywał tło zdjęcia i na stronie głównej nie było go widać. */
.hero--dark::before{
  opacity:.28;
  filter:grayscale(.2) contrast(1.06);
  -webkit-mask-image:linear-gradient(to top,#000 0%,#000 34%,rgba(0,0,0,.55) 70%,transparent 97%);
  mask-image:linear-gradient(to top,#000 0%,#000 34%,rgba(0,0,0,.55) 70%,transparent 97%);
}

.hero--red{background:var(--red);color:var(--white);border-bottom-color:var(--red)}
.hero--red .hero__eyebrow{color:var(--white)}
.hero--red .hero__eyebrow::before{background:var(--white)}
.hero--red .hero__lead{color:rgba(255,255,255,.85)}
.hero--red .hero__meta{border-top-color:rgba(255,255,255,.28);color:rgba(255,255,255,.8)}
.hero--red .hero__meta-item svg{color:var(--white)}
.hero--red .hero__meta-item b{color:var(--white)}

/* Hero kompaktowe - podstrony bez dużej grafiki. */
.hero--sm .hero__inner{padding-block:var(--sec-y-tight)}
/* Reguła wyżej ma tę samą wagę co .hero--over .hero__inner i stoi PO niej,
   więc kompaktowe hero pod przezroczystym nagłówkiem gubiło zapas na pasek
   i tytuł wchodził pod menu. Zapas wraca tu, w wersji zwartej. */
.hero--over.hero--sm .hero__inner{
  padding-top:calc(var(--nav-h) + var(--topbar-h) + var(--sec-y-tight));
}
.hero--sm .hero__title{font-size:clamp(1.8rem,4.6vw,3rem)}

/* --- Odstępy hero ze znakiem -------------------------------
   Rzecz kolejności: .hero--sm .hero__inner wyżej ustawia padding-block
   (obie krawędzie) i ma tę samą wagę, więc odstępy hero z logotypem
   muszą stać PO nim, inaczej nie doszłyby do skutku.
   Logotyp dokłada do pierwszego ekranu ok. 232px (208px znaku
   + --gap-5). Przy oknie 700px hero z pełnymi odstępami sekcyjnymi
   przestawało mieścić przyciski, więc oddane zostały odstępy:
   nad znakiem tylko zapas na pasek nawigacji + --gap-5, pod
   przyciskami --gap-7 zamiast --sec-y-tight. Logotyp i dolna
   granica clamp zostają nietknięte - to znak rozpoznawczy klienta. */
.hero--logo .hero__inner{padding-bottom:var(--gap-7)}
.hero--over.hero--logo .hero__inner{
  padding-top:calc(var(--nav-h) + var(--topbar-h) + var(--gap-5));
}
/* Rachunek pierwszego ekranu przy oknie 700px (strona główna, tytuł
   w dwóch wierszach): pasek 70 + 24 + znak 208 + 24 + nadtytuł 26
   + tytuł ~150 + lead 24+60 + przyciski 32+46 + dół 48 = ~712px,
   czyli o włos za dużo. Odstępy WEWNĄTRZ hero ze znakiem schodzą
   więc o jeden stopień skali: pod znakiem i nad leadem --gap-4
   zamiast --gap-5, metadane --gap-6 zamiast --gap-7. Razem oddaje to
   ~24px i przyciski mieszczą się w oknie 700px bez dotykania znaku.
   Hero bez logotypu zostaje przy pełnym rytmie z §17. */
.hero--logo .hero__logo-box{margin-bottom:var(--gap-4)}
.hero--logo .hero__lead{margin-top:var(--gap-4)}
.hero--logo .hero__meta{margin-top:var(--gap-6);padding-top:var(--gap-4)}

/* Hero dwukolumnowe: treść + kafle/tabela obok. */
.hero__grid{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:var(--gap-7);
  align-items:center;
}
@media (min-width:981px){
  .hero__grid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}
}
.hero__aside{min-width:0}


/* ============================================================
   18. PASEK WYNIKÓW (.ticker)
   ------------------------------------------------------------
   Przewijana taśma pod hero: kolejka BIEŻĄCA (ta, w której padł
   ostatni wynik) i zapowiedź NASTĘPNEJ. Zawartość buduje PHP,
   skrypt duplikuje ją raz, żeby pętla translateX(0 → -50%) była
   ciągła - dokładnie tak samo jak w karuzeli partnerów niżej.

   TŁO: CZERŃ - i to jest decyzja, nie ozdoba.
     1. Tekst w ruchu czyta się tym gorzej, im niższy kontrast.
        Biel na czerni daje w tej palecie maksimum (ok. 19:1);
        ten sam pas na --paper-3 zszedłby do granicy AA i wyniki,
        czyli jedyna treść tego pasa, byłyby najtrudniejszym
        elementem strony do przeczytania.
     2. Pas ma być odcięty od hero (białego) I od pierwszej sekcji
        pod nim (białej). Czerń robi to bez ramki, bez cienia
        i bez drugiego odcienia szarości w palecie.
     3. Kropka „na żywo" to jedyne miejsce w serwisie, gdzie kolor
        niesie stan; na czerni czerwień jest widoczna od razu,
        na jasnej szarości gubi się wśród liter.

   BLOKADA MOTYWU - rzecz do odnotowania przez agenta budującego
   index.php: ticker należy do CHROMU strony, tej samej rodziny co
   .topbar i .foot, które też są czarne, a nie do sekcji treści.
   NIE zużywa więc limitu „jedna sekcja ciemna na stronę" i strona
   może dalej mieć jedną .section--dark. Ale dwa czarne pasy nie
   mogą się stykać: jeśli index.php dostanie .hero--dark, hero
   i ticker zleją się w jeden blok i pas przestanie być paskiem.
   Przy ciemnym hero ticker trzeba przenieść w inne miejsce strony
   albo zostawić hero jasne - to drugie jest tańsze.

   Poza kropką stanu pas nie ma ani jednego czerwonego piksela:
   akcent w tej strefie należy do niej i tylko do niej.
   ============================================================ */
.ticker{
  /* Czas pełnego obiegu. 40s to tempo, przy którym nazwa drużyny
     zdąży przejechać wzrok, zanim zniknie za maską. */
  --ticker-time:40s;
  position:relative;
  background:var(--black);
  color:var(--white);
  /* Taśma jest szersza od ekranu - tu się ją ucina. Bez tego pas
     rozpychałby stronę w bok mimo blokady z §03. */
  overflow:hidden;
}
.ticker__inner{
  width:100%;
  max-width:var(--container);
  margin-inline:auto;
  /* Świadomie BEZ padding-inline: taśma ma dobiegać do krawędzi
     kolumny i wygasać pod maską, a nie zatrzymywać się na wcięciu. */
}
.ticker__viewport{
  display:flex;align-items:center;
  overflow:hidden;
  /* Wysokość zwarta - pas jest informacją, nie sekcją. Suma dwóch stopni
     skali: 60px na desktopie, ~40px przy 320px (oba stopnie są clamp). */
  min-height:calc(var(--gap-7) + var(--gap-3));
  /* Wygaszenie krawędzi: taśma wtapia się w tło zamiast urywać. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
}
.ticker__track{
  display:flex;align-items:center;
  width:max-content;
  /* .ticker__viewport jest kontenerem flex (centruje taśmę w pionie),
     więc bez flex:none taśma zostałaby ściśnięta do szerokości okna
     i pętla przesuwałaby pustkę zamiast wyników. */
  flex:none;
  will-change:transform;
  /* Animowana jest WYŁĄCZNIE własność transform - omija layout
     i paint, więc taśma nie kosztuje ani jednego przeliczenia
     układu na klatkę. Linearnie, bo ruch ciągły bez początku
     i końca nie ma czego przyspieszać ani wyhamowywać. */
  animation:ticker-run var(--ticker-time) linear infinite;
}
@keyframes ticker-run{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
/* Zatrzymanie: klasą (skrypt, przeciąganie palcem), najechaniem
   i fokusem wewnątrz taśmy. Fokus jest obowiązkowy - bez niego
   użytkownik klawiatury ściga linki, które uciekają. */
.ticker.is-paused .ticker__track,
.ticker__track.is-paused{animation-play-state:paused}
.ticker__viewport:focus-within .ticker__track{animation-play-state:paused}
@media (hover:hover) and (pointer:fine){
  .ticker:hover .ticker__track{animation-play-state:paused}
}

.ticker__group{display:flex;align-items:center;flex:none}

/* --- Etykieta kolejki ---------------------------------------
   Numer kolejki i data stoją w dwóch polach rozdzielonych cienką
   kreską - myślnik jako separator w metadanych jest zakazany. --- */
.ticker__round{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  flex:none;
  padding:var(--gap-1) var(--gap-3);
  margin-inline:var(--gap-5) var(--gap-3);
  border:1px solid var(--white);
  border-radius:var(--r);
  font-size:.6875rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;
  line-height:1.4;
  color:var(--white);
  white-space:nowrap;
}
.ticker__round time,
.ticker__round .ticker__round-date{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-weight:600;
  letter-spacing:.02em;
  text-transform:none;
  padding-left:var(--gap-2);
  border-left:1px solid var(--line-dark);
  color:var(--on-dark);
}
/* Kolejka następna jest przygaszona - z jednego spojrzenia widać,
   która część taśmy to wyniki, a która dopiero zapowiedź. */
.ticker__round--next{
  border-color:var(--line-dark);
  color:var(--on-dark-2);
}
.ticker__round--next time,
.ticker__round--next .ticker__round-date{color:var(--on-dark-2)}

/* --- Pojedynczy mecz ---------------------------------------- */
.ticker__match{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  flex:none;
  padding-inline:var(--gap-3);
  font-size:.875rem;
  line-height:1.2;
  white-space:nowrap;
}
.ticker__team{
  font-weight:700;
  letter-spacing:-.01em;
  color:var(--on-dark);
}
/* Wynik jest wyraźniejszy od nazw: to po niego się tu przychodzi. */
.ticker__score{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
  font-weight:700;
  font-size:.9375rem;
  letter-spacing:-.02em;
  color:var(--white);
  white-space:nowrap;
}
/* Rozdzielenie drużyn, gdy wyniku jeszcze nie ma. */
.ticker__vs{
  font-size:.6875rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--on-dark-2);
}
.ticker__time{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.8125rem;font-weight:600;
  color:var(--on-dark);
}
/* --- Wskaźnik meczu w trakcie -------------------------------
   Jedyna dopuszczalna w serwisie kolorowa kropka: niesie realny
   stan, a nie ozdobę. Sam napis zostaje BIAŁY - czerwień
   #d7332b na czerni daje 4,37:1, czyli poniżej progu AA dla
   małego tekstu; kolor bierze na siebie kropka, której kontrast
   nie dotyczy, bo nie jest tekstem. ---------------------------- */
.ticker__live{
  display:inline-flex;align-items:center;gap:var(--gap-1);
  flex:none;
  font-size:.625rem;font-weight:800;
  letter-spacing:.12em;text-transform:uppercase;
  color:var(--white);
}
.ticker__live::before{
  content:'';
  width:7px;height:7px;border-radius:50%;
  background:var(--red);flex:none;
  /* Pulsuje WYŁĄCZNIE przezroczystość - bez skalowania, bo kropka
     zmieniająca rozmiar przesuwałaby tekst obok o ułamek piksela. */
  animation:ticker-live 1.6s var(--ease-in-out) infinite;
}
@keyframes ticker-live{
  0%,100%{opacity:1}
  50%{opacity:.3}
}

/* Drużyna pauzująca w kolejce nieparzystej. */
.ticker__bye{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  flex:none;
  padding-inline:var(--gap-3);
  font-size:.75rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.08em;
  color:var(--on-dark-2);
  white-space:nowrap;
}

/* Separator między meczami: cienka pionowa kreska, nigdy myślnik. */
.ticker__sep{
  flex:none;
  width:1px;height:18px;
  background:var(--line-dark);
  margin-inline:var(--gap-1);
}

/* Linki w pasie: hover nie może zejść do --red-600, bo ta czerwień
   na czerni jest nieczytelna. Reakcją jest rozjaśnienie do bieli. */
@media (hover:hover) and (pointer:fine){
  .ticker a:hover{color:var(--white)}
  .ticker a:hover .ticker__team{color:var(--white)}
}

.ticker :focus-visible{outline-color:var(--white)}

/* --- Wariant bez ruchu --------------------------------------
   Ten sam pas, ale taśma jest zwykłym kontenerem przewijanym
   palcem. Maska schodzi: przy ręcznym przewijaniu wygaszona
   krawędź ukrywałaby treść, do której użytkownik właśnie dojechał.
   Wariant obsługuje DWA przypadki: prefers-reduced-motion (niżej,
   automatycznie) i brak JavaScriptu - bez skryptu zawartość nie
   jest zduplikowana, więc przesunięcie o -50% zjadłoby połowę
   wyników. ---------------------------------------------------- */
.ticker--static .ticker__viewport{
  overflow-x:auto;
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;
  scrollbar-color:var(--on-dark-2) transparent;
  -webkit-mask-image:none;mask-image:none;
}
.ticker--static .ticker__viewport::-webkit-scrollbar{height:6px}
.ticker--static .ticker__viewport::-webkit-scrollbar-track{background:transparent}
.ticker--static .ticker__viewport::-webkit-scrollbar-thumb{
  background:var(--line-dark);border:0;
}
.ticker--static .ticker__track{animation:none}

@media (scripting: none){
  .ticker__viewport{
    overflow-x:auto;
    overscroll-behavior-x:contain;
    -webkit-mask-image:none;mask-image:none;
  }
  .ticker__track{animation:none}
}


/* ============================================================
   19. KARUZELA PARTNERÓW (.partners)
   ------------------------------------------------------------
   Taśma jedzie w lewo o 50% swojej szerokości. Serwer renderuje
   zestaw logotypów dwa razy (skrypt dokłada kopię tylko wtedy,
   gdy jej brak), więc po przesunięciu o połowę obraz jest
   identyczny i szew pętli jest niewidoczny. Prędkość steruje
   zmienną --marquee-time (serwer ustawia ją proporcjonalnie do
   liczby logotypów, żeby tempo było stałe).

   KAFLE: panel zapisuje każde logo jako jednolity kafel 480x240
   (2:1, przezroczyste tło, logo wpasowane z marginesem 10%) -
   inc/media.php::media_save_logo. Kafel w taśmie ma więc STAŁĄ
   szerokość i proporcję 2:1 (wysokość liczona jawnie z szerokości,
   bo aspect-ratio nie działa w starszych Safari), a obrazek
   wypełnia go w całości. object-fit:contain to tylko zabezpieczenie
   dla plików wgranych przed zmianą (inne proporcje) - nie zmienia
   wysokości kafla, więc linia nie „faluje".

   SZEW PĘTLI: odstępy między kaflami niesie margin-inline kafla,
   NIE gap taśmy. Z gap połowa taśmy (N kafli) byłaby o pół odstępu
   krótsza od okresu wzoru i przy -50% taśma skakałaby o pół
   odstępu na złączeniu. Z marginesem każdy kafel zajmuje dokładnie
   szerokość + odstęp, więc połowa taśmy = N x (szerokość + odstęp)
   = okres wzoru i przejście jest ciągłe.
   ============================================================ */
.partners{
  --marquee-time:38s;
  --tile-w:160px;                       /* kafel zwykły: 160x80 */
  --tile-w-main:200px;                  /* partner główny: 200x100 */
  --tile-gap:clamp(var(--gap-5),3.5vw,2.75rem);
  position:relative;
  padding-block:var(--gap-6);
  background:var(--paper-2);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  overflow:hidden;              /* taśma wychodzi poza kontener - tu ją ucinamy */
}
.partners--dark{
  background:var(--black);
  border-color:var(--line-dark);
}
/* Podstrona /partnerzy: jasne tło, większe kafle, wolniejsze tempo
   (czas pętli ustawia serwer w --marquee-time). */
.partners--page{
  --tile-w:220px;                       /* 220x110 */
  --tile-w-main:280px;                  /* 280x140 */
  --tile-gap:clamp(var(--gap-6),4vw,3.5rem);
  padding-block:var(--gap-7);
  background:var(--paper);
  border-top:0;
}
.partners__head{
  display:flex;align-items:center;justify-content:center;gap:var(--gap-3);
  margin-bottom:var(--gap-4);
  font-size:.6875rem;
  font-weight:800;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink-3);
  text-align:center;
}
.partners--dark .partners__head{color:var(--on-dark-2)}
.partners--page .partners__head{margin-bottom:var(--gap-6)}

.partners__viewport{
  overflow:hidden;
  /* Wygaszenie krawędzi maską - logotypy nie „urywają się" ostro. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  cursor:grab;
}
.partners__viewport.is-dragging{cursor:grabbing}

.partners__track{
  display:flex;
  align-items:center;
  width:max-content;
  will-change:transform;
  animation:marquee var(--marquee-time) linear infinite;
}
@keyframes marquee{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
/* Pauza: najechanie, fokus wewnątrz taśmy i przeciąganie palcem. */
.partners__viewport:focus-within .partners__track,.partners__track.is-paused{animation-play-state:paused}
@media (hover:hover) and (pointer:fine){
  .partners__viewport:hover .partners__track{animation-play-state:paused}
}

.partners__item{
  display:block;
  flex:none;
  box-sizing:border-box;
  width:var(--tile-w);
  height:calc(var(--tile-w) / 2);
  margin-inline:calc(var(--tile-gap) / 2);
  border-radius:var(--r);
}
/* Partner główny - nieco większy, bo płaci najwięcej i tak wynika z umowy.
   Proporcja zostaje 2:1: plik logo ma 2:1, więc kafel tylko szerszy
   (a nie wyższy) pokazałby logo w tym samym rozmiarze co zwykły. Linia
   trzyma jedną, stałą wysokość równą kaflowi głównemu; zwykłe kafle
   stoją w niej wyśrodkowane. */
.partners__item--main{
  width:var(--tile-w-main);
  height:calc(var(--tile-w-main) / 2);
}
.partners__item img{
  display:block;
  width:100%;
  height:100%;
  object-fit:contain;
  filter:grayscale(1);
  opacity:.75;
  transition:filter .25s var(--ease-out),opacity .25s var(--ease-out);
  /* Obrazek nie może przechwytywać zdarzeń wskaźnika, bo przeglądarka
     zaczęłaby wtedy natywne przeciąganie obrazka zamiast taśmy. */
  pointer-events:none;
  user-select:none;
  -webkit-user-drag:none;
}
.partners__item:focus-visible img{filter:grayscale(0);opacity:1}
@media (hover:hover) and (pointer:fine){
  .partners__item:hover img{filter:grayscale(0);opacity:1}
}

/* Ciemne tło, monochrom: odwrócenie barw, żeby czarne znaki były jasne. */
.partners--dark .partners__item img{
  filter:grayscale(1) invert(1) brightness(1.7);
  opacity:.55;
}
.partners--dark .partners__item:focus-visible img{filter:grayscale(0);opacity:1}
@media (hover:hover) and (pointer:fine){
  .partners--dark .partners__item:hover img{filter:grayscale(0);opacity:1}
}

/* Tryb kolorowy (ustawienie partners_mono = 0, klasa z inc/layout.php):
   logotypy zawsze w kolorze, bez filtra i bez zmiany pod kursorem. */
.partners--color .partners__item img,
.partners--color .partners__item:focus-visible img{filter:none;opacity:1;transition:none}
@media (hover:hover) and (pointer:fine){
  .partners--color .partners__item:hover img{filter:none;opacity:1}
}
/* Kolor na czerni: BEZ invertu (zniszczyłby barwy znaku); za to kafel
   dostaje delikatne jasne tło, żeby ciemne logotypy nie ginęły w tle. */
.partners--dark.partners--color .partners__item{background:rgba(255,255,255,.06)}
.partners--dark.partners--color .partners__item img,
.partners--dark.partners--color .partners__item:focus-visible img{filter:none;opacity:1}
@media (hover:hover) and (pointer:fine){
  .partners--dark.partners--color .partners__item:hover img{filter:none;opacity:1}
}


/* ============================================================
   20. STOPKA (.foot)
   ============================================================ */
.foot{
  background:var(--black);
  color:var(--on-dark);
  /* Stopka wchodzi w rytm sekcji - ten sam odstęp od ostatniego bloku
     treści co między dwiema sekcjami strony. */
  padding-top:var(--sec-y);
  /* Zapas na pasek gestów w iOS. */
  padding-bottom:calc(var(--gap-5) + env(safe-area-inset-bottom));
  font-size:.9375rem;
}
.foot__inner{
  width:100%;max-width:var(--container);
  margin-inline:auto;
  padding-inline:var(--pad-x);
}
/* Cztery kolumny o ustalonych proporcjach: znak + dwie listy linków
   + kontakt. Wcześniej auto-fit rozsypywał je na pięć nierównych
   pasów; teraz rozkład jest ten sam na każdej szerokości powyżej 980px. */
.foot__grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));
  gap:var(--gap-7);
  padding-bottom:var(--gap-7);
}
@media (min-width:981px){
  .foot__grid{grid-template-columns:1.5fr 1fr 1fr 1.2fr}
}
.foot__col{display:flex;flex-direction:column;gap:var(--gap-2);min-width:0}
.foot__col--brand{max-width:38ch}
@media (min-width:981px){.foot__col--brand{padding-right:var(--gap-5)}}

.foot__logo{height:64px;width:auto;margin-bottom:var(--gap-3)}
.foot__desc{color:var(--on-dark-2);line-height:1.55;font-size:.875rem}
.foot__head{
  font-size:.6875rem;
  font-weight:800;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--white);
  margin-bottom:var(--gap-2);
}
.foot__col a{color:var(--on-dark);width:fit-content;max-width:100%}
@media (hover:hover) and (pointer:fine){
  .foot__col a:hover{color:var(--white)}
}

.foot__col a:focus-visible{color:var(--white)}
.foot__col p{color:var(--on-dark-2);font-size:.875rem;line-height:1.5}

.foot__addr{font-style:normal;color:var(--on-dark-2);font-size:.875rem;line-height:1.6}
.foot__addr b{display:block;color:var(--white);font-weight:800;font-size:.9375rem;letter-spacing:-.01em}

.foot__social{display:flex;gap:var(--gap-2);margin-top:var(--gap-3)}
.foot__social a{
  display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;
  border:1px solid var(--line-dark);
  border-radius:var(--r);
  color:var(--on-dark);
  transition:background-color .16s var(--ease-out),color .16s var(--ease-out),
             border-color .16s var(--ease-out),transform .16s var(--ease-out);
}
.foot__social a:active{transform:scale(.97)}
.foot__social a svg{width:18px;height:18px}
@media (hover:hover) and (pointer:fine){
  .foot__social a:hover{background:var(--white);border-color:var(--white);color:var(--black)}
}

/* Drobny druk: dane firmowe, partner medialny, dopisek z panelu.
   Trzymamy je pod siatką, żeby kolumna „Kontakt" została listą
   trzech konkretów, a nie ścianą tekstu. */
.foot__fine{
  display:flex;flex-wrap:wrap;gap:var(--gap-1) var(--gap-5);
  padding-bottom:var(--gap-5);
  font-size:.8125rem;line-height:1.5;
  color:var(--on-dark-2);
}
.foot__fine p{color:var(--on-dark-2);font-size:.8125rem}
.foot__fine a{color:var(--on-dark);text-decoration:underline;text-underline-offset:.16em}
@media (hover:hover) and (pointer:fine){
  .foot__fine a:hover{color:var(--white)}
}

.foot__fine:empty{display:none}

.foot__bar{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:var(--gap-3) var(--gap-5);
  padding-top:var(--gap-5);
  border-top:1px solid var(--line-dark);
  font-size:.8125rem;
  color:var(--on-dark-2);
}
.foot__bar-links{display:flex;flex-wrap:wrap;gap:var(--gap-2) var(--gap-4)}
/* „Realizacja: Lightbyte" - świadomie bez linku wychodzącego. */
.foot__credit{color:var(--on-dark-2);white-space:nowrap}
.foot__credit b{color:var(--on-dark);font-weight:700}

/* --- Podpis wykonawcy ------------------------------------------------
   Znak lightByte wchodzi jako wstawiony SVG i bierze kolor przez
   currentColor. Pod kursorem rozjaśnia się WYŁĄCZNIE znak - tekst
   „uszyte na miarę przez" zostaje przygaszony (--on-dark-2), dlatego
   oba fragmenty mają kolor ustawiony wprost, a nie dziedziczony
   z odnośnika (globalne a:hover zmieniłoby inaczej cały napis).
   Fokus klawiatury: pierścień na całym odnośniku niesie globalna
   reguła :focus-visible, znak rozjaśnia się tak samo jak pod kursorem.
   Wysokość znaku dobrana do wielkości tekstu stopki, nie odwrotnie. */
.lb-credit{
  display:inline-flex;align-items:center;gap:var(--gap-2);
  color:var(--on-dark-2);white-space:nowrap;
}
.lb-credit__text{color:var(--on-dark-2)}
.lb-credit__logo{display:inline-flex;color:var(--on-dark-2)}
.lb-credit__logo svg{height:15px;width:auto;display:block}
@media (hover:hover) and (pointer:fine){
  .lb-credit__logo{transition:color .16s var(--ease-out)}
  .lb-credit:hover{color:var(--on-dark-2)}
  .lb-credit:hover .lb-credit__text{color:var(--on-dark-2)}
  .lb-credit:hover .lb-credit__logo{color:var(--white)}
}
.lb-credit:focus-visible .lb-credit__text{color:var(--on-dark-2)}
.lb-credit:focus-visible .lb-credit__logo{color:var(--white)}
@media (max-width:400px){
  .lb-credit__logo svg{height:13px}
}


/* ============================================================
   21. PASEK COOKIES (.cookie-bar)
   ------------------------------------------------------------
   Unosi się nad treścią, więc wolno mu mieć miękki cień.
   ============================================================ */
.cookie-bar{
  position:fixed;z-index:120;
  left:max(12px,env(safe-area-inset-left));
  right:max(12px,env(safe-area-inset-right));
  bottom:max(12px,env(safe-area-inset-bottom));
  max-width:620px;
  margin-inline:auto;
  padding:var(--gap-4) var(--gap-5);
  background:var(--black);
  color:var(--white);
  border:1px solid var(--line-dark);
  border-radius:var(--r-2);
  box-shadow:0 10px 34px rgba(1,2,2,.34);
  translate:0 calc(100% + 24px);
  opacity:0;
  transition:translate .35s var(--ease-out),opacity .3s var(--ease-out);
}
.cookie-bar.is-in{translate:0 0;opacity:1}
.cookie-bar__title{
  font-size:1rem;font-weight:800;letter-spacing:-.02em;
  margin-bottom:var(--gap-1);
}
.cookie-bar__text{
  font-size:.875rem;line-height:1.5;color:var(--on-dark);
}
.cookie-bar__text a{color:var(--white);text-decoration:underline;text-underline-offset:.16em}
.cookie-bar__actions{
  display:flex;flex-wrap:wrap;gap:var(--gap-2);
  margin-top:var(--gap-4);
}
.cookie-bar__actions .btn{flex:1 1 auto;min-width:140px}


/* ============================================================
   22. FORMULARZE
   ============================================================ */
.field{display:flex;flex-direction:column;gap:var(--gap-1);min-width:0}
.field__label{
  font-size:.75rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-2);
}
.field__label .req{color:var(--red);margin-left:.15em}
.field__hint{font-size:.8125rem;color:var(--ink-3)}
.field__err{font-size:.8125rem;color:var(--red-700);font-weight:700}

/* --- Załączniki formularza kontaktowego (.cf-files) ---------------
   Właściwy <input type=file> jest ukryty (.visually-hidden), klikalna
   jest jego etykieta w skórze przycisku (.btn--line). Listę wybranych
   plików buduje skrypt (main.js, moduł 20) i oznacza pole klasą
   .cf-files--js. Bez skryptu przywracamy natywne pole (przeglądarka
   sama pokazuje wybrane pliki), a etykieta-przycisk schodzi ze sceny -
   inaczej po wyborze plików użytkownik nie miałby żadnej informacji
   zwrotnej. */
.cf-files{
  display:flex;flex-direction:column;align-items:flex-start;
  gap:var(--gap-2);
  min-width:0;
}
.cf-files:not(.cf-files--js) > input[type="file"]{
  position:static !important;width:100%;height:auto;
  margin:0;padding:var(--gap-2) 0;overflow:visible;
  clip:auto;clip-path:none;white-space:normal;
  font-size:.9375rem;
}
.cf-files:not(.cf-files--js) > label.btn{display:none}
/* Pierścień fokusu na przycisku, gdy ukryte pole dostaje fokus z klawiatury. */
.cf-files > input[type="file"]:focus-visible + .btn{outline:2px solid var(--red);outline-offset:2px}

.cf-files__list{
  display:flex;flex-direction:column;gap:var(--gap-1);
  width:100%;margin:0;padding:0;list-style:none;
}
.cf-files__list:empty{display:none}
.cf-files__item{
  display:flex;align-items:center;gap:var(--gap-3);
  min-height:38px;
  padding:var(--gap-1) var(--gap-1) var(--gap-1) var(--gap-3);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r);
  font-size:.875rem;
}
.cf-files__name{
  flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--ink);
}
.cf-files__size{
  flex:none;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:.75rem;color:var(--ink-3);
}
.cf-files__remove{
  flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;
  border-radius:var(--r);
  color:var(--ink-3);
  font-size:1.125rem;line-height:1;
  transition:color .16s var(--ease-out),background-color .16s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .cf-files__remove:hover{color:var(--red-700);background:var(--red-050)}
}
.cf-files__hint{margin:0;font-size:.8125rem;color:var(--ink-3)}
.cf-files__err{margin:0;font-size:.8125rem;color:var(--red-700);font-weight:700}
.cf-files__err:empty{display:none}
/* Stan błędu (limit, rozszerzenie): przycisk i podpowiedź czerwienieją,
   a komunikat wchodzi w .cf-files__err (aria-live na liście). */
.cf-files--error > label.btn{--btn-line:var(--red);--btn-fg:var(--red-700)}
.cf-files--error .cf-files__hint{color:var(--red-700)}

.input,.textarea,.select{
  width:100%;
  padding:var(--gap-3);
  min-height:46px;
  background:var(--paper);
  color:var(--ink);
  border:1px solid var(--line);
  border-radius:var(--r);
  font-size:1rem;
  line-height:1.45;
  transition:border-color .16s var(--ease-out),background-color .16s var(--ease-out);
  /* 16px na mobile - mniejszy rozmiar wymusza w iOS zoom przy fokusie. */
}
@media (hover:hover) and (pointer:fine){
  .input:hover,.textarea:hover,.select:hover{border-color:var(--ink-3)}
}

.input:focus,.textarea:focus,.select:focus{border-color:var(--ink);outline:none}
.input:focus-visible,.textarea:focus-visible,.select:focus-visible{
  outline:2px solid var(--red);outline-offset:2px;
}
.input::placeholder,.textarea::placeholder{color:var(--ink-3);opacity:.75}
.input[aria-invalid="true"],.textarea[aria-invalid="true"]{border-color:var(--red)}
.input[disabled],.textarea[disabled],.select[disabled]{
  background:var(--paper-2);color:var(--ink-3);cursor:not-allowed;
}
.textarea{min-height:140px;resize:vertical}
.select{
  appearance:none;
  padding-right:2.2rem;
  /* Strzałka rysowana tłem - bez dodatkowego elementu w HTML. */
  background-image:
    linear-gradient(45deg,transparent 50%,var(--ink-2) 50%),
    linear-gradient(135deg,var(--ink-2) 50%,transparent 50%);
  background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%;
  background-size:5px 5px,5px 5px;
  background-repeat:no-repeat;
  /* Bez min-width:0 rozmiar min-content <select> to szerokość najdłuższej
     opcji - pole nie dałoby się ścisnąć i wyszłoby poza ekran na telefonie. */
  min-width:0;
  max-width:100%;
  text-overflow:ellipsis;
}
.input--num{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  text-align:center;
}

.check{
  display:flex;align-items:flex-start;gap:var(--gap-3);
  font-size:.875rem;line-height:1.45;color:var(--ink-2);
  cursor:pointer;
}
.check input{
  width:20px;height:20px;flex:none;margin-top:var(--gap-0);
  accent-color:var(--red);
  cursor:pointer;
}

/* Honeypot formularza kontaktowego - niewidoczny, ale nie display:none,
   bo część botów pomija pola całkowicie usunięte z układu. */
.hp-field{
  position:absolute !important;
  left:-9999px;width:1px;height:1px;overflow:hidden;
  opacity:0;pointer-events:none;
}

.form-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
  gap:var(--gap-4);
}
.form-grid__full{grid-column:1 / -1}


/* ============================================================
   23. DROBNE KOMPONENTY POMOCNICZE
   ============================================================ */

/* Odliczanie do najbliższej kolejki ([data-countdown]). */
.countdown{display:flex;flex-wrap:wrap;gap:var(--gap-2)}
.countdown__unit{
  display:flex;flex-direction:column;align-items:center;
  min-width:62px;
  padding:var(--gap-2) var(--gap-3);
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--paper);
}
.countdown__val{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:1.5rem;font-weight:700;line-height:1;letter-spacing:-.04em;
}
.countdown__label{
  font-size:.5625rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.12em;color:var(--ink-3);
  margin-top:var(--gap-0);
}
.section--dark .countdown__unit,
.hero--dark .countdown__unit{background:transparent;border-color:var(--line-dark)}
.section--dark .countdown__label,
.hero--dark .countdown__label{color:var(--on-dark-2)}

/* Numer toru - mały monospace „znaczek". */
.lane{
  display:inline-flex;align-items:center;gap:var(--gap-1);
  padding:var(--gap-0) var(--gap-2);
  border:1px solid var(--line);
  border-radius:2px;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:.6875rem;font-weight:700;
  color:var(--ink-2);
  white-space:nowrap;
}
.lane svg{width:12px;height:12px}

/* Przycisk udostępniania / kopiowania linku. */
.share{display:inline-flex;align-items:center;gap:var(--gap-2);position:relative}
.share__done{
  position:absolute;left:50%;bottom:calc(100% + var(--gap-2));
  translate:-50% 0;
  padding:var(--gap-1) var(--gap-2);
  background:var(--black);color:var(--white);
  font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  border-radius:2px;white-space:nowrap;
  opacity:0;pointer-events:none;
  transition:opacity .2s var(--ease-out);
}
.share.is-copied .share__done{opacity:1}

/* Powrót na górę - link do kotwicy #top, więc działa bez JavaScriptu
   (płynne przewijanie daje scroll-behavior:smooth na <html>). Skrypt
   dokłada tylko .is-in, żeby przycisk pokazywał się po przewinięciu
   ekranu; przy wyłączonym JS pokazujemy go od razu. */
.to-top{
  position:fixed;z-index:90;
  right:max(14px,env(safe-area-inset-right));
  bottom:calc(14px + env(safe-area-inset-bottom));
  width:44px;height:44px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--black);color:var(--white);
  border:1px solid var(--black);
  border-radius:var(--r);
  opacity:0;visibility:hidden;translate:0 10px;
  transition:opacity .25s var(--ease-out),translate .25s var(--ease-out),visibility 0s linear .25s;
}
.to-top svg{width:20px;height:20px}
.to-top.is-in{
  opacity:1;visibility:visible;translate:0 0;
  transition:opacity .25s var(--ease-out),translate .25s var(--ease-out),visibility 0s linear 0s;
}
/* Przycisk powrotu wisi nad każdą sekcją, także nad tą, która ma
   własny czerwony akcent - dlatego jego stan hover zostaje czarny. */
@media (hover:hover) and (pointer:fine){
  .to-top:hover{background:var(--ink);border-color:var(--ink);color:var(--white)}
}

.to-top:focus-visible{outline-offset:2px}
@media (scripting: none){
  .to-top{opacity:1;visibility:visible;translate:0 0}
}

/* Lista definicji „etykieta → wartość" (profile drużyn i zawodników). */
.deflist{display:grid;gap:0}
.deflist__row{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:var(--gap-2) var(--gap-4);
  padding:var(--gap-3) 0;
  border-bottom:1px solid var(--line-2);
}
.deflist__row:last-child{border-bottom:0}
.deflist__k{
  font-size:.75rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3);
}
.deflist__v{font-weight:700;text-align:right;min-width:0;overflow-wrap:anywhere}
.deflist__v.is-num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.section--dark .deflist__row{border-bottom-color:var(--line-dark)}
.section--dark .deflist__k{color:var(--on-dark-2)}

/* Kafel-skrót na stronie głównej (duży link do sekcji). */
.tile{
  display:flex;flex-direction:column;justify-content:space-between;gap:var(--gap-5);
  padding:var(--card-pad);
  min-height:170px;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--r-2);
  transition:border-color .18s var(--ease-out),background-color .18s var(--ease-out),translate .18s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .tile:hover{border-color:var(--ink);translate:0 -2px}
}

/* Ikona kafla jest neutralna - kafle stoją po cztery w rzędzie, więc
   czerwone ikony byłyby czterema akcentami zamiast jednego. */
.tile__ico{
  width:34px;height:34px;color:var(--ink-2);
  transition:color .18s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .tile:hover .tile__ico{color:var(--red)}
}

.tile--dark .tile__ico{color:var(--white)}
.tile__title{font-size:1.15rem;font-weight:800;letter-spacing:-.025em}
.tile__desc{font-size:.875rem;color:var(--ink-3);line-height:1.45}
.tile--dark{background:var(--black);border-color:var(--black);color:var(--white)}
.tile--dark .tile__desc{color:var(--on-dark-2)}
@media (hover:hover) and (pointer:fine){
  .tile--dark:hover{border-color:var(--red)}
}

/* Duża liczba „sezonowa" jako element dekoracyjny (płaska, obrysowa). */
.ghost-num{
  font-family:var(--mono);
  font-size:clamp(4rem,14vw,10rem);
  font-weight:700;
  line-height:.85;
  letter-spacing:-.06em;
  color:transparent;
  -webkit-text-stroke:1px var(--line);
  user-select:none;
  pointer-events:none;
}
.section--dark .ghost-num{-webkit-text-stroke-color:var(--line-dark)}

/* Nagłówek profilu (drużyna / zawodnik). */
.profile-head{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--gap-6);
}
.profile-head__img{
  width:clamp(74px,14vw,110px);
  height:clamp(74px,14vw,110px);
  flex:none;
  object-fit:contain;
  background:var(--paper-2);
  border:1px solid var(--line);
  border-radius:var(--r-2);
}
.profile-head__img--round{border-radius:50%;object-fit:cover}
.profile-head__main{min-width:0;flex:1 1 260px}
.profile-head__title{font-size:clamp(1.7rem,4.4vw,2.9rem);letter-spacing:-.04em}
.profile-head__meta{
  display:flex;flex-wrap:wrap;gap:var(--gap-2) var(--gap-4);
  margin-top:var(--gap-2);
  font-size:.875rem;color:var(--ink-3);
}

/* Kropka rozdzielająca w metadanych. */
.dot-sep::before{content:'·';margin-inline:var(--gap-2);opacity:.5}


/* ============================================================
   23a. WYKRES FORMY ZAWODNIKA (.form-chart)
   ------------------------------------------------------------
   Słupki kolejnych gier w sezonie z etykietą pod KAŻDĄ pozycją
   (wynik, kolejka, rywal) i linią średniej. Rysowany samym CSS-em,
   bez biblioteki. Skala: 300 punktów = 100% wysokości (maksimum
   w bowlingu), więc wykresy dwóch zawodników są porównywalne.

   DANE, NIE ODSTĘPY: jedyne dopuszczalne style inline w markupie
   to height:NN% na .form-chart__fill i bottom:NN% na .form-chart__avg.
   To wartości wyników, które zna tylko PHP. Wysokość słupka NIE jest
   animowana: słupek jest liczbą, a liczba nie „dojeżdża". Wejście
   całości niesie [data-reveal] na opakowaniu .table-scroll.

   GEOMETRIA: .form-chart__plot ma stałą wysokość i to ona jest
   obszarem 0-300. Słupek (.form-chart__bar) wypełnia CAŁĄ wysokość
   kolumny, a etykieta stoi absolutnie POD osią - dzięki temu procent
   wypełnienia słupka i procent linii średniej liczą się od tej samej
   wysokości i średnia 187 trafia dokładnie w słupek 187. Miejsce na
   etykiety rezerwuje margin-bottom obszaru (--chart-label-h).

   PRZEWIJANIE: wykres stoi WEWNĄTRZ .table-scroll. Kolumna ma
   min-width 56px, żeby etykieta „187 / K7 / AQU" się zmieściła, więc
   przy 20 grach całość ma ponad 1100px - przewija się w kontenerze
   i nigdy nie rozpycha strony (SPEC §6.4). Liczby są też w tabeli
   pod wykresem, dlatego obszar słupków ma aria-hidden: tabela jest
   źródłem dla czytników ekranu.

   MARKUP (buduje zawodnik.php):
     .table-scroll[data-reveal] > .form-chart
       > .form-chart__plot[aria-hidden]
           > .form-chart__avg[style=bottom:NN%] > span „śr. NNN"
           > a[href=/mecz?id=…] > .form-chart__col
               > .form-chart__bar > .form-chart__fill[style=height:NN%]
               > .form-chart__label > __score / __round / __opp
       > p.form-chart__legend
   Kolumna może być owinięta w <a> (link do meczu) lub stać bez
   niego - obie formy są obsłużone. Stan pusty (brak gier) obsługuje
   istniejący .empty, dlatego .form-chart--empty nie istnieje.
   ============================================================ */
.form-chart{
  --chart-h:180px;
  /* Rezerwa pod etykietę: --gap-2 + wynik (.85rem × 1.25) + kolejka
     i rywal (2 × .72rem × 1.25) = ~3.4rem. Rozmiary są w rem, więc
     rezerwa nie zależy od danych i etykieta nigdy nie wjeżdża na legendę. */
  --chart-label-h:3.5rem;
  display:flex;flex-direction:column;
  /* Szerokość = suma kolumn (max-content), ale nigdy mniej niż kontener:
     przy kilku grach oś i legenda dobiegają do prawej krawędzi karty,
     przy kilkunastu wykres wyjeżdża poza nią i .table-scroll go przewija.
     Padding wchodzi do przewijanej szerokości, bo należy do tego bloku,
     a nie do przewijanego rodzica. */
  width:max-content;min-width:100%;
  padding:var(--card-pad);
  color:var(--ink);
}
.form-chart__plot{
  position:relative;
  display:flex;align-items:flex-end;
  gap:var(--gap-1);
  height:var(--chart-h);
  margin-bottom:var(--chart-label-h);
  /* Oś X - płaska czarna kreska, jak dolna linia nagłówka tabeli. */
  border-bottom:2px solid var(--ink);
}

/* --- Linia średniej ------------------------------------------
   Pozioma kreska przez cały obszar; bottom:NN% ustawia markup.
   z-index, bo słupki są pozycjonowane i stoją w DOM po linii -
   bez tego malowałyby się nad nią. --------------------------- */
.form-chart__avg{
  position:absolute;left:0;right:0;z-index:1;
  height:0;
  border-top:2px dashed var(--red);
  pointer-events:none;
}
/* Etykieta „śr. NNN" przy prawej krawędzi, tuż nad linią, na własnym
   tle - inaczej cyfry nakładałyby się na słupek stojący pod nimi. */
.form-chart__avg>span{
  position:absolute;right:0;bottom:3px;
  padding:var(--gap-0) var(--gap-1);
  background:var(--paper);
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.72rem;font-weight:700;line-height:1.25;
  color:var(--red-600);
  white-space:nowrap;
}

/* --- Kolumna: link + słupek + etykieta ---------------------- */
/* Link owijający kolumnę jest elementem siatki flex, więc dostaje te
   same reguły rozmiaru co kolumna; kolor dziedziczony, bez podkreślenia. */
.form-chart__plot>a{
  display:flex;flex:0 0 auto;
  height:100%;
  color:inherit;text-decoration:none;
  border-radius:var(--r);
}
.form-chart__plot>a:focus-visible{outline-offset:2px}
.form-chart__col{
  position:relative;
  display:flex;flex-direction:column;
  flex:0 0 auto;
  min-width:56px;
  height:100%;
}
.form-chart__bar{
  position:relative;
  flex:1 1 auto;
  min-height:0;
  background:var(--paper-3);
}
.form-chart__fill{
  position:absolute;left:0;right:0;bottom:0;
  /* Zero też ma być widoczne - 2px kreska zamiast pustego toru. */
  min-height:2px;
  background:var(--black);
  transition:background-color .15s var(--ease-out);
}
.form-chart__fill--best{background:var(--red)}
.form-chart__fill--low{background:var(--ink-3)}
@media (hover:hover) and (pointer:fine){
  .form-chart__plot>a:hover .form-chart__fill,
  a.form-chart__col:hover .form-chart__fill{background:var(--red-600)}
}
.form-chart__plot>a:focus-visible .form-chart__fill,
a.form-chart__col:focus-visible .form-chart__fill{background:var(--red-600)}

/* Etykieta stoi pod osią - absolutnie, żeby nie odejmować wysokości
   słupkowi (patrz GEOMETRIA w nagłówku sekcji). */
.form-chart__label{
  position:absolute;left:0;right:0;top:100%;
  padding-top:var(--gap-2);
  text-align:center;
  font-size:.72rem;line-height:1.25;
  color:var(--ink-3);
  white-space:nowrap;
}
.form-chart__label>span{display:block}
/* Wynik jest najważniejszą liczbą etykiety - większy, ciemny, monospace. */
.form-chart__score{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-size:.85rem;font-weight:700;
  color:var(--ink);
}
.form-chart__round{font-weight:600}
.form-chart__opp{letter-spacing:.04em}

/* Wiersz pod wykresem: liczba gier, najlepsza, najsłabsza. Margines
   liczy się od rezerwy na etykiety, nie od osi. contain:inline-size:
   akapit nie ma wpływać na szerokość max-content całości - bez tego
   przy trzech grach to długość zdania, a nie suma kolumn, decydowałaby
   o przewijaniu przy 320px. */
.form-chart__legend{
  margin-top:var(--gap-3);
  font-size:.8125rem;line-height:1.45;
  color:var(--ink-3);
  contain:inline-size;
}
.form-chart__legend b{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;color:var(--ink);
}


/* ============================================================
   24. ANIMACJE WEJŚCIA
   ------------------------------------------------------------
   Element wchodzi z opacity 0 i 14px poniżej miejsca docelowego -
   krótkie dojście, nie przelot przez pół ekranu. Nic nie startuje
   od scale(0): w realnym świecie nic nie pojawia się z niczego,
   a rzecz rosnąca od zera czyta się jak wyskakujące okienko.
   Czas 380ms (warianty boczne 340ms) - poniżej progu, przy którym
   przewijanie zaczyna czekać na animację.
   Ruch wyłącznie na translate/scale i opacity: obie własności omijają
   layout i paint.
   Cały blok stoi w @media (prefers-reduced-motion: no-preference) -
   bez tego warunku element zostałby przezroczysty, gdyby skrypt się
   nie wykonał, a przy wyłączonym ruchu treść ma być od razu widoczna.
   ============================================================ */
@media (prefers-reduced-motion: no-preference){
  [data-reveal]{
    opacity:0;
    translate:0 14px;
    transition:opacity .38s var(--ease-out),translate .38s var(--ease-out);
  }
  [data-reveal].is-in{opacity:1;translate:0 0}
  /* Warianty kierunku - do bloków wjeżdżających z boku. */
  [data-reveal="left"]{translate:-16px 0;transition-duration:.34s}
  [data-reveal="right"]{translate:16px 0;transition-duration:.34s}
  [data-reveal="left"].is-in,[data-reveal="right"].is-in{translate:0 0}
  /* „zoom" nie zaczyna od zera, tylko od 0.96 - element już jest,
     tylko dochodzi do swojej wielkości. */
  [data-reveal="zoom"]{
    translate:0 0;scale:.96;
    transition:opacity .38s var(--ease-out),scale .38s var(--ease-out);
  }
  [data-reveal="zoom"].is-in{scale:1}
}


/* ============================================================
   25. RESPONSYWNOŚĆ
   ------------------------------------------------------------
   Punkty: 1180 / 980 / 760 / 560 / 400 px.
   Kolumny drugorzędne tabeli ligowej znikają stopniowo, żeby
   przy 320px zostało: pozycja, drużyna, mecze, punkty.
   ============================================================ */

/* --- 1180px: mniej powietrza, węższa kolumna boczna --------- */
@media (max-width:1180px){
  :root{--nav-h:66px}
  .nav__link{padding-inline:var(--gap-2);font-size:.9rem}
  .nav__logo{height:40px}
  .nav.is-scrolled .nav__logo{height:34px}
  .tbl--standings{min-width:720px}
}

/* --- 980px: menu chowa się pod hamburgera ------------------- */
@media (max-width:980px){
  /* Pasek główny schodzi do menu mobilnego, które niesie pełną listę
     pozycji wraz z przyciskiem „Zgłoś drużynę". */
  .nav__links{display:none}
  .nav__burger{display:inline-flex}
  .nav__actions .btn{display:none}
  /* Kafle partnerów: 144x72 (główny 180x90); /partnerzy 200x100 (250x125). */
  .partners{--tile-w:144px;--tile-w-main:180px}
  .partners--page{--tile-w:200px;--tile-w-main:250px}
  .foot__col--brand{grid-column:span 1}
}

/* --- 760px: tabela gubi kolumny opcjonalne, karty schodzą w pion */
@media (max-width:760px){
  :root{--nav-h:62px}
  .nav__logo{height:36px}
  .nav.is-scrolled .nav__logo{height:32px}
  .section__head{align-items:flex-start;flex-direction:column}
  .foot__logo{height:56px}

  /* Siatki treści: dokładnie DWIE kolumny. auto-fit zostawiałby jedną
     kolumnę już od ~690px (2 × 320 + przerwa), a przy 561-760px karty
     mieszczą się po dwie (246-330px każda) bez ściskania treści;
     tabele wewnątrz kart przewijają się w swoim .table-scroll.
     .grid--5 (drobne kafle) zostaje na auto-fit - patrz komentarz w §05. */
  .grid--2,.grid--3,.grid--4{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Kolumny R / P / małe pkt - pierwsze do ukrycia. */
  .tbl__col--opt{display:none}
  .tbl--standings{--pos-w:44px;min-width:520px}
  .tbl--standings th:nth-child(2),
  .tbl--standings td:nth-child(2){min-width:150px}
  .tbl{font-size:.875rem;min-width:460px}
  .tbl{--cell-y:var(--gap-2);--cell-x:var(--gap-2)}
  .table-hint.is-scrollable{display:flex}

  .match__logo{width:36px;height:36px}
  .match__score{min-width:84px;padding-inline:var(--gap-2)}
  .stat__val{font-size:clamp(1.7rem,7vw,2.2rem)}
  .cookie-bar__actions .btn{min-width:0}
}

/* --- 560px: skróty nazw drużyn, ciaśniejsze karty ----------- */
@media (max-width:560px){
  .tbl--standings{--pos-w:38px;min-width:420px}
  .tbl--standings th:nth-child(2),
  .tbl--standings td:nth-child(2){min-width:120px}
  /* Pełna nazwa ustępuje skrótowi z teams.short_name. */
  .team-cell__full{display:none}
  .team-cell__short{display:inline}
  .team-cell__logo{width:24px;height:24px}
  .team-cell{gap:var(--gap-2)}
  .pos{width:26px;height:26px;font-size:.8125rem}
  .form-strip__i{width:17px;height:17px;font-size:.625rem}

  /* Karty w JEDNEJ kolumnie. Udokumentowany wyjątek: .grid--4 niesie
     kafle liczbowe (.stat) i - tak jak .stat-row - zostaje przy dwóch
     kolumnach, bo liczby są krótkie, a pion marnowałby ekran. */
  .grid--2,.grid--3{grid-template-columns:minmax(0,1fr)}

  /* Wykres formy: niższy obszar słupków, kolumny i etykiety bez zmian -
     przy 56px na kolumnę przewijanie w .table-scroll robi resztę. */
  .form-chart{--chart-h:140px}

  /* Wcięcie karty niesie już płynny --card-pad, zostaje sam gap siatki. */
  .match{gap:var(--gap-2)}
  .match__name{font-size:.875rem;-webkit-line-clamp:2}
  .match__logo{width:30px;height:30px}
  .match__score{min-width:74px;font-size:1.05rem;border-width:1px}
  .match--featured::before{font-size:.5625rem;letter-spacing:.1em}

  /* Znak w hero schodzi proporcjonalnie (width nadal auto), ale zostaje
     duży: 24vw to 90px przy 375px szerokości - ponad dwa razy więcej
     niż logotyp w pasku, więc identyfikacja klienta nie ginie. */
  .hero__logo{height:clamp(88px,24vw,112px)}
  .hero__logo-box{margin-bottom:var(--gap-4)}

  .round-nav__item{min-width:56px;padding:var(--gap-2);font-size:.875rem}
  .round-nav__arrow{width:34px;height:34px}
  .btn{font-size:.875rem}
  .btn--lg{padding:var(--gap-3) var(--gap-5);min-height:50px;font-size:1rem}
  .pagination a,.pagination span{min-width:38px;height:38px;font-size:.875rem}
  .player-card__photo{width:70px;height:70px}
  /* Kafle partnerów: 128x64 (główny 160x80); /partnerzy 168x84 (210x105). */
  .partners{--tile-w:128px;--tile-w-main:160px}
  .partners--page{--tile-w:168px;--tile-w-main:210px;padding-block:var(--gap-6)}

  /* Pas wyników na telefonie: mniejsze litery i ciaśniejsze wcięcia,
     żeby w oknie mieściły się dwa mecze naraz, a nie półtora. */
  .ticker__match{font-size:.8125rem;padding-inline:var(--gap-2)}
  .ticker__score{font-size:.875rem}
  .ticker__round{margin-inline:var(--gap-4) var(--gap-2)}
  .ticker__bye{padding-inline:var(--gap-2)}
}

/* --- 400px: absolutne minimum - zostają cztery kolumny ------ */
@media (max-width:400px){
  :root{--pad-x:max(14px,env(safe-area-inset-left),env(safe-area-inset-right))}
  .tbl--standings{--pos-w:34px;min-width:330px}
  .tbl--standings th:nth-child(2),
  .tbl--standings td:nth-child(2){min-width:104px}
  .tbl--standings thead th,
  .tbl--standings tbody td{padding:var(--gap-2) var(--gap-1);font-size:.8125rem}
  /* Forma (ostatnie 5) też schodzi ze sceny - zostaje w profilu drużyny. */
  .tbl--standings .is-form{display:none}
  .tbl{min-width:320px}

  .match{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:var(--gap-1)}
  .match__logo{display:none}
  .match__score{min-width:66px;font-size:.9375rem;padding:var(--gap-1)}
  .stat{padding:var(--gap-4)}
  .stat-row{grid-template-columns:repeat(auto-fit,minmax(min(100%,140px),1fr))}
  .cookie-bar{padding:var(--gap-3) var(--gap-4)}
  .nav__logo{height:34px}
  .nav.is-scrolled .nav__logo{height:32px}
  /* Kafle partnerów: 112x56 (główny 140x70); /partnerzy 140x70 (176x88). */
  .partners{--tile-w:112px;--tile-w-main:140px}
  .partners--page{--tile-w:140px;--tile-w-main:176px}
}

/* Ekrany bardzo niskie w poziomie - menu mobilne musi się przewijać. */
@media (max-height:560px){
  .nav__menu{padding-top:calc(var(--nav-h) + var(--gap-4))}
  .nav__menu-link{font-size:1.15rem;padding-block:var(--gap-3)}
  .nav__menu-foot{padding-top:var(--gap-5)}
}

/* --- Urządzenia dotykowe ------------------------------------
   Wszystkie reguły :hover w tym arkuszu stoją w
   @media (hover:hover) and (pointer:fine) - dotyk wywołuje fałszywe
   hovery, które zostają „przyklejone" po puknięciu w element.
   Tutaj zostają wyłącznie reguły POZYTYWNE: to, co na dotyku ma
   wyglądać inaczej, bo najechania nigdy nie będzie.
   ------------------------------------------------------------ */
@media (hover:none){
  .partners__viewport{cursor:default}
  /* Logotypy partnerów odbarwiają się pod kursorem; na dotyku nie ma
     kursora, więc pokazujemy je od razu w czytelniejszej wersji. */
  .partners__item img{filter:grayscale(0);opacity:.85}
}


/* ============================================================
   26. DRUK
   ------------------------------------------------------------
   Wydruk tabeli ligowej i terminarza ma być czytelny na A4:
   czarny tekst na białym, bez elementów interfejsu, tabela
   rozwinięta na całą szerokość (żadnego przewijania na papierze).
   ============================================================ */
@media print{
  :root{
    --nav-h:0px;--topbar-h:0px;
    --sec-y:0.6rem;
    --pad-x:0;
  }
  html,body{
    background:#fff;color:#000;
    font-size:10.5pt;line-height:1.35;
  }
  /* Elementy interaktywne i ozdobne nie mają sensu na papierze. */
  .topbar,.nav,.nav__menu,.cookie-bar,.to-top,.ticker,.partners,
  .foot__social,.round-nav__arrow,.share,.pagination,.table-hint,
  .skip-link,.hero__actions,.tabs,.btn,.btn-icon{display:none !important}

  .section{padding-block:.6rem;background:#fff !important;color:#000 !important}
  .section--dark,.hero--dark,.hero--red,.card--dark,.match--dark{
    background:#fff !important;color:#000 !important;border-color:#000 !important;
  }
  .section--dark *,.hero--dark *,.hero--red *{color:#000 !important}
  .hero{border-bottom:1pt solid #000;padding-bottom:.4rem}
  .hero--dark::before,.hero--dark::after{display:none}
  .hero__title{font-size:20pt}
  .hero__lead{font-size:11pt}

  a{color:#000;text-decoration:none}
  /* Adresy przy linkach treściowych - na wydruku nie da się kliknąć. */
  .prose a[href^="http"]::after{content:' (' attr(href) ')';font-size:8pt;color:#444}

  /* Tabela: pełna szerokość, wszystkie kolumny, bez sticky. */
  .table-scroll{overflow:visible !important;border:0;border-radius:0}
  .tbl,.tbl--standings,.tbl--compact{
    min-width:0 !important;width:100%;font-size:9.5pt;
    page-break-inside:auto;
  }
  .tbl__col--opt{display:table-cell !important}
  .tbl--standings th:first-child,.tbl--standings td:first-child,
  .tbl--standings th:nth-child(2),.tbl--standings td:nth-child(2){
    position:static !important;background:transparent !important;
  }
  .tbl thead{display:table-header-group}          /* nagłówek powtarza się na każdej stronie */
  .tbl tr{page-break-inside:avoid}
  .tbl thead th{
    background:#fff;border-bottom:1.5pt solid #000;color:#000;font-size:8pt;
  }
  .tbl tbody td{border-bottom:.5pt solid #999;padding:.28rem .3rem}
  .tbl tbody tr:hover{background:transparent}
  .pos{border:.75pt solid #000;background:#fff !important;color:#000 !important;width:22px;height:22px}
  .pos--1,.pos--2,.pos--3{font-weight:800;border-width:1.5pt}
  .form-strip__i{border:.5pt solid #000;background:#fff !important;color:#000 !important}

  /* Terminarz: karty meczów jedna pod drugą, bez łamania w środku. */
  .match{
    border:.75pt solid #000;border-radius:0;
    padding:.35rem .5rem;margin-bottom:.25rem;
    page-break-inside:avoid;
  }
  .match--featured::before,.match--live::after{display:none}
  .match__score{border:.75pt solid #000;font-size:11pt;padding:.1rem .3rem}
  .match__logo,.team-cell__logo{display:none}
  .card,.stat,.news-card,.player-card,.rank-row{
    border:.5pt solid #666;border-radius:0;page-break-inside:avoid;
  }
  .news-card__img{display:none}

  /* Wykres formy zostaje - to dane. Kolory schodzą do czerni i szarości,
     kolumny dzielą szerokość strony między siebie (bez przewijania
     na papierze), etykiety mniejsze, żeby 20 gier zmieściło się na A4. */
  .form-chart{width:100%;min-width:0;padding:.3rem 0;--chart-h:120px;--chart-label-h:2.8rem}
  .form-chart__plot{border-bottom-color:#000}
  .form-chart__plot>a,.form-chart__col{flex:1 1 0;min-width:0}
  .form-chart__bar{background:#eee}
  .form-chart__fill{background:#333 !important}
  .form-chart__fill--best{background:#000 !important}
  .form-chart__fill--low{background:#999 !important}
  .form-chart__avg{border-top-color:#000}
  .form-chart__avg>span{color:#000;background:#fff;font-size:6.5pt}
  .form-chart__label{font-size:6.5pt;color:#444}
  .form-chart__score{font-size:7.5pt;color:#000}
  .form-chart__legend{color:#000;font-size:8pt}
  .foot{
    background:#fff !important;color:#000 !important;
    border-top:1pt solid #000;padding:.5rem 0;font-size:8.5pt;
  }
  .foot__grid{display:none}
  .foot__bar{border-top:0;color:#000}
  h1,h2,h3,h4{page-break-after:avoid}
  [data-reveal]{opacity:1 !important;translate:none !important}
}


/* ============================================================
   27. prefers-reduced-motion: reduce
   ------------------------------------------------------------
   Ostatnia sekcja arkusza - musi nadpisać wszystko powyżej.
   Zasada: MNIEJ I ŁAGODNIEJ, nie „zero". Prośba o ciszę ruchową
   dotyczy ruchu, nie zmian stanu - interfejs, w którym wszystko
   przeskakuje bez żadnego przejścia, jest dla tych osób trudniejszy,
   nie łatwiejszy.
   Zostają: przejścia opacity, koloru tekstu, tła, obwódki i obrysu.
   Znikają: przesunięcia, skalowanie, obroty, pętle animacji
   i przewijanie płynne. Karuzela partnerów przestaje być taśmą
   i staje się zwykłą listą przewijaną palcem.
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  /* Zawężenie listy własności zamiast wygaszenia czasu: kolor i
     przezroczystość nadal przechodzą płynnie, wszystko, co przesuwa
     lub skaluje, zmienia się natychmiast. */
  *,*::before,*::after{
    transition-property:opacity,color,background-color,border-color,
                        outline-color,fill,stroke !important;
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    scroll-behavior:auto !important;
  }
  html{scroll-behavior:auto}

  [data-reveal],[data-reveal].is-in{opacity:1 !important;translate:none !important;scale:1 !important}

  /* Potwierdzenie kliknięcia zostaje, ale bez kurczenia się przycisku -
     niesie je zmiana koloru tła zdefiniowana wyżej. */
  .btn:active,.btn-icon:active,.pagination a:active,
  .round-nav__arrow:active,.foot__social a:active,
  .nav__burger:active{transform:none}

  /* Taśma partnerów → statyczna, przewijalna lista. */
  .partners__track{
    animation:none !important;
    width:auto;
    overflow-x:auto;
    overscroll-behavior-x:contain;
    -webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;
    padding-bottom:var(--gap-2);
  }
  .partners__item{scroll-snap-align:center}
  .partners__viewport{
    overflow-x:auto;
    -webkit-mask-image:none;mask-image:none;
    cursor:auto;
  }

  /* Pas wyników → dokładnie to samo co .ticker--static: zwykły
     kontener przewijany palcem, bez maski i bez pętli. */
  .ticker__track{animation:none !important;width:max-content}
  .ticker__viewport{
    overflow-x:auto;
    overscroll-behavior-x:contain;
    -webkit-overflow-scrolling:touch;
    -webkit-mask-image:none;mask-image:none;
  }

  /* Punkt „na żywo" bez pulsowania - zostaje sam kolor. */
  .chip--live::before,.match--live::after,
  .ticker__live::before{animation:none !important;opacity:1}

  /* Warstwy unoszące się nad treścią pojawiają się samą
     przezroczystością, bez wjazdu z dołu. */
  .cookie-bar,.cookie-bar.is-in{translate:0 0}
  .nav__menu{translate:0 0}
  .to-top,.to-top.is-in{translate:0 0}

  /* Powiększenie okładki i unoszenie kart - sam kolor obwódki zostaje. */
  .news-card__img img,.news-card:hover .news-card__img img{scale:1}
  .card:hover,a.card:hover,.match--link:hover,a.match:hover,
  .news-card:hover,.player-card:hover,.tile:hover{translate:0 0}

  /* Szkielet i pasek ładowania: stan bez pulsu i bez przesuwania. */
  .skeleton{animation:none !important;opacity:.75}
  .is-loading::after{animation:none !important;transform:scaleX(1)}
}

/* ============================================================
   Regulamin (.reg-*) - dokument prawny, nie artykuł
   ------------------------------------------------------------
   Osobna typografia od .prose: wisząca numeracja punktów (numer
   w marginesie przez ::marker, tekst wyrównany do siebie), wspólna
   rynna dla numerów rozdziałów i punktów, wąska kolumna (68ch),
   line-height 1.65. Spis treści to sama lista z kreską po lewej -
   bez karty, żeby nie konkurował z treścią. Na >=981px dwie kolumny
   (spis 240px, przyklejony), niżej spis zwinięty w <details> nad
   treścią. Objaśnienia redakcyjne (.reg-formula, .reg-footnote)
   są wizualnie oddzielone od tekstu regulaminu: tło --paper-2
   i drobna etykieta - czytelnik ma widzieć, co jest dokumentem,
   a co komentarzem.
   ============================================================ */

/* --- Pasek meta dokumentu ------------------------------------ */
.reg-meta{
  display:flex;flex-wrap:wrap;
  gap:var(--gap-2) 0;
  margin:0 0 var(--gap-7);
  padding-block:var(--gap-3);
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  font-size:.9375rem;
  color:var(--ink-2);
}
.reg-meta__item{
  display:inline-flex;align-items:baseline;gap:var(--gap-2);
  min-width:0;
  padding-inline:var(--gap-5);
  border-left:1px solid var(--line);
}
.reg-meta__item:first-child{padding-left:0;border-left:0}
.reg-meta__k{
  font-size:.6875rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);
}
.reg-meta__v{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:600;color:var(--ink)}

/* --- Układ: spis + dokument ---------------------------------- */
.reg-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--gap-6)}

/* --- Spis treści --------------------------------------------- */
.reg-toc{min-width:0}
.reg-toc__summary{
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--gap-3);
  padding:var(--gap-3) 0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  font-size:.75rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.14em;
  color:var(--ink-2);
  cursor:pointer;list-style:none;
}
.reg-toc__summary::-webkit-details-marker{display:none}
/* Chevron z obwódki - bez ikony, bez ruchu; po otwarciu obraca się skokowo. */
.reg-toc__summary::after{
  content:'';flex:none;
  width:8px;height:8px;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  rotate:45deg;
  margin-right:var(--gap-1);
}
.reg-toc__details[open] .reg-toc__summary::after{rotate:225deg;margin-top:var(--gap-1)}
.reg-toc__details[open] .reg-toc__summary{border-bottom-color:transparent}

.reg-toc__list{
  margin:0;padding:0;
  border-left:1px solid var(--line);
}
.reg-toc__link{
  display:flex;align-items:baseline;gap:var(--gap-2);
  margin-left:-1px;
  padding:var(--gap-2) var(--gap-4);
  border-left:2px solid transparent;
  font-size:.9375rem;line-height:1.35;
  color:var(--ink-2);
  transition:color .16s var(--ease-out),border-color .16s var(--ease-out);
}
.reg-toc__no{
  flex:none;min-width:2ch;text-align:right;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:.8125rem;color:var(--ink-3);
  transition:color .16s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .reg-toc__link:hover{color:var(--ink);border-left-color:var(--line)}
}
.reg-toc__link[aria-current="true"]{
  color:var(--ink);font-weight:700;
  border-left-color:var(--red);
}
.reg-toc__link[aria-current="true"] .reg-toc__no{color:var(--red-700)}

/* --- Kolumna dokumentu --------------------------------------- */
/* 68ch tekstu + rynna numeracji (3rem), żeby wiersz nie przekraczał
   miary czytelnej dla przepisów: ok. 65-70 znaków. */
.reg-doc{
  max-width:calc(68ch + 3rem);
  min-width:0;
  line-height:1.65;
}
.reg-doc a{
  color:var(--red-700);text-decoration:underline;text-underline-offset:.18em;
  overflow-wrap:anywhere;
}
@media (hover:hover) and (pointer:fine){
  .reg-doc a:hover{color:var(--red-600)}
}

/* --- Rozdział ------------------------------------------------ */
.reg-chapter+.reg-chapter{
  margin-top:var(--gap-7);
  padding-top:var(--gap-7);
  border-top:1px solid var(--line);
}
/* Numer rozdziału stoi w tej samej rynnie co numery punktów - to numeracja
   dokumentu, nie ozdobny nadtytuł. Wyrównanie do linii bazowej tytułu. */
.reg-chapter__head{margin-bottom:var(--gap-5)}
.reg-chapter__title{
  display:grid;grid-template-columns:3rem minmax(0,1fr);
  align-items:baseline;
  margin:0;
  font-size:var(--fs-h3);
  text-wrap:balance;
}
.reg-chapter__no{
  justify-self:end;padding-right:.5ch;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:1rem;font-weight:800;letter-spacing:0;
  color:var(--ink-3);
}
.reg-chapter__hint{
  margin:var(--gap-2) 0 0;
  padding-left:3rem;
  font-size:.8125rem;line-height:1.45;
  color:var(--ink-3);
}
/* Akapity bez numeracji (rozdział „Nagrody") stoją w kolumnie tekstu. */
.reg-chapter__body{padding-left:3rem}
.reg-chapter__body>*+*{margin-top:var(--gap-3)}

/* --- Punkty z wiszącą numeracją ------------------------------ */
.reg-list{
  margin:0;padding-left:3rem;
  list-style:decimal outside;
}
.reg-list>li{
  min-width:0;
  overflow-wrap:anywhere;
  padding-left:.5ch;
}
.reg-list>li+li{margin-top:var(--gap-3)}
.reg-list>li::marker{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:600;font-size:.9375rem;
  color:var(--ink-3);
}
/* Druga lista rozdziału HDCP zaczyna od 4 (start="4") - wstawka
   redakcyjna stoi między nimi jako osobny blok. */
.reg-list+.reg-list{margin-top:var(--gap-3)}

/* Uwaga w treści punktu: własna linia, czerwona kreska, bez zmiany tekstu. */
.reg-note{
  display:block;
  margin-top:var(--gap-2);
  padding-left:var(--gap-3);
  border-left:3px solid var(--red);
  font-weight:700;
}

/* --- Dopisek redakcyjny: wzór HDCP --------------------------- */
.reg-formula{
  margin:var(--gap-5) 0 var(--gap-5) 3rem;
  padding:var(--gap-4) var(--gap-5);
  background:var(--paper-2);
  border-radius:var(--r);
}
.reg-formula__label{
  display:block;
  margin-bottom:var(--gap-3);
  font-size:.6875rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.12em;
  color:var(--ink-3);
}
.reg-formula__code{
  display:block;
  margin:0;padding:var(--gap-2) 0;
  overflow-x:auto;-webkit-overflow-scrolling:touch;
  font-family:var(--mono);font-size:.9375rem;font-weight:600;
  line-height:1.5;white-space:pre;
  color:var(--ink);
}
.reg-formula__rules{
  margin:var(--gap-3) 0 0;padding:0;
  font-size:.9375rem;line-height:1.55;color:var(--ink-2);
}
.reg-formula__rules li{
  position:relative;padding-left:var(--gap-4);
}
.reg-formula__rules li+li{margin-top:var(--gap-1)}
.reg-formula__rules li::before{
  content:'';position:absolute;left:0;top:.72em;
  width:6px;height:2px;background:var(--red);
}

/* --- Przykład z rozdziału HDCP ------------------------------- */
.reg-example{margin-top:var(--gap-4)}
.reg-example>*+*{margin-top:var(--gap-4)}
.reg-example__title{
  margin:var(--gap-6) 0 0;
  font-size:var(--fs-h4);
}
.reg-example>.reg-example__title:first-child{margin-top:0}

/* Wiersz meczu: drużyna | wynik | drużyna | kto wygrał. */
.reg-matches{margin:0;padding:0;border-top:1px solid var(--line)}
.reg-match{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto minmax(0,1fr) minmax(0,1.6fr);
  align-items:center;gap:var(--gap-3);
  padding:var(--gap-2) 0;
  border-bottom:1px solid var(--line);
  font-size:.9375rem;
}
.reg-match__team{font-weight:700}
.reg-match__team--away{text-align:right}
.reg-match__score{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-weight:700;white-space:nowrap;
  padding-inline:var(--gap-2);
}
.reg-match__win{color:var(--ink-2);text-align:right}

/* Tabele wyliczeń: liczby mono, do prawej; nagłówki bez łamania. */
.reg-tbl{min-width:0}
.reg-tbl thead th{white-space:nowrap}
.reg-tbl th[scope="row"]{
  text-align:left;font-weight:700;
  padding:var(--cell-y) var(--cell-x);
  border-bottom:1px solid var(--line-2);
}
.reg-tbl tbody tr:last-child th{border-bottom:0}
/* Kolejka II: każdy mecz we własnym <tbody>, między nimi pełna linia. */
.reg-tbl tbody+tbody tr:first-child th,
.reg-tbl tbody+tbody tr:first-child td{border-top:1px solid var(--line)}
.reg-tbl td.is-num{white-space:nowrap}
.reg-tbl .is-result{font-weight:800;color:var(--ink)}
/* Dopisek w komórce (sufit, zapadka): własna linia, krój tekstowy. */
.reg-tbl__why{
  display:block;
  font-family:var(--font);font-size:.75rem;font-weight:500;
  white-space:normal;color:var(--ink-3);
  text-align:right;
}
.reg-tbl td.is-note{font-size:.8125rem;color:var(--ink-2)}
.reg-tbl caption{font-size:.9375rem}

/* Przypis redakcyjny pod tabelą - komentarz, nie tekst regulaminu. */
.reg-footnote{
  margin-top:var(--gap-3);
  padding:var(--gap-3) var(--gap-4);
  background:var(--paper-2);
  border-radius:var(--r);
  font-size:.8125rem;line-height:1.55;color:var(--ink-2);
}
.reg-footnote__mark,
.reg-tbl sup{
  font-family:var(--mono);font-size:.6875rem;font-weight:700;
  color:var(--red-700);
  vertical-align:super;line-height:0;
}

/* --- Stopka dokumentu ---------------------------------------- */
.reg-foot{
  margin-top:var(--gap-7);
  padding-left:3rem;
  font-size:.9375rem;color:var(--ink-3);
}
.reg-foot p+p{margin-top:var(--gap-1)}

/* --- Responsywność ------------------------------------------- */
@media (min-width:981px){
  .reg-layout{grid-template-columns:240px minmax(0,1fr);gap:var(--gap-7);align-items:start}
  .reg-toc{
    position:sticky;
    top:calc(var(--nav-h) + var(--topbar-h) + var(--gap-5));
    max-height:calc(100vh - var(--nav-h) - var(--topbar-h) - var(--gap-6));
    overflow-y:auto;
  }
  /* Ze skryptem <details> jest zawsze otwarty i pasek „Spis treści"
     schodzi ze sceny - zostaje sama lista. Bez skryptu pasek zostaje,
     żeby dało się listę rozwinąć. */
  .reg-toc--js .reg-toc__summary{display:none}
}
@media (max-width:1180px){
  .reg-layout{gap:var(--gap-6)}
}
@media (max-width:980px){
  .reg-meta{margin-bottom:var(--gap-6)}
}
@media (max-width:760px){
  /* Przykład HDCP wraca na pełną szerokość kolumny - tabela ma
     wtedy o rynnę więcej miejsca, zanim zacznie się przewijać. */
  .reg-example{margin-left:-3rem}
  .reg-match{
    grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
  }
  .reg-match__win{grid-column:1 / -1;text-align:left;font-size:.875rem}
}
@media (max-width:560px){
  .reg-meta{flex-direction:column;gap:var(--gap-2)}
  .reg-meta__item{padding-inline:0;border-left:0}
  .reg-doc{max-width:none}
  .reg-chapter__title{grid-template-columns:2.5rem minmax(0,1fr)}
  .reg-chapter__body,.reg-chapter__hint,.reg-foot{padding-left:2.5rem}
  .reg-list{padding-left:2.5rem}
  .reg-formula{margin-left:0;padding:var(--gap-4)}
  .reg-formula__code{font-size:.875rem}
  .reg-example{margin-left:-2.5rem}
  .reg-chapter+.reg-chapter{margin-top:var(--gap-6);padding-top:var(--gap-6)}
}
@media (max-width:400px){
  .reg-chapter__title{grid-template-columns:2.25rem minmax(0,1fr)}
  .reg-chapter__body,.reg-chapter__hint,.reg-foot{padding-left:2.25rem}
  .reg-list{padding-left:2.25rem}
  .reg-example{margin-left:-2.25rem}
}

/* --- Druk ---------------------------------------------------- */
@media print{
  .reg-toc{display:none !important}
  .reg-layout{display:block}
  .reg-doc{max-width:none}
  .reg-meta{border-color:#000;color:#000}
  .reg-chapter+.reg-chapter{border-top-color:#000;margin-top:1rem;padding-top:1rem}
  .reg-chapter{page-break-inside:auto}
  .reg-chapter__head{page-break-after:avoid}
  .reg-note{border-left-color:#000}
  .reg-formula,.reg-footnote{background:#fff;border:1pt solid #000}
  .reg-formula__rules li::before{background:#000}
  .reg-tbl th,.reg-tbl td{border:1px solid #000 !important;background:#fff !important}
  .reg-match{border-bottom-color:#000}
  .reg-doc a{color:#000;text-decoration:none}
  .reg-doc a[href^="http"]::after{content:' (' attr(href) ')';font-size:8pt;color:#444}
  .reg-example{margin-left:0}
}

/* ============================================================
   Social bar - pasek nawigacji, arkusz menu, stopka
   Jedna lista ikon (Phosphor, waga fill) z layout_social_links().
   W pasku tylko na szerokim ekranie - na telefonie ma go arkusz menu.
   ============================================================ */
.nav__social{display:none;align-items:center;gap:var(--gap-1)}
@media (min-width:981px){.nav__social{display:flex}}
.nav__social a{
  display:inline-flex;padding:6px;border-radius:999px;
  color:inherit;opacity:.72;
  transition:opacity .16s var(--ease-out),transform .16s var(--ease-out);
}
.nav__social a svg{width:20px;height:20px}
@media (hover:hover) and (pointer:fine){.nav__social a:hover{opacity:1}}
.nav__social a:focus-visible{opacity:1}
.nav__social a:active{transform:scale(.97)}

.nav__menu-social{display:flex;justify-content:center;gap:var(--gap-2)}
.nav__menu-social a{
  display:inline-flex;padding:10px;border-radius:999px;
  border:1px solid rgba(255,255,255,.18);color:var(--white);
  transition:border-color .16s var(--ease-out),background-color .16s var(--ease-out),transform .16s var(--ease-out);
}
.nav__menu-social a svg{width:22px;height:22px}
@media (hover:hover) and (pointer:fine){
  .nav__menu-social a:hover{border-color:rgba(255,255,255,.6);background:rgba(255,255,255,.06)}
}
.nav__menu-social a:focus-visible{border-color:var(--white)}
.nav__menu-social a:active{transform:scale(.97)}

/* ============================================================
   Tekst ciągły: justowanie z dzieleniem wyrazów (html lang="pl")
   Dotyczy akapitów i punktów, nigdy nagłówków, przycisków, tabel.
   Ostatnia linia do lewej; w blokach wycentrowanych - do środka.
   ============================================================ */
.prose p,.prose li,.lead,.hero__lead,.section__desc,.news-card__excerpt,.tile__desc,
.foot__desc,.reg-chapter__body,.reg-list>li,.card__body p,.empty p{
  text-align:justify;text-align-last:start;
  -webkit-hyphens:auto;hyphens:auto;hyphenate-limit-chars:7 4 3;
  overflow-wrap:break-word;
}
.section__head--center .section__desc,.empty p{text-align-last:center}

/* ============================================================
   Telefon: albo do środka, albo do krawędzi - bez stanów pośrednich.
   Do środka: hero, nagłówek sekcji z opisem, stopka (marka, kolumny,
   pasek dolny), stopka arkusza menu, paginacja.
   Do krawędzi: karty, listy, tabele, formularze (bez zmian) oraz
   akapity - justowane, więc równe z obu stron.
   ============================================================ */
@media (max-width:760px){
  .hero__inner{text-align:center}
  .hero__logo-box{margin-inline:auto}
  .hero__lead{margin-inline:auto;text-align-last:center}
  .hero__actions,.hero__meta{justify-content:center}

  .section__head{align-items:center;text-align:center}
  .section__head-main{max-width:none}
  .section__desc{margin-inline:auto;text-align-last:center}

  .foot__grid{justify-items:center;text-align:center}
  .foot__col{align-items:center}
  .foot__col--brand{max-width:none;padding-right:0}
  .foot__desc{text-align-last:center}
  .foot__social{justify-content:center}
  .foot__bar{flex-direction:column;align-items:center;text-align:center;gap:var(--gap-3)}
  .foot__bar-links{justify-content:center}
  .foot__addr,.foot__fine{text-align:center}

  .nav__menu-foot{align-items:center;text-align:center}
  .nav__menu-meta,.nav__menu-secondary{justify-content:center}

  .pagination{justify-content:center}
}
