/*
 * DartCon — fundament wspólny dla wszystkich ekranów.
 *
 * Ten plik wczytuje KAŻDA strona, przed swoim własnym arkuszem. Trzyma to,
 * co nie może się różnić między stroną główną a panelem: kolory, siatkę,
 * typografię, przyciski, logotyp.
 *
 * Powód rozdziału (2026-08-14, etap 2.2): gdy powstał pierwszy ekran poza
 * stroną główną, alternatywą było skopiowanie zmiennych do drugiego pliku.
 * Kopia zawsze się w końcu rozjeżdża i kończy pytaniem „dlaczego panel ma
 * inny odcień granatu”. Jedno źródło, zero kopii.
 *
 * ── SIATKA 8 PX ──────────────────────────────────────────────────────────────
 * Wszystkie odstępy (margin, padding, gap) pochodzą wyłącznie ze zmiennych
 * --s-*, a każda z nich jest wielokrotnością 8 px. Nigdzie — ani tu, ani
 * w arkuszach ekranów — nie powinna pojawić się surowa wartość odstępu.
 * Brakuje kroku? Dopisujemy zmienną, nie wyjątek. Nazwa zasady: 8-point grid.
 *
 * Dwa dopuszczone wyjątki:
 *   • --s-0 (4 px) — pół kroku, wyłącznie wewnątrz drobnych elementów
 *     (gałka przełącznika, znacznik odhaczenia), nigdy w układzie strony;
 *   • wymiary rysunków w CSS (ptaszek, strzałka) — to grafika, nie odstęp.
 *
 * ── PALETY ───────────────────────────────────────────────────────────────────
 * Plik odziedziczony 1:1 z dart-managera (dartcon.pl) przy budowie tej apki
 * (9 września — „UI zostawiamy tak jak jest"). Historia niżej („gold" vs
 * „ember" vs „slate") to decyzja DARTCON-a, nie tej aplikacji — zostawiona
 * tu wyłącznie dlatego, że mechanizm przełączania (`data-palette`) działa
 * i jest nieszkodliwy; żaden szablon dartcast.pl nie prosi o te warianty.
 *
 * DECYZJA 2026-09-10 (Jarek): dartcast.pl dostaje WŁASNĄ, odróżnioną od
 * dartcon.pl paletę — „teal": granat + turkus. Punkt wyjścia — cztery
 * gotowe kolory podane przez Jarka (Blue Zodiac, Tiara, Fountain Blue,
 * Regent Gray); reszta zmiennych (surface/border/text-soft/faint,
 * accent-hover) dopełniona metodą dartcon-a — te same przesunięcia
 * jasności co przy tworzeniu „gold" z jego bazowego granatu, żeby rodzina
 * odcieni trzymała się spójnie, nie na oko.
 *
 * ⚠ Kontrasty policzone (WCAG, luminancja względna), nie ocenione wzrokiem:
 * tekst (Tiara) na tle 10,17:1, akcent (turkus) na tle 7,42:1, --on-accent
 * (granat) na akcencie też 7,42:1 (ten sam kontrast w obie strony — to nie
 * przypadek, tak działa formuła), --text-muted (Regent Gray) na tle 4,59:1
 * — wszystko nad normą 4,5:1 dla tekstu.
 *
 * ⚠ NIE DOTYCZY nakładek OBS (`public/js/obs/*.js`, `public/css/obs/*.css`)
 * — ich wygląd jest CELOWO niezależny od palety serwisu i ma zostać taki,
 * jak jest (komentarz w każdym pliku nakładki: „dopasowany do transmisji,
 * nie do serwisu"). Ta zmiana koloruje panel i logowanie, nie wizję.
 *
 * ⚠ Teal jest teraz wartością DOMYŚLNą (:root). Nie dopisywać
 * `data-palette="teal"` do szablonów z tego samego powodu co przy „slate"
 * w dartcon-ie: byłoby to powtórzenie wartości domyślnej w wielu miejscach.
 */

/* ─── Siatka i typografia (wspólne dla obu palet) ─────────────────────────── */

:root {
    --s-0: 4px; /* pół kroku — tylko wewnątrz drobnych elementów, nigdy w układzie strony */
    --s-1: 8px;
    --s-2: 16px;
    --s-3: 24px;
    --s-4: 32px;
    --s-5: 40px;
    --s-6: 48px;
    --s-7: 56px;
    --s-8: 64px;
    --s-9: 72px;
    --s-10: 80px;
    --s-12: 96px;
    --s-16: 128px;

    --radius: 8px;
    --radius-lg: 16px;

    --container: 1216px; /* 152 x 8 */

    --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;

    /*
     * Mówi przeglądarce, że strona jest ciemna — a przez to każdy element
     * rysowany przez system, na który nie mamy wpływu: kalendarz przy polu daty,
     * zegar przy polu godziny, rozwinięta lista pola wyboru, paski przewijania.
     * Bez tego jasny kalendarz wyskakuje z ciemnego formularza jak latarka.
     */
    color-scheme: dark;
}

