/*
 * Dwa bardzo rozne ekrany z jednego arkusza:
 *  - host: telewizor ogladany z 3-4 metrow, wiec skala idzie na vmin, nie na px,
 *  - player: telefon w rece, kciukiem, czesto w polciemnym pokoju.
 * Stad ciemny motyw na sztywno - na imprezie nikt nie przelacza trybu.
 */

:root {
    --bg: #0b0d17;
    --bg-soft: #151829;
    --fg: #f5f6fb;
    --muted: #8d93b0;
    --accent: #f5a524;
    --ok: #30a46c;
    --err: #e5484d;
    --radius: 16px;
    --team-color: var(--accent);

    /* Jeden kolor na gre - kafelek, lobby, strona glowna i panel hosta musza
       zgadzac sie ze soba. Bez wspolnego zrodla Kolo bylo pomaranczowe wszedzie
       oprocz .c-bg-kolo, ktora dzielila (bledny) niebieski z melodia. */
    --g-melodia: #3e63dd;
    --g-kolo: #f5a524;
    --g-kalambury: #30a46c;
    --g-panstwa: #8e4ec6;
    --g-quiz: #5b7cf0;
    --g-dutch: #12b886;
    --g-ostatnia-litera: #e5484d;
    --g-kalambury-rysowane: #e64980;

    color-scheme: dark;
}

* {
    box-sizing: border-box;
}

/* Atrybut hidden ustawia display:none tylko na poziomie stylu przeglądarki,
   więc każde nasze display:flex/grid go nadpisuje. Bez tej reguły ukrywane
   z JS-a fragmenty (wybór talii, klawiatura liter, komunikaty) zostają na
   ekranie - a zauważa się to dopiero przy graczach. */
[hidden] {
    display: none !important;
}

html,
body {
    margin: 0;
    min-height: 100dvh;
}

body {
    background: radial-gradient(circle at 50% 0%, #1b2040 0%, var(--bg) 60%);
    color: var(--fg);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-text-size-adjust: 100%;
}

.screen-center {
    display: grid;
    place-items: center;
    padding: 1.5rem;
}

.muted {
    color: var(--muted);
}

.logo {
    margin: 0;
    font-size: clamp(1.4rem, 3vmin, 2.4rem);
    letter-spacing: -0.02em;
}

.flash {
    margin: 0;
    padding: 0.9rem 1.2rem;
    text-align: center;
    font-weight: 600;
    background: var(--err);
}

.flash-success {
    background: var(--ok);
}

/* ---------- przyciski i pola ---------- */

/* Przyciski i pola gry są celowo grube - obsługuje się je palcem, w półmroku,
   często nie patrząc. Dlatego NIE dotyczą panelu treści: tam pracuje się myszą
   przy biurku i standardowe komponenty Tablera są czytelniejsze niż nasze
   przerośnięte guziki. Stąd body:not(.admin) - panel zostaje czystym Tablerem. */
body:not(.admin) .btn {
    padding: 0.8rem 1.4rem;
    border: 1px solid #2b3050;
    border-radius: var(--radius);
    background: var(--bg-soft);
    color: var(--fg);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    /* Palec, nie kursor - ponizej 44px trafienie robi sie loteria. */
    min-height: 44px;
}

body:not(.admin) .btn:active {
    transform: translateY(1px);
}

body:not(.admin) .btn-primary {
    background: var(--accent);
    border-color: transparent;
    color: #22160a;
}

body:not(.admin) .btn-lg {
    width: 100%;
    padding: 1.1rem 1.6rem;
    font-size: 1.25rem;
}

body:not(.admin) .btn-ghost {
    background: transparent;
    color: var(--muted);
}

body:not(.admin) input {
    padding: 0.9rem 1rem;
    border: 1px solid #2b3050;
    border-radius: var(--radius);
    background: #0e1120;
    color: var(--fg);
    font: inherit;
    /* 16px to prog, ponizej ktorego iOS zoomuje strone przy fokusie pola. */
    font-size: 16px;
    width: 100%;
}

/* Selektor "button", nie tylko ".btn" - przyciski budowane w JS bez tej
   klasy (kafelki gier, karty Dutcha, koło fortuny...) miały zerowy obrys
   fokusa (P2-24 audytu). Bardziej specyficzne reguły (np. .l2-panel) i tak
   wygrywają kaskadą, więc to tylko siatka bezpieczeństwa dla reszty. */
body:not(.admin) input:focus-visible,
body:not(.admin) button:focus-visible,
body:not(.admin) [role="button"]:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
}

/* ---------- strona startowa ---------- */

.home-screen {
    min-height: 100dvh;
    display: grid;
    align-content: center;
    justify-items: center;
    gap: clamp(1.2rem, 4vmin, 2.5rem);
    padding: clamp(1.2rem, 5vmin, 3rem);
    text-align: center;
}

.home .brand-name {
    font-size: clamp(2rem, 9vw, 4.5rem);
}

.home-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
    gap: clamp(0.8rem, 2.5vmin, 1.5rem);
    width: min(46rem, 100%);
}

.home-card {
    display: grid;
    gap: 0.8rem;
    align-content: start;
    padding: clamp(1.2rem, 4vmin, 2rem);
    border-radius: 20px;
    background: rgba(21, 24, 41, 0.72);
    border: 1px solid #232741;
}

.home-card h2 {
    margin: 0;
    font-size: 1.15rem;
}

.home-card .row {
    display: flex;
    gap: 0.6rem;
}

/* Formularz "Nowa gra" - zwykle samo haslo miejsce na jeden przycisk, ale
   z bramka hosta (HostAccess) dochodzi pole hasla nad nim. */
.host-form {
    display: grid;
    gap: 0.6rem;
}

.home-games {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 1.2rem;
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--fg);
    font-weight: 600;
}

.home-games .soon {
    color: var(--muted);
    font-weight: 400;
}

.home-games em {
    font-size: 0.8em;
    opacity: 0.7;
}

.dot {
    display: inline-block;
    width: 0.7em;
    height: 0.7em;
    margin-right: 0.45em;
    border-radius: 50%;
    background: var(--dot);
}

.home-foot {
    margin: 0;
    font-size: 0.85rem;
    max-width: 26rem;
}

.panel {
    width: min(28rem, 100%);
    display: grid;
    gap: 1.25rem;
    padding: 2rem;
    border-radius: 24px;
    background: rgba(21, 24, 41, 0.7);
    border: 1px solid #232741;
    text-align: center;
}

.lead {
    margin: 0;
    color: var(--muted);
}

.join-by-code {
    display: grid;
    gap: 0.6rem;
    padding-top: 1rem;
    border-top: 1px solid #232741;
    font-size: 0.9rem;
    color: var(--muted);
}

.join-by-code .row {
    display: flex;
    gap: 0.6rem;
}

.code-input {
    text-align: center;
    letter-spacing: 0.5em;
    text-transform: uppercase;
    font-weight: 700;
    font-size: 1.4rem;
}

/* Panel treści (/admin) przeszedł na czysty Tabler - .admin-shell/-bar/-brand/
   -block/-row/-form/-list/-items/.slug/.note/.snippet z pierwszej wersji
   panelu nie mają już żadnego szablonu, który by ich używał (P2-26 audytu).
   .btn-danger zostaje - to jedyna klasa stąd, którą admin/category.html.twig
   wciąż odwołuje (przycisk usuwania kategorii). */
.btn-danger {
    background: var(--err);
    border-color: transparent;
    color: #fff;
}

/* ---------- ekran hosta (TV) ----------

   Telewizor ogląda się z 3-4 metrów, więc wszystko skaluje się na vmin,
   a nie na px: ten sam układ ma działać na monitorze 24" i na TV 55". */

.tv {
    height: 100dvh;
    display: grid;
    /* Pasek dostaje tyle, ile potrzebuje; CAŁA reszta ekranu należy do gry.
       Wcześniej nagłówek z logo i QR zabierał górną wstęgę przez cały czas,
       a tablo dolną - plansza dostawała środkowy pasek i z kanapy nie było
       jej widać. */
    grid-template-rows: auto minmax(0, 1fr);
    gap: clamp(0.6rem, 1.6vmin, 1.4rem);
    padding: clamp(0.6rem, 1.8vmin, 1.8rem);
    overflow: hidden;
    background:
        radial-gradient(circle at 15% -10%, #232a52 0%, transparent 55%),
        radial-gradient(circle at 85% 0%, #1d2547 0%, transparent 50%);
}

/* ---------- pasek górny ---------- */

.tv-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(0.6rem, 2vmin, 1.6rem);
}

/* ---------- nagłówek poczekalni (wg _other/layout2.png) ---------- */

.tv-bar-lobby {
    align-items: flex-start;
    flex-wrap: wrap;
}

.brand-block {
    transform: rotate(-1.5deg);
}

/* Logotyp jest bohaterem poczekalni - to pierwsze, co widać z drugiego końca
   pokoju, więc skaluje się agresywnie z szerokością ekranu. */
.brand-word {
    margin: 0;
    font-size: clamp(2.2rem, 7.5vmin, 6rem);
    font-weight: 900;
    line-height: 0.92;
    letter-spacing: -0.02em;
    text-shadow: 0 0.06em 0 rgba(0, 0, 0, 0.45);
}

/* Gwiazdka w miejscu "O" - z makiety. Wpisana w żółte koło, żeby czytało się
   jako litera, a nie jako ozdobnik doklejony obok. */
.brand-o {
    display: inline-grid;
    place-items: center;
    width: 0.86em;
    height: 0.86em;
    margin: 0 0.02em;
    border-radius: 50%;
    background: var(--accent);
    color: #22160a;
    font-size: 0.78em;
    vertical-align: baseline;
    transform: translateY(0.04em);
}

.brand-tag {
    margin: 0.1em 0 0 0.4em;
    color: var(--accent);
    font-size: clamp(0.9rem, 2.2vmin, 1.8rem);
    font-weight: 700;
}

.join-inline {
    display: flex;
    align-items: center;
    gap: clamp(0.7rem, 2vmin, 1.6rem);
}

/* Komunikat "to nowy kod" po wznowieniu zapisanego turnieju - widoczny, ale
   nie tak alarmujacy jak .flash (czerwony blad): to informacja, nie problem. */
.resumed-banner {
    margin: 0 0 clamp(0.5rem, 1.5vh, 1rem);
    padding: 0.7em 1.1em;
    border-radius: 12px;
    background: rgba(245, 165, 36, 0.14);
    border: 1px solid rgba(245, 165, 36, 0.4);
    color: var(--fg);
    font-size: clamp(0.8rem, 1.8vmin, 1.15rem);
    text-align: center;
}

.join-inline-text {
    text-align: right;
}

.join-inline-lead,
.join-inline-url {
    margin: 0;
    color: var(--muted);
    font-size: clamp(0.75rem, 1.6vmin, 1.15rem);
}

/* Kod wpisuje się z telefonu, patrząc na ekran - duży i rozstrzelony,
   żeby nie trzeba było mrużyć oczu przy przepisywaniu. */
.join-inline-code {
    margin: 0.1em 0;
    font-size: clamp(1.8rem, 5vmin, 4rem);
    font-weight: 900;
    line-height: 1;
    letter-spacing: 0.06em;
    color: var(--accent);
}

.join-inline-qr {
    width: clamp(90px, 13vmin, 190px);
    height: auto;
    border-radius: 10px;
    /* Białe tło: czytniki telefonów gubią kod odwrócony kolorystycznie. */
    background: #fff;
    padding: 0.4rem;
}

.tv-brand {
    margin: 0;
    font-size: clamp(1rem, 2.4vmin, 1.9rem);
    font-weight: 900;
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
}

.tv-bar-right {
    display: flex;
    align-items: center;
    gap: clamp(0.5rem, 1.4vmin, 1.1rem);
}

.btn-join {
    background: var(--accent);
    color: #22160a;
    font-weight: 800;
    font-size: clamp(0.85rem, 1.8vmin, 1.35rem);
    padding: 0.5em 1em;
}

.bar-code {
    margin-left: 0.5em;
    letter-spacing: 0.18em;
    font-weight: 900;
}

.btn-reset {
    font-size: clamp(0.75rem, 1.5vmin, 1.05rem);
    padding: 0.5em 0.9em;
}

/* ---------- korpus: scena + drużyny ---------- */

/* Panel punktacji po LEWEJ, scena po prawej - kolejność z prośby użytkownika.
   Kolumna jest stała, scena bierze resztę; minmax(0,...) na scenie nie pozwala
   wielkiej planszy rozepchnąć siatki i wypchnąć tablo poza ekran. */
/* Tryb pełnego ekranu: znika pasek u góry i (domyślnie) punktacja z boku,
   scena gry dostaje cały telewizor. Punkty nadal się liczą - schowany jest
   tylko ich podgląd i ręczna korekta, więc wyjście musi zostać widoczne.
   ".tv-focus-show-teams" to osobny, niezależny przełącznik (menu pełnego
   ekranu) - host może chcieć immersyjny widok BEZ paska, a mimo to widzieć
   wyniki z boku; stąd druga klasa zamiast jednego bitu "focus=schowaj wszystko". */
.tv.tv-focus > .tv-bar { display: none; }
.tv.tv-focus:not(.tv-focus-show-teams) .tv-teams { display: none; }

/* Bez tego scena ląduje w wierszu po schowanym nagłówku (czyli w tym "auto"),
   a wiersz 1fr zostaje pusty na dole ekranu. */
.tv.tv-focus { grid-template-rows: minmax(0, 1fr); }

.tv.tv-focus:not(.tv-focus-show-teams) .tv-body { grid-template-columns: minmax(0, 1fr); }

.tv-focus-exit {
    display: none;
    position: fixed;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 40;
    width: 2.4rem;
    height: 2.4rem;
    place-items: center;
    border: 1px solid #2c3358;
    border-radius: 50%;
    background: rgba(13, 16, 30, 0.6);
    color: var(--muted);
    font-size: 1.1rem;
    cursor: pointer;
}

.tv-focus-exit:hover {
    color: var(--fg);
    background: rgba(13, 16, 30, 0.9);
}

.tv.tv-focus .tv-focus-exit { display: grid; }

/* Menu w pełnym ekranie - te same akcje co schowany pasek (Zmień grę, Reset,
   Tablica, Dźwięk), tylko za jednym przyciskiem w rogu. Bez niego jedynym
   sposobem dosięgnięcia ich byłoby najpierw wyjść z pełnego ekranu. */
.tv-focus-menu-btn {
    display: none;
    position: fixed;
    top: 0.6rem;
    /* Po lewej stronie przycisku wyjścia (2.4rem szerokości + 0.6rem odstępu). */
    right: 3.6rem;
    z-index: 40;
    width: 2.4rem;
    height: 2.4rem;
    place-items: center;
    border: 1px solid #2c3358;
    border-radius: 50%;
    background: rgba(13, 16, 30, 0.6);
    color: var(--muted);
    font-size: 1.1rem;
    cursor: pointer;
}

.tv-focus-menu-btn:hover {
    color: var(--fg);
    background: rgba(13, 16, 30, 0.9);
}

.tv.tv-focus .tv-focus-menu-btn { display: grid; }

.tv-focus-menu {
    position: fixed;
    top: 3.4rem;
    right: 0.6rem;
    z-index: 40;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem;
    min-width: 12rem;
    border-radius: 14px;
    border: 1px solid #2c3358;
    background: rgba(13, 16, 30, 0.92);
    backdrop-filter: blur(6px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
}

.tv-focus-menu form { margin: 0; }
.tv-focus-menu .btn { width: 100%; }

.tv-body {
    display: grid;
    /* Wąska kolumna punktacji po LEWEJ, scena bierze resztę. minmax(0,...)
       na scenie jest konieczne: bez tego wielka plansza rozpycha grid zamiast
       się w nim zmieścić i kolumna z drużynami ucieka poza ekran. */
    grid-template-columns: clamp(11rem, 15vw, 17rem) minmax(0, 1fr);
    gap: clamp(0.6rem, 1.8vmin, 1.6rem);
    min-height: 0;
}

/* Jedna kolumna na pełną szerokość, wyśrodkowana w pionie.
   NIE "place-content: center": to zwęża ścieżki gridu do szerokości treści,
   przez co siatka kafelków gier dostaje kilkanaście centymetrów i układa się
   w pionową listę zamiast rozłożyć się w rząd. */
.tv-stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: clamp(0.5rem, 1.6vmin, 1.4rem);
    min-height: 0;
    overflow: hidden;
}

/* Karta Tablera, ale rozciągnięta na wysokość kolumny i z listą, która
   przewija się w środku zamiast rozpychać kartę poza ekran. */
.tv-teams {
    display: grid;
    grid-template-rows: auto auto minmax(0, 1fr);
    min-height: 0;
    overflow: hidden;
}

.teams-head {
    margin: 0;
    /* Tabler daje nagłówkom kart rozmiar do czytania z 50 cm - na telewizorze
       oglądanym z trzech metrów to za mało. */
    font-size: clamp(0.95rem, 2vmin, 1.6rem);
}

/* Drużyny jedna pod drugą i możliwie duże - to jest tablo oglądane z kanapy,
   a nie lista w formularzu. Przewijamy dopiero, gdy rodzin jest naprawdę wiele. */
.tv-teams .teams {
    display: grid;
    grid-template-columns: 1fr;
    align-content: start;
    gap: clamp(0.35rem, 1vmin, 0.8rem);
    margin: 0;
    padding: clamp(0.5rem, 1.4vmin, 1rem);
    list-style: none;
    min-height: 0;
    overflow-y: auto;
}

.tv-teams .team {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
        'name score'
        'buttons score';
    align-items: center;
    gap: 0.2em 0.6em;
    padding: clamp(0.4rem, 1.2vmin, 0.9rem) clamp(0.5rem, 1.4vmin, 1rem);
    border-radius: 12px;
    border-left: 6px solid var(--team-color, var(--accent));
    background: rgba(242, 239, 230, 0.07);
}

.tv-teams .team-name {
    grid-area: name;
    /* Nazwa drużyny to jedyna rzecz, której gracz szuka wzrokiem co rundę -
       stary sufit (1.25rem) był dobrany pod laptopa i na TV oglądanym
       z kanapy nie rósł powyżej ~20px (P2-23 audytu). */
    font-size: clamp(1rem, 2.4vmin, 2.2rem);
    font-weight: 800;
    overflow-wrap: anywhere;
}

.tv-teams .team-score {
    grid-area: score;
    /* Punkty to najważniejsza liczba na tablo - mają być czytelne z drugiego
       końca pokoju. Stała szerokość, żeby przyciski nie skakały przy 9 → 10. */
    font-size: clamp(1.2rem, 2.6vmin, 2.2rem);
    font-weight: 900;
    line-height: 1;
    min-width: 2.5ch;
    text-align: right;
    color: var(--team-color, var(--fg));
}

.tv-teams .team-buttons {
    grid-area: buttons;
    display: flex;
    gap: 0.35rem;
}

/* ---------- wąski ekran: telefon, tablet, okno na pół monitora ----------

   Ekran hosta jest projektowany pod telewizor, ale otwiera się go też na
   laptopie i na telefonie (choćby żeby sprawdzić pokój). Sztywna wysokość
   100dvh z overflow: hidden obcinałaby wtedy treść bez możliwości przewinięcia,
   a kolumna drużyn zabierałaby połowę i tak wąskiego ekranu. */
@media (max-width: 60rem) {
    .tv {
        height: auto;
        min-height: 100dvh;
        overflow: visible;
    }

    .tv-body {
        grid-template-columns: minmax(0, 1fr);
    }

    .tv-teams {
        grid-template-rows: auto auto auto;
    }

    .tv-bar {
        flex-wrap: wrap;
        justify-content: center;
    }

    .tv-stage {
        overflow: visible;
    }

    .game-panel {
        height: auto;
    }

    /* Koło pod planszą, a nie obok niej - w pionie jest miejsce, w poziomie nie. */
    .kolo-stage {
        flex-direction: column;
    }

    .wheel {
        height: auto;
        width: min(86vw, 60vmin);
    }
}

.brand-name {
    margin: 0;
    font-size: clamp(1.8rem, 5.5vmin, 4.5rem);
    font-weight: 900;
    letter-spacing: -0.01em;
    line-height: 0.95;
    /* Lekki obrót i cień: logo ma wyglądać na naklejkę, nie na nagłówek h1. */
    transform: rotate(-1.5deg);
    text-shadow: 0 0.06em 0 rgba(0, 0, 0, 0.45);
}

.brand-star {
    display: inline-block;
    margin: 0 0.12em;
    color: var(--accent);
    transform: rotate(8deg);
}

.brand-tag {
    margin: 0.2em 0 0;
    color: var(--accent);
    font-size: clamp(0.9rem, 2vmin, 1.6rem);
    font-weight: 700;
    transform: rotate(-1.5deg);
}

/* ---------- wysuwany panel dołączania ---------- */

/* Nakładka, a nie miejsce w układzie: gdy jest schowana, plansza dostaje
   pełny ekran. Position fixed zamiast wiersza w gridzie, żeby otwarcie panelu
   w trakcie gry niczego nie przesuwało - koło nie może podskoczyć w chwili,
   gdy ktoś dosiada się do zabawy. */
.join-drawer {
    position: fixed;
    inset: 0;
    z-index: 20;
    display: grid;
    place-items: center;
    padding: 2vmin;
    background: rgba(9, 11, 22, 0.82);
    backdrop-filter: blur(4px);
}

.join-card {
    display: grid;
    justify-items: center;
    gap: clamp(0.5rem, 1.6vmin, 1.2rem);
    padding: clamp(1rem, 3vmin, 2.4rem);
    border-radius: 22px;
    background: #151829;
    border: 1px solid #2b3050;
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
    text-align: center;
}

.join-lead {
    margin: 0;
    font-size: clamp(1rem, 2.4vmin, 1.9rem);
    color: var(--muted);
}

/* .join-url i .qr miały tu drugą, sprzeczną definicję niżej w pliku - ta
   druga (bliżej końca arkusza) zawsze wygrywała kaskadą, więc ta pierwsza
   nigdy się nie renderowała. Została usunięta (P2-26 audytu: .qr
   zdefiniowany dwukrotnie, druga wersja wygrywa i unieważnia komentarz
   "Duży: kod jest skanowany z drugiego końca pokoju"). */

/* ---------- dolny pas poczekalni (wg _other/layout2.png) ---------- */

.lobby-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: clamp(0.5rem, 1.4vmin, 1.2rem);
    width: 100%;
}