/* ─── Paleta APLIKACJI: granat + turkus ─────────────────────────────────────────── */

/*
 * ⚠ TEN BLOK MUSI STAĆ PRZED POZOSTAŁYMI PALETAMI. Ma tę samą szczegółowość
 * co one, więc przy równej wadze decyduje kolejność w pliku — przesunięty
 * niżej nadpisywałby turkus na stronach, które go wybierają.
 *
 * „teal" — paleta WŁASNA dartcast.pl (2026-09-10), nie dziedziczona z
 * dartcon.pl. Uzasadnienie i pełny rachunek kontrastów stoją w komentarzu
 * na górze pliku, sekcja „PALETY".
 *
 * ⚠ WARTOŚCI SĄ PRZEPISANE, nie odziedziczone — każda paleta poniżej
 * („gold", „ember") jest osobnym, kompletnym zestawem po dartcon-ie i tak
 * ma zostać: to cudza, zamknięta historia, nietykana przy zmianach tutaj.
 */
:root,
[data-palette="teal"] {
    /* Blue Zodiac — kolor podany przez Jarka, baza całej palety. */
    --bg: #0c243c;
    --bg-rgb: 12, 36, 60;
    --bg-alt: #0e2742;
    --surface: #132e4c;
    --surface-2: #173557;
    --border: #234266;
    --border-soft: #1b3654;

    /* Tiara — jasny, chłodny szary z lekkim błękitem, zamiast czystej bieli. */
    --text: #c9d1d5;
    --text-soft: #a7b2bb;
    /* Regent Gray — kolor podany przez Jarka, na wprost jako text-muted. */
    --text-muted: #7e8c9c;
    --text-faint: #58626d;

    /* Fountain Blue — kolor podany przez Jarek, akcent całej apki. Turkus
       zamiast złota dartcon-a jest tu celem samym w sobie: odróżnić na
       pierwszy rzut oka, które okno jest którą aplikacją. */
    --accent: #55c2c3;
    --accent-hover: #6ecbcc;
    --accent-soft: rgba(85, 194, 195, .14);
    --on-accent: #0c243c; /* Blue Zodiac — ten sam granat co tło, na turkusowym przycisku */

    /* Stany zapożyczone z sensownie najbliższej palety dartcon-a („gold") —
       tam już były liczone pod ciemny granat, a Blue Zodiac jest tego samego
       rzędu ciemności. Kontrast na --bg: bad 5,06:1, warn 9,06:1 (policzone
       na nowo pod ten konkretny granat, nie przepisane na wiarę). */
    --ok: #6ecf8e;
    --ok-soft: rgba(110, 207, 142, .12);
    --warn: #e8c04a;
    --warn-soft: rgba(232, 192, 74, .12);
    --bad: #e8697d;
    --bad-soft: rgba(232, 105, 125, .12);

    --placeholder-bg: #0e2742;
    --placeholder-stripe: rgba(255, 255, 255, .022);
    --placeholder-text: #62788c;
}

/* ─── Paleta zapasowa: granat + złoto ──────────────────────────────────────────── */

[data-palette="gold"] {
    --bg: #0b1220;
    --bg-rgb: 11, 18, 32; /* to samo co --bg, rozłożone na składowe pod przyciemnienie */
    --bg-alt: #0d1526;
    --surface: #121c30;
    --surface-2: #16233b;
    --border: #22304a;
    --border-soft: #1a2438;

    --text: #eef2f8;
    --text-soft: #c2cddd;
    --text-muted: #8d9cb4;
    --text-faint: #5f6e86;

    /*
     * Złoto na próbę (Jarek, 2026-08-15). Głębsze i mocniej nasycone od
     * poprzedniego — bliżej mosiądzu niż szampana.
     *
     * ⚠ POWRÓT do poprzedniego to podmiana tych trzech wartości i nic więcej:
     *     --accent: #d9b45b;
     *     --accent-hover: #e7c674;
     *     --accent-soft: rgba(217, 180, 91, .14);
     * Cała aplikacja bierze kolor stąd — żaden inny plik nie zna go z nazwy.
     *
     * Kontrast sprawdzony: #c89020 na granacie tła daje 6,7:1, a granat na
     * złotym przycisku tyle samo. Norma dla tekstu to 4,5:1, więc jest zapas
     * — poprzednie złoto miało 9,5:1, czyli jaśniejsze, ale i bardziej blade.
     */
    --accent: #c89020;
    --accent-hover: #dfa635;
    --accent-soft: rgba(200, 144, 32, .14);
    --on-accent: #0b1220; /* granat tła — napis na złotym przycisku */

    /*
     * Kolory STANU (2026-08-16, polecenie Jarka przy liście kont). Zielony,
     * żółty i czerwony niosą znaczenie, którego akcent nieść nie może: akcent
     * mówi „tu kliknij", a te mówią „tak jest".
     *
     * ⚠ Kolor NIGDY nie jest jedynym nośnikiem znaczenia — przy każdym takim
     * napisie stoi słowo („aktywne", „zablokowane"). Inaczej ekran byłby
     * nieczytelny dla osób nierozróżniających barw i na wydruku.
     *
     * Odcienie są jaśniejsze, niż wyglądają na papierze — na granacie mocna
     * czerwień i ciemna zieleń stają się nieczytelne. Kontrast na tle --bg:
     * zielony 9,9:1, żółty 9,6:1, czerwony 5,7:1. Norma dla tekstu to 4,5:1.
     *
     * Żółty jest CIEPLEJSZY i jaśniejszy od akcentu, żeby nie czytało się go
     * jako złota — te dwa kolory stoją czasem w jednej tabeli.
     */
    --ok: #6ecf8e;
    --ok-soft: rgba(110, 207, 142, .12);
    --warn: #e8c04a;
    --warn-soft: rgba(232, 192, 74, .12);
    --bad: #e8697d;
    --bad-soft: rgba(232, 105, 125, .12);

    --placeholder-bg: #101a2b;
    --placeholder-stripe: rgba(255, 255, 255, .022);
    --placeholder-text: #6b83a8;
}

/* ─── Paleta odrzucona: grafit + pomarańcz ──────────────────────────────────────── */

[data-palette="ember"] {
    --bg: #0f1012;
    --bg-rgb: 15, 16, 18;
    --bg-alt: #131518;
    --surface: #17191c;
    --surface-2: #1c1f23;
    --border: #2a2e34;
    --border-soft: #212429;

    --text: #edeef0;
    --text-soft: #c8cbd0;
    --text-muted: #9aa0a6;
    --text-faint: #6b7076;

    --accent: #d1512e;
    --accent-hover: #e26139;
    --accent-soft: rgba(209, 81, 46, .14);
    --on-accent: #ffffff;

    /*
     * ⚠ Czerwony stanu jest tu RÓŻOWAWY i celowo odsunięty od pomarańczowego
     * akcentu tej palety. Gdyby był czystą czerwienią, „zablokowane" zlewałoby
     * się z każdym przyciskiem na ekranie.
     */
    --ok: #62c98a;
    --ok-soft: rgba(98, 201, 138, .12);
    --warn: #e6bf4b;
    --warn-soft: rgba(230, 191, 75, .12);
    --bad: #ef7d92;
    --bad-soft: rgba(239, 125, 146, .12);

    --placeholder-bg: #141619;
    --placeholder-stripe: rgba(255, 255, 255, .022);
    --placeholder-text: #7c848d;
}

/* ─── Podstawy ────────────────────────────────────────────────────────────── */

* { box-sizing: border-box; }

/*
 * Zabezpieczenie przed przesuwaniem strony w bok na telefonie.
 *
 * MUSI być `hidden` i MUSI stać na <html>. Wcześniej stało tu `clip` — wybrane
 * dlatego, że nie zamienia strony w kontener przewijania — i nie działało:
 * `clip` na dokumencie NIE jest przenoszone na okno przeglądarki, więc okno
 * dalej pozwalało przewijać w bok. `hidden` na <html> jest przenoszone i jako
 * jedyne zatrzymuje przewijanie.
 *
 * Nie dopisywać tego samego do <body>: wtedy to body stałoby się kontenerem
 * przewijania i przestałyby działać elementy przyklejone do krawędzi okna.
 *
 * Zmierzone 2026-08-15 na telefonie: okno 411 px, strona 695 px, przy czym
 * wykrywacz nie znalazł ANI JEDNEGO elementu szerszego od okna. Nadmiar bierze
 * się więc z czegoś, czego nie widać w treści — obcięcie go niczego nie ukrywa.
 */
html { overflow-x: hidden; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 24px;
    -webkit-font-smoothing: antialiased;
}

/*
 * Paski przewijania w kolorach aplikacji zamiast systemowych (prośba Jarka,
 * 2026-08-15). Obie właściwości są dziedziczone, więc ustawione raz na
 * dokumencie obowiązują też w każdym pojemniku z własnym przewijaniem —
 * w oknie wyboru lokalu, w tabeli porównania planów, w pasku nawigacji panelu.
 *
 * Reguły `::-webkit-scrollbar` niżej są dla starszych przeglądarek. Nowsze,
 * gdy widzą `scrollbar-color`, pomijają je — i dobrze, bo dają ten sam efekt.
 */
html {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

::-webkit-scrollbar {
    width: var(--s-1);
    height: var(--s-1);
}

::-webkit-scrollbar-track { background: transparent; }

::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: var(--radius);
}

::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }

a { color: inherit; text-decoration: none; }

img { max-width: 100%; display: block; }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

.container {
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding-left: var(--s-3);
    padding-right: var(--s-3);
}

@media (min-width: 768px) {
    .container {
        padding-left: var(--s-4);
        padding-right: var(--s-4);
    }
}

/* ─── Drobiazgi wielokrotnego użytku ──────────────────────────────────────── */

/* Napis techniczny: nadtytuł sekcji, etykieta pola, numer kroku. */
.eyebrow {
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 16px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-faint);
}