.strip-tile {
    padding: clamp(0.7rem, 1.8vmin, 1.4rem);
    border-radius: 16px;
    background: rgba(21, 24, 41, 0.66);
    border: 1px solid #232741;
    text-align: left;
}

.strip-tile h2 {
    margin: 0 0 0.7em;
    font-size: clamp(0.9rem, 1.9vmin, 1.4rem);
}

.steps {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: clamp(0.72rem, 1.4vmin, 1rem);
    color: var(--muted);
}

.steps strong {
    color: var(--fg);
}

.step-no {
    display: inline-grid;
    place-items: center;
    width: 1.7em;
    height: 1.7em;
    margin-right: 0.5em;
    border-radius: 8px;
    background: var(--accent);
    color: #22160a;
    font-weight: 900;
}

.strip-rows,
.strip-rank {
    display: grid;
    gap: 0.45rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: clamp(0.72rem, 1.5vmin, 1.05rem);
}

.strip-rows > div,
.strip-rank li {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
}

.strip-rows dt,
.strip-rank span {
    margin: 0;
    color: var(--muted);
}

.strip-rows dd,
.strip-rank strong {
    margin: 0;
    font-weight: 800;
}

/* Lider wyróżniony kolorem akcentu - z makiety. */
.strip-rank li:first-child strong,
.strip-rank li:first-child span {
    color: var(--accent);
}

/* ---------- poczekalnia: cała mieści się w ekranie, bez pełnego ekranu ----------

   Scena poczekalni to dwa rzędy: kafelki gier biorą całą wolną wysokość (są
   bohaterem), a dolny pas informacyjny tyle, ile potrzebuje. Wcześniej
   align-content: center zlepiał je w słupek wyższy niż ekran i telewizor obcinał
   dół - stąd konieczność włączania pełnego ekranu. Teraz kafelki KURCZĄ się z
   wysokością okna (rozmiary w vh), więc na niższym telewizorze wszystko wchodzi. */
.tv-stage-lobby {
    grid-template-rows: minmax(0, 1fr) auto;
    align-content: stretch;
    gap: clamp(0.5rem, 1.6vmin, 1.4rem);
}

.tv-stage-lobby .game-grid {
    align-content: center;
    min-height: 0;
}

/* ---------- kafelki gier ---------- */

/* Kafelki gier w rzędzie, nie w kolumnie. min(100%, 12rem) sprawia, że na
   telefonie schodzą do jednej kolumny same, bez media query - a na telewizorze
   mieszczą się obok siebie nawet obok kolumny z drużynami. */
.game-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
    gap: clamp(0.6rem, 1.6vmin, 1.4rem);
    width: 100%;
    align-content: center;
}

/* Kafelek: jasny korpus z kolorowym pasem gry u góry, ilustracja na kolorowym
   medalionie i przycisk w barwie gry. Kolorowa poświata (box-shadow w --card)
   sprawia, że każda gra „świeci" swoim kolorem - z drugiego końca pokoju widać
   od razu, czym jest, zanim ktokolwiek przeczyta tytuł. */
.game-card {
    position: relative;
    display: grid;
    grid-template-rows: auto 1fr auto auto;
    gap: clamp(0.3rem, 1vmin, 0.85rem);
    padding: 0 0 clamp(0.7rem, 1.7vmin, 1.3rem);
    border: none;
    border-radius: 20px;
    background: linear-gradient(180deg, #ffffff 0%, #efeadd 100%);
    color: #15182a;
    text-align: center;
    overflow: hidden;
    box-shadow:
        0 10px 26px rgba(0, 0, 0, 0.42),
        0 16px 42px -14px var(--card);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/* Podniesienie i mocniejsza poświata pod kursorem - dla hosta na laptopie.
   Na telewizorze nieszkodliwe: bez myszy po prostu się nie odpala. */
.game-card:hover {
    transform: translateY(-6px);
    box-shadow:
        0 18px 40px rgba(0, 0, 0, 0.5),
        0 24px 56px -12px var(--card);
}

.game-card-title {
    margin: 0;
    padding: clamp(0.5rem, 1.5vmin, 0.95rem) 0.5rem clamp(0.45rem, 1.3vmin, 0.85rem);
    background: var(--card);
    color: #fff;
    font-size: clamp(1rem, 2.5vmin, 2rem);
    font-weight: 900;
    line-height: 1.04;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    text-shadow: 0 2px 5px rgba(0, 0, 0, 0.28);
}

/* Ilustracja na kolorowym medalionie. Rozmiary w vh, żeby na niższym ekranie
   kafelek się skrócił zamiast wypchnąć dół sceny poza telewizor. */
.game-card-art {
    position: relative;
    display: grid;
    place-items: center;
    width: 100%;
    margin-top: clamp(0.3rem, 1vmin, 0.7rem);
}

.game-card-art::before {
    content: '';
    position: absolute;
    width: clamp(70px, 16vh, 145px);
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--card);
    opacity: 0.12;
}

.game-card-art svg {
    position: relative;
    width: clamp(50px, 12.5vh, 118px);
    height: auto;
    color: var(--card);
    filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.14));
}

.game-card-lead {
    margin: 0;
    padding-inline: clamp(0.7rem, 1.8vmin, 1.3rem);
    font-size: clamp(0.78rem, 1.5vmin, 1.05rem);
    color: #454a63;
}

.game-card-btn {
    margin: clamp(0.15rem, 0.7vmin, 0.45rem) clamp(0.7rem, 1.8vmin, 1.3rem) 0;
    padding: 0.6em 1em;
    border: none;
    border-radius: 12px;
    background: var(--card);
    color: #fff;
    font: inherit;
    font-size: clamp(0.9rem, 1.8vmin, 1.3rem);
    font-weight: 800;
    letter-spacing: 0.08em;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.32), 0 6px 16px -5px var(--card);
    transition: filter 0.15s ease;
}

.game-card-btn::after {
    content: ' ▶';
    font-size: 0.75em;
    vertical-align: 0.05em;
}

.game-card-btn:hover {
    filter: brightness(1.08);
}

.game-card-btn:disabled {
    opacity: 0.6;
}

.reset-form {
    margin-left: auto;
}

.conn {
    padding: 0.35em 0.9em;
    border-radius: 999px;
    background: var(--bg-soft);
    color: var(--muted);
    font-size: clamp(0.75rem, 1.4vmin, 1rem);
    font-weight: 600;
}

.conn[data-state="online"] {
    color: var(--ok);
}

.conn[data-state="offline"] {
    color: var(--err);
}

.join-url {
    margin: 0;
    font-size: clamp(1.2rem, 3vmin, 2.4rem);
    font-weight: 600;
}

.room-code {
    margin: 0;
    font-size: clamp(2.5rem, 9vmin, 7rem);
    font-weight: 800;
    letter-spacing: 0.08em;
    line-height: 1;
    color: var(--accent);
}

.room-code.small {
    font-size: clamp(2.5rem, 12vmin, 4rem);
}

.qr {
    width: clamp(140px, 26vmin, 320px);
    height: auto;
    border-radius: var(--radius);
    /* Biale tlo pod QR: czytniki telefonow gubia kod odwrocony kolorystycznie. */
    background: #fff;
    padding: 0.5rem;
}

/* ---------- panel gry na ekranie hosta ---------- */

/* Panel gry wypełnia scenę - to on jest treścią ekranu, a nie kafelek
   pośrodku pustego tła. min-height: 0 pozwala planszy i kołu kurczyć się
   do dostępnej wysokości zamiast rozpychać stronę poza ekran. */
.game-panel {
    display: grid;
    align-content: center;
    gap: clamp(0.5rem, 1.6vmin, 1.2rem);
    padding: clamp(0.8rem, 2.2vmin, 1.8rem);
    border-radius: var(--radius);
    background: rgba(21, 24, 41, 0.75);
    border: 1px solid #232741;
    justify-items: center;
    text-align: center;
    height: 100%;
    min-height: 0;
}

.panel-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    justify-content: center;
}

/* Przyciski hosta obsługuje się z kanapy, często pilotem albo na oko -
   mają być duże i trudne do chybienia. */
.panel-controls .btn {
    width: auto;
    min-width: 12ch;
    font-size: clamp(1rem, 2.4vmin, 1.8rem);
    padding: 0.6em 1.4em;
}

.select {
    padding: 0.8rem 1rem;
    border: 1px solid #2b3050;
    border-radius: var(--radius);
    background: #0e1120;
    color: var(--fg);
    font: inherit;
    font-size: 1rem;
    min-height: 44px;
}

.track-line {
    display: grid;
    gap: 0.2rem;
}

/* Rozwiązanie - tytuł utworu albo hasło. Pokazuje się WYŁĄCZNIE po odsłonięciu
   (melodia: finish/cancel, koło: rozwiązane hasło), bo ten ekran ogląda cały
   pokój. Kontroler czyści je w każdej innej fazie. */
.track-answer {
    font-size: clamp(1.4rem, 4vmin, 3.2rem);
    font-weight: 800;
    color: var(--accent);
}

.buzz-banner {
    margin: 0;
    padding: 0.4em 1em;
    border-radius: 999px;
    background: var(--team-color, var(--accent));
    color: #10121f;
    font-size: clamp(1.4rem, 4.5vmin, 3.4rem);
    font-weight: 900;
    animation: pop 0.35s ease-out;
}

.hint {
    margin: 0;
    font-size: clamp(0.85rem, 1.6vmin, 1.1rem);
    min-height: 1.4em;
}

.board h2 {
    font-size: clamp(1rem, 2.4vmin, 1.8rem);
    margin: 0 0 0.8em;
}

.empty {
    color: var(--muted);
    font-size: clamp(1rem, 2.4vmin, 1.8rem);
}

.teams {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: clamp(0.6rem, 1.6vmin, 1.4rem);
}

.team {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: clamp(0.8rem, 2vmin, 1.6rem);
    border-radius: var(--radius);
    background: var(--bg-soft);
    border-left: 6px solid var(--team-color);
    font-size: clamp(1.1rem, 3vmin, 2.4rem);
    font-weight: 600;
}

/* Subtelny "wyrzuć drużynę" - widoczny, ale nie krzyczy obok samego wyniku.
   Osobny przycisk zamiast kliknięcia w kafelek: kafelek drużyny nigdzie
   indziej nie jest klikalny, więc przypadkowe dotknięcie nie usuwa nikogo. */
.team-remove {
    flex: 0 0 auto;
    grid-area: remove;
    width: 1.8em;
    height: 1.8em;
    display: grid;
    place-items: center;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--muted);
    font-size: 0.7em;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.team-remove:hover,
.team-remove:focus-visible {
    opacity: 1;
    background: rgba(229, 72, 77, 0.18);
    color: var(--err);
}

.team-score {
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    color: var(--team-color);
    margin-left: auto;
}

.team-buttons {
    display: flex;
    gap: 0.4rem;
}

/* Host klika te przyciski z odleglosci reki, czesto nie patrzac - stad
   duze pole trafienia i staly rozmiar niezalezny od skali reszty tablo. */
.btn-score {
    min-width: 2.2em;
    min-height: 2.2em;
    padding: 0;
    font-size: clamp(1rem, 2vmin, 1.6rem);
    line-height: 1;
    display: grid;
    place-items: center;
}

.btn-score:disabled {
    opacity: 0.5;
}

.teams-inline {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
}

.teams-inline li {
    padding: 0.35em 0.9em;
    border-radius: 999px;
    background: var(--bg-soft);
    border-left: 4px solid var(--team-color);
    font-size: 0.9rem;
}

/* Nowa druzyna i zmiana punktu musza byc widoczne katem oka z kanapy. */
.team-new {
    animation: pop 0.45s ease-out;
}

.bump {
    animation: bump 0.45s ease-out;
}

@keyframes pop {
    from {
        opacity: 0;
        transform: translateY(0.8rem) scale(0.96);
    }
}

@keyframes bump {
    50% {
        transform: scale(1.35);
    }
}

@media (prefers-reduced-motion: reduce) {
    .team-new,
    .bump,
    .buzz-banner,
    .tv-teams .team-score.bump,
    .standings-list .team-score.bump,
    .standings-modal {
        animation: none;
    }
}

/* ---------- sterownik telefonu ---------- */

.player-screen {
    min-height: 100dvh;
    display: grid;
    grid-template-rows: auto 1fr auto;
    gap: 1rem;
    /* safe-area: pelnoekranowa PWA na iPhonie chowa tresc pod notchem. */
    padding: max(1rem, env(safe-area-inset-top)) 1rem max(1rem, env(safe-area-inset-bottom));
}

/* Pasek gracza: nazwa, punkty, status - w jednym rzędzie, bez zawijania.
   Wcześniej flex-wrap przy dłuższej nazwie drużyny łamał pasek na trzy piętra
   i zjadał połowę ekranu telefonu. Teraz nazwa się skraca (text-truncate),
   a punkty i status mają stałe miejsce. */
.player-bar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.player-bar .team-badge {
    flex: 0 1 auto;
    min-width: 0;
}

.score-unit {
    color: var(--muted);
    font-size: 0.8em;
}

.team-badge {
    padding: 0.4em 1em;
    border-radius: 999px;
    background: var(--team-color);
    color: #10121f;
    font-weight: 800;
}

/* Treść gry bierze pełną szerokość telefonu i jest wyśrodkowana w pionie.
   NIE "place-content: center": to zwęża ścieżkę siatki do szerokości treści,
   przez co karty i klawiatura liter zbiegały się w wąski sznurek pośrodku
   ekranu zamiast wykorzystać całą dostępną szerokość. */
.player-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: 0.5rem;
    min-width: 0;
}

.big-score {
    margin: 0;
    font-size: clamp(4rem, 30vmin, 9rem);
    font-weight: 800;
    line-height: 1;
    color: var(--team-color);
    font-variant-numeric: tabular-nums;
}