/*
 * Treść dla czytników ekranu, niewidoczna na ekranie.
 *
 * ⚠ Jest pozycjonowana bezwzględnie, więc bez najbliższego „punktu odniesienia”
 * przyczepia się do CAŁEGO DOKUMENTU. Wewnątrz ramki przewijanej w poziomie
 * oznacza to, że ucieka poza jej przewijanie i rozciąga stronę — objaw:
 * na telefonie da się przesunąć całą stronę w bok, choć nic nie wystaje.
 *
 * Każdy pojemnik z własnym przewijaniem, w którym używamy tej klasy, musi mieć
 * `position: relative` (przykład: .table-scroll w landing.css).
 */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Fragment, który nie ma prawa złamać się w połowie — np. kwota z jednostką. */
.nowrap { white-space: nowrap; }

/*
 * Miejsce na grafikę, której jeszcze nie ma. Paski rysowane gradientem, więc
 * nie ma tu żadnego pliku do zgubienia. Opis w środku mówi, co ma tu trafić
 * i w jakim rozmiarze.
 */
.placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--s-6) var(--s-3);
    min-height: 240px;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background-color: var(--placeholder-bg);
    background-image: repeating-linear-gradient(
        45deg,
        var(--placeholder-stripe) 0,
        var(--placeholder-stripe) 8px,
        transparent 8px,
        transparent 16px
    );
}

.placeholder span {
    font-family: var(--font-mono);
    font-size: 13px;
    line-height: var(--s-3);
    color: var(--placeholder-text);
    text-align: center;
}

/* ─── Logotyp ─────────────────────────────────────────────────────────────── */

.brand {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    flex: none;
}

.brand-name {
    font-family: var(--font-mono);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
}

.brand-mark {
    width: var(--s-4);
    height: var(--s-4);
    border-radius: 50%;
    border: 2px solid var(--accent);
    position: relative;
    flex: none;
}

.brand-mark::after {
    content: "";
    position: absolute;
    inset: var(--s-1);
    border-radius: 50%;
    background: var(--accent);
}

/* ─── Przyciski ───────────────────────────────────────────────────────────── */

/*
 * Wysokość przycisku jest ustalona wprost, a nie wyliczana z wypełnienia —
 * dzięki temu warianty nie mogą się rozjechać, gdy któremuś zmienimy stopień
 * pisma albo obramowanie. Każdy wariant ma też widoczną ramkę we własnym
 * kolorze, żeby wszystkie miały tę samą budowę optyczną.
 */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    min-height: var(--s-6);
    padding: var(--s-1) var(--s-3);
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: inherit;
    font-size: 15px;
    line-height: 24px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}

.btn-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

.btn-ghost {
    background: transparent;
    border-color: var(--border);
    color: var(--text);
}

/*
 * Potwierdzenie obecności na odprawie (polecenie Jarka, 2026-08-21: „potwierdź
 * na zielono"). Wypełniony, bo w dniu turnieju klika się go co kilkanaście
 * sekund i musi być celem dla kciuka, a nie kolejną ramką do wypatrzenia.
 *
 * ⚠ Napis w kolorze tła aplikacji, nie biały: zieleń jest jasna i biały tekst
 * na niej znika. Ten zestaw daje kontrast powyżej normy AA.
 */
.btn-ok {
    background: var(--ok);
    border-color: var(--ok);
    color: var(--bg);
}

.btn-ok:hover {
    background: color-mix(in srgb, var(--ok) 85%, #fff);
    border-color: color-mix(in srgb, var(--ok) 85%, #fff);
}

.btn-ghost:hover { border-color: var(--text-muted); }

/* Wypełniony przycisk drugiego wyboru — czytelny na zdjęciu w tle hero. */
.btn-secondary {
    background: var(--surface);
    border-color: var(--border);
    color: var(--text);
}

.btn-secondary:hover { background: var(--surface-2); }

/*
 * Wejście przez Google. Wygląda inaczej niż nasze przyciski celowo — ludzie
 * rozpoznają ten guzik z dziesiątek innych serwisów i to rozpoznanie jest tu
 * całą wartością.
 *
 * ⚠ To zwykły ODNOŚNIK do naszego własnego adresu, który dopiero przekierowuje
 * do Google. Żadnej biblioteki od Google w stronie: polityka bezpieczeństwa
 * z etapu 1.3 zostaje nietknięta, a Google nie dowiaduje się, kto ogląda
 * formularz, dopóki nikt świadomie nie kliknie.
 */
.btn-google {
    gap: var(--s-1);
    background: #ffffff;
    border-color: #dadce0;
    color: #1f1f1f;
}

.btn-google:hover {
    background: #f1f3f4;
    border-color: #c6cacd;
}

.btn-google svg {
    flex: none;
    width: var(--s-3);
    height: var(--s-3);
}

/* Kreska z napisem „albo" między dwiema drogami wejścia. Rysowana obramowaniem
   po bokach napisu, więc nie potrzeba dodatkowych znaczników w treści. */
.or-sep {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin: var(--s-2) 0;
    font-size: 13px;
    color: var(--text-faint);
}

.or-sep::before,
.or-sep::after {
    content: "";
    flex: 1 1 auto;
    border-top: 1px solid var(--border-soft);
}

.btn-block { width: 100%; }

.btn-sm {
    min-height: var(--s-5);
    padding: var(--s-0) var(--s-2);
    font-size: 14px;
}

/* Przycisk nieaktywny — funkcja jeszcze nie istnieje. Renderowany jako <span>, */
/* więc nie da się w niego kliknąć ani dojść do niego tabulatorem.              */
.btn-disabled {
    background: transparent;
    border-color: var(--border-soft);
    color: var(--text-faint);
    cursor: not-allowed;
}

/*
 * Przycisk wyłączony ATRYBUTEM — wygląda tak samo jak `.btn-disabled`, który jest
 * wersją dla elementów niebędących przyciskami (np. `<span>` udający przycisk).
 *
 * ⚠ Bez tej reguły `<button class="btn btn-primary" disabled>` zostawał w kolorze
 * akcentu, czyli wyglądał na gotowy do kliknięcia, mimo że nie reagował. Dotyczyło to już
 * dwóch miejsc: zgody na regulamin i przycisku zapisu na turniej, wygaszanego
 * do czasu podania nazwiska.
 *
 * Dwa człony selektora, bo `:disabled` musi wygrać z `.btn-primary`.
 */
.btn:disabled,
.btn[disabled] {
    background: transparent;
    border-color: var(--border-soft);
    color: var(--text-faint);
    cursor: not-allowed;
}

/* ─── Drobiazgi wspólne dla panelu i stron publicznych ────────────────────── */

/*
 * Przeniesione tutaj z panel.css 2026-08-15, gdy strona turnieju zaczęła
 * otwierać się samodzielnie — bez niczego z panelu organizatora. Wszystko
 * poniżej pojawia się w obu miejscach.
 */

/* Wszystko, co ma sens wyłącznie przy działającym skrypcie. */
html:not(.has-js) .js-only { display: none; }

/*
 * Odwrotność `.js-only`: droga na piechotę, którą skrypt zastępuje czymś
 * wygodniejszym. Element ZOSTAJE w kodzie strony i dalej działa — chowamy go
 * wyłącznie przed oczami, bo obok stanął przycisk robiący to samo.
 *
 * Pierwsze użycie (2026-08-30): pole „Usuń tę kategorię przy zapisie" w edycji
 * turnieju. Bez skryptu jest jedyną drogą do skasowania kategorii; ze skryptem
 * przełącza je kosz w rzędzie.
 */
html.has-js .js-off { display: none; }

/* Kółko z inicjałami zalogowanego — w belce panelu i na stronie turnieju. */
.avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--s-4);
    height: var(--s-4);
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--surface-2);
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-soft);
}

/*
 * Pasek zapełnienia — ile miejsc zajętych. To <progress>, a nie kolorowy
 * prostokąt z szerokością wpisaną w HTML: styl wpisany w znacznik łamie
 * `style-src 'self'` i skasowałby wynik z etapu 1.3. Przy okazji czytnik ekranu
 * dostaje wartość i maksimum bez dodatkowej pracy.
 *
 * Szerokość ustala miejsce użycia — tu jest tylko wygląd.
 */
.fill-bar {
    appearance: none;
    display: block;
    width: 120px;
    height: var(--s-0);
    border: 0;
    border-radius: var(--radius);
    background: var(--border-soft);
}

.fill-bar::-webkit-progress-bar {
    background: var(--border-soft);
    border-radius: var(--radius);
}

.fill-bar::-webkit-progress-value {
    background: var(--accent);
    border-radius: var(--radius);
}

.fill-bar::-moz-progress-bar {
    background: var(--accent);
    border-radius: var(--radius);
}

/*
 * Ramka przewijana w poziomie — na tabele szersze od telefonu.
 *
 * ⚠ Przeniesione z landing.css (2026-08-16), gdy tabele pojawiły się także
 * w panelu: lista zgłoszeń, lista rezerwowa i konta w administracji. Panel nie
 * wczytuje arkusza strony głównej, więc reguła musiała trafić do wspólnego.
 *
 * `position: relative` NIE jest tu ozdobnikiem — bez niego przeglądarki potrafią
 * zgubić zaokrąglenie przy przewijaniu zawartości.
 *
 * Tabela w środku ma mieć `min-width`: to ona decyduje, kiedy zaczyna się
 * przewijanie. Bez tego ściśnie się do szerokości ekranu i zrobi z treści kaszę,
 * zamiast pozwolić przesunąć ją palcem.
 */
.table-scroll {
    position: relative;
    max-width: 100%;
    overflow-x: auto;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-lg);
}

/* Znacznik stanu: szkic, opublikowany, zakończony. */
.badge {
    display: inline-block;
    padding: 0 var(--s-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-alt);
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: var(--s-3);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Adres do wysłania innym, z przyciskiem kopiowania obok. */
.share {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-1);
    padding: var(--s-1) var(--s-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-alt);
}