.waiting {
    color: var(--muted);
    max-width: 22rem;
}

/* Host usunął tę drużynę - nakładka na CAŁY ekran telefonu, ponad wszystkim
   (nawet ponad ewentualnym pełnoekranowym widokiem gry), bo telefon i tak
   nie ma już do czego wracać - drużyny nie ma już w Redisie. */
.player-removed-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: grid;
    place-items: center;
    justify-items: center;
    gap: 1rem;
    padding: 2rem 1.5rem;
    text-align: center;
    background: rgba(10, 12, 22, 0.97);
}

.player-removed-title {
    margin: 0;
    font-size: clamp(1.4rem, 6vw, 2rem);
    font-weight: 800;
}

.player-removed-note {
    margin: 0;
    color: var(--muted);
    max-width: 26rem;
}

.score-pill {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* ---------- koło fortuny ---------- */

/* Wylosowane pole na cały ekran - żeby z kanapy było jasne, co padło. */
.kolo-result {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: grid;
    place-items: center;
    pointer-events: none;
}

.kolo-result-value {
    font-size: clamp(3rem, 15vmin, 10rem);
    font-weight: 900;
    line-height: 1;
    padding: 0.18em 0.55em;
    border-radius: 28px;
    letter-spacing: 0.02em;
    box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
}

.kolo-result.is-win .kolo-result-value {
    background: linear-gradient(150deg, #ffd27d, #f5a524);
    color: #201500;
}

.kolo-result.is-stop .kolo-result-value {
    background: #e5484d;
    color: #fff;
}

.kolo-result.is-bankrut .kolo-result-value {
    background: #1b1e2e;
    color: #fff;
    border: 3px solid #e5484d;
}

/* Kolumna flex, nie grid: tylko wtedy scena koła może dostać "flex: 1"
   i zabrać całą wysokość, która zostanie po planszy hasła. W gridzie
   liczba wierszy zmienia się przy każdym ukryciu elementu (display: none
   wypada z układu), więc sztywny grid-template-rows byłby nie do utrzymania. */
.kolo-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.kolo-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(1rem, 4vmin, 3rem);
    flex-wrap: wrap;
    /* Scena koła zjada całą wysokość, jaka zostanie po planszy hasła. */
    flex: 1;
    min-height: 0;
    width: 100%;
}

/* Koło jest bohaterem tego ekranu - bierze tyle wysokości, ile zostało po
   planszy hasła. Wcześniej stało na sztywnym 21vmin i na telewizorze wychodziło
   wielkości podstawki pod kubek. */
.wheel {
    width: auto;
    height: min(52vmin, 100%);
    max-width: 100%;
}

.kolo-side {
    min-width: min(18rem, 32vw);
    text-align: center;
}

.kolo-side .card-body {
    display: grid;
    gap: clamp(0.4rem, 1.4vmin, 1rem);
    padding: clamp(0.7rem, 2vmin, 1.6rem);
}

/* Pasek porządkowy nad planszą: kategoria i numer hasła. Celowo drobny
   i stonowany - gdyby był duży, konkurowałby wzrokowo z samą planszą. */
.panel-eyebrow {
    margin: 0;
    color: var(--muted);
    font-size: clamp(0.8rem, 1.6vmin, 1.15rem);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.turn-line {
    margin: 0;
    font-size: clamp(1.2rem, 3vmin, 2.4rem);
    font-weight: 800;
}

.banner-small {
    margin: 0;
    font-size: clamp(1.1rem, 3vmin, 2.2rem);
    font-weight: 800;
    color: var(--accent);
    min-height: 1.2em;
}

/* Plansza hasła: kafelek na znak, żeby z kanapy było widać długość słów. */
.puzzle-board {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    /* Odstęp między WYRAZAMI: pierwsze pole to wiersze, drugie - przerwa
       między słowami. Kolumna szersza od odstępu liter w słowie, żeby granica
       wyrazów była widoczna z drugiego końca pokoju. */
    gap: 0.4rem clamp(0.7rem, 2.4vmin, 1.6rem);
    align-items: flex-start;
}

/* Jeden wyraz = jeden nierozrywalny kafelkowy blok. flex-wrap: nowrap sprawia,
   że litery wyrazu trzymają się jednego wiersza; łamie się dopiero plansza,
   między wyrazami. */
.puzzle-word {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.25rem 0.2rem;
}

.puzzle-cell {
    display: grid;
    place-items: center;
    width: clamp(1.4rem, 4.4vmin, 3.6rem);
    height: clamp(2rem, 6vmin, 4.8rem);
    border-radius: 6px;
    background: #f5f6fb;
    color: #10121f;
    font-size: clamp(1.1rem, 3.6vmin, 2.9rem);
    font-weight: 800;
}

/* Spacja to przerwa, nie kafelek - inaczej hasło zlewa się w jedno słowo. */
.puzzle-space {
    background: transparent;
    width: clamp(0.5rem, 1.6vmin, 1.2rem);
}

.puzzle-hint {
    margin: 0;
    color: var(--muted);
    font-size: clamp(0.9rem, 2vmin, 1.4rem);
    font-style: italic;
}

/* ---------- koło: telefon ---------- */

/* Pełna szerokość na telefonie, ograniczona dopiero na tablecie i wyżej -
   na 7-calowym ekranie 30rem to było mniej niż połowa dostępnego miejsca. */
.kolo-player {
    width: 100%;
    max-width: 38rem;
    margin-inline: auto;
}

.puzzle-mini {
    margin: 0;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: clamp(1rem, 5vw, 1.6rem);
    font-weight: 700;
    letter-spacing: 0.12em;
    word-break: break-word;
}

.small {
    font-size: 0.85rem;
}

/* Bank to liczba, na którą gracz zerka najczęściej - ma być duża i czytelna
   kątem oka, bez czytania podpisu. */
.bank-value {
    font-size: clamp(1.6rem, 9vw, 2.6rem);
    font-weight: 900;
    line-height: 1.1;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.turn-note {
    margin: 0;
    font-weight: 700;
    color: var(--team-color);
    min-height: 1.4em;
}

.kolo-actions {
    display: grid;
    gap: 0.75rem;
}

/* Klawiatura liter. Klawisz musi być trafialny kciukiem w ruchu - stąd
   kwadratowe pole i wymiary powyżej zalecanych 44 px, a nie upakowanie
   jak największej liczby liter w rzędzie. */
.letters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(2.9rem, 1fr));
    gap: 0.4rem;
}

.letter-key {
    min-height: 3.4rem;
    border: 1px solid #2b3050;
    border-radius: 12px;
    background: var(--bg-soft);
    color: var(--fg);
    font: inherit;
    font-size: 1.35rem;
    font-weight: 700;
    cursor: pointer;
    touch-action: manipulation;
}

/* Przycisk "Zakręć kołem" - najważniejsza akcja w grze, na pełną szerokość. */
.btn-xl {
    font-size: 1.35rem;
    font-weight: 800;
    padding: 0.9em 1.2em;
    min-height: 3.6rem;
}

.letter-key:disabled {
    opacity: 0.3;
}

.letter-key:active:not(:disabled) {
    background: var(--team-color);
    color: #10121f;
}

.solve-form {
    display: flex;
    gap: 0.5rem;
}

/* ---------- buzzer ---------- */

/* Rozmiar trzyma kontener, a przycisk go wypełnia. Ustawiony na samym
   przycisku rozjeżdżał się: jako element siatki z aspect-ratio dostawał
   automatyczny rozmiar minimalny i wychodził poza ekran telefonu. */
.buzzer {
    width: min(78vw, 62vh);
    max-width: 100%;
    aspect-ratio: 1;
    justify-self: center;
}

.buzzer-button {
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 50%;
    background: #2a2f4a;
    color: var(--fg);
    font: inherit;
    font-size: clamp(1.4rem, 7vmin, 3rem);
    font-weight: 900;
    letter-spacing: 0.02em;
    cursor: pointer;
    box-shadow: 0 0.6rem 0 #1a1e33;
    transition: transform 0.06s ease, box-shadow 0.06s ease;
    /* touch-action: telefon nie może przewijać strony ani zoomować w trakcie
       walenia w buzzer - to zjadałoby część naciśnięć. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}

.buzzer[data-state="armed"] .buzzer-button {
    background: var(--team-color);
    color: #10121f;
    box-shadow: 0 0.6rem 0 rgba(0, 0, 0, 0.45);
    animation: ready 1.6s ease-in-out infinite;
}

.buzzer[data-state="armed"] .buzzer-button:active {
    transform: translateY(0.55rem);
    box-shadow: 0 0.05rem 0 rgba(0, 0, 0, 0.45);
}

.buzzer[data-state="floor"] .buzzer-button {
    background: var(--ok);
    color: #06120c;
    animation: none;
}

.buzzer[data-state="locked"] .buzzer-button,
.buzzer[data-state="sent"] .buzzer-button {
    background: #23273f;
    color: var(--muted);
    box-shadow: none;
}

.buzzer-button:disabled {
    cursor: default;
}

@keyframes ready {
    50% {
        filter: brightness(1.18);
    }
}

@media (prefers-reduced-motion: reduce) {
    .buzzer[data-state="armed"] .buzzer-button {
        animation: none;
    }
}

.player-footer {
    text-align: center;
    font-size: 0.85rem;
}

.join-form {
    display: grid;
    gap: 0.75rem;
    text-align: left;
}

/* ================= ekrany gier wg makiet w _other/ =================

   Wspólny układ dla melodii i koła (jaka_to_melodia.png, kolo_fortuny.png):
   lewa szyna z tytułem i ilustracją, środek z akcją, tablo po prawej rysuje
   ekran hosta. Reguły są na końcu pliku celowo - nadpisują wcześniejsze
   definicje .game-panel i .kolo-panel bez podbijania specyficzności. */

.game-panel {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    grid-template-areas:
        'rail main'
        'foot foot';
    align-content: stretch;
    justify-items: stretch;
    text-align: left;
    gap: clamp(0.6rem, 1.8vmin, 1.6rem);
}

/* .kolo-panel dostawał wcześniej flex-column - tu wraca do wspólnej siatki. */
.kolo-panel {
    display: grid;
}

.game-rail {
    grid-area: rail;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: clamp(0.5rem, 1.6vmin, 1.2rem);
    min-height: 0;
}

/* Tytuł gry łamany na dwie linie, tak jak na makiecie - druga linia jest
   większa i kolorowa, bo to ona niesie nazwę. */
.game-name {
    margin: 0;
    display: grid;
    line-height: 0.94;
    text-transform: uppercase;
}

.game-name-1 {
    font-size: clamp(1.2rem, 3.4vmin, 3rem);
    font-weight: 900;
}

.game-name-2 {
    font-size: clamp(1.6rem, 4.6vmin, 4rem);
    font-weight: 900;
}

.c-melodia { color: var(--g-melodia); }
.c-kolo { color: var(--g-kolo); }

.game-art {
    display: grid;
    place-items: center;
    min-height: 0;
}

.game-art svg,
.game-rail .wheel {
    width: auto;
    height: min(38vmin, 100%);
    max-width: 100%;
}

/* Niebieska karta z instrukcją dla graczy - z makiety. */
.tip-card {
    margin: 0;
    padding: clamp(0.6rem, 1.6vmin, 1.1rem);
    border-radius: 14px;
    background: rgba(46, 107, 216, 0.16);
    border: 1px solid rgba(62, 123, 250, 0.45);
    color: var(--fg);
    /* Instrukcja dla graczy - stary sufit (1.1rem) był dobrany pod laptopa
       (P2-23 audytu). */
    font-size: clamp(0.85rem, 2.1vmin, 1.6rem);
}

.game-main {
    grid-area: main;
    display: grid;
    align-content: center;
    justify-items: center;
    gap: clamp(0.5rem, 1.6vmin, 1.2rem);
    padding: clamp(0.7rem, 2vmin, 1.6rem);
    border-radius: 18px;
    background: rgba(13, 16, 30, 0.55);
    border: 1px solid #232741;
    min-height: 0;
    text-align: center;
}

.board-head {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
}

.board-hint {
    color: var(--accent);
}

/* Stopka panelu - drobna wskazówka na dole ekranu, jak na makiecie. */
.game-foot {
    grid-area: foot;
    margin: 0;
    color: var(--muted);
    /* Stary sufit (1rem) był dobrany pod laptopa (P2-23 audytu). */
    font-size: clamp(0.75rem, 1.8vmin, 1.4rem);
    text-align: center;
}

/* Tablo po prawej to "PUNKTACJA" z makiety. */
.teams-head {
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

/* ---------- telefon wg makiet ---------- */

.player-brand {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 900;
    letter-spacing: 0.02em;
    flex: 0 0 auto;
}

/* Drużyna i punkty jako mała informacja w pasku - nie zjada ekranu do grania. */
.player-who {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--muted);
    overflow: hidden;
}

.player-who-dot {
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 50%;
    background: var(--team-color, var(--accent));
    flex: 0 0 auto;
}

.player-who-name {
    color: var(--fg);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.player-who-score { flex: 0 0 auto; }
.player-who-score b { color: var(--team-color, var(--fg)); font-weight: 900; }

/* Pasek z nazwą gry - pełna szerokość, kolor gry. */
.game-tab {
    margin: 0 0 0.75rem;
    padding: 0.7em 1em;
    border-radius: 12px;
    text-align: center;
    font-weight: 900;
    font-size: 1.15rem;
    letter-spacing: 0.04em;
    color: #fff;
}

.c-bg-melodia { background: var(--g-melodia); }
.c-bg-kolo { background: var(--g-kolo); }

.player-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.fact-card {
    display: grid;
    gap: 0.15rem;
    padding: 0.7rem 0.9rem;
    border-radius: 12px;
    background: rgba(242, 239, 230, 0.06);
    border: 1px solid #232741;
    text-align: center;
}

.fact-label {
    color: var(--muted);
    font-size: 0.85rem;
}

.fact-value {
    font-size: 1.8rem;
    font-weight: 900;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--team-color, var(--fg));
}

.fact-team {
    font-size: 1.4rem;
}

/* Okrągła akcja główna - dominanta ekranu telefonu, jak na makietach. */
.round-action {
    display: grid;
    place-items: center;
    width: min(64vw, 17rem);
    aspect-ratio: 1;
    margin: 0.5rem auto;
    border: 6px solid rgba(255, 255, 255, 0.85);
    border-radius: 50%;
    color: #fff;
    font-size: clamp(1.4rem, 7vw, 2.2rem);
    font-weight: 900;
    line-height: 1.05;
    text-transform: uppercase;
    cursor: pointer;
    touch-action: manipulation;
}

.round-action:active {
    transform: scale(0.97);
}

.action-caption {
    margin: 0.5rem 0 0;
    text-align: center;
    color: var(--muted);
}

/* ---------- panel punktacji po lewej (miejsca + animacja) ---------- */

.tv-teams {
    grid-template-rows: auto auto minmax(0, 1fr);
}

/* Kafelek drużyny: numer miejsca, nazwa, wynik, przyciski hosta. */
.tv-teams .team {
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
        'rank name score'
        'rank buttons score';
}

.tv-teams .team-rank {
    grid-area: rank;
    display: grid;
    place-items: center;
    width: 1.7em;
    height: 1.7em;
    margin-right: 0.5rem;
    border-radius: 8px;
    background: rgba(242, 239, 230, 0.1);
    color: var(--muted);
    font-size: clamp(0.9rem, 1.9vmin, 1.5rem);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
}

/* Lider wyróżniony - z kanapy widać, kto prowadzi, bez czytania liczb. */
.tv-teams .team:first-child .team-rank {
    background: var(--accent);
    color: #22160a;
}

/* Zmiana wyniku podbija liczbę; przesunięcie kafelka animuje kontroler
   techniką FLIP, bo CSS nie widzi zmiany kolejności w DOM-ie. */
.tv-teams .team-score.bump {
    animation: pop 0.35s ease-out;
}

/* ---------- poprawki po obejrzeniu zrzutów ekranu ----------

   Wąska kolumna punktacji nie mieściła wyniku w jednym rzędzie z nazwą
   i przyciskami - liczba punktów wypadała poza kafelek. Układ pionowy:
   miejsce i nazwa na górze, pod spodem duży wynik i przyciski hosta. */

/* Jeden rząd: miejsce, nazwa, a po prawej duży, zawsze aktualny wynik.
   Ręcznej korekty punktów już nie ma - liczby prowadzą same gry. */
/* Usuwanie idzie POD nazwą, nie obok niej w tym samym rzędzie - czwarta
   kolumna obcinała szerokość nazwy (przy wąskim panelu "Alfa" łamało się
   na "Alf"/"a"). Rank i wynik nadal rozciągają się na oba wiersze - są
   w obu liniach `grid-template-areas`, tak jak w historycznym układzie
   dwurzędowym z buttons/score wyżej w tym pliku. */
.tv-teams .team {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    grid-template-areas:
        'rank name score'
        'rank remove score';
    align-items: center;
    gap: 0.15rem 0.6rem;
}

.tv-teams .team-rank {
    margin-right: 0;
}

.tv-teams .team-remove {
    grid-area: remove;
    justify-self: start;
    width: 1.4em;
    height: 1.4em;
    font-size: 0.6em;
}

.tv-teams .team-score {
    grid-area: score;
    text-align: right;
    font-size: clamp(1.4rem, 3vmin, 2.6rem);
}

/* Scena wypełnia całą wysokość zamiast skleić się do górnej krawędzi.
   Dolna połowa ekranu telewizora stała pusta, bo align-content: center
   przy jednym wierszu ustawia go w pionie na środku, ale nie rozciąga. */
.tv-stage {
    align-content: stretch;
}

.game-panel {
    grid-template-rows: minmax(0, 1fr) auto;
    height: 100%;
}

.game-main {
    height: 100%;
}

/* Koło bierze tyle wysokości, ile zostanie po tytule i karcie z instrukcją. */
.game-rail .wheel {
    height: min(52vmin, 100%);
}

/* ---------- proporcje sceny i plansza hasła ----------

   Pół na pół: koło jest bohaterem gry i zasługuje na tyle samo miejsca
   co plansza. Wcześniej szyna miała sztywne 20rem i koło dusiło się
   w kolumnie węższej niż jedna trzecia ekranu. */
.game-panel {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}

.game-rail .wheel {
    height: min(64vmin, 100%);
}

/* Odstępy rozłożone równomiernie zamiast zbicia treści w środku karty
   z pustką nad i pod. */
.game-main {
    align-content: space-evenly;
}

/* Kafelki hasła mają czytać się jako miejsca na litery także wtedy, gdy są
   puste - stąd ramka. Bez niej to były bezkształtne szare prostokąty. */
/* Kafelek hasła ma dwie strony: zakrytą i literę na odwrocie. Kolory i ramka
   siedzą na ścianach, nie na kafelku - inaczej przy obrocie prześwitywałyby
   przez siebie. */
.puzzle-cell {
    background: transparent;
    border: 0;
    perspective: 700px;
}

.cell-inner {
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    transition: transform 620ms cubic-bezier(0.25, 0.8, 0.3, 1);
}

.cell-inner.revealed { transform: rotateY(180deg); }

.cell-face {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    border-radius: 6px;
    border: 2px solid #38406a;
    backface-visibility: hidden;
}

.cell-back { background: #1a1f36; }

/* Kalambury: zakryte kafelki w kolorze gry. Ciemny granat zlewał się z tłem
   ekranu i z drugiego końca pokoju nie dało się policzyć liter - a właśnie po
   to ta plansza tam jest. */
.kalambury-panel .cell-back {
    background: #1f7a51;
    border-color: #35b57c;
}

.kalambury-panel .cell-front {
    background: #e8f7ef;
    border-color: #35b57c;
}

.cell-front {
    background: #f5f6fb;
    color: #10121f;
    transform: rotateY(180deg);
}

.puzzle-space {
    border-color: transparent;
    background: transparent;
}

/* ---------- przegląd ekranów: czytelność na TV i telefonie ---------- */

/* Plansza hasła na osi karty - wcześniej uciekała w lewo, bo flex-start
   wyrównywał ją do krawędzi zamiast do środka. */
.puzzle-board {
    align-content: center;
    width: 100%;
}

/* Telefon: kolejność z makiety to pasek gry, potem drużyna i punkty.
   order zamiast przenoszenia znaczników, bo pasek należy do szablonu
   modułu (rdzeń nie zna nazw gier), a karty do rdzenia. */
.player-main {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0.5rem;
}

.game-tab {
    order: -1;
    margin-bottom: 0;
}

/* Akcja główna wypełnia to, co zostanie - bez pustki nad kartami. */
.buzzer,
.kolo-player {
    flex: 1;
    min-height: 0;
}

.player-facts {
    margin-bottom: 0;
}

/* Nazwa drużyny na telefonie: kolor drużyny bywa ciemny na ciemnym tle,
   więc trzymamy pełny kontrast i tylko akcentujemy kolorem obwódkę karty. */
.fact-team {
    color: var(--fg);
}

.player-facts .fact-card:first-child {
    border-left: 5px solid var(--team-color);
}

/* Kontener buzzera rośnie, ale sam przycisk zostaje kołem: rozciągnięty
   flexem robił się elipsą, bo aspect-ratio przegrywa z wysokością ścieżki. */
.buzzer {
    display: grid;
    place-items: center;
}

.buzzer-button {
    width: min(78vw, 58vh);
    height: auto;
    aspect-ratio: 1;
}

/* ---------- kalambury ---------- */

.c-kalambury { color: var(--g-kalambury); }
.c-bg-kalambury { background: var(--g-kalambury); }

/* Zegar rundy: największa liczba na ekranie po planszy hasła - zgadujący
   patrzą na niego przez całą rundę. Ostatnie 10 sekund na czerwono. */
.clock {
    display: grid;
    place-items: center;
    padding: clamp(0.5rem, 1.6vmin, 1.2rem);
    border-radius: 18px;
    background: rgba(242, 239, 230, 0.06);
    border: 2px solid #232741;
}

.clock-value {
    font-size: clamp(2.5rem, 12vmin, 8rem);
    font-weight: 900;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.clock[data-state="urgent"] {
    border-color: var(--err);
}

.clock[data-state="urgent"] .clock-value {
    color: var(--err);
}

.clock-phone .clock-value {
    font-size: clamp(3rem, 22vw, 6rem);
}

/* Ostatnia litera: cale TV liczy sie tylko z zegarem i literami, wiec stac
   go na wieksze cyfry niz gry z plansza/hasłem obok. */
.clock-huge .clock-value {
    font-size: clamp(4rem, 20vmin, 14rem);
}

/* Hasło dla aktora - jedyne miejsce w grze, gdzie tekst ma być duży
   i czytelny z ręki, bo pokazuje się je na oczach reszty stołu. */
.secret-word {
    font-size: clamp(1.6rem, 9vw, 2.8rem);
    font-weight: 900;
    line-height: 1.1;
    color: var(--accent);
    text-transform: uppercase;
}

.kalambury-player {
    display: grid;
    align-content: start;
    gap: 0.6rem;
}

/* ---------- kalambury rysowane ---------- */

.c-kalambury-rysowane { color: var(--g-kalambury-rysowane); }
.c-bg-kalambury-rysowane { background: var(--g-kalambury-rysowane); }

.rys-player {
    display: grid;
    align-content: start;
    gap: 0.6rem;
}

/* .game-panel ma własną, sztywną siatkę grid-template-areas "rail main"/
   "foot foot" (patrz reguła .game-panel niżej w pliku) - .rys-panel jest
   jej bezpośrednim potomkiem razem z .game-rail/.game-main/.game-foot, więc
   nakładka wyboru roli NIE MOŻE być kolejnym poziomem zagnieżdżenia w tej
   siatce (to właśnie złamało cały layout przy pierwszym podejściu - kreska
   i widok graczy "znikały", bo canvas dziedziczył zerowy rozmiar po
   zapadniętym opakowaniu). Zamiast tego wychodzi z siatki przez
   position:absolute i po prostu przykrywa całą kartę, dopóki host nie wybierze roli. */
.rys-panel {
    position: relative;
    /* Domyślnie (i na tablecie) jedna kolumna - płótno zajmuje prawie cały
       ekran. Projektor dostaje z powrotem wąską szynę po lewej (reguła
       niżej), bo tam jest miejsce na kategorię/zegar/punkty BEZ odbierania
       płótnu miejsca - "sidebar po lewo... a reszta to duży ekran
       z rysunkiem" (życzenie użytkownika). */
    grid-template-columns: 1fr;
    grid-template-areas:
        'main'
        'foot';
}

.rys-panel[data-role="projector"] {
    grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
    grid-template-areas:
        'rail main'
        'foot foot';
}

/* Szyna istnieje w DOM zawsze (musi - .game-panel wymaga bezpośrednich
   dzieci main/foot niezależnie od tego, czy 'rail' akurat jest w układzie,
   patrz komentarz w host.html.twig), ale poza projektorem po prostu znika -
   na tablecie płótno ma zająć to miejsce, nie pustą, zarezerwowaną kolumnę. */
.rys-panel:not([data-role="projector"]) .game-rail {
    display: none;
}

/* Na tablecie płótno ma być "jak największe" - pasek gospodarza na górze
   (Zmień grę/Reset/dołączanie) i wspólna kolumna z drużynami/punktami po
   lewej (.tv-bar/.tv-teams, spoza tego panelu, patrz host/screen.html.twig)
   są tam zbędne: rysujący trzyma tablet, nie zarządza imprezą. :has() sięga
   z korzenia (.tv/.tv-body) do roli ustawionej głęboko w moim panelu -
   ukrycie samego .tv-teams by nie wystarczyło, bo .tv-body ma STAŁĄ
   szerokość jego kolumny (clamp(11rem,15vw,17rem)) niezależną od tego, czy
   coś w niej siedzi, więc bez nadpisania grid-template-columns zostałaby
   pusta, zarezerwowana szpara zamiast oddanego miejsca. Degraduje się
   bezpiecznie w przeglądarce bez :has() - chrom po prostu zostaje widoczny. */
.tv:has(.rys-panel[data-role="tablet"]) .tv-bar {
    display: none;
}

/* Bez tego .tv-body (jedyny widoczny grid item .tv, skoro .tv-bar zniknął)
   dostawał się przez auto-placement do PIERWSZEGO, "auto"-wysokiego wiersza
   (dotąd zajmowanego przez pasek) zamiast do drugiego, "minmax(0,1fr)" -
   auto-placement nie wie, że .tv-body "należy" do drugiego wiersza, po
   prostu wypełnia po kolei to, co jest. Efekt: cała gra kurczyła się do
   naturalnej wysokości treści, a pod spodem zostawała pusta, czarna szpara
   dokładnie wielkości nieużywanego drugiego wiersza - zgłoszenie użytkownika
   ("ŹLE" na zrzucie ekranu). Jawne przypięcie do wiersza 2 naprawia to bez
   dotykania układu innych gier. */
.tv:has(.rys-panel[data-role="tablet"]) .tv-body {
    grid-row: 2;
}

/* "Rysuj na całym ekranie" na TABLECIE (rysowanki_host_controller.js) woła
   TEN SAM przełącznik pełnego ekranu co przycisk w pasku (patrz komentarz
   przy .rys-focus-toggle) - a `.tv.tv-focus` wyżej w tym pliku ścieśnia
   `.tv` z powrotem do JEDNEGO wiersza (`grid-template-rows: minmax(0,1fr)`).
   Bez tej reguły `.tv-body` zostawał przypięty do wiersza 2, którego w tym
   trybie po prostu NIE MA - grid dokładał go niejawnie na dole, a cała gra
   (z płótnem włącznie) spadała pod widoczny ekran, zostawiając pusty,
   "1fr"-owy wiersz 1 u góry. Ten sam bug co przy .tv-bar wyżej, tylko
   odwrócony w czasie: tam zniknięcie sąsiada zostawiało puste MIEJSCE,
   tu zniknięcie WIERSZA zostawia osierocone przypięcie. */
.tv.tv-focus:has(.rys-panel[data-role="tablet"]) .tv-body {
    grid-row: 1;
}

.tv-body:has(.rys-panel[data-role="tablet"]) {
    grid-template-columns: 1fr;
}

.tv-body:has(.rys-panel[data-role="tablet"]) .tv-teams {
    display: none;
}

/* .tv-stage domyślnie centruje swoją zawartość w pionie zamiast ją
   rozciągać (align-content: center, wiersz siatki wysokości "auto") - dla
   gier z bogatszą planszą różnica jest niezauważalna, bo naturalna wysokość
   treści i tak wychodzi bliska pełnej. W kalamburach rysowanych, zwłaszcza
   na tablecie (bez szyny, bez paska gospodarza u góry - patrz reguły wyżej),
   treść bez płótna jest wyraźnie niższa niż ekran, więc ".game-panel" po
   prostu wisiał wyśrodkowany z dużą czarną szparą pod spodem, zamiast
   oddać tę przestrzeń płótnu - zgłoszenie użytkownika. Rozciągnięcie
   dotyczy WYŁĄCZNIE tej gry (:has(.rys-panel)), inne plansze zostają przy
   dotychczasowym centrowaniu. */
.tv-stage:has(.rys-panel) {
    grid-template-rows: minmax(0, 1fr);
    align-content: stretch;
}

/* Zawsze widoczny (nawet w trybie pełnoekranowym - patrz reguły `.rys-focus`
   niżej), więc wychodzi z siatki .game-panel tak samo jak .rys-role-gate
   (position:absolute zamiast bycia czwartym potomkiem rail/main/foot).
   z-index niższy niż bramka wyboru roli (30) - zanim host wybierze rolę,
   bramka i tak zakrywa ten przycisk, więc nie da się kliknąć "w ciemno". */
.rys-focus-toggle {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 20;
    width: 2.3rem;
    height: 2.3rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid #2b3050;
    border-radius: 999px;
    background: rgba(10, 12, 22, 0.55);
    color: var(--muted);
    cursor: pointer;
    font-size: 1.1rem;
    transition: opacity 0.15s ease, color 0.15s ease;
}

.rys-focus-toggle:hover,
.rys-focus-toggle:focus-visible {
    color: var(--fg);
}

/* "Rysuj na całym ekranie" - chowa szynę projektora i pasek nad płótnem
   (kategoria/tura/hasło/zegar/punkty), zostawiając tylko rysunek i
   sterowanie POTRZEBNE do gry (wybór trudności, wskazanie kto zgadł,
   "Wyczyść") - te żyją w .game-main pod HUD-em/szyną, nie w nich, więc
   zostają. Rail wraca do jednej kolumny tak jak domyślnie na tablecie
   (patrz .rys-panel bazowe) - projektor w tym trybie nie różni się już
   układem od tabletu. */
.rys-panel.rys-focus {
    grid-template-columns: 1fr;
    grid-template-areas:
        'main'
        'foot';
}

.rys-panel.rys-focus .game-rail,
.rys-panel.rys-focus .rys-hud,
.rys-panel.rys-focus .game-foot {
    display: none;
}

.rys-rail {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    text-align: left;
    min-height: 0;
}

.rys-rail-category,
.rys-rail-turn {
    font-size: clamp(0.8rem, 1.3vw, 0.95rem);
    color: var(--muted);
    margin: 0;
}

/* "Delikatny" licznik: sam tekst, bez ramki/tła/plakietki jak reszta
   zegarów w appce - to jedynie okienko z boku, nie centralny element ekranu
   (życzenie użytkownika: "licznik zrób taki delikatny"). Selektory tej sekcji
   celowo zaczynają się od ".rys-panel", nie od samej klasy elementu -
   ".rys-rail-clock .clock-value" i ".clock-value" (reguła bazowa, dużo
   niżej w tym pliku) mają tę samą specyficzność, a o kolejność w źródle
   nietrudno się potknąć przy każdej kolejnej zmianie (już się zdarzyło -
   patrz komentarz przy .rys-only-tablet). Dodatkowa klasa w selektorze
   gwarantuje wygraną niezależnie od tego, co jeszcze dopisze się niżej. */
.rys-panel .rys-rail-clock {
    padding: 0.2rem 0;
    background: transparent;
    border: none;
    justify-items: start;
}

.rys-panel .rys-rail-clock .clock-value {
    font-size: clamp(1.4rem, 2.4vw, 1.9rem);
    color: var(--muted);
}

/* Goła liczba sekund nie mówi nic o sobie w wąskiej szynie bez podpisu -
   ikona zamiast osobnego wiersza tekstu, żeby zostać "delikatnym". */
.rys-panel .rys-rail-clock .clock-value::before {
    content: '⏱ ';
    font-size: 0.6em;
    opacity: 0.7;
}

.rys-panel .rys-rail-clock[data-state="urgent"] .clock-value {
    color: var(--err);
}

/* Ta sama "delikatność" dla punktów - bez plakietki z obwódką, którą ma
   wersja na tablecie (tam jest głównym elementem informacyjnym obok hasła,
   tutaj tylko dopowiedzeniem obok zegara). */
.rys-panel .rys-rail-points {
    display: block;
    padding: 0;
    background: transparent;
    border: none;
    font-weight: 600;
    color: var(--muted);
}

.rys-panel .rys-rail-points span {
    font-size: clamp(1.1rem, 1.8vw, 1.3rem);
    color: var(--g-kalambury-rysowane);
    font-weight: 800;
}

.rys-rail .rys-role-switch {
    margin-top: auto;
}

/* Zwarty pasek nad płótnem: kategoria/tura na projektorze, hasło na
   tablecie, zegar, punkty i mała ikona zmiany roli - wszystko, co gdzie
   indziej siedziałoby w szynie .game-rail, tutaj celowo NIE rośnie
   (.rys-panel .game-main > * ma flex: 0 0 auto), żeby płótno poniżej
   dostało resztę wysokości. */
.rys-hud {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.4rem 0.9rem;
    width: 100%;
    padding-block: 0.2rem;
}

/* .secret-word (reguła współdzielona z Kalamburami) już ustawia rozmiar
   i kolor - to opakowanie jest tu tylko po to, żeby hasło siedziało w tym
   samym wierszu flex co zegar i punkty. */
.rys-hud-word {
    display: inline-flex;
    align-items: baseline;
}

.rys-panel .rys-hud-clock {
    padding: 0.35rem 0.8rem;
    border-radius: 12px;
}

.rys-panel .rys-hud-clock .clock-value {
    font-size: clamp(1.3rem, 3.4vmin, 2.1rem);
}

.rys-panel .rys-hud-points {
    padding: 0.3rem 0.8rem;
}

.rys-panel .rys-hud-points span {
    font-size: clamp(1.05rem, 2.6vmin, 1.5rem);
}

.rys-role-switch {
    margin-left: auto;
    width: 2.1rem;
    height: 2.1rem;
    display: grid;
    place-items: center;
    padding: 0;
    background: transparent;
    border: 1px solid #2b3050;
    border-radius: 999px;
    color: var(--muted);
    cursor: pointer;
    font-size: 1rem;
}

/* Jedyny "komunikat", jaki tablet w trakcie rysowania jeszcze pokazuje
   (patrz #render() w rysowanki_host_controller.js, `tabletDrawing`) - reszta
   szyny (zegar, punkty, przełącznik roli) znika, żeby zostało tylko płótno. */
.rys-word-toggle {
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    border: 1px solid #2b3050;
    background: transparent;
    color: var(--muted);
    font-weight: 700;
    cursor: pointer;
}

.rys-word-toggle:hover,
.rys-word-toggle:focus-visible {
    color: var(--fg);
    border-color: var(--g-kalambury-rysowane);
}

/* Wybór roli tego konkretnego ekranu (projektor kontra tablet) - jedyny
   moment, w którym host musi coś skonfigurować PRZED wejściem w grę, więc
   dostaje środek ekranu, nie mały panel z boku. */
.rys-role-gate {
    position: absolute;
    inset: 0;
    z-index: 30;
    display: grid;
    align-content: center;
    justify-items: center;
    gap: 1rem;
    padding: clamp(1rem, 3vh, 2.5rem) 1rem;
    text-align: center;
    background: rgba(10, 12, 22, 0.97);
    border-radius: var(--radius);
    overflow-y: auto;
}

.rys-role-gate > * {
    max-width: 32rem;
}

.rys-role-choices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.8rem;
    width: 100%;
}

/* Etykieta w osobnych blokowych <span>, nie <br>+<small> - dzięki temu tekst
   zawija się przewidywalnie zamiast wypływać poza zaokrąglony przycisk. */
.rys-role-btn {
    display: grid;
    gap: 0.3rem;
    padding-block: 1rem;
    white-space: normal;
    overflow-wrap: break-word;
}

.rys-role-btn-title {
    font-size: 1.05rem;
    font-weight: 800;
}

.rys-role-btn-sub {
    font-size: 0.82rem;
    font-weight: 500;
    opacity: 0.8;
}

.rys-transfer-qr {
    border-radius: 12px;
    background: #fff;
    padding: 0.5rem;
}

.rys-transfer-warn {
    color: var(--err);
    font-weight: 700;
    max-width: 26rem;
}

/* Role dzielą jeden szablon - CSS chowa to, co nie należy do danego ekranu,
   zamiast dwóch osobnych widoków, które łatwo rozjechać przy każdej zmianie.
   Reguła TYLKO wyłącza (display: none), NIGDY nie próbuje z powrotem
   "włączyć" - pierwsza wersja robiła to przez `display: revert`, co brzmi
   jak "przywróć własny styl", ale naprawdę cofa do domyślnego wyglądu
   znacznika w przeglądarce BEZ ARKUSZY AUTORA: dla zwykłego <div> to
   zawsze "block", nigdy "grid" ani "flex". Efekt: `.rys-choices` (na co
   dzień display:grid, 3 kolumny) na tablecie wracało jako `display:block` -
   trzy oferty trudności stały jedna pod drugą zamiast obok siebie, mimo że
   reguła "w poziomie" (patrz .rys-choices niżej) była poprawna i w ogóle
   się nie odpalała. Zamiast zgadywać każdemu ".rys-only-*" jego właściwy
   `display`, selektor hide warunkujemy przez `:not([data-role=...])` -
   gdy rola pasuje, reguła po prostu NIE DOTYCZY elementu i jego WŁASNA
   reguła (np. `.rys-choices { display: grid }`) obowiązuje bez przeszkód. */
.rys-panel:not([data-role="tablet"]) .rys-only-tablet { display: none; }
.rys-panel[data-role="tablet"] .rys-only-projector { display: none; }

.rys-points-badge {
    display: grid;
    place-items: center;
    padding: 0.5rem 1rem;
    border-radius: 999px;
    background: rgba(230, 73, 128, 0.16);
    border: 2px solid var(--g-kalambury-rysowane);
    font-weight: 800;
    text-align: center;
}

.rys-points-badge span {
    font-size: clamp(1.6rem, 5vmin, 3rem);
    font-variant-numeric: tabular-nums;
}

/* Trzy oferty trudności - kolor rośnie z pulą punktów, tak jak reszta
   trójkolorowych skal w tej appce (zielony/żółty/czerwony). */
/* Zawsze TRZY kolumny obok siebie, nie auto-fit - auto-fit zwijał się do
   jednej kolumny (trzy oferty jedna pod drugą, "brzydko") na węższym
   tablecie w pionie, mimo że trzy węższe kolumny mieszczą się bez problemu -
   zgłoszenie użytkownika ("zrób je w poziomie"). */
.rys-choices {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(0.4rem, 1.5vw, 0.7rem);
}

.rys-choice {
    display: grid;
    align-content: center;
    gap: 0.3rem;
    padding: 1rem 0.5rem;
    border-radius: 14px;
    border-width: 2px;
    text-align: center;
    line-height: 1.25;
    overflow-wrap: break-word;
    min-width: 0;
}

.rys-choice-label {
    font-size: 0.9rem;
    opacity: 0.85;
}

/* Hasła bywają wielowyrazowe i długie - łamią się na spacjach same, ale
   pojedyncze długie słowo (np. "dziewięćdziesiąt") bez break-word/hyphens
   wypływało poza zaokrąglony przycisk zamiast się zawinąć. */
.rys-choice-word {
    /* .rys-choice jest siatką, a jej dzieci mają domyślnie min-width:auto -
       bez zerowania tego długie hasło ("Czerwony Kapturek") odmawiało
       zawijania na spacji i po prostu wypływało poza kolumnę, mimo
       overflow-wrap/word-break niżej (te łamią słowo w środku, nie
       wymuszają zawinięcia dwuwyrazowej frazy). */
    min-width: 0;
    font-size: clamp(0.9rem, 2.2vw, 1.3rem);
    font-weight: 800;
    text-transform: uppercase;
    overflow-wrap: break-word;
    word-break: break-word;
    hyphens: auto;
}

.rys-choice-latwy { border-color: var(--g-kalambury); }
.rys-choice-sredni { border-color: var(--g-kolo); }
.rys-choice-trudny { border-color: var(--err); }

/* Płótno ma dominować ekran projektora - reszta treści (kategoria, zegar,
   sterowanie) jest zwarta i nie rośnie, .game-main zamienia się w kolumnę,
   w której WYŁĄCZNIE płótno (albo, gdy jest ukryte, wybór trudności na
   tablecie) dostaje flex-grow i zabiera całą resztę wysokości. Nadpisuje
   wspólną (grid) regułę .game-main tylko wewnątrz tej gry - reszta gier jej
   nie widzi. */
.rys-panel .game-main {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    height: 100%;
    min-height: 0;
}

.rys-panel .game-main > * {
    flex: 0 0 auto;
}

.rys-panel .rys-canvas-wrap,
.rys-panel .rys-choices {
    flex: 1 1 auto;
    min-height: 0;
}

/* touch-action: none, bo bez tego dotyk na tablecie przewijałby stronę
   zamiast rysować. */
/* Płótno musi mieć IDENTYCZNE proporcje na projektorze i na tablecie -
   inaczej ta sama kreska (współrzędne 0..1 względem własnego pudełka
   płótna, patrz rysowanki_host_controller.js) wychodzi na drugim ekranie
   rozciągnięta, bo dzieli przez inną szerokość/wysokość (życzenie
   użytkownika: "takie samo skalowanie i taki sam rozmiar pola rysowania").
   .rys-canvas-wrap wypełnia dostępne miejsce i centruje w nim
   .rys-canvas-frame, który ma STAŁY, wspólny dla obu ekranów format.

   Format 16:9, nie kwadrat - użytkownik zdecydował, że tablet ZAWSZE stoi
   w poziomie, więc oba ekrany są w praktyce tego samego, szerokiego typu
   (projektor i tak jest 16:9) i nie ma już dwóch konkurujących orientacji
   do pogodzenia kompromisem. Kwadrat był kompromisem WYŁĄCZNIE dlatego, że
   tablet stał w pionie - bez tego założenia 16:9 wykorzystuje przestrzeń
   lepiej niż kwadrat na obu ekranach. `width/height: auto` + `max-width/
   max-height: 100%` to standardowy wzorzec "zmieść największe pudełko
   o tych proporcjach w dostępnym miejscu" (letterboxing) - patrz
   .rys-canvas-frame niżej za policzeniem tego wprost przez container query.
   Ramka (nie samo płótno) niesie ten format, żeby przycisk "Wyczyść" mógł
   się do niej przypiąć rogiem - inaczej, przy węższym niż pudełko płótnie,
   wisiałby w pustym marginesie zamiast przy realnej krawędzi rysunku. */
.rys-canvas-wrap {
    position: relative;
    width: 100%;
    height: 100%;
    /* Dwie pierwsze próby (place-items: center/stretch + aspect-ratio na
       pustym divie) nie działały: "center" nie ma z czego policzyć rozmiaru
       pudełka bez treści i spada do zastępczych 300×150 (kwadrat drobny
       mimo mnóstwa wolnego miejsca), a "stretch" ignoruje aspect-ratio i po
       prostu rozciąga na cały prostokąt (kwadrat wychodzi jako elipsoida -
       zniekształcony). Container query rozwiązuje to wprost: .rys-canvas-wrap
       STAJE SIĘ jednostką odniesienia (cqw/cqh) dla własnego dziecka. */
    container-type: size;
    display: grid;
    place-items: center;
}

.rys-canvas-frame {
    position: relative;
    /* Szerokość największego pudełka 16:9, jakie mieści się w kontenerze
       (cqw/cqh, patrz container-type na .rys-canvas-wrap), policzona wprost -
       ten sam trik co przy kwadracie (patrz historia wyżej), tylko z drugim
       wymiarem przeskalowanym przez współczynnik proporcji: gdyby o rozmiar
       decydowała wysokość (100cqh), szerokość takiego pudełka to 100cqh*16/9,
       nie 100cqh - stąd `calc()` zamiast gołego "100cqh" w drugim argumencie
       min(). Bez tego przeskalowania silnik porównywałby wysokość kontenera
       wprost z jego szerokością, co dawałoby kwadrat, nie 16:9. */
    width: min(100cqw, calc(100cqh * 16 / 9));
    aspect-ratio: 16 / 9;
    min-width: 16rem;
}

.rys-canvas {
    display: block;
    width: 100%;
    height: 100%;
    background: #f4ecff;
    border-radius: 18px;
    touch-action: none;
    cursor: crosshair;
}

.rys-clear-btn {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
}

/* ---------- państwa i miasta ---------- */

.c-panstwa { color: var(--g-panstwa); }
.c-bg-panstwa { background: var(--g-panstwa); }

/* Litera jest sercem tej gry: musi być czytelna z kanapy przez całą rundę,
   więc dostaje tyle miejsca, ile zostanie po zegarze. */
.letter-box {
    display: grid;
    place-items: center;
    padding: clamp(0.5rem, 2vmin, 1.5rem);
    border-radius: 24px;
    background: rgba(142, 78, 198, 0.12);
    border: 3px solid #8e4ec6;
    /* Perspektywa dla klapki - bez niej obrót w pionie wygląda płasko. */
    perspective: 800px;
}

/* Litera jak klapka na dworcowej tablicy: ciemna karta z bruzdą w połowie
   wysokości. Rozmiary w em, żeby karta kurczyła się razem z literą na
   ekranie punktacji. */
.letter-value {
    display: grid;
    place-items: center;
    min-width: 1em;
    padding: 0.16em 0.26em 0.2em;
    font-size: clamp(4rem, 20vmin, 14rem);
    font-weight: 900;
    line-height: 1;
    color: #f4ecff;
    background: linear-gradient(#2a2033, #14101b);
    border-radius: 0.1em;
    box-shadow:
        0 0.08em 0.28em rgba(0, 0, 0, 0.55),
        inset 0 0 0 1px rgba(201, 162, 236, 0.18);
    text-shadow: 0 0.03em 0.06em rgba(0, 0, 0, 0.6);
    position: relative;
    backface-visibility: hidden;
}

/* Bruzda dzieląca klapkę na pół - to ona robi „dworcową tablicę". */
.letter-value::after {
    content: '';
    position: absolute;
    left: 7%;
    right: 7%;
    top: 50%;
    height: 0.03em;
    transform: translateY(-50%);
    background: rgba(0, 0, 0, 0.55);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* Postęp drużyn w trakcie pisania. Kropki zamiast liczb, bo z kanapy liczy
   się jedno: czy ktoś jeszcze pisze, czy wszyscy już czekają. */
.pm-progress {
    display: grid;
    gap: 0.5rem;
    align-content: start;
}

.pm-progress-row {
    display: grid;
    grid-template-columns: minmax(6rem, 12rem) 1fr auto;
    align-items: center;
    gap: 0.75rem;
    font-size: clamp(1rem, 2.2vmin, 1.6rem);
}

.pm-progress-name {
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pm-dots {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.pm-dot {
    width: clamp(0.7rem, 1.8vmin, 1.2rem);
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgba(242, 239, 230, 0.14);
}

.pm-dot-on {
    background: #8e4ec6;
}

.pm-progress-count {
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

/* Tabela wyników. Mieści się w panelu bez rozpychania go w bok - przy ośmiu
   rubrykach i pięciu drużynach to jedyny sposób, żeby dało się ją przeczytać. */
.pm-results {
    overflow: auto;
    max-height: 100%;
}

.pm-table {
    width: 100%;
    border-collapse: collapse;
    font-size: clamp(0.75rem, 1.6vmin, 1.15rem);
}

.pm-table th,
.pm-table td {
    padding: 0.35rem 0.5rem;
    text-align: left;
    border-bottom: 1px solid #232741;
}

.pm-table th {
    color: var(--muted);
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.75em;
    letter-spacing: 0.04em;
}

.pm-team {
    border-left: 4px solid var(--team-color, #8e4ec6);
    padding-left: 0.5rem !important;
    color: var(--fg) !important;
    text-transform: none !important;
    font-size: 1em !important;
}

/* Komórka jest przyciskiem: klik uznaje albo odrzuca odpowiedź. Kursor
   i podświetlenie mówią o tym wprost, bo host klika to na dużym ekranie. */
.pm-cell {
    cursor: pointer;
    border-radius: 6px;
}

.pm-cell:hover {
    background: rgba(242, 239, 230, 0.06);
}

.pm-cell .pm-text {
    display: block;
    line-height: 1.2;
}

.pm-cell .pm-points {
    display: block;
    font-size: 0.8em;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

.pm-unique .pm-text { color: var(--ok, #30a46c); font-weight: 700; }
.pm-shared .pm-text { color: var(--accent); }
.pm-empty { cursor: default; color: var(--muted); }
.pm-empty:hover { background: none; }
.pm-wrong_letter .pm-text,
.pm-too_short .pm-text,
.pm-rejected .pm-text {
    color: var(--err);
    text-decoration: line-through;
}

/* Słowo spoza wykazu państw i miast to nie to samo, co pudło: automat nie zna
   każdej miejscowości, więc komórka czeka na decyzję hosta, a nie ogłasza
   wyroku. Stąd żółty i znak zapytania zamiast przekreślenia. */
.pm-unknown .pm-text {
    color: var(--accent);
    text-decoration: underline dotted;
}

.pm-unknown .pm-text::after {
    content: ' ?';
    font-weight: 800;
}

/* Ślad po decyzji hosta - żeby po chwili było widać, co poprawiał ręcznie. */
.pm-forced {
    outline: 2px dashed rgba(142, 78, 198, 0.7);
    outline-offset: -2px;
}

.pm-total {
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    text-align: right !important;
}

/* ---------- państwa i miasta: telefon ---------- */

.panstwa-player {
    display: grid;
    align-content: start;
    gap: 0.7rem;
}

.pm-head {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 0.75rem;
}

/* Klapka jak na telewizorze, w miniaturze: ciemna karta z bruzdą w połowie. */
.pm-letter {
    display: grid;
    place-items: center;
    width: clamp(3.5rem, 18vw, 5rem);
    aspect-ratio: 1;
    border-radius: 12px;
    background: linear-gradient(#2a2033, #14101b);
    box-shadow:
        0 4px 12px rgba(0, 0, 0, 0.45),
        inset 0 0 0 1px rgba(201, 162, 236, 0.2);
    font-size: clamp(2rem, 10vw, 3rem);
    font-weight: 900;
    color: #f4ecff;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
    position: relative;
    backface-visibility: hidden;
}

.pm-letter::after {
    content: '';
    position: absolute;
    left: 8%;
    right: 8%;
    top: 50%;
    height: 2px;
    transform: translateY(-1px);
    background: rgba(0, 0, 0, 0.55);
}

.pm-fields {
    display: grid;
    gap: 0.5rem;
}

.pm-field {
    display: grid;
    gap: 0.15rem;
}

.pm-field-name {
    font-size: 0.85rem;
    color: var(--muted);
    font-weight: 700;
}

/* Duże pole: wpisuje się je kciukiem, w pośpiechu i na kolanie. */
.pm-input {
    font-size: 1.15rem;
    padding: 0.6rem 0.75rem;
}

.pm-input:disabled {
    opacity: 0.55;
}

/* STOP kończy rundę wszystkim - musi być trudny do przypadkowego trafienia
   i łatwy do celowego. Stąd osobny, szeroki przycisk pod polami. */
.btn-stop {
    width: 100%;
    padding: 1rem;
    font-size: 1.6rem;
    font-weight: 900;
    letter-spacing: 0.08em;
    background: var(--err);
    color: #fff;
    border: none;
    border-radius: 16px;
}

.btn-stop:disabled {
    opacity: 0.5;
}

.pm-note {
    color: var(--muted);
    text-align: center;
    margin: 0;
}


/* Punktacja zmienia hierarchie ekranu: litera zrobila swoje, teraz wszyscy
   czytaja tabele. Bez tego wyniki zostawaly drobnym drukiem obok wielkiej
   litery - sprawdzone na zrzucie z 1920x1080. */
.panstwa-panel[data-state="scoring"] {
    grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
}

.panstwa-panel[data-state="scoring"] .letter-value {
    font-size: clamp(2.5rem, 8vmin, 5rem);
}

.panstwa-panel[data-state="scoring"] .pm-table {
    font-size: clamp(1rem, 2.1vmin, 1.9rem);
}

.panstwa-panel[data-state="scoring"] .pm-table th,
.panstwa-panel[data-state="scoring"] .pm-table td {
    padding: 0.5rem 0.7rem;
}

.panstwa-panel[data-state="scoring"] .game-main {
    align-content: start;
}

/* Wąski pas w trybie punktacji: litera przestaje się rozciągać na całą
   wysokość, a nazwa gry schodzi na rozmiar, który się w nim mieści. */
.panstwa-panel[data-state="scoring"] .letter-box {
    align-self: start;
    aspect-ratio: 1;
}

.panstwa-panel[data-state="scoring"] .game-name {
    font-size: 0.6em;
}

.panstwa-panel[data-state="scoring"] .game-name-1,
.panstwa-panel[data-state="scoring"] .game-name-2 {
    font-size: clamp(1rem, 2.4vmin, 1.8rem);
}

/* ---------- animacje: ruch ma coś znaczyć ---------- */

/* Wszystkie animacje na tej stronie znikają, gdy system prosi o ograniczenie
   ruchu. Migający ekran przy stole to nie tylko kwestia gustu - dla części
   ludzi to realny problem. */
@media (prefers-reduced-motion: reduce) {
    .vinyl .vinyl-disc,
    .quiz-option.entering,
    .mime.acting .mime-arm-l,
    .mime.acting .mime-arm-r,
    .mime.acting svg,
    .letter-box.rolling,
    .letter-box.landed {
        animation: none !important;
    }

    /* Obrót kafelka i opadanie ramienia to przejścia, nie animacje - samo
       "animation: none" ich nie dotyka. */
    .cell-inner,
    .vinyl .vinyl-arm-tube {
        transition: none !important;
    }
}

/* --- koło: ładowanie zamachu na telefonie --- */

/* Przycisk puchnie i jaśnieje w miarę trzymania - gracz musi widzieć, ile
   już naładował, zanim puści. Bez tego "trzymaj i puść" jest zgadywanką. */
.round-action.charging {
    transform: scale(calc(1 + 0.12 * var(--power, 0)));
    filter: brightness(calc(1 + 0.5 * var(--power, 0)));
    transition: transform 90ms linear, filter 90ms linear;
}

.round-action.charging::after {
    content: '';
    position: absolute;
    inset: auto 0 0 0;
    height: calc(100% * var(--power, 0));
    background: rgba(255, 255, 255, 0.18);
    pointer-events: none;
}

.round-action {
    position: relative;
    overflow: hidden;
}

/* --- melodia: płyta kręci się, gdy leci dźwięk --- */

.vinyl-stage {
    position: relative;
    /* Płyta to główna ilustracja tego ekranu, więc bierze całą szerokość szyny
       i tyle wysokości, ile zostaje po tytule i karcie z podpowiedzią. */
    width: min(100%, 62vmin);
    aspect-ratio: 1;
    margin-inline: auto;
    filter:
        drop-shadow(0 1.5vmin 3vmin rgba(0, 0, 0, 0.75))
        drop-shadow(0 0 6vmin rgba(62, 123, 250, 0.14));
}

/* Rowki: kilkaset prążków z powtarzanego gradientu. Rysowane okręgi dawały
   tarczę strzelniczą - dopiero drobne ziarno wygląda jak tłoczony winyl. */
.vinyl .vinyl-disc {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    transform-origin: 50% 50%;
    background:
        repeating-radial-gradient(circle at center,
            #08090f 0, #08090f 2px, #171a2c 3px, #171a2c 4px),
        radial-gradient(circle at center, #1a1d31 0%, #05060d 100%);
    box-shadow:
        inset 0 0 6vmin rgba(0, 0, 0, 0.9),
        inset 0 0 12vmin rgba(0, 0, 0, 0.5);
    will-change: transform;
}

/* Dwa jaśniejsze pierścienie: krawędź płyty i przejście w pole etykiety.
   Bez nich rowki ciągną się do samego środka i płyta traci głębię. */
.vinyl .vinyl-disc::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: radial-gradient(circle at center,
        transparent 0%, transparent 36%,
        rgba(120, 132, 190, 0.35) 36.4%, transparent 36.8%,
        transparent 91%,
        rgba(120, 132, 190, 0.28) 91.4%, transparent 91.8%,
        transparent 100%);
}

.vinyl .vinyl-label {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 34%;
    height: 34%;
    border-radius: 50%;
    display: grid;
    align-content: center;
    justify-items: center;
    gap: 0.2em;
    text-align: center;
    background:
        radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.18), transparent 50%),
        radial-gradient(circle at center, #4b86ff, #2f6bd8 72%, #1b3f86);
    box-shadow:
        inset 0 0 2vmin rgba(0, 0, 0, 0.45),
        0 0 0 2px rgba(0, 0, 0, 0.4);
    color: #f2efe6;
}

/* Kreski nad i pod napisem - tyle zostaje z typografii etykiety, gdy koło
   ma na ekranie kilkanaście centymetrów. */
.vinyl .vinyl-label::before,
.vinyl .vinyl-label::after {
    content: '';
    position: absolute;
    left: 15%;
    width: 70%;
    height: 1px;
    background: rgba(245, 165, 36, 0.5);
}

.vinyl .vinyl-label::before { top: 12%; }
.vinyl .vinyl-label::after { bottom: 12%; }

/* Przerwa pod nazwą robi miejsce na otwór - inaczej trzpień przecina napis
   z prędkościami, czyli dokładnie ten wiersz, który ma być czytelny. */
.vinyl .vinyl-brand {
    margin-bottom: 1.5em;
    font-weight: 900;
    font-size: clamp(0.55rem, 2.1vmin, 1.3rem);
    letter-spacing: 0.04em;
    line-height: 1;
}

.vinyl .vinyl-rpm {
    font-size: clamp(0.4rem, 1.1vmin, 0.75rem);
    letter-spacing: 0.22em;
    color: var(--accent);
}

.vinyl .vinyl-side {
    font-size: clamp(0.35rem, 0.95vmin, 0.65rem);
    letter-spacing: 0.18em;
    color: rgba(242, 239, 230, 0.7);
}

/* Połysk stoi w miejscu, gdy płyta się kręci - światło w sali też stoi,
   a bez tej nieruchomej smugi obrót jednolitej czerni jest niewidoczny. */
.vinyl .vinyl-shine {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    z-index: 3;
    pointer-events: none;
    background: linear-gradient(125deg,
        transparent 35%,
        rgba(255, 255, 255, 0.05) 48%,
        rgba(255, 255, 255, 0.13) 50%,
        rgba(255, 255, 255, 0.05) 52%,
        transparent 65%);
}

.vinyl .vinyl-hole {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3.2%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: #05060d;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
    z-index: 4;
}

.vinyl.playing .vinyl-disc {
    /* 1,8 s na obrót to mniej więcej tempo, w jakim oko czyta ruch płyty;
       przy 2,4 s wyglądała, jakby zwalniała. */
    animation: vinyl-spin 1.8s linear infinite;
}

/* Ramię opada na płytę razem ze startem - drobiazg, ale to on sprzedaje
   całą metaforę gramofonu. */
.vinyl .vinyl-arm {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 5;
    overflow: visible;
    filter: drop-shadow(0 0.4vmin 0.8vmin rgba(0, 0, 0, 0.6));
}

/* W spoczynku igła stoi tuż za krawędzią płyty, przy starcie opada mniej
   więcej w dwóch trzecich promienia - tam, gdzie zaczyna się nagranie. */
.vinyl .vinyl-arm-tube {
    transform-origin: 184px 28px;
    transform: rotate(-8deg);
    transition: transform 900ms cubic-bezier(0.3, 0.8, 0.4, 1);
}

.vinyl.playing .vinyl-arm-tube {
    transform: rotate(14deg);
}

@keyframes vinyl-spin {
    to { transform: rotate(360deg); }
}

/* --- kalambury: ludzik pokazuje na migi --- */

.mime {
    display: grid;
    place-items: center;
    min-height: 0;
    color: #30a46c;
}

.mime svg {
    width: 100%;
    height: 100%;
    max-height: 34vmin;
}

/* Poza rundą ludzik stoi. Ruch na ekranie ma znaczyć "gramy", a nie
   "strona się wczytała". */
.mime.acting svg {
    animation: mime-hop 900ms ease-in-out infinite;
}

.mime.acting .mime-arm-l {
    transform-origin: 60px 56px;
    animation: mime-wave-l 700ms ease-in-out infinite alternate;
}

.mime.acting .mime-arm-r {
    transform-origin: 60px 56px;
    animation: mime-wave-r 620ms ease-in-out infinite alternate;
}

@keyframes mime-hop {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-6px); }
}

@keyframes mime-wave-l {
    from { transform: rotate(-18deg); }
    to { transform: rotate(26deg); }
}

@keyframes mime-wave-r {
    from { transform: rotate(22deg); }
    to { transform: rotate(-20deg); }
}

/* --- państwa i miasta: losowanie litery --- */

/* Przewijaniem zajmuje się teraz klapka (GSAP obraca literę w pionie),
   więc pudło już nie drga - dwa ruchy naraz robiły tylko bałagan. */

/* Wylądowała - jedno mocne uderzenie, żeby wszyscy podnieśli głowy. */
.letter-box.landed {
    animation: letter-land 600ms cubic-bezier(0.2, 1.4, 0.4, 1);
}

@keyframes letter-land {
    0% { transform: scale(1.35); box-shadow: 0 0 0 0 rgba(142, 78, 198, 0.6); }
    100% { transform: scale(1); box-shadow: 0 0 0 2.5rem rgba(142, 78, 198, 0); }
}

/* ---------- jaka to melodia: wariant 1 z 4 ---------- */

.c-quiz { color: var(--g-quiz); }
.c-bg-quiz { background: var(--g-quiz); }

.game-badge {
    /* Bez fit-content siatka nazwy gry rozciąga odznakę na całą szerokość
       szyny - wygląda wtedy jak pasek ładowania, nie jak plakietka. */
    align-self: start;
    justify-self: start;
    width: fit-content;
    background: #5b7cf0;
    color: #fff;
    border-radius: 999px;
    padding: 0.1rem 0.6rem;
    font-size: 0.45em;
    font-weight: 800;
    letter-spacing: 0.04em;
}

/* ---------- wybór kategorii (obie melodie) ---------- */

/* Kategorie zaznacza się jak listę, a nie wybiera jedną z rozwijanego pola:
   nagrania lecą ze wspólnej puli wszystkich zaznaczonych. */
.cat-picker {
    display: grid;
    justify-items: center;
    gap: clamp(0.5rem, 1.4vmin, 1rem);
    width: 100%;
}

.cat-picker-lead {
    margin: 0;
    color: var(--muted);
    font-size: clamp(0.8rem, 1.5vmin, 1.1rem);
}

.cat-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
    max-height: 46vh;
    overflow-y: auto;
}

.cat-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.45em 0.9em;
    border-radius: 999px;
    border: 2px solid #2c3358;
    background: rgba(242, 239, 230, 0.06);
    color: var(--fg);
    font-weight: 700;
    font-size: clamp(0.85rem, 1.6vmin, 1.2rem);
    cursor: pointer;
}

.cat-chip-count {
    padding: 0.05em 0.5em;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    color: var(--muted);
    font-size: 0.85em;
    font-variant-numeric: tabular-nums;
}

.cat-chip.on {
    border-color: #5b7cf0;
    background: rgba(91, 124, 240, 0.2);
}

.cat-chip.on .cat-chip-count {
    background: #5b7cf0;
    color: #fff;
}

/* Koło ratunkowe stoi obok zwykłych przycisków rundy, więc musi się od nich
   odróżniać - ale nie krzyczeć: to wyjście awaryjne, nie główna ścieżka. */
.btn-lifeline {
    border: 2px solid var(--accent);
    color: var(--accent);
    background: transparent;
}

/* Kaseta magnetofonowa: szpule kręcą się, gdy leci nagranie, a obrys obudowy
   skraca się z każdą sekundą rundy. Na TV to jedyny sygnał, ile czasu zostało,
   bo zegar telefonu widzi tylko gracz. */
.quiz-tape {
    position: relative;
    width: 100%;
    align-self: center;
    margin-inline: auto;
    /* Poświata siedzi pod kasetą, ale nie pod całym panelem - bez izolacji
       z-index -1 przebiłby się przez tło ekranu hosta. */
    isolation: isolate;
}

.quiz-tape::before {
    content: '';
    position: absolute;
    inset: -20% -12%;
    z-index: -1;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(91, 124, 240, 0.24), transparent 72%);
    opacity: 0;
    transition: opacity 450ms ease;
}

.quiz-tape.playing::before { opacity: 1; }

.quiz-cassette {
    display: block;
    width: 100%;
    height: auto;
    filter: drop-shadow(0 1.2vmin 2.4vmin rgba(0, 0, 0, 0.45));
}

.tape-shell {
    fill: #1b1f38;
    stroke: #2c3358;
    stroke-width: 2;
}

.tape-run {
    fill: none;
    stroke: #5b7cf0;
    stroke-width: 4;
    stroke-linecap: round;
    transition: stroke-dashoffset 220ms linear;
}

.quiz-tape[data-state="urgent"] .tape-run { stroke: var(--err); }

.tape-label { fill: #f2efe6; }
.tape-strip { fill: #5b7cf0; }
.quiz-tape[data-state="urgent"] .tape-strip { fill: var(--err); }

.tape-window {
    fill: #0b0e1d;
    stroke: #2c3358;
    stroke-width: 1.5;
}

/* Nawinięta taśma: lewa szpula pełna, prawa dopiero zaczyna. */
.tape-wrap { fill: #33260f; stroke: #5a4620; stroke-width: 2; }

.tape-cog {
    fill: none;
    stroke: #cfd6ff;
    stroke-width: 5;
    /* Kreskowanie zamiast rysowanych zębów - obrót widać po nich najlepiej. */
    stroke-dasharray: 3 4.2;
}

.tape-spoke { stroke: #8f9ad6; stroke-width: 2; }
.tape-band { stroke: #5a4620; stroke-width: 3; fill: none; }
.tape-hole { fill: #0b0e1d; stroke: #2c3358; stroke-width: 1.5; }
.tape-screw { fill: #2c3358; }

/* Obrót liczony od środka bryły grupy - bez fill-box punkt zaczepienia
   wypadłby w rogu układu SVG, a szpula uciekłaby poza kasetę. */
.tape-hub {
    transform-box: fill-box;
    transform-origin: center;
}

.quiz-tape.playing .tape-hub-left { animation: tape-spin 2.6s linear infinite; }
.quiz-tape.playing .tape-hub-right { animation: tape-spin 1.7s linear infinite; }

@keyframes tape-spin {
    to { transform: rotate(360deg); }
}

/* Odczyt sekund leży na etykiecie kasety - stąd ciemny tekst na kremowym tle. */
.quiz-readout {
    position: absolute;
    left: 9%;
    right: 9%;
    top: 12%;
    height: 34%;
    display: grid;
    place-content: center;
    justify-items: center;
    gap: 0.1rem;
    color: #1c2138;
}

.quiz-count {
    font-size: clamp(1.6rem, 6vmin, 3.2rem);
    font-weight: 900;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.quiz-tape[data-state="urgent"] .quiz-count { color: var(--err); }

.quiz-count-label {
    font-size: clamp(0.5rem, 1.1vmin, 0.75rem);
    letter-spacing: 0.12em;
    font-weight: 700;
    color: #5c6386;
}

/* Słupki równiarki ruszają się tylko wtedy, gdy faktycznie leci dźwięk. */
.quiz-eq {
    display: flex;
    align-items: flex-end;
    gap: 0.16rem;
    height: 1.2rem;
}

.quiz-eq i {
    width: 0.2rem;
    height: 0.3rem;
    border-radius: 0.1rem;
    background: #5b7cf0;
    display: block;
}

.quiz-tape.playing .quiz-eq i { animation: quiz-eq 850ms ease-in-out infinite; }
.quiz-eq i:nth-child(2) { animation-delay: 100ms; }
.quiz-eq i:nth-child(3) { animation-delay: 220ms; }
.quiz-eq i:nth-child(4) { animation-delay: 330ms; }
.quiz-eq i:nth-child(5) { animation-delay: 150ms; }
.quiz-eq i:nth-child(6) { animation-delay: 280ms; }
.quiz-eq i:nth-child(7) { animation-delay: 50ms; }

@keyframes quiz-eq {
    0%, 100% { height: 0.3rem; }
    50% { height: 1.1rem; }
}

/* Cztery odpowiedzi: dwie kolumny na telefonie, cztery na telewizorze. */
/* Zawsze 2 x 2, także na telewizorze. Cztery kolumny robiły z tytułów słupki
   po dwa słowa w wierszu - z kanapy nie do przeczytania w 30 sekund. */
.quiz-options {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(0.5rem, 1.5vmin, 0.9rem);
}

/* Na dużym ekranie karta jest szeroka, więc litera staje obok tytułu, a nie nad
   nim - tak jak na telefonie. W pionie zostawałby pas pustego tła. */
@media (min-width: 52rem) {
    /* Obie kolumny równe: kaseta ma tyle samo miejsca co odpowiedzi. Płyta
       w wariancie buzzerowym dostaje tę samą szynę - jest tam jedyną ilustracją. */
    .quiz-panel,
    .melodia-panel { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    /* Nazwy drużyn pod kasetą czyta się z kanapy, więc rosną razem z ekranem. */
    .game-rail .quiz-chip { font-size: clamp(1rem, 2.1vmin, 1.6rem); }

    /* Szyna wspólna dla gier ma trzy wiersze i rozciąga ten środkowy; tutaj
       elementów jest pięć, więc rozciągała podpis kategorii, a kaseta lądowała
       przy samym dole. Flex plus auto-marginesy wyśrodkowują to, co ma być
       wyśrodkowane - kasetę. */
    .quiz-panel .game-rail {
        display: flex;
        flex-direction: column;
    }

    /* Kaseta rośnie z kolumną, ale nie w nieskończoność - powyżej tej szerokości
       zaczyna wyglądać jak mebel, a nie jak kaseta. */
    .quiz-panel .quiz-tape {
        margin-block: auto;
        max-width: 36rem;
    }

    /* Karty mają wysokość swojej treści, a nie całej kolumny: na telewizorze to
       nie są przyciski do trafienia, tylko cztery czytelne opcje. Rozciągnięte
       na pół ekranu wyglądały jak panele z tekstem zagubionym w środku.
       Kolumna jest flexem, żeby cały blok stał w pionowym środku. */
    .quiz-panel .game-main {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .quiz-panel .quiz-options { align-self: stretch; }

    .quiz-options .quiz-option { align-content: center; }

    .quiz-options { gap: clamp(0.9rem, 2vmin, 1.6rem); }

    .quiz-options .quiz-option {
        grid-template-columns: auto minmax(0, 1fr);
        justify-items: start;
        align-items: center;
        gap: 1rem;
        text-align: left;
        padding: clamp(0.9rem, 2.2vmin, 1.4rem) clamp(1rem, 2.4vmin, 1.6rem);
    }

    .quiz-options .quiz-letter {
        width: 2.2rem;
        font-size: 1.25rem;
    }

    /* Karta jest teraz o połowę węższa niż przy szynie 30rem, więc podpis musi
       zejść ze skali - inaczej "TOMMY DORSEY & HIS ORCHESTRA" idzie na cztery
       linie i z kanapy wygląda jak akapit, nie jak odpowiedź. */
    .quiz-options .quiz-title { font-size: clamp(0.95rem, 1.9vmin, 1.35rem); }
}

.quiz-option,
.quiz-choice {
    display: grid;
    justify-items: center;
    align-content: start;
    gap: 0.45rem;
    padding: clamp(0.6rem, 1.8vmin, 1rem) 0.7rem;
    border-radius: 14px;
    background: #f2efe6;
    color: #1c2138;
    border: 3px solid #5b7cf0;
    position: relative;
    text-align: center;
    font-family: inherit;
}

.quiz-letter {
    display: grid;
    place-items: center;
    width: 1.7rem;
    aspect-ratio: 1;
    border-radius: 8px;
    background: #5b7cf0;
    color: #fff;
    font-weight: 900;
}

.quiz-title {
    font-weight: 700;
    font-size: clamp(0.85rem, 2vmin, 1.15rem);
    line-height: 1.2;
}

/* Karty wchodzą kaskadą - jedna po drugiej, od A do D. Opóźnienie ustawia
   kontroler, żeby kolejność nie zależała od tego, ile ich akurat jest. */
.quiz-option.entering {
    animation: quiz-enter 420ms cubic-bezier(0.25, 0.8, 0.3, 1) both;
    animation-delay: var(--enter-delay, 0ms);
}

@keyframes quiz-enter {
    from {
        opacity: 0;
        transform: translateY(0.8rem) scale(0.97);
    }
}

/* Wyniki: zielona poprawna, czerwone wskazane błędnie, reszta przygaszona. */
.quiz-option.good,
.quiz-choice.good {
    border-color: #30a46c;
    background: #e8f7ef;
}

.quiz-option.good .quiz-letter,
.quiz-choice.good .quiz-letter { background: #30a46c; }

.quiz-option.bad,
.quiz-choice.bad {
    border-color: var(--err);
    background: #fbecee;
}

.quiz-option.bad .quiz-letter,
.quiz-choice.bad .quiz-letter { background: var(--err); }

.quiz-option.dim,
.quiz-choice.dim { opacity: 0.42; }

/* Ile drużyn wskazało tę odpowiedź - dopiero po rundzie. */
.quiz-count-badge {
    position: absolute;
    top: -0.6rem;
    right: -0.6rem;
    min-width: 1.6rem;
    padding: 0.1rem 0.4rem;
    border-radius: 999px;
    background: #10142b;
    color: var(--fg);
    font-weight: 800;
    font-size: 0.85rem;
}

.quiz-message {
    margin: 0;
    font-weight: 800;
    font-size: clamp(1rem, 2.4vmin, 1.5rem);
    min-height: 1.2em;
}

.quiz-message.good { color: #30a46c; }
.quiz-message.bad { color: var(--err); }

/* Kto już odpowiedział - bez treści odpowiedzi, ta jest tajna do końca rundy. */
/* Kto już odpowiedział, a po rundzie - kto trafił. Z drugiego końca pokoju ma
   to być czytelne jednym spojrzeniem, więc plakietki są duże, w kolorze drużyny
   i ze znacznikiem stanu: kropka czeka, ptaszek odpowiedział, krzyżyk spudłował. */
.quiz-who {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
}

.quiz-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    border-radius: 999px;
    padding: 0.3em 0.9em 0.3em 0.35em;
    font-size: 0.9rem;
    font-weight: 800;
    background: rgba(242, 239, 230, 0.06);
    border: 2px solid #2c3358;
    color: var(--muted);
}

.quiz-chip-mark {
    display: grid;
    place-items: center;
    width: 1.7em;
    height: 1.7em;
    border-radius: 50%;
    background: #2c3358;
    color: #0b0e1d;
    font-size: 0.95em;
    line-height: 1;
}

.quiz-chip.answered {
    border-color: var(--team-color, #5b7cf0);
    background: rgba(91, 124, 240, 0.12);
    color: var(--fg);
}

.quiz-chip.answered .quiz-chip-mark {
    background: var(--team-color, #5b7cf0);
    color: #0b0e1d;
}

.quiz-chip.won {
    background: #30a46c;
    border-color: #30a46c;
    color: #fff;
}

.quiz-chip.won .quiz-chip-mark {
    background: #e8f7ef;
    color: #1a7f4f;
}

/* Pudło nie znika z ekranu - drużyna ma zobaczyć, że jej odpowiedź weszła
   i była zła, a nie że jej plakietka gdzieś przepadła. */
.quiz-chip.missed {
    border-color: var(--err);
    color: var(--err);
}

.quiz-chip.missed .quiz-chip-mark {
    background: var(--err);
    color: #fff;
}

.quiz-chip-points {
    font-variant-numeric: tabular-nums;
    opacity: 0.9;
}

/* ---------- wariant 1 z 4: telefon ---------- */

.quiz-player {
    display: grid;
    align-content: start;
    gap: 0.7rem;
}

.quiz-choices {
    display: grid;
    gap: 0.55rem;
}

/* Na telefonie odpowiedzi idą w pionie i w poprzek całej szerokości - wybiera
   się je kciukiem, w pośpiechu i przy muzyce. */
.quiz-choice {
    grid-template-columns: auto minmax(0, 1fr);
    justify-items: start;
    align-items: center;
    gap: 0.7rem;
    text-align: left;
    width: 100%;
    cursor: pointer;
}

.quiz-choice.picked {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
}

.quiz-choice:disabled { cursor: default; }

.quiz-note {
    color: var(--muted);
    text-align: center;
    margin: 0;
}

@media (prefers-reduced-motion: reduce) {
    .quiz-tape.playing .quiz-eq i,
    .quiz-tape.playing .tape-hub { animation: none !important; }
}

/* ---------- tablica wyników (osobny widok /host/{code}/tablo) ---------- */
.standings {
    max-width: 900px;
    margin: 0 auto;
    padding: clamp(1rem, 4vmin, 3rem) clamp(1rem, 3vmin, 2rem);
    display: flex;
    flex-direction: column;
    gap: clamp(1rem, 3vmin, 2rem);
    min-height: 100dvh;
}

.standings-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.standings-title {
    margin: 0;
    font-size: clamp(1.8rem, 5vmin, 3.4rem);
    font-weight: 900;
    letter-spacing: 0.01em;
}

.standings-empty { color: var(--muted); font-size: 1.2rem; }

/* „Po N grach" - podpowiada, że tu liczy się turniej, nie bieżąca gra. */
.standings-note {
    color: var(--muted);
    font-size: clamp(0.85rem, 1.8vmin, 1.15rem);
    font-weight: 600;
}

/* Ciasny ekran (telefon otwarty na tablo) - pigułki gier znikają, zostaje
   ranking i suma, bo to one muszą być czytelne. */
@media (max-width: 560px) {
    .standings-list .team { grid-template-columns: auto minmax(0, 1fr) auto; }
    .standings-list .team-games { display: none; }
}

.standings-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: clamp(0.5rem, 1.6vmin, 1rem);
}

.standings-list .team {
    display: grid;
    /* ranga | nazwa | pigułki gier | suma */
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: clamp(0.6rem, 2vmin, 1.4rem);
    padding: clamp(0.6rem, 1.8vmin, 1.2rem) clamp(0.8rem, 2.2vmin, 1.5rem);
    border-radius: 16px;
    border-left: 8px solid var(--team-color, var(--accent));
    background: var(--bg-soft);
}

/* Rozbicie na gry: skąd dorobek drużyny. Zwija się i chowa przy ciasnym
   ekranie - suma jest ważniejsza niż to, z której gry przyszła. */
.standings-list .team-games {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.3rem;
    max-width: 40%;
}

.standings-list .team-game-pill {
    padding: 0.15em 0.5em;
    border-radius: 999px;
    background: rgba(242, 239, 230, 0.08);
    color: var(--muted);
    font-size: clamp(0.65rem, 1.5vmin, 0.95rem);
    font-weight: 700;
    white-space: nowrap;
}

.standings-list .team-rank {
    display: grid;
    place-items: center;
    width: 2em;
    height: 2em;
    border-radius: 10px;
    background: rgba(242, 239, 230, 0.1);
    color: var(--muted);
    font-size: clamp(1.1rem, 2.6vmin, 1.9rem);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
}

/* Lider na złoto - widać z drugiego końca sali, kto prowadzi. */
.standings-list .team:first-child .team-rank {
    background: var(--accent);
    color: #22160a;
}

.standings-list .team-name {
    font-size: clamp(1.1rem, 3vmin, 2.2rem);
    font-weight: 800;
    overflow-wrap: anywhere;
}

.standings-list .team-score {
    font-size: clamp(1.6rem, 4vmin, 3rem);
    font-weight: 900;
    line-height: 1;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--team-color, var(--fg));
}

.standings-list .team-score.bump { animation: pop 0.35s ease-out; }

/* --- wyniki jako modal na ekranie hosta --- */
.standings-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: grid;
    place-items: center;
    padding: clamp(1rem, 4vmin, 3rem);
    background: rgba(5, 6, 12, 0.78);
    backdrop-filter: blur(5px);
    animation: fade-in 0.15s ease-out;
}

.standings-modal-card {
    width: min(780px, 100%);
    max-height: 88vh;
    overflow-y: auto;
    background: var(--bg);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 22px;
    padding: clamp(1.2rem, 3vmin, 2.2rem);
    display: flex;
    flex-direction: column;
    gap: clamp(1rem, 2.5vmin, 1.6rem);
    box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
}

.standings-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.standings-modal-title {
    margin: 0;
    font-size: clamp(1.4rem, 3.4vmin, 2.4rem);
    font-weight: 900;
}

.standings-modal .standings-list { gap: 0.6rem; }

/* Zapis turnieju w modalu: nazwa + przycisk w jednej linii, zawijane na wąsko. */
.standings-save {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.standings-save .form-control {
    flex: 1 1 12rem;
    min-width: 0;
}

.home-resume {
    margin: 0.75rem 0 0;
    color: var(--muted);
    font-size: 0.95rem;
}

/* Lista zapisanych turniejów. */
.saved-list {
    list-style: none;
    margin: 0 auto;
    padding: 0;
    width: min(640px, 100%);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.saved-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 1rem 1.25rem;
    border-radius: 16px;
    background: var(--bg-soft);
    border: 1px solid rgba(255, 255, 255, 0.06);
}

.saved-main { min-width: 0; }
.saved-name { margin: 0; font-size: 1.3rem; font-weight: 800; overflow-wrap: anywhere; }
.saved-meta { margin: 0.25rem 0 0; color: var(--muted); font-size: 0.95rem; }
.saved-item form { margin: 0; }

.standings-modal-link {
    align-self: flex-end;
    color: var(--muted);
    text-decoration: none;
    font-weight: 700;
}
.standings-modal-link:hover { color: var(--fg); }

@keyframes fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ---------- Dutch (gra karciana) ---------- */
.c-dutch { color: var(--g-dutch); }
.c-bg-dutch { background: var(--g-dutch); }

/* ---------- Ostatnia litera ---------- */
.c-ostatnia-litera { color: var(--g-ostatnia-litera); }
.c-bg-ostatnia-litera { background: var(--g-ostatnia-litera); }

/* Środek stołu: talia i stos odrzuconych, każde z podpisem u góry. */
.dutch-center {
    display: flex;
    gap: 24px;
    justify-content: center;
    margin: 12px 0 18px;
}

.dutch-pile-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

.dutch-pile-label {
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
}

.dutch-deck {
    /* Ten sam wzrost co stos obok (--cw/--ch pile-wrap) - talia i stos to
       jeden wspolny punkt stolu i musza rosnac razem (P2-23 audytu: Dutch
       byl na sztywnych px i na duzym ekranie zostawal wielkosci okienka). */
    width: clamp(100px, 12.2vmin, 230px);
    height: clamp(140px, 17.08vmin, 322px);
    border-radius: 16px;
    display: grid;
    place-items: center;
    background: repeating-linear-gradient(45deg, #12b886 0 12px, #0e9c76 12px 24px);
    color: #04231b;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), inset 0 0 0 2px rgba(255, 255, 255, 0.15);
}

.dutch-pile-count { font-size: clamp(1.6rem, 4.5vmin, 3.4rem); font-weight: 900; }
.dutch-pile-label { font-size: clamp(0.65rem, 1.6vmin, 1.1rem); }

/* Stos i talia to wspólny punkt stołu - największe i najczytelniejsze karty. */
.dutch-pile-wrap .dutch-card { --cw: clamp(100px, 12.2vmin, 230px); --ch: calc(var(--cw) * 1.4); }

/* Stos pokazuje dwie wierzchnie karty, lekko przesunięte - widać, co padło. */
.dutch-discard-pile {
    position: relative;
    --cw: clamp(100px, 12.2vmin, 230px);
    --ch: calc(var(--cw) * 1.4);
    width: calc(var(--cw) + 12px);
    height: calc(var(--ch) + 14px);
}

.dutch-discard-pile .dutch-card {
    --cw: clamp(100px, 12.2vmin, 230px);
    --ch: calc(var(--cw) * 1.4);
    position: absolute;
    top: 0;
    left: 0;
}

.dutch-discard-pile .dutch-pile-card {
    top: calc(var(--i) * 12px);
    left: calc(var(--i) * 11px);
}

/* Karta jak prawdziwa: rogi z figurą i kolorem oraz duży znak na środku.
   Rozmiar sterowany zmiennymi --cw/--ch, więc ta sama karta skaluje się
   na stole, w ręce i w locie. */
.dutch-card {
    --cw: clamp(48px, 5.9vmin, 110px);
    --ch: calc(var(--cw) * 1.4);
    position: relative;
    flex: 0 0 auto;
    width: var(--cw);
    height: var(--ch);
    padding: 0;
    border: none;
    border-radius: calc(var(--cw) * 0.14);
    background: #fff;
    color: #10121f;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
    overflow: hidden;
    font: inherit;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.dutch-card.red { color: var(--err); }

.dutch-card.dutch-down {
    background: repeating-linear-gradient(45deg, #12b886 0 9px, #0e9c76 9px 18px);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), inset 0 0 0 2px rgba(255, 255, 255, 0.15);
}

.dutch-card.dutch-down > * { display: none; }

.dutch-card.dutch-empty {
    background: color-mix(in srgb, var(--bg-soft) 70%, transparent);
    border: 2px dashed rgba(255, 255, 255, 0.18);
    box-shadow: none;
}

.dutch-card.dutch-empty::after {
    content: '—';
    display: grid;
    place-items: center;
    height: 100%;
    color: var(--muted);
    font-size: 1.4rem;
}

/* Świeżo odkryta karta „wskakuje” - drobny akcent, że coś się zmieniło. */
.dutch-card.dutch-up { animation: dutch-pop 0.18s ease; }

@keyframes dutch-pop {
    from { transform: scale(0.86); opacity: 0.4; }
    to { transform: scale(1); opacity: 1; }
}

.dutch-corner {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 0.92;
    font-weight: 800;
    font-size: calc(var(--ch) * 0.17);
}

.dutch-corner-tl { top: calc(var(--ch) * 0.05); left: calc(var(--cw) * 0.09); }
.dutch-corner-br { bottom: calc(var(--ch) * 0.05); right: calc(var(--cw) * 0.09); transform: rotate(180deg); }
.dutch-corner b { font-weight: 900; }
.dutch-corner span { font-size: 0.85em; }

.dutch-pip {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: calc(var(--ch) * 0.44);
    line-height: 1;
}

/* Figura (walet/dama/król) - większy znak, żeby od razu było widać, że to figura. */
.dutch-pip-figure { font-size: calc(var(--ch) * 0.56); }

/* --- stół hosta --- */
/* Stół hosta: pionowa lista kompaktowych wierszy - mieści się nawet sześciu
   graczy. W grze każdy wiersz pokazuje nazwę i LICZBĘ kart; karty odsłaniamy
   dopiero na koniec rundy. */
.dutch-table {
    display: flex;
    flex-direction: column;
    gap: clamp(6px, 1.4vmin, 12px);
    max-width: 640px;
    margin: 8px auto 16px;
}

.dutch-seat {
    display: flex;
    align-items: center;
    gap: 14px;
    border-radius: 14px;
    background: var(--bg-soft);
    padding: clamp(0.5rem, 1.6vmin, 1rem) clamp(0.7rem, 2vmin, 1.2rem);
    border: 2px solid transparent;
    border-left: 6px solid var(--team-color, var(--accent));
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

/* Czyja tura ma być widać z kanapy - wyraźna poświata w kolorze drużyny. */
.dutch-seat.is-turn {
    border-color: var(--team-color);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--team-color) 45%, transparent);
    transform: translateX(6px);
}

.dutch-seat.is-caller { border-color: var(--accent); }
.dutch-seat.is-winner { background: color-mix(in srgb, var(--ok) 24%, var(--bg-soft)); }

.dutch-seat-name {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 800;
    font-size: clamp(1rem, 2.4vmin, 1.6rem);
    color: var(--team-color);
    overflow-wrap: anywhere;
}

.dutch-flag {
    font-size: 0.65rem;
    letter-spacing: 0.1em;
    background: var(--accent);
    color: #201500;
    border-radius: 6px;
    padding: 1px 6px;
}

/* Liczba kart - najważniejsza informacja o graczu w trakcie gry. */
.dutch-seat-count {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}

.dutch-seat-count b {
    font-size: clamp(1.6rem, 3.6vmin, 2.8rem);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    color: var(--fg);
}

.dutch-seat-unit { color: var(--muted); font-size: clamp(0.8rem, 1.6vmin, 1.1rem); }

.dutch-seat-peek {
    color: var(--muted);
    font-size: clamp(0.75rem, 1.5vmin, 1rem);
    margin-right: 6px;
}

/* Mały rewers przy liczniku - żeby od razu było wiadomo, że to karty. */
.dutch-mini-back {
    width: 26px;
    height: 36px;
    border-radius: 5px;
    background: repeating-linear-gradient(45deg, #12b886 0 5px, #0e9c76 5px 10px);
    box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.15);
}

/* Odsłonięcie: wiersz rozwija się w pasek małych kart i sumę. */
.dutch-seat.is-open { flex-wrap: wrap; }

.dutch-seat-open {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.dutch-card.dutch-mini { --cw: clamp(32px, 3.9vmin, 72px); --ch: calc(var(--cw) * 1.4); }

.dutch-seat-sum {
    font-weight: 900;
    font-size: clamp(1.2rem, 2.8vmin, 2rem);
    font-variant-numeric: tabular-nums;
    color: var(--team-color);
    margin-left: auto;
}

/* --- ranking --- */
.dutch-standings { max-width: 460px; margin: 0 auto; }

.dutch-rank-title {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin: 0 0 6px;
}

.dutch-rank-row {
    display: grid;
    grid-template-columns: 28px 1fr auto;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 10px;
    background: var(--bg-soft);
    margin-bottom: 4px;
}

.dutch-rank-place { color: var(--muted); font-weight: 700; }
.dutch-rank-pts { font-weight: 800; }

/* --- telefon --- */
/* Dutch wypełnia cały ekran gracza (facts poszły do paska) i centruje rękę. */
.dutch-player { display: flex; flex-direction: column; gap: 16px; align-items: center; flex: 1; justify-content: center; }

.dutch-status {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    min-height: 28px;
}

.dutch-turn { font-weight: 700; color: var(--muted); }
.dutch-turn.is-mine { color: var(--fg); }

.dutch-mini-pile {
    font-weight: 700;
    background: var(--bg-soft);
    border-radius: 8px;
    padding: 4px 10px;
}
.dutch-mini-pile.red { color: var(--err); }

.dutch-hand {
    display: grid;
    grid-template-columns: repeat(2, 96px);
    grid-auto-rows: 134px;
    gap: 14px;
}

.dutch-hand .dutch-card { --cw: clamp(70px, 8.9vmin, 165px); --ch: calc(var(--cw) * 1.4); }
.dutch-hand .dutch-card.is-peekable,
.dutch-hand .dutch-card.is-snap { cursor: pointer; }

/* Karty do podmiany pulsują - jasny sygnał „dotknij mnie”. */
.dutch-hand .dutch-card.is-target {
    cursor: pointer;
    box-shadow: 0 0 0 3px var(--accent);
    animation: dutch-target 1s ease-in-out infinite;
}

@keyframes dutch-target {
    0%, 100% { box-shadow: 0 0 0 3px var(--accent); }
    50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 45%, transparent); }
}

.dutch-drawn {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    justify-content: center;
}

.dutch-drawn-label { color: var(--muted); }
.dutch-drawn-card { --cw: clamp(60px, 7.4vmin, 135px); --ch: calc(var(--cw) * 1.4); }
.dutch-drawn-pts { font-weight: 800; font-size: 1.1rem; }

.dutch-controls { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }

.dutch-btn-primary { background: #12b886; color: #04231b; border: none; }
.dutch-btn-call { background: var(--accent); color: #201500; border: none; }

/* "Pomiń" w pickerze mocy - wyjście awaryjne, nie ma świecić jak akcja główna. */
.dutch-btn-ghost {
    background: transparent;
    color: var(--muted);
    border: 2px solid rgba(242, 239, 230, 0.25);
}

.dutch-note { color: var(--muted); text-align: center; margin: 0; max-width: 320px; }

/* Nakładka damy: wybór karty do podejrzenia albo podejrzana karta. */
.dutch-overlay {
    width: 100%;
    background: var(--bg-soft);
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    border: 2px solid var(--accent);
}

.dutch-overlay-title { margin: 0; font-weight: 800; text-align: center; }

.dutch-pick-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
}

.dutch-pick-name {
    font-weight: 700;
    color: var(--team-color);
    min-width: 92px;
}

.dutch-pick-cards { display: flex; gap: 8px; }
.dutch-pick-card { --cw: clamp(34px, 4.3vmin, 78px); --ch: calc(var(--cw) * 1.4); cursor: pointer; }
.dutch-pick-card.is-selected { box-shadow: 0 0 0 3px var(--accent); }

/* Walet: przyciski graczy do wskazania (zamianę losuje serwer). */
.dutch-pick-player {
    width: 100%;
    justify-content: flex-start;
    text-align: left;
    border-left: 6px solid var(--team-color, var(--accent));
}
.dutch-pick-player.is-selected { box-shadow: 0 0 0 3px var(--accent); }

/* Nietrafione dorzucenie: wielka karta na środku ekranu przez 3 sekundy. */
.dutch-missnap {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    pointer-events: none;
    background: rgba(5, 6, 12, 0.5);
    animation: fade-in 0.15s ease-out;
}

.dutch-missnap-label {
    font-size: clamp(1.2rem, 3vmin, 2rem);
    font-weight: 800;
    text-shadow: 0 2px 10px #000;
}

.dutch-missnap-card {
    --cw: clamp(112px, 13.9vmin, 260px);
    --ch: calc(var(--cw) * 1.4);
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6);
}
.dutch-seen-card { --cw: clamp(86px, 10.7vmin, 200px); --ch: calc(var(--cw) * 1.4); }

/* Karta wylatująca z miejsca gracza na stos - leci w osobnej warstwie. */
/* Lecąca karta - transformacją steruje GSAP, tu tylko warstwa i rozmiar. */
.dutch-fly {
    position: fixed;
    z-index: 60;
    --cw: clamp(58px, 7.2vmin, 132px);
    --ch: calc(var(--cw) * 1.4);
    pointer-events: none;
    will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
    .dutch-card.dutch-up { animation: none; }
    .dutch-hand .dutch-card.is-target { animation: none; }
    .dutch-seat.is-turn { transform: none; }
    .dutch-fly { display: none; }
    .dutch-missnap { animation: none; }
}

/* ============================================================================
   EKRAN WYBORU GRY — WERSJA 2 („ściana gier", ?v=2)

   Zupełnie osobny zestaw reguł (prefiks l2-), niezależny od wersji 1. Koncept:
   pełnoekranowy rząd wysokich, kolorowych paneli — każda gra świeci swoją barwą
   na całą wysokość, jak automaty w salonie gier. Rozmiary w vh/vw, więc mieści
   się w każdym 16:9 bez przewijania i bez pełnego ekranu.
   ============================================================================ */

.l2 {
    height: 100dvh;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    gap: clamp(0.6rem, 1.8vh, 1.5rem);
    padding: clamp(0.7rem, 2.2vh, 1.7rem) clamp(0.8rem, 2vw, 2.2rem);
    overflow: hidden;
    color: #f2efe6;
    background:
        radial-gradient(circle at 18% -12%, #262e5a 0%, transparent 55%),
        radial-gradient(circle at 88% -6%, #1e2749 0%, transparent 52%),
        #0b0e1a;
}

/* Ciało: gracze po lewej (wąska kolumna), ściana gier bierze resztę. */
.l2-body {
    display: grid;
    grid-template-columns: clamp(11rem, 15vw, 17rem) minmax(0, 1fr);
    gap: clamp(0.6rem, 1.4vw, 1.4rem);
    min-height: 0;
}

/* ---------- lewa kolumna: dołączający gracze ---------- */

.l2-side {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: clamp(0.5rem, 1.2vh, 1rem);
    min-height: 0;
    padding: clamp(0.6rem, 1.4vh, 1.1rem);
    border-radius: 18px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
}

.l2-side-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.l2-side-title {
    font-weight: 800;
    font-size: clamp(0.9rem, 1.9vh, 1.35rem);
}

/* Lista przewija się w środku kolumny - dwudziestu graczy nie rozepcha układu. */
.l2-side-list {
    min-height: 0;
    overflow-y: auto;
}

.l2-side-foot {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* .reset-form ma margin-left: auto dla paska poziomego z v1 (.tv-bar-right) -
   w tej pionowej kolumnie ten sam formularz ma się zachowywać jak reszta
   przycisków, nie doklejać do prawej krawędzi. */
.l2-side-foot .reset-form {
    margin-left: 0;
}

.l2-side-foot .l2-ctrl,
.l2-side-foot .reset-form button {
    width: 100%;
}

/* ---------- górny pasek: logo + dołączanie ---------- */

.l2-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.l2-brand {
    display: flex;
    align-items: baseline;
    gap: 0.7rem;
}

.l2-logo {
    font-size: clamp(1.5rem, 4vh, 3rem);
    font-weight: 900;
    letter-spacing: 0.01em;
}

.l2-star {
    color: #f5a524;
}

.l2-tag {
    color: #9aa0b8;
    font-weight: 600;
    font-size: clamp(0.8rem, 1.8vh, 1.15rem);
}

.l2-join {
    display: flex;
    align-items: center;
    gap: clamp(0.6rem, 1.5vw, 1.3rem);
    padding: clamp(0.4rem, 1vh, 0.8rem) clamp(0.6rem, 1.4vw, 1.2rem);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.09);
}

.l2-join-text {
    display: flex;
    flex-direction: column;
    text-align: right;
    line-height: 1.1;
}

.l2-join-lead { color: #9aa0b8; font-size: clamp(0.7rem, 1.5vh, 0.95rem); }
.l2-code {
    font-size: clamp(1.6rem, 4.6vh, 3.4rem);
    font-weight: 900;
    letter-spacing: 0.14em;
    color: #fff;
    line-height: 1;
}
.l2-url { color: #9aa0b8; font-size: clamp(0.65rem, 1.4vh, 0.9rem); }

.l2-qr {
    /* Sufit podniesiony ze 118px do 190px - tyle miał kod w wersji 1,
      skanowany z drugiego końca pokoju (P2-25 audytu). */
    width: clamp(80px, 15vh, 190px);
    height: auto;
    border-radius: 10px;
    background: #fff;
    padding: 5px;
}

/* ---------- ściana gier ---------- */

.l2-wall {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    /* auto-fit + minmax: przegladarka sama dobiera liczbe kolumn z szerokosci
       ekranu, a "1fr" rozciaga ostatni niepelny rzad tak, zeby wypelnil cala
       szerokosc - dziala identycznie przy 2 grach i przy 12, bez liczenia
       parzystosci gdziekolwiek. grid-auto-rows: 1fr dzieli wysokosc po rowno
       miedzy tyle rzedow, ile faktycznie wyjdzie. Wiekszy prog minmax (wiecej
       niz podnoszenie samego "1fr") = mniej, ale szerszych kolumn w rzedzie -
       zyczenie uzytkownika ("mniej w linii, zeby byly szersze pola"). */
    grid-template-columns: repeat(auto-fit, minmax(clamp(11rem, 26vw, 21rem), 1fr));
    grid-auto-rows: 1fr;
    gap: clamp(0.6rem, 1.3vw, 1.4rem);
}

/* Panel jednej gry: nasycony kolor gry, biały tytuł, wielkie emoji. Świeci
   swoją barwą (box-shadow w --c), więc z kanapy widać, co jest czym.
   Padding/gap/czcionki tunowane pod scenariusz z kilkoma rzędami (auto-fit
   układa gry w 1 do kilku rzędów zależnie od tego, ile ich jest - nie znamy
   liczby rzędów z góry, więc bezpieczniej za małe niż wystające poza kafelek). */
.l2-panel {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(0.3rem, 1vh, 0.8rem);
    padding: clamp(0.7rem, 2vh, 1.7rem) clamp(0.5rem, 1.4vw, 1.3rem);
    border: none;
    border-radius: 22px;
    cursor: pointer;
    color: #fff;
    text-align: center;
    position: relative;
    overflow: hidden;
    background: linear-gradient(165deg, var(--c) 0%, rgba(9, 11, 20, 0.55) 128%);
    box-shadow: 0 14px 40px -12px var(--c), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1), box-shadow 0.22s ease, filter 0.22s ease;
}

/* Refleks u góry - panel wygląda jak gładka, wypukła płytka. */
.l2-panel::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 46%;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), transparent);
    pointer-events: none;
}

.l2-panel:hover,
.l2-panel:focus-visible {
    transform: translateY(-10px) scale(1.02);
    filter: brightness(1.07);
    box-shadow: 0 26px 62px -12px var(--c), inset 0 1px 0 rgba(255, 255, 255, 0.32);
    z-index: 1;
}

/* Fokus musi zostać widoczny nawet bez przesunięcia - z klawiaturą albo przy
   prefers-reduced-motion (który wyłącza transform niżej) samo podniesienie
   karty nie wystarcza za wskaźnik fokusa (WCAG 2.4.7, P2-24 audytu). */
.l2-panel:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 3px;
}

/* Podkładka pod ikoną - bez niej ciemniejsze detale (np. płyta melodii,
   #15182a) gubiły się w dolnej, przyciemnionej części gradientu kafelka.
   Ten sam pomysł co medalion pod ikoną karty v1 (.game-card-art::before),
   tylko ciemny zamiast jasnego - tu tło JEST już kolorem gry. */
.l2-icon-wrap {
    position: relative;
    display: grid;
    place-items: center;
}

.l2-icon-wrap::before {
    content: '';
    position: absolute;
    inset: -22%;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.22);
}

.l2-icon {
    position: relative;
    display: block;
    width: clamp(2.6rem, 9vh, 5.4rem);
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.4));
}

.l2-icon svg {
    display: block;
    width: 100%;
    height: auto;
}

/* Delikatniejszy tytuł - 900 na kafelku w intensywnym kolorze krzyczał,
   zwłaszcza gdy kafelki urosły (mniej ich w rzędzie, patrz .l2-wall).
   Grubość w dół, cień płytszy, bez zmiany rozmiaru czy wersalików. */
.l2-name {
    font-size: clamp(1rem, 2.6vh, 2rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    line-height: 1.15;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}

.l2-hook {
    font-size: clamp(0.78rem, 1.9vh, 1.15rem);
    opacity: 0.94;
    max-width: 20ch;
}

.l2-go {
    margin-top: clamp(0.3rem, 1vh, 0.9rem);
    padding: 0.4em 1.2em;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.26);
    border: 1px solid rgba(255, 255, 255, 0.38);
    font-weight: 800;
    letter-spacing: 0.09em;
    font-size: clamp(0.72rem, 1.7vh, 1.05rem);
}

/* ---------- gracze: pionowa lista w lewej kolumnie ---------- */

.l2-empty { color: #9aa0b8; font-style: italic; font-size: clamp(0.8rem, 1.7vh, 1.05rem); }

.l2-players {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.l2-players .team {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45em 0.7em;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
    border-left: 5px solid var(--team-color, #888);
}

.l2-players .team-rank { display: none; }

.l2-players .team-name {
    font-weight: 700;
    font-size: clamp(0.82rem, 1.7vh, 1.1rem);
    overflow-wrap: anywhere;
}

/* Przycisk pełnego ekranu - ten sam styl co link turnieju, ale jako <button>. */
.l2-ctrl {
    padding: 0.3em 0.9em;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.05);
    color: #9aa0b8;
    font: inherit;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.l2-ctrl:hover {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.32);
}

/* Telefon albo wąskie okno: ściana zawija się i przewija, zamiast miażdżyć
   panele do nieczytelnych słupków. Host to telewizor, ale niech nie pęka. */
@media (max-width: 820px) {
    /* Wąsko (host na telefonie): gracze wracają na górę poziomym paskiem,
       ściana gier pod spodem. */
    .l2-body {
        grid-template-columns: 1fr;
        grid-template-rows: auto minmax(0, 1fr);
    }

    .l2-side { grid-template-rows: auto auto auto; }
    .l2-side-list { max-height: 22vh; }
    .l2-players { flex-direction: row; flex-wrap: wrap; }
    .l2-players .team { border-left-width: 4px; }

    .l2-wall {
        grid-template-columns: repeat(2, 1fr);
        grid-auto-rows: minmax(32vh, auto);
        overflow-y: auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .l2-panel { transition: none; }
    .l2-panel:hover, .l2-panel:focus-visible { transform: none; }
}

/* Ostatnia litera: wymagana litera, kredyty druzyn, panel sedziego. */
.required-letter {
    font-size: 2.5rem;
    font-weight: 900;
    line-height: 1;
}

/* Litera obok zegara na telefonie - klawiatura zjada dol ekranu, ale ten rzad
   siedzi nad nia razem z zegarem, wiec zostaje widoczny. */
.ol-clock-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
}

.ol-letter-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
}

.ol-input-upper {
    text-transform: uppercase;
}

.ol-teams {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    padding: 0;
    margin: 0.5rem 0;
}

.ol-team {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.8rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.ol-team-active {
    border-color: var(--g-ostatnia-litera);
    box-shadow: 0 0 0 1px var(--g-ostatnia-litera);
}

.ol-team-out {
    opacity: 0.4;
    text-decoration: line-through;
}

.ol-team-credits {
    font-weight: 700;
    white-space: nowrap;
}

.judge-panel {
    margin: 0.75rem 0;
    padding: 1rem;
    border-radius: 12px;
    background: rgba(229, 72, 77, 0.12);
    border: 1px solid rgba(229, 72, 77, 0.4);
}

.judge-question {
    margin: 0 0 0.25rem;
    opacity: 0.8;
}

.judge-word {
    font-size: 1.75rem;
    font-weight: 900;
    margin: 0 0 0.75rem;
}

.ol-input-row {
    display: flex;
    gap: 0.5rem;
    margin: 0.5rem 0;
}

.ol-input-row .form-control {
    flex: 1;
}

.ol-error {
    color: var(--bs-danger, #dc3545);
    min-height: 1.25em;
}

/* Lancuch podanych slow na ekranie hosta - rosnie przez cala runde, wiec
   ogranicznik wysokosci ze scrollem, zeby nie zepchnal reszty panelu. */
.ol-word-chain {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    list-style: none;
    padding: 0;
    margin: 0.5rem 0;
    max-height: 14vh;
    overflow-y: auto;
}

.ol-word-chain-item {
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    font-weight: 700;
    text-transform: uppercase;
    white-space: nowrap;
}

.ol-word-chain-item:not(:last-child)::after {
    content: '→';
    margin-left: 0.4rem;
    opacity: 0.5;
    font-weight: 400;
}

.ol-word-chain-current {
    border-color: var(--g-ostatnia-litera);
    box-shadow: 0 0 0 1px var(--g-ostatnia-litera);
}