.share-link {
    flex: 1 1 180px;
    min-width: 0;
    overflow-wrap: anywhere;
    font-family: var(--font-mono);
    font-size: 13px;
    line-height: var(--s-3);
    color: var(--text);
}

/* Ramka „to jeszcze makieta". Znika razem z podłączeniem prawdziwych danych. */
.mockup-note {
    margin: var(--s-4) 0 0;
    padding: var(--s-2);
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    font-size: 13px;
    line-height: var(--s-3);
    color: var(--text-faint);
}

/* ─── Pola formularza ─────────────────────────────────────────────────────── */

/*
 * Przeniesione tutaj z landing.css 2026-08-15, gdy powstał drugi formularz
 * (ogłoszenie turnieju). Pole tekstowe musi wyglądać tak samo przy zakładaniu
 * konta i przy tworzeniu turnieju — inaczej po zalogowaniu człowiek trafia
 * do aplikacji, która wygląda jak inny produkt.
 *
 * Tu jest wyłącznie samo pole: etykieta, ramka, podpowiedź. Wszystko, co dotyczy
 * układu konkretnego formularza (karta rejestracji, sekcje panelu), zostaje
 * w arkuszu tamtego ekranu.
 */

/* Część formularza z własnym nagłówkiem — np. „Twoje konto” i „Twój klub”. */
.field-group { margin-bottom: var(--s-3); }

.field-group > .eyebrow {
    display: block;
    margin-bottom: var(--s-2);
    padding-bottom: var(--s-1);
    border-bottom: 1px solid var(--border-soft);
}

.field { margin-bottom: var(--s-1); }

/*
 * Pola obok siebie — ale dopiero, gdy jest na to miejsce. Na wąskim telefonie
 * dwa pola w rzędzie robią się węższe niż wpisywana w nie treść.
 */
.field-row { display: grid; gap: var(--s-2); }

/* Odstępy w rzędzie daje siatka, więc pola nie dokładają własnych — inaczej
   po zwinięciu do jednej kolumny sumowałyby się z odstępem siatki. */
.field-row > .field { margin-bottom: 0; }

@media (min-width: 600px) {
    .field-row { grid-template-columns: 1fr 1fr; }
    .field-row-3 { grid-template-columns: 1fr 1fr 1fr; }
}

/*
 * Wyłącznie etykieta BEZPOŚREDNIO w polu — stąd `>`, a nie zwykły odstęp.
 *
 * Bez tego reguła łapała każdą etykietę gdziekolwiek w środku: warianty wyboru,
 * pola wyboru z opisem, całą zawartość okna wyboru lokalu. Skutek był widoczny
 * gołym okiem (zgłoszone 2026-08-15): nazwy lokali wielkimi literami czcionką
 * maszynową, a rozstrzelony tekst rozpychał okno na boki.
 */
.field > label {
    display: block;
    margin-bottom: var(--s-1);
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 16px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.field input,
.field select,
.field textarea {
    width: 100%;
    padding: var(--s-1) var(--s-2);
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-family: inherit;
    font-size: 15px;
    line-height: 24px;

    /*
     * Kolor zaznaczenia w elementach, których NIE rysujemy my: podświetlony
     * dzień w kalendarzu przy polu daty, zaznaczona pozycja na rozwiniętej
     * liście wyboru. Sam kalendarz jest okienkiem przeglądarki nad stroną —
     * CSS nie sięga do jego tła ani kroju pisma i nie da się go upodobnić
     * do aplikacji. To jedyny kolor, na który mamy tam wpływ, i tylko w tych
     * przeglądarkach, które go uwzględniają.
     *
     * Świadoma decyzja (2026-08-15): zostajemy przy kalendarzu przeglądarki
     * zamiast pisać własny. Na telefonie systemowy wybierak dat jest wygodniejszy
     * od czegokolwiek, co zbudowalibyśmy sami, i działa z klawiatury oraz
     * z czytnikiem ekranu bez naszej pracy.
     */
    accent-color: var(--accent);
}

/*
 * Spis powodów odrzucenia formularza (2026-08-22). Odpowiednik `.notice-ok`,
 * tylko w drugą stronę — stoi w base.css, a nie przy jednym ekranie, bo każdy
 * formularz, który potrafi odmówić, potrafi też odmówić niewidzialnie.
 */
.notice-bad {
    margin: 0 0 var(--s-3);
    padding: var(--s-2) var(--s-3);
    background: var(--bad-soft);
    border-left: 3px solid var(--bad);
    border-radius: 0 var(--radius) var(--radius) 0;
}

.notice-bad-title {
    margin: 0 0 var(--s-1);
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}

.notice-bad-list {
    margin: 0;
    padding-left: var(--s-2);
    font-size: 14px;
    line-height: var(--s-3);
    color: var(--text-muted);
}

.field textarea {
    min-height: var(--s-12);
    resize: vertical; /* w poziomie nie — rozciągnięte pole wyłamałoby się z siatki */
}

/*
 * SAMODOPASOWANIE WYSOKOŚCI DO TREŚCI (zgłoszenie Jarka, 2026-09-08: pole
 * opisu trzeba było rozciągać albo przewijać, żeby zobaczyć cały wpisany
 * tekst). `[data-autogrow]` w HTML-u, wysokość liczy `wireAutogrow()`
 * w panel.js — stąd `.has-js`, bo bez skryptu nie ma kto tego policzyć i pole
 * zostaje przy zwykłym, ręcznym rozciąganiu jak dotąd.
 *
 * `resize: none`, bo ręczne rozciąganie i automatyczne dopasowanie kłóciłyby
 * się o wysokość przy każdym kolejnym znaku — z autodopasowaniem uchwyt jest
 * już zbędny.
 *
 * `max-height` to WYŁĄCZNIE siatka bezpieczeństwa dla bardzo długiego opisu
 * (limit pola to 5000 znaków) — powyżej tej wysokości pole przewija się samo
 * w sobie, zamiast rozpychać całą stronę w nieskończoność.
 */
.has-js .field textarea[data-autogrow] {
    max-height: 70vh;
    overflow-y: auto;
    resize: none;
}

/* Wybór pliku. Sam przycisk rysuje przeglądarka, więc ustawiamy mu wygląd
   osobno — domyślnie jest jasny i wygląda jak wyrwany z innej strony. */
.field input[type="file"] {
    padding: var(--s-0) var(--s-1);
    font-size: 14px;
}

.field input[type="file"]::file-selector-button {
    margin-right: var(--s-1);
    padding: var(--s-0) var(--s-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
}

.field input[type="file"]::file-selector-button:hover { border-color: var(--text-muted); }

.field input::placeholder,
.field textarea::placeholder { color: var(--text-faint); }

.field input:focus,
.field select:focus,
.field textarea:focus {
    outline: none;
    border-color: var(--accent);
}

/* Pole wyłączone: czytelne, ale widać, że nie da się w nie wpisać. */
.field input:disabled,
.field select:disabled,
.field textarea:disabled {
    border-color: var(--border-soft);
    color: var(--text-faint);
    cursor: not-allowed;
}

/*
 * Zdanie pod polem: jednostka, ograniczenie, wyjaśnienie skutku.
 *
 * Kolor to --text-muted, nie --text-faint. Najsłabszy odcień palety jest
 * przeznaczony do napisów technicznych (numer kroku, nadtytuł sekcji), które
 * wystarczy zauważyć. Tego zdania trzeba faktycznie *dokonać* — a na tle
 * formularza --text-faint nie dobija do wymaganego kontrastu 4,5:1 i po prostu
 * ginie (zgłoszone 2026-08-15).
 */
.field-hint {
    margin: var(--s-0) 0 0;
    font-size: 13px;
    line-height: var(--s-3);
    color: var(--text-muted);
}

/* Gwiazdka przy polu wymaganym. Sama gwiazdka nic nie mówi czytnikowi ekranu,
   stąd atrybut `required` na polu — to on jest właściwą informacją. */
.req { color: var(--accent); }

/*
 * Pole wyboru z opisem. Cały wiersz jest etykietą, więc klika się także w tekst,
 * a nie wyłącznie w kwadracik o boku 16 px — na telefonie to różnica między
 * „działa” a „nie da się trafić”.
 */
.check {
    display: flex;
    align-items: flex-start;
    gap: var(--s-1);
    margin-bottom: var(--s-1);
    font-size: 14px;
    line-height: var(--s-3);
    color: var(--text-soft);
    cursor: pointer;
}

.check input {
    flex: none;
    width: var(--s-2);
    height: var(--s-2);
    margin: var(--s-0) 0 0; /* opuszczone o pół kroku, żeby stanęło w osi pierwszego wiersza */
    accent-color: var(--accent);
}

.check span { display: block; }

.check .field-hint { margin: 0; }

/* ─── Ekran zamarkowany ───────────────────────────────────────────────────── */

/*
 * Szkielet ekranu, którego jeszcze nie ma — patrz resources/views/partials/stub.
 * W base.css, bo takich ekranów jest kilkanaście i stoją w trzech różnych
 * ramach: panelu klubu, panelu zawodnika i administracji.
 *
 * Ramka przerywana zamiast ciągłej. To jedyne miejsce w serwisie, gdzie używamy
 * przerywanej linii, i niesie ona znaczenie: rzecz nieskończona, w budowie.
 */
.stub {
    padding: var(--s-4);
    border: 1px dashed var(--border);
    border-radius: var(--radius-lg);
    background: var(--bg-alt);
}

.stub-why {
    margin: var(--s-1) 0 0;
    max-width: 60ch;
    color: var(--text-soft);
}

.stub-lead {
    margin: var(--s-3) 0 var(--s-1);
    font-weight: 600;
}

.stub-list {
    margin: 0;
    padding-left: var(--s-3);
    max-width: 70ch;
    line-height: var(--s-4);
    color: var(--text-soft);
}

.stub-note {
    margin: var(--s-4) 0 0;
    padding-top: var(--s-2);
    border-top: 1px solid var(--border-soft);
    font-size: 13px;
    line-height: var(--s-3);
    color: var(--text-faint);
}

/* `.badge-on` skasowane 2026-08-16. Zastąpione przez `.state` z kolorem —
   plakietki w ramkach zniknęły z list kont i zgłoszeń. `.badge` zostaje:
   używa go lista turniejów na oznaczenie szkicu i turnieju zakończonego,
   gdzie stoi samotnie przy nazwie, a nie w kolumnie obok innych wartości. */

/*
 * Wartość pola opisana słowem i wsparta kolorem — stan konta, rola, stan
 * zgłoszenia. Zastąpiła plakietki w ramkach na liście kont (polecenie Jarka,
 * 2026-08-16): ramka wokół jednej wartości w kolumnie, gdzie reszta stoi bez
 * ramki, czyta się jak wyróżnienie, a nie jak inna wartość tego samego pola.
 *
 * W base.css, bo te same stany pojawią się poza administracją — przy klubach,
 * kodach promocyjnych i zgłoszeniach.
 */
.state {
    font-size: 14px;
    line-height: var(--s-3);
    color: var(--text-muted);
}

/* Stan normalny, ale nie warty uwagi — przygaszony mocniej niż zwykły `.state`.
   Dodany 2026-08-17 do kolumny „konto" w składzie drużyny: brak konta jest
   przewidziany, więc nie może świecić ani na zielono, ani na czerwono. */
.state-off { color: var(--text-faint); }

/*
 * Stan pisany jak etykieta, nie jak zdanie: wersaliki czcionką maszynową,
 * jak nagłówki kolumn i liczniki. Wprowadzony 2026-08-21 do kolumny „Status"
 * na liście startowej — przy odprawie ta kolumna jest czytana rzutem oka
 * w dół listy, a nie słowo po słowie.
 */
.state-tag {
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.state-ok { color: var(--ok); }

.state-warn { color: var(--warn); }

.state-bad { color: var(--bad); }

.state-accent { color: var(--accent); }

/* ─── STANDARD PRZYCISKÓW ─────────────────────────────────────────────────── */

/*
 * Ustalony 2026-08-16 na prośbę Jarka („tak róbmy przyciski w całej aplikacji").
 *
 * ── CO JEST WSPÓLNE DLA WSZYSTKICH PRZYCISKÓW W SERWISIE ────────────────────
 *
 *   • pismo 15 px, grubość 600, wiersz 24 px;
 *   • napis WYŚRODKOWANY w obu osiach;
 *   • wysokość 48 px (--s-6), a w wersji małej 40 px (--s-5);
 *   • obwódka po każdej stronie, także gdy jest przezroczysta — dzięki temu
 *     warianty mają tę samą budowę i nie przeskakują o piksel przy zmianie.
 *
 * Wszystko to siedzi w `.btn` wyżej. Kolorystyka zależy od tła, na którym
 * przycisk stoi, i tylko ona różni warianty: `.btn-primary`, `.btn-ghost`,
 * `.btn-secondary`, `.btn-google`, `.btn-danger`, `.btn-disabled`.
 *
 * ⚠ Element, który wygląda jak przycisk, MA UŻYWAĆ `.btn`. Osobne klasy
 * odtwarzające ten wygląd zawsze w końcu rozjeżdżają się co do grubości pisma
 * albo wysokości — tak było z nawigacją panelu (zgłoszenie Jarka: „font jakby
 * inny"), która miała własne reguły i pismo o stopień jaśniejsze oraz cieńsze.
 *
 * WYJĄTEK, który przyciskiem NIE jest: pozycja menu z podpisem (`.club-item`
 * w przełączniku kont i klubów). Ma dwa wiersze tekstu i wyrównanie do lewej,
 * bo to spis do czytania, a nie zestaw czynności do klikania.
 *
 * ── PIONOWY ZESTAW ──────────────────────────────────────────────────────────
 *
 * Gdy przyciski stoją jeden pod drugim w wąskiej kolumnie — czynności w panelu
 * bocznym, nawigacja panelu w układzie kolumnowym — dochodzi jedna liczba:
 * odstęp między nimi to 8 px (--s-1).
 *
 * ⚠ Obwódka MA BYĆ ledwo widoczna (`--border`). Pierwsza wersja nawigacji
 * dostała ramkę w kolorze napisu i wyszła krzykliwa — pięć jasnych prostokątów
 * zjadało uwagę należną treści strony (zgłoszenie Jarka: „chodziło o coś
 * delikatniejszego"). Kolor akcentu zostaje wyłącznie dla pozycji czynnej.
 *
 * `.side-actions` przeniesione tu z panel.css, żeby standard i jego użycia
 * nie leżały w dwóch plikach.
 */
.btn-stack,
.side-actions {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
}
