@charset "UTF-8";

/* ===== ZNAK MARKI =====
   Logo to szeroki wordmark (~5:1), a nie kwadratowa ikonka - wysokosc zadajemy my, szerokosc
   wynika z proporcji. width/height w HTML sa RZECZYWISTE (2677x522) tylko po to, zeby
   przegladarka zarezerwowala wlasciwe miejsce przed wczytaniem pliku i uklad nie podskakiwal.
   Wariant (czarny/bialy) zalezy od TLA, nie od motywu aplikacji. Karta logowania stoi na
   ciemnym hero, wiec tam wariant jest staly; nagłówek aplikacji i pasek Spolecznosci maja
   tlo strony, ktore zmienia sie z motywem - tam logo idzie za motywem (.wg-motywu). */
.logo-marka { height: 36px; width: auto; display: block; }
/* Wariant sledzacy motyw: dwa pliki, przelaczane CSS-em zamiast podmiany src z JS -
   podmiana src daje mignięcie przy kazdym przelaczeniu, a przy starcie strony pokazalaby
   na moment zly wariant. */
/* Wariant podstawowy (czarny) siedzi w atrybucie src, nie w CSS - gdyby `content` na <img>
   gdziekolwiek nie zadzialalo, widac poprawne logo zamiast ikony zepsutego obrazka.
   CSS podmienia je wylacznie w motywie ciemnym. */
[data-theme="dark"] .logo-marka.wg-motywu { content: url('../../assets/img/logo-biale.png'); }

/* ===== IKONY INTERFEJSU (Uicons by Flaticon) =====
   Font ikon zamiast emoji w elementach STERUJĄCYCH (przyciski, nagłówki, akcje). Emoji
   zostają tam, gdzie są TREŚCIĄ, a nie interfejsem: ikonka fiszki wybrana przez użytkownika,
   flagi języków. Powód jest praktyczny, nie estetyczny -
   emoji renderuje system, więc ta sama "lupa" wygląda inaczej na Windows, Androidzie i iOS,
   a części z nich (np. ✍️) starsze Androidy nie mają wcale.
   line-height:0 + vertical-align:-0.1em zapobiega rozpychaniu wierszy przez glif. */
.ico { font-style: normal; line-height: 0; vertical-align: -0.12em; display: inline-block; }
.ico:not(:only-child) { margin-right: 0.45em; }
.ico::before { line-height: 0; }
/* Ikona w przycisku dziedziczy jego kolor i rozmiar - nic nie trzeba dopisywać przy każdym użyciu. */
button .ico, a .ico { color: inherit; }

/* ===== RESET & ZMIENNE ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ===== PALETA: STYL KANWY (2026-09-26) =====
     Alek po zatwierdzeniu kanwy: „bazując na wyglądzie aplikacji odśwież aplikację desktopową, dodając te style,
     kolory, treści w samą grę na desktopie również". Wartości idą za aplikacją mobilną (lingaria-app/src/motyw/
     tokeny.ts, JASNY i CIEMNY) i planszami kanwy: granat #17183B, niebieski #2463E9, żółty #FFC83D, czerwień
     #DB2727 i zieleń #35A64D z logo, lawendowe tło #F3F5FB. Do tego dnia zalogowana aplikacja miała grafit
     #0F172A, zielony akcent i Fredokę - czyli wyglądała jak inny produkt niż strona główna i telefon.

     NAZWY ZMIENNYCH ZOSTAŁY (czytają je setki reguł), zmieniły się WARTOŚCI i - w dwóch miejscach - ROLE:
     - --oro to od teraz AKCENT INTERFEJSU: przycisk główny, zakładka i pozycja wybrana, obwódka pod kursorem,
       suwak, przełącznik. Granat w jasnym motywie, żółty w ciemnym (na granatowym tle granatowy przycisk byłby
       pustą dziurą - ta sama zamiana, co w aplikacji: `przycisk`). Tekst na nim: --na-akcencie.
     - --verde to od teraz WYŁĄCZNIE ZIELEŃ SUKCESU: poziom łatwy, dobra odpowiedź, postęp. Dawniej była też
       akcentem przycisków i te dwie role zlewały się w jedną zieleń (zielony „Zaloguj" obok zielonego „dobrze").
       Reguły, w których --verde znaczyło przycisk albo wybór, przeszły na --oro (patrz komentarze przy nich).
       Wartość to zieleń logo PRZYCIEMNIONA do #1F7A35, bo #35A64D z białym napisem ma 3,1 : 1, a jako tekst
       na bieli 2,9 : 1; #1F7A35 ma 5,4 : 1. Pełna zieleń logo (wypełnienia pasków, „Łatwe") to --marka-zielony. */
  --granat: #17183B;         /* stały granat marki: kolorowe ekrany, tekst na żółtym i zielonym */
  --granat-jasny: #24265A;   /* kafle na granacie (ściana Premium, karta „Twoje fiszki") */
  --niebieski-ciemny: #204EB8;
  --zolty: #FFC83D;          /* akcent marki: aktywna zakładka, kółko na strzałkę w przycisku, liczby na granacie */
  --lawenda: #D4D5F0;        /* drugi tekst na granacie */
  --lawenda-ciemna: #C9CAE8;
  --szary-marki: #9A9CB8;    /* obwódka słówka „nowe" */
  --font-tekst: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-naglowek: 'Outfit', 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Dwa odcienie zieleni, które NIE zmieniają się z motywem - do gradientów, które mają zostać gradientami
     w obu trybach (gdyby oba końce jechały za --verde, w ciemnym motywie wyszedłby z tego jednolity pasek). */
  --zielen-gleboka: #1F7A35;
  --zielen-pastel:  #9AD2A6;
  /* Ledwie zielone tło pod rzeczami „świeżymi, ale nie alarmującymi": nieprzeczytane powiadomienie, ramka
     z materiałami obserwowanych twórców. W ciemnym motywie jaśniejszy odcień i mocniejsze krycie. */
  --zielen-tlo: rgba(53, 166, 77, 0.10);

  --primary: #2463E9;      /* niebieski z logo - poziom średni, odnośniki, wykresy */
  --primary-dark: #204EB8;
  --verde:   #1F7A35;      /* zieleń sukcesu (patrz wyżej) */
  --rosso:   #DB2727;      /* błędy / poziom trudne */
  /* BARWY LOGA - ZMIERZONE 2026-09-22 z assets/img/logo-czarne.png (GD, środek każdego z trzech klastrów
     nasyconych barw): zieleń #35A64D, błękit #2463E9, czerwień #DB2727. Kropki lektora w Mówieniu, ramki
     i oceny fiszek (komponenty/fiszka.php), paski postępu. W ciemnym motywie czerwień i błękit jaśnieją
     (na granacie miały 3,0 i 2,8 : 1). */
  --marka-zielony:   #35A64D;
  --marka-czerwony:  #DB2727;
  --marka-niebieski: #2463E9;
  --srednie: #2463E9;  /* poziom średnie - ten sam błękit co ramka fiszki i kropka w statystykach */
  --bianco:  #FFFFFF;
  --crema:   #F3F5FB;  /* tło strony - lawendowa biel z kanwy */
  --oro:     #17183B;  /* AKCENT INTERFEJSU (patrz wyżej): granat, w ciemnym żółty */
  /* Kolor TEKSTU na wypełnieniu --oro albo --verde. Biały na granacie i na #1F7A35; w ciemnym motywie
     granatowy, bo tam akcent jest żółty, a zieleń pastelowa. */
  --na-akcencie: #FFFFFF;
  /* Nazwy dla nowych reguł stylu kanwy - to samo, co --oro i --na-akcencie, tylko czytelniej w miejscu użycia. */
  --przycisk: var(--oro);
  --na-przycisku: var(--na-akcencie);
  --fokus: #2463E9;    /* obwódka klawiatury - na planszach niebieska w jasnym, żółta w ciemnym */
  /* Kółko ze strzałką w głównym przycisku (.btn-strzalka): żółte z granatową strzałką na granatowej pigułce,
     w ciemnym motywie granatowe z żółtą na żółtej. Strzałki jako gotowe obrazki, bo SVG w url() nie czyta var(). */
  --strzalka-granatowa: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317183B' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E");
  --strzalka-zolta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFC83D' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E");
  --przycisk-kolko: #FFC83D;
  --przycisk-kolko-strzalka: var(--strzalka-granatowa);
  /* Oko w kółku „Pokaż odpowiedź" (plansza „Fiszki") - ten sam przycisk, inna ikona w kółku. */
  --oko-granatowe: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317183B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 12s3.5-6.5 9.5-6.5 9.5 6.5 9.5 6.5-3.5 6.5-9.5 6.5S2.5 12 2.5 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
  --oko-zolte: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFC83D' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 12s3.5-6.5 9.5-6.5 9.5 6.5 9.5 6.5-3.5 6.5-9.5 6.5S2.5 12 2.5 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
  --testo:   #17183B;  /* główny tekst - granat marki */
  --grigio:  #4A4B6B;  /* tekst drugiego planu z plansz (dawniej #64748B - szarość bez koloru marki) */
  --card-bg: #FFFFFF;
  /* KARTY PŁASKIE Z OBWÓDKĄ zamiast ciężkich cieni - tak stoją na planszach. Cień został śladowy (żeby karta
     odkleiła się od lawendowego tła), a pod kursorem krótki i miękki. */
  --shadow:  0 1px 2px rgba(23, 24, 59, 0.05);
  --shadow-hover: 0 14px 30px -16px rgba(23, 24, 59, 0.35);
  --radius:  22px;
  --transition: 0.3s cubic-bezier(.4,0,.2,1);

  /* Tokeny strukturalne - wydzielone z kolorów wpisanych kiedyś na sztywno, żeby tryb ciemny (niżej) mógł je
     nadpisać zamiast zostawiać jasne plamy na ciemnym tle. Wartości z aplikacji (ramka, powierzchnia2…). */
  --border:       #E3E4EF; /* główny, neutralny kolor obramowań */
  --border-2:     #D4D5F0; /* mocniejsze obramowanie (inputy, tabele) - lawenda */
  --bg-soft:      #ECEDF6; /* delikatne tło poboczne (kafel „Nowe", tor paska) */
  --muted-light:  #9A9CB8; /* najjaśniejszy odcień tekstu pomocniczego */
  --muted-dark:   #2E3055; /* najciemniejszy odcień tekstu pomocniczego */
  --border-warm:      #E3E4EF; /* obramowanie kart - dominujące w całej appce */
  --border-warm-soft: #EDEEF6; /* subtelniejszy wariant, do cienkich linii/separatorów */
  --border-warm-dash: #9A9CB8; /* kreskowane obramowanie stref uploadu */
  --border-warm-2:    #EDEEF6; /* najsubtelniejszy wariant, wiersze tabeli rankingu */
  --bg-error-soft:   #FBE6E6; /* pastelowe tło błędu/poziomu trudnego */
  --bg-error-soft2:  #F8D9D9; /* pastelowe tło błędu, mocniejszy wariant (odznaki) */
  /* Kolor gwiazdki ✦ na końcu wstawki AI. Ciemniejszy niż sama czerwień podkreślenia, bo znak jest drobny
     (0.58em) i w kolorze kreski gubiłby się w tekście. */
  --ai-wstawka-znak: #B81E1E;
  --bg-success-soft: #E4F3E7; /* pastelowe tło sukcesu/poziomu łatwego */
  --bg-warn-soft:    #E6EDFC; /* pastelowe tło poziomu średniego (błękit, jak --srednie) */
  --bg-amber-soft:   #EEEFF5; /* pastelowe tło statusu oczekiwania (neutralne) */
  --bg-info-soft:    #E6EDFC; /* pastelowe tło informacyjne (np. dni zamrożenia) */
  /* Plakietki w Społeczności są CELOWO bezbarwne. Leżą na zdjęciach i kartach o dowolnej kolorystyce, więc
     kolorowa pigułka konkurowała z treścią zamiast ją opisywać. --pigulka-* stoi na jasnej KARCIE, więc musi
     się odwrócić w ciemnym motywie; plakietki leżące wprost na zdjęciu mają czerń wpisaną na sztywno. */
  --pigulka-tlo:   rgba(23, 24, 59, 0.72);
  --pigulka-tekst: #FFFFFF;
  --pigulka-cicha: rgba(23, 24, 59, 0.07);
  --kratka-linia:    #E3E6F2; /* linie papieru w kratkę w trybie Teksty */
  --tekst-neutralny: #6B6D8A; /* zdanie jeszcze nieocenione */
  /* PODŚWIETLENIE WYBRANEGO: żółta poświata, bo akcent wyboru na planszach jest żółty (aktywna zakładka,
     wybrany plan). Dawniej zielona - w tej samej zieleni co „dobrze", więc wybór wyglądał jak zaliczenie. */
  --bg-highlight:    #FFF4D6;
  --bg-gold-soft:    #FFF6DC; /* wybrany kafelek gry, plakietka Premium, pasek paczki */
  --bg-success-grad-a: #EEF8F0; /* gradient tła sukcesu - początek */
  --bg-success-grad-b: #E4F3E7; /* gradient tła sukcesu - koniec */
  --chart-latwe: #35A64D; /* linia "łatwe" na wykresie historii - zieleń logo, nie var(--verde) */
  --audio-tile-bg: #EEEDFB; /* tło kafelka "tylko dźwięk" w Grze w pary */
  --audio-tile-border: #C9CAE8;
  --wordmap-latwe-border:   #A8DBB3; /* obramowanie chipów mapy słówek wg poziomu - pastele barw logo */
  --wordmap-srednie-border: #A9C1F5;
  --wordmap-trudne-border:  #F0A9A9;
  /* MINI QUIZY Z KANWY (2026-10-03, sekcja 16): dolna krawędź kafla i pusty slot, pierścień fokusu pola, ciemna
     czerwień napisu „Prawie!” i krzyżyka (te same wartości, co --ai-wstawka-znak), szara strzałka wyłączonego „Sprawdź”. */
  --krawedz-kafla: #CBD0E1;
  --fokus-pierscien: rgba(36, 99, 233, 0.14);
  --czerwien-tekst: #B81E1E;
  --strzalka-szara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A8DAA' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E");
}

/* ===== TRYB CIEMNY =====
   Dwie ścieżki włączenia: automatyczna (system, prefers-color-scheme) i ręczna (przełącznik w Ustawieniach
   zapisany w localStorage jako atrybut data-theme na <html>). Atrybut data-theme, gdy ustawiony, zawsze wygrywa
   z preferencją systemową.
   GRANAT ZAMIAST GRAFITU (2026-09-26): tło #0E0F26, powierzchnia #17183B, druga powierzchnia #212350, obwódka
   #2E3068, tekst #F3F4FF - ciemny motyw aplikacji mobilnej (tokeny.ts, CIEMNY). Grafit #0F172A obok granatowych
   ekranów marki (ściana Premium, karta „Twoje fiszki") czytał się jak dwie różne aplikacje sklejone w jedną.
   Kolorowe ekrany marki trzymają swoje barwy w obu motywach i ten blok ich nie dotyka. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --zielen-gleboka: #1F7A35;
    --zielen-pastel:  #9AD2A6;
    --zielen-tlo: rgba(76, 194, 102, 0.16);
    --primary: #5B90F5;
    --primary-dark: #4F82F0;
    --verde:   #8BDDA0;
    --rosso:   #FF6B6B;
    /* Kropki lektora i ramki fiszek na granacie: zieleń loga zostaje, czerwień #DB2727 (3,0 : 1) i błękit
       #2463E9 (2,8 : 1) schodzą pod próg 3 : 1 dla elementów graficznych - ten sam odcień, jaśniej. */
    --marka-czerwony:  #EF4444;
    --marka-niebieski: #3B82F6;
    --srednie: #5B90F5;
    --bianco:  #17183B;
    --crema:   #0E0F26;
    --oro:     #FFC83D;
    --na-akcencie: #17183B;
    --fokus: #FFC83D;
    --przycisk-kolko: #17183B;
    --przycisk-kolko-strzalka: var(--strzalka-zolta);
    --testo:   #F3F4FF;
    --grigio:  #B4B6D8;
    --card-bg: #17183B;
    --shadow:  0 4px 24px rgba(0,0,0,0.35);
    --shadow-hover: 0 14px 34px -14px rgba(0,0,0,0.7);

    --border:       #2E3068;
    --border-2:     #4A4C80;
    --bg-soft:      #212350;
    --muted-light:  #9A9CC0;
    --muted-dark:   #D4D5F0;
    --border-warm:      #2E3068;
    --border-warm-soft: #24265A;
    --border-warm-dash: #4A4C80;
    --border-warm-2:    #212350;
    --bg-error-soft:   #3A1620;
    --bg-error-soft2:  #451B26;
    --ai-wstawka-znak: #FCA5A5;
    --bg-success-soft: #15331F;
    --bg-warn-soft:    #16254F;
    --bg-amber-soft:   #24265A;
    --bg-info-soft:    #16254F;
    --pigulka-tlo:   rgba(243, 244, 255, 0.16);
    --pigulka-tekst: #F3F4FF;
    --pigulka-cicha: rgba(243, 244, 255, 0.10);
    --kratka-linia:    #262856;
    --tekst-neutralny: #9A9CC0;
    --bg-highlight:    rgba(255, 200, 61, 0.14);
    --bg-gold-soft:    rgba(255, 200, 61, 0.12);
    --bg-success-grad-a: #15331F;
    --bg-success-grad-b: #13301D;
    --chart-latwe: #4CC266;
    --audio-tile-bg: #2B2A55;
    --audio-tile-border: #7B77C7;
    --wordmap-latwe-border:   #2D6B3C;
    --wordmap-srednie-border: #2B4A8F;
    --wordmap-trudne-border:  #7A2E36;
    --krawedz-kafla: #3A3E73;
    --fokus-pierscien: rgba(91, 144, 245, 0.22);
    --czerwien-tekst: #FCA5A5;
    --strzalka-szara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B6D9A' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E");
  }
}
:root[data-theme="dark"] {
  --zielen-gleboka: #1F7A35;
  --zielen-pastel:  #9AD2A6;
  --zielen-tlo: rgba(76, 194, 102, 0.16);
  --primary: #5B90F5;
  --primary-dark: #4F82F0;
  --verde:   #8BDDA0;
  --rosso:   #FF6B6B;
  /* Kropki lektora i ramki fiszek - jak w bloku prefers-color-scheme wyżej (ta sama para, ten sam powód). */
  --marka-czerwony:  #EF4444;
  --marka-niebieski: #3B82F6;
  --srednie: #5B90F5;
  --bianco:  #17183B;
  --crema:   #0E0F26;
  --oro:     #FFC83D;
  --na-akcencie: #17183B;
  --fokus: #FFC83D;
  --przycisk-kolko: #17183B;
  --przycisk-kolko-strzalka: var(--strzalka-zolta);
  --testo:   #F3F4FF;
  --grigio:  #B4B6D8;
  --card-bg: #17183B;
  --shadow:  0 4px 24px rgba(0,0,0,0.35);
  --shadow-hover: 0 14px 34px -14px rgba(0,0,0,0.7);

  --border:       #2E3068;
  --border-2:     #4A4C80;
  --bg-soft:      #212350;
  --muted-light:  #9A9CC0;
  --muted-dark:   #D4D5F0;
  --border-warm:      #2E3068;
  --border-warm-soft: #24265A;
  --border-warm-dash: #4A4C80;
  --border-warm-2:    #212350;
  --bg-error-soft:   #3A1620;
  --bg-error-soft2:  #451B26;
  --ai-wstawka-znak: #FCA5A5;
  --bg-success-soft: #15331F;
  --bg-warn-soft:    #16254F;
  --bg-amber-soft:   #24265A;
  --bg-info-soft:    #16254F;
  --pigulka-tlo:   rgba(243, 244, 255, 0.16);
  --pigulka-tekst: #F3F4FF;
  --pigulka-cicha: rgba(243, 244, 255, 0.10);
  --kratka-linia:    #262856;
  --tekst-neutralny: #9A9CC0;
  --bg-highlight:    rgba(255, 200, 61, 0.14);
  --bg-gold-soft:    rgba(255, 200, 61, 0.12);
  --bg-success-grad-a: #15331F;
  --bg-success-grad-b: #13301D;
  --chart-latwe: #4CC266;
  --audio-tile-bg: #2B2A55;
  --audio-tile-border: #7B77C7;
  --wordmap-latwe-border:   #2D6B3C;
  --wordmap-srednie-border: #2B4A8F;
  --wordmap-trudne-border:  #7A2E36;
  --krawedz-kafla: #3A3E73;
  --fokus-pierscien: rgba(91, 144, 245, 0.22);
  --czerwien-tekst: #FCA5A5;
  --strzalka-szara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B6D9A' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E");
}
html { color-scheme: light dark; }
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

body {
  /* Figtree zamiast Fredoki (styl kanwy, 2026-09-26) - patrz --font-tekst. Nagłówki i duże liczby
     przechodzą na Outfit regułą niżej (h1, h2, h3, .card-title…). */
  font-family: var(--font-tekst);
  font-weight: 500;
  background: var(--crema);
  color: var(--testo);
  min-height: 100vh;
  /* Dlugie ciagi bez spacji - wklejony adres, sklejony niemiecki rzeczownik, nazwa pliku -
     potrafia rozepchnac kolumne na szerokosc, ktorej nie da sie juz zawinac. */
  overflow-wrap: break-word;
}

/* Naglowek chowa sie przy przewijaniu w dol i wraca przy przewijaniu w gore - na
   telefonie zajmowal 183 px, czyli 22% ekranu, i to przy KAZDYM zdaniu czytanki.
   Klase dokłada wylacznie kod dotykowy (patrz obsluzChowanieNaglowka), wiec na myszce
   pasek stoi jak stal. */
.app-header { transition: transform 0.22s ease; }
body.naglowek-schowany .app-header { transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) { .app-header { transition: none; } }

/* Powiekszanie palcami wylaczone na zyczenie. manipulation zdejmuje przy okazji
   400-milisekundowa zwloke po tapnieciu, ktora niektore przegladarki dokladaja,
   czekajac na ewentualne podwojne tapniecie. */
body { touch-action: manipulation; }

/* MINIMUM 16 px W POLACH TEKSTOWYCH NA DOTYKU.
   iOS Safari SAM powieksza cala strone w momencie wejscia w pole, ktorego czcionka jest
   mniejsza niz 16 px - to zachowanie przegladarki, nie nasze. Dopoki powiekszanie palcami
   dzialalo, uzytkownik po prostu wracal szczypnieciem i nikt tego nie zglaszal. Po jego
   zablokowaniu ta sama sciezka konczyla sie uwiezieniem w powiekszeniu: strona zostawala
   przycieta i nie bylo jak jej cofnac.
   Nasze pola mialy 0.88-0.98 rem, czyli 14-15.7 px - kazde z nich wyzwalalo ten mechanizm.
   !important jest tu swiadome: to obejscie zachowania przegladarki, ktore musi wygrac
   z kazda regula kolorystyczna czy rozmiarowa w tym pliku, a nie kolejny glos w dyskusji. */
@media (hover: none) and (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  textarea, select, [contenteditable="true"] { font-size: 16px !important; }
}

/* =========================================================================
   RUCH STRONY WYLACZNIE W PIONIE
   Telefon ma przewijac gora-dol i nic wiecej - takze po obroceniu na poziom.
   ========================================================================= */
html, body {
  max-width: 100%;
  /* hidden jako zapas dla starszych Safari; clip nadpisuje go tam, gdzie jest wspierany.
     Roznica jest istotna: overflow: hidden na <body> robi z niego KONTENER PRZEWIJANIA,
     co psuje position: sticky w srodku (naglowek przestaje sie przyklejac) i potrafi
     przyciac elementy position: fixed. clip obcina, nie tworzac kontenera. */
  overflow-x: hidden;
  overflow-x: clip;
  /* Blokuje poziome "gumowanie" i gest przewiniecia w bok, ktory w mobilnym Safari
     i Chrome cofa do poprzedniej strony. Pionowego przewijania nie rusza.
     Swiadomie NIE uzywamy touch-action: pan-y - to wylaczyloby takze przesuwanie po
     powiekszeniu palcami, czyli uwiezilo osoby, ktore powiekszaja tekst, zeby go przeczytac. */
  overscroll-behavior-x: none;
}
/* Odsuniecie od wciecia aparatu. env() jest zerem wszedzie poza telefonami, ktore to
   zglaszaja, wiec max() sprowadza sie na zwyklych ekranach do wartosci bazowej i nic
   nie zmienia. Dotyczy pasow przyklejonych do krawedzi - te w ukladzie strony sa
   odsuniete wlasnym paddingiem. */
@supports (padding: env(safe-area-inset-left)) {
  .header-inner {
    padding-left:  max(24px, env(safe-area-inset-left));
    padding-right: max(24px, env(safe-area-inset-right));
  }
  .start-pasek-demo {
    padding-left:  max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }
  .cookie-baner {
    padding-left:  max(22px, env(safe-area-inset-left));
    padding-right: max(22px, env(safe-area-inset-right));
    padding-bottom: max(18px, env(safe-area-inset-bottom));
  }
}

html {
  /* iOS Safari po obroceniu telefonu do poziomu sam powieksza czcionki ("text autosizing"),
     przez co teksty przestaja miescic sie w kolumnach policzonych dla pionu - i wlasnie
     wtedy pojawia sie przewijanie w bok, ktorego w pionie nie bylo. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
h1, h2, h3, .card-title, .btn, .header-title, .card-word, .card-word-back,
.mode-tab, .settings-title, .count, .leaderboard-time, .stat-num {
  font-weight: 700;
}
/* KROJE STYLU KANWY (2026-09-26). Outfit 800 niesie nagłówki i DUŻE LICZBY (licznik słówek, wynik, XP) -
   tak stoją na planszach („Twoje fiszki 5", „Powtórka zrobiona! 24"). Reszta to Figtree z body.
   Przyciski i pola nie dziedziczą kroju same z siebie (przeglądarka daje im systemowy), więc bez tej reguły
   każdy przycisk bez własnego font-family mówiłby Arialem obok Figtree - dawniej tak samo obok Fredoki. */
/* :not(.auth-screen *) - strona główna ma własne kroje i rozstrzelenia w klasach .lp-* (tokeny --lp-font*), a ta reguła
   dokładała jej nagłówkom -0,01em i przełamywała tytuły artykułów w innym miejscu (zmierzone różnicą zrzutów 1440 px
   przed i po). :where() trzyma specyficzność na poziomie jednej klasy, żeby reguły komponentów dalej wygrywały. */
:where(button, input, select, textarea):not(.auth-screen *) { font-family: inherit; }
:where(h1, h2, h3, .card-word, .card-word-back, .settings-title, .count, .stat-num):not(.auth-screen *) {
  font-family: var(--font-naglowek);
  font-weight: 800;
  letter-spacing: -0.01em;
}
/* Mały nagłówek karty w panelu bocznym („DODAJ SŁÓWKA", „POSTĘP") zostaje w Figtree: na planszach etykiety
   wersalikami („TWOJE FISZKI", „TWOJA TALIA") to Figtree 800 z rozstrzeleniem, a Outfit jest dla tytułów. */
:focus-visible { outline-color: var(--fokus); }

/* ===== HEADER =====
   Nagłówek jest CELOWO w kolorze tła strony, a nie w niebieskim gradiencie marki. Poprzednia
   wersja odcinała się od reszty aplikacji ciemną belką na całą szerokość i to ona, a nie
   fiszki, przyciągała wzrok. Dodatkowo pasek Społeczności (patrz .cmty-nawigacja) był już
   jasny - te same przyciski wyglądały więc inaczej w zależności od zakładki. Teraz oba paski
   wyglądają tak samo, a kolory zakładek, konta i przełącznika motywu są opisane RAZ, w ich
   własnych regułach, zamiast być dublowane w nadpisaniach pod .cmty-nawigacja. */
.app-header {
  background: var(--crema);
  color: var(--testo);
  padding: 0;
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid var(--border-warm-soft);
}
.header-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.header-title {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.5px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.header-title span { font-size: 2rem; }
.header-actions { display: flex; align-items: center; gap: 10px; }

/* Przełącznik aktywnego języka nauki - mała strzałeczka przy fladze w nagłówku, patrz
   renderHeaderLangMenu() w JS. Konto może mieć dodanych kilka języków (user_jezyki), to
   tylko przełącza, który jest aktualnie widoczny w Fiszkach/Grze - limit słówek i passa
   zostają wspólne dla całego konta, ranking gry jest osobny na każdy język. */
.header-lang { position: relative; display: flex; align-items: center; gap: 2px; }
.header-lang-caret {
  background: var(--border); border: none; border-radius: 6px;
  color: var(--testo); font-size: 0.7rem; cursor: pointer; padding: 2px 4px;
  line-height: 1; opacity: 0.85;
}
.header-lang-caret:hover { opacity: 1; background: var(--border-2); }
.header-lang-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 200;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft);
  border-radius: 12px; box-shadow: var(--shadow-hover);
  min-width: 170px; padding: 6px; font-size: 0.8rem; font-weight: 600;
}
.header-lang-item {
  display: flex; align-items: center; gap: 7px; padding: 7px 10px;
  border-radius: 8px; cursor: pointer; color: var(--testo);
}
.header-lang-item:hover { background: var(--crema); }
/* Nazwa rozpycha się na całą szerokość, więc licznik i kosz stoją równo przy prawej krawędzi
   niezależnie od tego, czy język nazywa się "Włoski" czy "Niderlandzki". */
.header-lang-item > span:first-of-type { flex: 1; }
.header-lang-ile {
  font-size: 0.72rem; font-weight: 800; color: var(--grigio);
  background: var(--crema); border-radius: 999px; padding: 2px 7px; white-space: nowrap;
}
.header-lang-item.active .header-lang-ile { background: var(--card-bg); }
/* Kosz wchodzi dopiero pod kursorem: to operacja nie do cofnięcia, więc nie ma prawa stać
   stale obok języka, na który po prostu chce się przełączyć. Na dotyku hovera nie ma,
   więc tam pokazujemy go przygaszony - inaczej byłby nieosiągalny. */
.header-lang-kosz {
  border: none; background: transparent; color: var(--grigio); cursor: pointer;
  padding: 2px 4px; border-radius: 6px; opacity: 0; transition: var(--transition);
  display: inline-flex; align-items: center;
}
.header-lang-item:hover .header-lang-kosz { opacity: 1; }
.header-lang-kosz:hover { color: var(--rosso); background: var(--bg-error-soft); }
@media (hover: none) { .header-lang-kosz { opacity: 0.55; } }
.header-lang-kosz .ico { margin: 0; font-size: 0.78rem; }

/* Wyliczenie tego, co zniknie razem z językiem. "Usuniesz język" nic nie znaczy, dopóki
   nie widać, że idzie z nim 320 fiszek - a tego nie da się cofnąć. */
.usun-jezyk-lista {
  list-style: none; margin: 0 0 16px; padding: 12px 14px;
  background: var(--bg-error-soft); border-radius: 10px;
  font-size: 0.84rem; line-height: 1.9; color: var(--testo);
}
.usun-jezyk-lista li { display: flex; justify-content: space-between; gap: 12px; }
.usun-jezyk-lista li b { font-weight: 800; }
/* Znacznik przy wierszu historii maili: poszło / nie poszło. Kolor plus słowo, bo sama
   zieleń i czerwień nie wystarczą - część osób ich nie odróżni. */
/* (Rząd akcji karty Społeczności: sekcja 21b na końcu głównego arkusza, od 2026-10-11 jeden dla czterech typów.) */

/* --- Podgląd tekstu w społeczności: ta sama kartka co w czytance --- */
/* Karta na tablicy pokazuje tekst DOKŁADNIE tak, jak będzie wyglądał przy czytaniu - z kratką
   i z podświetlonymi słowami, które ten konkretny użytkownik już zna. To jedyna informacja,
   która realnie odpowiada na pytanie "czy dam radę": lista zdań bez tego jest tylko ścianą
   obcego tekstu, a procent pokrycia to liczba bez twarzy. */
.cmty-kartka {
  background:
    linear-gradient(var(--kratka-linia, rgba(120,140,170,0.13)) 1px, transparent 1px) 0 0 / 100% 26px,
    linear-gradient(90deg, var(--kratka-linia, rgba(120,140,170,0.13)) 1px, transparent 1px) 0 0 / 26px 100%;
  background-color: var(--card-bg);
  border: 1px solid var(--border-warm); border-radius: 12px;
  padding: 14px 16px 14px 22px; position: relative; overflow: hidden;
}
/* Czerwona linia marginesu - ten sam znak co na kartce w czytance. */
.cmty-kartka::before {
  content: ''; position: absolute; left: 14px; top: 0; bottom: 0; width: 1px;
  background: color-mix(in srgb, var(--rosso) 32%, transparent);
}
.cmty-kartka-zdanie {
  font-size: 0.9rem; line-height: 26px; color: var(--testo); font-weight: 600;
  padding-left: 10px;   /* żeby tekst nie wchodził na pionową linię kartki */
}
.cmty-kartka-wiecej {
  font-size: 0.78rem; line-height: 26px; color: var(--grigio); font-style: italic; padding-left: 10px;
}
.cmty-kartka-legenda {
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
  font-size: 0.72rem; color: var(--grigio); margin-top: 8px;
}

/* --- Tryb paczki: cała nauka zawężona do jednego zbioru ---
   UKŁAD: [ikona] [tytuł + liczby] ----- [akcje] [wyjście], a pod spodem cichszy wiersz planu.
   Wcześniej wszystko leżało w jednym płaskim, zawijanym rzędzie: długi tytuł filmu rozpychał
   pasek, przyciski lądowały raz obok tekstu, raz pod nim, a drugi wiersz czytał się jak jedno
   długie zdanie z kropkami. Teraz tytuł ma własną kolumnę i się przycina, przyciski trzymają
   się prawej krawędzi, a fakty o planie są osobnymi pigułkami.
   ZIELEŃ ZESZŁA DO LEWEJ SZYNY. Pełna zielona ramka wokół całego paska krzyczała mocniej niż
   przycisk „Ćwicz" pod nim - a to jest informacja o stanie, nie wezwanie do działania. */
.paczka-pasek-trybu {
  display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 12px; border-radius: 12px;
  background: var(--bg-gold-soft);
  border: 1px solid var(--border-warm); border-left: 4px solid var(--verde);
  font-size: 0.82rem; font-weight: 600; color: var(--testo);
}
/* Ikona w kaflu, nie gołym znakiem: przy dwuwierszowym bloku tekstu samotna emotka wisiała
   w powietrzu obok pierwszej linijki. */
.ppt-ikona {
  flex: none; width: 27px; height: 27px; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--card-bg); border: 1px solid var(--border-warm);
  color: var(--verde); font-size: 0.85rem;
}
.ppt-ikona .ico { margin: 0; }
.ppt-tresc { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* Tytuł przycina się wielokropkiem zamiast rozpychać pasek. Bez min-width:0 wyżej element
   flex nie kurczy się poniżej swojej treści i cały ten zabieg byłby bez skutku. */
.ppt-tytul {
  font-weight: 600; color: var(--muted-dark);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ppt-tytul b { font-weight: 800; color: var(--testo); }
.ppt-tresc b { font-weight: 800; }
/* Drugi wiersz bloku: ile tego jest i ile już siedzi. „Umiesz 47%" dostaje przy okazji
   pasek - liczba w rzędzie innych liczb nie pokazuje, czy to blisko końca, czy daleko. */
.ppt-meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: 3px 9px;
  font-size: 0.74rem; font-weight: 700; color: var(--grigio);
}
.ppt-umiesz { display: inline-flex; align-items: center; gap: 6px; }
.ppt-umiesz-tor {
  width: 52px; height: 5px; border-radius: 999px; background: var(--border);
  overflow: hidden; display: inline-block;
}
.ppt-umiesz-tor i { display: block; height: 100%; border-radius: 999px; background: var(--marka-zielony); }
.ppt-wyjscie {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  border-radius: 999px; padding: 5px 12px; font: inherit; font-size: 0.78rem; font-weight: 700;
  transition: var(--transition);
}
.ppt-wyjscie:hover { border-color: var(--rosso); color: var(--rosso); }
.ppt-wyjscie .ico { margin: 0; }
/* Drugi wiersz paska: ten poziom na tle CAŁEGO planu. Łamie się na całą szerokość (flex-basis
   100%), żeby nie ścisnąć przycisków, i jest wyraźnie cichszy od pierwszego wiersza - to jest
   kontekst, a nie kolejna rzecz do zrobienia. */
.ppt-plan {
  flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 5px;
  padding-top: 7px; margin-top: 1px; border-top: 1px solid var(--border-warm);
  font-size: 0.72rem; font-weight: 600; color: var(--grigio);
}
/* Każdy fakt w swojej pigułce. Rozdzielone samym odstępem zlewały się w jedno zdanie
   („łącznie 57 słówek 4 poziomów odblokowano 2/4 cel osiągniesz za…"), w którym nie było
   widać, gdzie kończy się jedna liczba, a zaczyna następna. */
.ppt-plan > span:not(.ppt-plan-zasada) {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 999px;
  background: var(--card-bg); border: 1px solid var(--border-warm);
}
.ppt-plan .ico { margin: 0; }
.ppt-plan b { font-weight: 800; color: var(--testo); font-variant-numeric: tabular-nums; }
/* Cel osiągnięty (każdy poziom nad progiem) - pigułka w kolorze sukcesu zamiast daty. */
.ppt-plan > span.ppt-cel-gotowy { color: var(--verde); border-color: var(--verde); }
/* Premia XP w trybie „wszystkie odblokowane poziomy" - złota, bo to nagroda, nie fakt. */
.ppt-plan > span.ppt-premia { color: #B45309; border-color: #F59E0B; }
/* Zasada progu to przypis, nie fakt: bez pigułki i najciszej z całego paska. Stoi jednak
   NA POCZĄTKU wiersza, a nie pod nim - jako osobna, ostatnia linijka była najniższą rzeczą
   w pasku, czyli tą, którą oko mija, a to ona tłumaczy, po co są wszystkie liczby obok.
   `order: -1` zamiast przeniesienia w kodzie: kolejność w drzewie zostaje logiczna (fakty,
   potem przypis), więc czytnik ekranu czyta ją tak, jak była czytana. */
.ppt-plan-zasada {
  order: -1; flex-basis: 100%; font-weight: 500; font-size: 0.71rem;
  color: var(--muted-light);
}
/* Podpowiedź o mapie (pigułka „pokaż mapę" przy prawej krawędzi drugiego wiersza) odeszła 2026-09-26: ścieżkę poziomów
   otwiera dziś żółty przycisk w akcjach paska (odswiezAkcjePaczki), widoczny także na telefonie. */
/* Akcje w pasku paczki: doszlifowanie reszty i powrót do tekstu źródłowego. Wyglądają tak samo
   jak „Wyjdź z paczki" - stoją w tym samym rzędzie i są tego samego rodzaju wyjściem z sytuacji.
   Włączone zawężenie jest WYPEŁNIONE kolorem: inaczej nie widać, że talia skurczyła się z woli
   użytkownika, i brakujące słówka wyglądałyby na zgubione. */
/* Akcje i wyjście trzymają się PRAWEJ krawędzi paska: to jedyne rzeczy w nim do kliknięcia,
   więc mają być w jednym, przewidywalnym miejscu, a nie tuż za końcem tytułu - czyli raz tu,
   raz tam, zależnie od długości nazwy filmu. */
.ppt-akcje { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
@media (max-width: 720px) {
  /* Wąsko przyciski i tak spadają do własnego rzędu - dociśnięte tam do prawej krawędzi
     zostawiały po lewej pustą połowę paska. */
  .ppt-akcje { margin-left: 0; }
}
.ppt-akcja {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  border-radius: 999px; padding: 5px 12px; font: inherit; font-size: 0.78rem; font-weight: 700;
  transition: var(--transition);
}
.ppt-akcja:hover { border-color: var(--zielen-gleboka); color: var(--zielen-gleboka); }
.ppt-akcja.aktywna { background: var(--zielen-gleboka); border-color: var(--zielen-gleboka); color: #fff; }
.ppt-akcja.aktywna:hover { color: #fff; opacity: 0.9; }
.ppt-akcja .ico { margin: 0; }
.ppt-akcja-ile { opacity: 0.7; font-weight: 800; }
/* Strzałka PLAY przy wierszu paczki w mapie słówek. */
.wordmap-paczka-graj {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border: none; border-radius: 999px; padding: 5px 13px;
  background: var(--zielen-gleboka); color: #fff; font: inherit; font-size: 0.76rem; font-weight: 800;
  transition: var(--transition);
}
.wordmap-paczka-graj:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* --- Odmiana czasownika --- */
/* Przycisk siedzi obok głośnika i wchodzi TYLKO dla słów, które mogą być czasownikami.
   Gdy serwer raz powie "to nie czasownik", znika i już nie wraca (patrz nieCzasowniki). */
.odmiana-btn {
  position: absolute; top: 14px; right: 54px; z-index: 3;
  border: none; background: transparent; cursor: pointer;
  font-size: 1.05rem; line-height: 1; padding: 4px; border-radius: 8px;
  opacity: 0.45; transition: var(--transition);
  /* Ten sam powod co przy .speak-btn: wlasny z-index = wlasny kontekst rysowania, wiec
     ukrycie tylnej sciany strony karty NIE obejmuje tego przycisku - przeswitywalby
     w lustrze po obrocie. */
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.odmiana-btn:hover { opacity: 1; transform: scale(1.15); }

.odmiana-naglowek {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 1.15rem; font-weight: 800; margin-bottom: 14px;
}
.odmiana-czas { margin-bottom: 16px; }
.odmiana-czas-nazwa { font-size: 0.9rem; font-weight: 800; color: var(--testo); }
.odmiana-czas-opis { font-size: 0.76rem; color: var(--grigio); line-height: 1.5; margin-bottom: 8px; }
/* Siatka, nie tabela: przy sześciu osobach dwie kolumny czytają się szybciej niż jedna
   długa lista, a na telefonie i tak zwija się do jednej. */
.odmiana-formy { display: grid; grid-template-columns: repeat(2, 1fr); gap: 3px 16px; margin-bottom: 8px; }
@media (max-width: 520px) { .odmiana-formy { grid-template-columns: 1fr; } }
.odmiana-forma { display: flex; gap: 8px; font-size: 0.84rem; padding: 3px 0; border-bottom: 1px dashed var(--border-warm-soft); }
.odmiana-forma-osoba { color: var(--grigio); min-width: 62px; }
.odmiana-forma-tekst { font-weight: 800; color: var(--testo); }
.odmiana-przyklad {
  font-size: 0.78rem; line-height: 1.6; padding: 8px 12px; border-radius: 8px;
  background: var(--crema); color: var(--testo);
}
.odmiana-przyklad i { color: var(--grigio); font-style: normal; }

/* --- Krok quizu: zdanie z luką + koło form --- */
/* Zdanie jest TWOJE (przykład z fiszki), więc stoi na wierzchu jak kartka, a nie jak
   polecenie. Luka wypełnia się na bieżąco tym, co akurat wybrane w kole - dzięki temu
   przez cały czas czyta się CAŁE zdanie i słychać, czy brzmi. O to w tym ćwiczeniu chodzi:
   nie o wskazanie formy z listy, tylko o usłyszenie, która pasuje. */
.odm-karta {
  border: 1px solid var(--border-warm); border-radius: 16px;
  padding: 22px 20px; text-align: center; margin-bottom: 6px;
  font-size: 1.12rem; font-weight: 700; line-height: 1.7; color: var(--testo);
}
/* Tłumaczenie zdania po odpowiedzi - przyklejone do górnej krawędzi karty ze zdaniem, tak
   żeby czytało się jak druga linijka tego samego zdania, a nie jak osobna informacja. Ujemny
   margines zlewa obie ramki w jedną kreskę. */
.odm-tlum-nad {
  border: 1px solid var(--border-warm); border-bottom: none;
  border-radius: 16px 16px 0 0; margin-bottom: -1px;
  padding: 11px 18px 9px; background: var(--bg-soft);
  text-align: center; font-size: 0.88rem; font-weight: 700; line-height: 1.5; color: var(--grigio);
}
/* Karta traci zaokrąglenie od góry dopiero wtedy, gdy pasek nad nią faktycznie jest. */
.odm-karta.z-tlumaczeniem { border-top-left-radius: 0; border-top-right-radius: 0; }

.odm-luka {
  display: inline-block; min-width: 66px; padding: 0 6px;
  border-bottom: 2px solid var(--oro); color: var(--primary); font-weight: 800;
}
.odm-luka.pusta { color: var(--muted-light); }
.odm-luka.dobra { color: var(--zielen-gleboka); border-bottom-color: var(--zielen-gleboka); }
.odm-luka.zla   { color: var(--rosso);          border-bottom-color: var(--rosso); }

/* Czasownik i czas - bez osoby. Osoby CELOWO nie podajemy: to ZDANIE ma powiedzieć, o kogo
   chodzi, i na tym polega całe ćwiczenie. Etykieta "lui/lei" pozwalałaby wybrać formę bez
   czytania zdania. Jednoznaczność zapewnia bramka na podmiot w odmiana_w_zdaniu() (db.php),
   która odrzuca zdania bez nazwanego podmiotu. */
.odm-bezok { font-size: 0.74rem; font-weight: 700; color: var(--grigio); text-align: center; margin-bottom: 10px; }

/* --- Wybierz rodzajnik --- */
/* Rzeczownik z pustym miejscem przed nim. Luka jest częścią hasła, a nie osobnym polem:
   rodzajnik w językach romańskich zapamiętuje się razem ze słowem, nie obok niego. */
.rodz-haslo { text-align: center; font-size: 1.7rem; font-weight: 800; color: var(--testo); margin-bottom: 4px; }
.rodz-luka {
  display: inline-block; min-width: 52px; margin-right: 8px;
  border-bottom: 3px solid var(--oro); color: var(--primary);
}
/* Pusta luka jest PUSTA - stoi w niej twarda spacja, a nie schowana odpowiedź. Wcześniej
   było tu color: transparent i rodzajnik dawał się odczytać przez zaznaczenie tekstu. */
.rodz-luka.pusta { user-select: none; }
.rodz-tlum { text-align: center; font-size: 0.8rem; color: var(--grigio); margin-bottom: 18px; }
/* Angielski: luka stoi W ZDANIU (rodzajnik kontekstowy - patrz REGULY_JEZYKA w db.php). */
.rodz-zdanie { text-align: center; font-size: 1.3rem; font-weight: 700; line-height: 1.6; color: var(--testo); max-width: 560px; margin: 0 auto 6px; }
.rodz-zdanie .rodz-luka { margin: 0 2px; }
.rodz-opcje { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.rodz-opcja {
  min-width: 84px; padding: 14px 18px; border-radius: 14px; cursor: pointer;
  border: 2px solid var(--border-warm); background: var(--card-bg);
  font: inherit; font-size: 1.25rem; font-weight: 800; color: var(--primary);
  transition: var(--transition);
}
.rodz-opcja:hover { border-color: var(--oro); transform: translateY(-2px); }
.rodz-opcje.zablokowane .rodz-opcja { cursor: default; transform: none; }
/* Opcja wskazana KLAWIATURA (A/D, strzalki - patrz „KLAWIATURA W MINI QUIZACH" w JS). Wlasna
   klasa zamiast :focus-visible, bo fokus ustawiany skryptem przegladarki pokazuja roznie -
   a wybor ma byc widoczny zawsze tak samo. Po odpowiedzi (.zablokowane) ramka znika: wtedy
   liczy sie juz tylko zielen/czerwien werdyktu. */
.rodz-opcja.klaw-wybor, .pf-btn.klaw-wybor, .intruz-opcja.klaw-wybor,
.quiz-slowo-opcja.klaw-wybor, .game-tile.klaw-wybor, .quiz-kafel.klaw-wybor {
  outline: 3px solid var(--oro); outline-offset: 3px; transform: translateY(-2px);
}
.zablokowane .klaw-wybor { outline: none; }
/* To samo wskazanie dla WYJSC Z PYTANIA PISANEGO - „Nie moge teraz sluchac", „Nie moge teraz
   pisac", „nie wiem" i „Sprawdz" (gora/dol; patrz „KLAWIATURA W PYTANIU PISANYM" w JS).
   Bez translateY, ktore maja opcje wyzej: tamte leza w siatce i podskok dotyczy jednego
   kafelka, a te stoja w kolumnie jeden pod drugim - uniesienie przesuwaloby wszystko ponizej. */
.mini-exam-card .bez-audio-btn.klaw-wybor,
.mini-exam-card .quiz-glosnik.klaw-wybor,
.mini-exam-card .quiz-mik.klaw-wybor,
.mini-exam-card .quiz-sprawdz.klaw-wybor {
  outline: 3px solid var(--oro); outline-offset: 3px;
}
.rodz-opcja.poprawna { border-color: var(--zielen-gleboka); color: var(--zielen-gleboka); background: var(--bg-success-soft); }
.rodz-opcja.bledna   { border-color: var(--rosso); color: var(--rosso); background: var(--bg-error-soft); }

/* --- Prawda czy fałsz --- */
.pf-para { text-align: center; margin-bottom: 6px; }
.pf-slowo { font-size: 1.5rem; font-weight: 800; color: var(--testo); }
.pf-tlum { font-size: 1.5rem; font-weight: 800; color: var(--primary); }
/* Pasek czasu kurczy się od pełnej szerokości do zera - animacja CSS, nie setInterval,
   więc nie zacina się przy zajętym wątku i nie trzeba jej odliczać w JS. */
.pf-czas { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; margin: 18px 0; }
.pf-czas-fill { height: 100%; width: 100%; border-radius: 999px; background: var(--oro); transform-origin: left; }
.pf-czas.leci .pf-czas-fill { animation: pfOdliczanie var(--pf-czas, 3s) linear forwards; }
@keyframes pfOdliczanie { from { transform: scaleX(1); } to { transform: scaleX(0); } }
/* Przyciski „Prawda” / „Fałsz”: kafle 128 z kołem w sekcji 16 „MINI QUIZY” (2026-10-03). Dawne pastelowe pigułki ze
   znakami ✓/✕ miały max-width 160 px, które przeżyło w siatce kanwy i zwężało oba kafle do lewej krawędzi komórki. */

/* ===== COMBO (mnożnik XP za serię poprawnych odpowiedzi) =====
   Licznik przy karcie pytania + tło całego quizu w zamki SVG, których kolor rośnie
   z progami combo: bazowe (szare, ledwo widoczne) -> x2 błękit -> x3 fiolet -> x5 złoto.
   Wszystko na przejściach, żeby zmiana tła była falą, nie przeskokiem. */
.combo-licznik {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 13px;
  border-radius: 999px; font-weight: 900; font-size: 0.95rem; line-height: 1;
  background: var(--bg-soft); color: var(--testo);
  border: 2px solid var(--border-2);
  transition: background 0.4s, color 0.4s, border-color 0.4s, box-shadow 0.4s;
}
.combo-licznik .combo-znak { display: inline-flex; align-items: center; }
.combo-licznik .combo-znak svg { display: block; }
.combo-licznik .combo-mnoznik {
  font-size: 0.72rem; font-weight: 900; padding: 2px 7px; border-radius: 999px;
  background: color-mix(in srgb, currentColor 14%, transparent);
}
.combo-licznik.combo-t1 {
  background: linear-gradient(135deg, #DBEAFE, #BFDBFE); color: #1D4ED8; border-color: #60A5FA;
  box-shadow: 0 0 14px rgba(59, 130, 246, 0.35);
}
.combo-licznik.combo-t2 {
  background: linear-gradient(135deg, #EDE9FE, #DDD6FE); color: #6D28D9; border-color: #A78BFA;
  box-shadow: 0 0 18px rgba(139, 92, 246, 0.45);
}
.combo-licznik.combo-t3 {
  background: linear-gradient(135deg, #FEF3C7, #FDE68A, #FCA5A5); color: #B45309; border-color: #F59E0B;
  box-shadow: 0 0 24px rgba(245, 158, 11, 0.65);
}
.combo-licznik.combo-t3 .combo-znak { animation: comboKorona 0.55s ease-in-out infinite; }
@keyframes comboKorona { 0%, 100% { transform: scale(1) rotate(-4deg); } 50% { transform: scale(1.25) rotate(5deg); } }
@keyframes comboPuls { 0% { transform: scale(1); } 40% { transform: scale(1.22); } 100% { transform: scale(1); } }
.combo-licznik.puls { animation: comboPuls 0.3s ease; }
@keyframes comboProg {
  0% { transform: scale(0.7) rotate(-8deg); }
  45% { transform: scale(1.55) rotate(4deg); }
  70% { transform: scale(0.92) rotate(-2deg); }
  100% { transform: scale(1) rotate(0); }
}
.combo-licznik.prog { animation: comboProg 0.55s cubic-bezier(.3, 1.4, .5, 1); }
@keyframes comboPek {
  0% { transform: scale(1); filter: none; }
  25% { transform: scale(1.15) rotate(3deg); background: #FEE2E2; border-color: #EF4444; color: #B91C1C; }
  55% { transform: scale(0.9) rotate(-6deg); opacity: 0.8; }
  100% { transform: scale(0.3) rotate(12deg); opacity: 0; }
}
.combo-licznik.combo-pek { animation: comboPek 0.6s ease forwards; }
/* WIELKI BANER "COMBO xN" na środku ekranu - sekunda chwały po KAŻDEJ dobrej odpowiedzi
   w trybie combo (od aktywacji przy 3). Gradientowy napis wg progu, ogień po bokach
   i płomyki unoszące się spod napisu. pointer-events:none - nic nie blokuje. */
.combo-baner {
  position: fixed; inset: 0; z-index: 99985; display: flex;
  align-items: center; justify-content: center; pointer-events: none;
}
.combo-baner-tekst {
  position: relative;
  display: flex; align-items: center; gap: 16px;
  font-size: clamp(2.6rem, 9vw, 5.4rem); font-weight: 900; letter-spacing: 0.04em;
  background-clip: text; -webkit-background-clip: text; color: transparent;
  animation: comboBanerZycie 1.1s cubic-bezier(.25, 1.2, .4, 1) forwards;
  /* Wydzielona warstwa GPU: bez tego skala+opacity na wielkim gradientowym tekście
     przycinały ekran. Poświata NIE idzie przez filter:drop-shadow (przeliczany co
     klatkę animacji = główne źródło lagów) - robi ją ::before z miękkim radialem. */
  will-change: transform, opacity;
}
.combo-baner-tekst::before {
  content: ''; position: absolute; inset: -30% -14%; z-index: -1; border-radius: 50%;
  background: radial-gradient(closest-side, var(--combo-blask, rgba(245, 158, 11, 0.4)), transparent 72%);
}
.combo-baner-tekst.t1 { background-image: linear-gradient(135deg, #60A5FA, #2563EB); --combo-blask: rgba(59, 130, 246, 0.38); }
.combo-baner-tekst.t2 { background-image: linear-gradient(135deg, #C4B5FD, #7C3AED); --combo-blask: rgba(139, 92, 246, 0.4); }
.combo-baner-tekst.t3 { background-image: linear-gradient(135deg, #FDE68A, #F59E0B, #EF4444); --combo-blask: rgba(245, 158, 11, 0.45); }
@keyframes comboBanerZycie {
  0%   { transform: scale(0.35); opacity: 0; }
  16%  { transform: scale(1.18); opacity: 1; }
  28%  { transform: scale(1); }
  74%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(1.08) translateY(-34px); opacity: 0; }
}
/* Pioruny mocy po bokach napisu (własne SVG - ogień jest zajęty przez passę).
   Rodzic ma color:transparent od gradientu tekstu, więc kolor pioruna ustawiamy
   jawnie wg progu; drugi piorun jest lustrem pierwszego. */
.combo-baner-tekst .blysk {
  /* `text-align` i `padding` piorun dziedziczył po ogólnej regule `.blysk`, która odeszła
     razem z Błyskawicą (2026-09-23) - stoją tu, żeby baner wyglądał tak samo, co do piksela. */
  text-align: center; padding: 8px 4px 4px;
  display: inline-flex; align-items: center;
  animation: comboBanerBlysk 0.4s ease-in-out infinite alternate;
}
.combo-baner-tekst .blysk svg { display: block; width: 0.8em; height: auto; }
.combo-baner-tekst .blysk.lustro { transform: scaleX(-1); }
.combo-baner-tekst.t1 .blysk { color: #3B82F6; }
.combo-baner-tekst.t2 .blysk { color: #8B5CF6; }
.combo-baner-tekst.t3 .blysk { color: #F59E0B; }
@keyframes comboBanerBlysk { from { scale: 1; rotate: -7deg; } to { scale: 1.22; rotate: 7deg; } }
/* Iskry-gwiazdki unoszące się spod napisu - wirują i gasną w locie. */
.combo-plomyk {
  position: absolute; left: 50%; top: 58%; pointer-events: none;
  animation: comboPlomyk 1s ease-out forwards; opacity: 0;
  will-change: transform, opacity;   /* każda iskra na własnej, taniej warstwie */
}
.combo-plomyk svg { display: block; color: #F59E0B; }
.combo-baner.t1 .combo-plomyk svg { color: #60A5FA; }
.combo-baner.t2 .combo-plomyk svg { color: #A78BFA; }
.combo-baner.t3 .combo-plomyk svg { color: #FBBF24; }
@keyframes comboPlomyk {
  0%   { transform: translate(var(--p-x0, 0), 0) scale(0.5) rotate(0); opacity: 1; }
  100% { transform: translate(var(--p-x), -140px) scale(1.25) rotate(240deg); opacity: 0; }
}

/* Fala uderzeniowa przy wejściu na próg - rozchodzący się pierścień w kolorze progu. */
.combo-fala {
  position: fixed; border-radius: 50%; pointer-events: none; z-index: 99980;
  border: 3px solid var(--combo-fala-kolor, #F59E0B);
  animation: comboFala 0.7s ease-out forwards;
}
@keyframes comboFala {
  0% { transform: scale(0.2); opacity: 0.9; }
  100% { transform: scale(3.2); opacity: 0; }
}
/* TŁO W ZAMKI NA CAŁEJ STRONIE: klasa combo-tN siedzi na <body>, więc wzór wychodzi
   na boki i dół - wszędzie tam, gdzie prześwituje tło aplikacji (karty i panele mają
   własne, nieprzezroczyste tła i zostają czyste). Kafel 360x280 z TRZEMA różnymi
   sylwetkami (zamek trójwieżowy, samotna wieża z proporcem, niska twierdza z bramą)
   rozrzuconymi rzadko; widoczność zaszyta w fill-opacity samego wzoru - celowo ledwo
   obecna, ma być drogą teksturą, nie tapetą. Kolor tła przechodzi płynnie. */
body { transition: background-color 0.9s ease; }
body.combo-t1, body.combo-t2, body.combo-t3 {
  background-attachment: fixed;
  background-size: 360px 280px;
  background-color: var(--combo-tlo);
  background-image: var(--combo-zamki);
  /* Zamki lekko dryfują po skosie - jeden pełny kafel na ~2 minuty, ledwie zauwazalny
     ruch "żywego" tła. Kto prosi system o mniej ruchu, dostaje tło nieruchome. */
  animation: comboZamkiDryf 120s linear infinite;
}
@keyframes comboZamkiDryf {
  from { background-position: 0 0; }
  to   { background-position: 360px 280px; }
}
@media (prefers-reduced-motion: reduce) {
  body.combo-t1, body.combo-t2, body.combo-t3 { animation: none; }
}
/* JASNY motyw: tlo miesza kolor progu z --crema (zmienna tla strony), sylwetki
   w nasyconych odcieniach o niskiej opacity. */
body.combo-t1 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #3B82F6) 6%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%2360A5FA' fill-opacity='0.09' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}
body.combo-t2 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #8B5CF6) 7%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23A78BFA' fill-opacity='0.11' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}
body.combo-t3 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #F59E0B) 8%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23F59E0B' fill-opacity='0.13' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}
/* CIEMNY motyw (obie ścieżki włączenia, jak wszędzie w aplikacji): mocniejsza domieszka
   koloru w tle (na granacie subtelna ginie) i JAŚNIEJSZE sylwetki o ciut wyższej opacity,
   żeby zamki dalej było widać - ale wciąż jako teksturę, nie tapetę. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body.combo-t1 {
    --combo-tlo: color-mix(in srgb, var(--combo-akcent, #3B82F6) 16%, var(--crema));
    --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%2393C5FD' fill-opacity='0.12' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
  }
  :root:not([data-theme="light"]) body.combo-t2 {
    --combo-tlo: color-mix(in srgb, var(--combo-akcent, #8B5CF6) 18%, var(--crema));
    --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23C4B5FD' fill-opacity='0.14' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
  }
  :root:not([data-theme="light"]) body.combo-t3 {
    --combo-tlo: color-mix(in srgb, var(--combo-akcent, #F59E0B) 15%, var(--crema));
    --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23FCD34D' fill-opacity='0.15' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
  }
}
:root[data-theme="dark"] body.combo-t1 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #3B82F6) 16%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%2393C5FD' fill-opacity='0.12' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}
:root[data-theme="dark"] body.combo-t2 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #8B5CF6) 18%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23C4B5FD' fill-opacity='0.14' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}
:root[data-theme="dark"] body.combo-t3 {
  --combo-tlo: color-mix(in srgb, var(--combo-akcent, #F59E0B) 15%, var(--crema));
  --combo-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23FCD34D' fill-opacity='0.15' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
}

/* ===== AWANS SŁÓWKA (trudne -> średnie, średnie -> łatwe) =====
   Miejsce, w którym padło przejście (karta fiszki albo karta quizu), wibruje chwilę,
   a spod jego dolnej krawędzi wystrzeliwuje konfetti. Sam efekt - zero zmian w logice. */
/* Siła drżenia sterowana zmienną --wib-sila (1 = domyślna): dopasowanie par podkręca ją
   z każdą trafioną parą, od ledwo wyczuwalnej do finałowego trzęsienia. */
@keyframes awansWibracja {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  15% { transform: translate(calc(-6px * var(--wib-sila, 1)), calc(1px * var(--wib-sila, 1))) rotate(calc(-0.5deg * var(--wib-sila, 1))); }
  30% { transform: translate(calc(5px * var(--wib-sila, 1)), calc(-1px * var(--wib-sila, 1))) rotate(calc(0.4deg * var(--wib-sila, 1))); }
  45% { transform: translate(calc(-4px * var(--wib-sila, 1)), calc(1px * var(--wib-sila, 1))) rotate(calc(-0.3deg * var(--wib-sila, 1))); }
  60% { transform: translate(calc(3px * var(--wib-sila, 1)), 0) rotate(calc(0.2deg * var(--wib-sila, 1))); }
  78% { transform: translate(calc(-2px * var(--wib-sila, 1)), 0) rotate(0); }
}
.awans-wibracja { animation: awansWibracja 0.5s ease; }
.konfetti-scena { position: fixed; width: 0; height: 0; z-index: 99990; pointer-events: none; }
.konfetti-kawalek {
  position: absolute; width: 9px; height: 14px; border-radius: 2px; opacity: 0;
  animation: konfettiLot var(--k-czas, 1.1s) cubic-bezier(.2, .5, .4, 1) forwards;
}
/* Lot w dwóch aktach: wystrzał w górę z rozrzutem na boki, potem opad z obrotem i zanik. */
@keyframes konfettiLot {
  0%   { transform: translate(0, 0) rotate(0) scale(1); opacity: 1; }
  55%  { transform: translate(calc(var(--k-dx) * 0.7), var(--k-wznos)) rotate(var(--k-obrot)) scale(1); opacity: 1; }
  100% { transform: translate(var(--k-dx), var(--k-spad)) rotate(calc(var(--k-obrot) * 2)) scale(0.7); opacity: 0; }
}

/* ===== PÓŁMETEK - „umiesz już 50%" w miejscu karty albo pytania quizu =====
   Nakładka wypełnia #flashcard-area (stąd position: relative na nim), więc zasłania dokładnie
   to, co user właśnie robił, i nic więcej - pasek paczki nad nią i panel obok zostają na
   miejscu. Wjeżdża z odbiciem, liczba nabija się od zera (JS), przycisk dostaje fokus, żeby
   Enter i spacja działały bez sięgania po mysz. */
.polmetek {
  position: absolute; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; border-radius: var(--radius);
  background: var(--card-bg);
  box-shadow: inset 0 0 0 2px var(--verde);
  overflow: hidden;
}
.polmetek.hidden { display: none !important; }
.polmetek::before {
  content: ''; position: absolute; inset: -40%;
  background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--verde) 24%, transparent) 0, transparent 55%);
  animation: polmetekPoswiata 2.4s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes polmetekPoswiata { from { transform: scale(0.9); opacity: 0.7; } to { transform: scale(1.1); opacity: 1; } }
.polmetek-tresc { position: relative; text-align: center; max-width: 460px; }
.polmetek.wjazd .polmetek-tresc { animation: polmetekWjazd 0.55s cubic-bezier(0.22, 1.4, 0.36, 1); }
@keyframes polmetekWjazd { from { transform: scale(0.6); opacity: 0; } to { transform: none; opacity: 1; } }
.polmetek-pct {
  font-size: clamp(3.6rem, 12vw, 6rem); font-weight: 900; line-height: 1; color: var(--verde);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
  text-shadow: 0 6px 24px color-mix(in srgb, var(--verde) 35%, transparent);
}
.polmetek-tytul { font-size: 1.35rem; font-weight: 800; margin-top: 10px; }
.polmetek-opis { font-size: 0.95rem; color: var(--grigio); line-height: 1.55; margin-top: 8px; }
.polmetek-akcje { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 22px; }
.polmetek-btn { margin: 0; font-size: 1.05rem; padding: 12px 26px; }
.polmetek-hint { font-size: 0.74rem; color: var(--muted-light); margin-top: 10px; }
/* ZAMROŻENIE PLANSZY NA WEJŚCIU (planszaZamroz w JS): przez pierwszą sekundę przyciski są głuche i przygaszone,
   a z każdego zsuwa się w prawo zasłona w barwie tła planszy (--plansza-tlo) przez --zamrozenie-ms - przycisk
   „wypełnia się” kolorem od lewej i widać, kiedy zacznie działać. Zasłona, a nie opacity samego przycisku, bo
   przezroczystości nie da się odsłaniać kawałkami. pointer-events to druga warstwa obok strażnika w JS. */
.polmetek { --plansza-tlo: var(--card-bg); }
.polmetek.polowa { --plansza-tlo: #2463E9; }
.polmetek.rekord { --plansza-tlo: var(--zolty); }
.polmetek.combo { --plansza-tlo: var(--nak-kolor, #2463E9); }
.polmetek.brawo, .polmetek.cel-slowek { --plansza-tlo: var(--zolty); }
.polmetek.cel-slowek.koniec { --plansza-tlo: #35A64D; }
.polmetek.zamrozona .polmetek-btn, .polmetek.zamrozona .cs-nie { pointer-events: none; }
.polmetek.zamrozona .polmetek-btn { position: relative; overflow: hidden; }
.polmetek.zamrozona .polmetek-btn::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: color-mix(in srgb, var(--plansza-tlo) 58%, transparent);
  transform-origin: right center;
  animation: planszaOdmrazanie var(--zamrozenie-ms, 1s) linear forwards;
}
@keyframes planszaOdmrazanie { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.polmetek.zamrozona .cs-nie { opacity: 0.4; }
/* Zasłona to WSKAŹNIK POSTĘPU („za chwilę zadziała”), nie ozdoba - przy ograniczonym ruchu zsuwa się tak samo, jak pasek
   odliczania panelu combo niżej i PasekCzasu quizu w aplikacji (tam ta sama zasłona, useZamrozenie). */
/* Statystyka poziomu na 100%: co szło najgorzej. Lewe wyrównanie w środku wyśrodkowanej
   nakładki - lista słówek czytana od lewej, jak każda lista; sumy w jednej linii nad nią. */
.polmetek-staty {
  margin: 14px auto 0; text-align: left; max-width: 400px;
  background: var(--bg-soft); border: 1px solid var(--border-2); border-radius: 14px;
  padding: 10px 14px; font-size: 0.86rem; line-height: 1.5;
}
.polmetek-staty.hidden { display: none; }
.polmetek-staty .ps-suma { color: var(--grigio); font-weight: 600; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.polmetek-staty .ps-naglowek { font-weight: 800; margin: 8px 0 3px; }
.polmetek-staty .ps-czysto { margin-top: 6px; color: var(--verde); font-weight: 700; display: flex; gap: 6px; align-items: center; }
.polmetek-staty ol { margin: 0; padding-left: 20px; }
.polmetek-staty li { margin: 2px 0; }
.polmetek-staty li small { color: var(--grigio); }
.polmetek-staty li span { color: var(--rosso); font-weight: 700; white-space: nowrap; margin-left: 4px; }

/* CEL DNIA (słówka) - plansza wejściowa i zakończenie w miejscu karty: ta sama nakładka co
   półmetek, bursztynowy akcent zamiast zieleni. Karty ze słówkami wjeżdżają od lewej jedna po
   drugiej (opóźnienie z --i), z przestrzeleniem i lekkim obrotem - „uderzenie", nie przenikanie;
   plansza drga przy każdym lądowaniu (klasa .huk dokładana z JS w rytm opóźnień). */
/* Treść od góry i przewijana, nie wyśrodkowana: z ilustracją nad kartami (zakończenie) plansza bywa wyższa niż
   miejsce karty, a wyśrodkowanie wypychało celownik ponad ramkę i podpowiedź pod nią (zmierzone na zakończeniu,
   gdy nad kartami stała jeszcze postać z konsoli). ::before bez ujemnego inset - przy overflow:auto dodawałby przewijanie. */
.polmetek.cel-slowek { --cs-akcent: #D97706; box-shadow: inset 0 0 0 2px var(--cs-akcent);
  align-items: flex-start; overflow-y: auto; padding: 28px 24px 22px; }
.polmetek.cel-slowek::before { inset: 0; background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--cs-akcent) 22%, transparent) 0, transparent 55%); }
.polmetek.cel-slowek .polmetek-tresc { max-width: 580px; width: 100%; margin: auto 0; }
.polmetek.cel-slowek.koniec .cs-karty { margin: 12px 0 4px; gap: 10px 8px; }
.polmetek.cel-slowek.koniec .cs-karta { width: 140px; min-height: 0; padding: 12px 8px 8px; }
/* PÓŁKA 3D na przycisku planszy - ta sama, co pod „Sprawdź" quizu i ocenami fiszki (.ocena-btn):
   bok 4 px w ciemniejszym odcieniu, :active wciska o 3 px. Selektor z .cel-slowek, bo .btn:hover
   stoi w pliku PÓŹNIEJ i przy równej specyficzności zamieniałby półkę na zwykły rozmyty cień. */
.polmetek.cel-slowek .cs-glowny {
  --polka-kolor: var(--verde);
  margin-bottom: 4px;
  transition: background 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 8px 12px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
.polmetek.cel-slowek .cs-glowny:hover {
  transform: none;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 8px 12px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
.polmetek.cel-slowek .cs-glowny:active:not(:disabled) {
  transform: translateY(3px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 2px 4px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
.polmetek.cel-slowek.huk .polmetek-tresc { animation: csHuk 0.18s ease-out; }
@keyframes csHuk { 0% { transform: none; } 30% { transform: translate(-3px, 2px); } 60% { transform: translate(3px, -1px); } 100% { transform: none; } }
.cs-ikona { font-size: 2.1rem; line-height: 1; color: var(--cs-akcent); }
.cs-karty { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 10px; margin: 18px 0 6px; }
.cs-karta {
  --i: 0;
  width: 156px; min-height: 92px; padding: 14px 10px 10px; box-sizing: border-box; position: relative;
  background: var(--bg-soft); border: 1px solid var(--border-2); border-radius: 14px; text-align: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
  animation: csWjazd 0.55s cubic-bezier(0.22, 1.5, 0.36, 1) both;
  animation-delay: calc(var(--i) * 170ms);
}
.cs-karta.zaliczone { border-color: var(--verde); box-shadow: inset 0 0 0 2px var(--verde), 0 6px 18px rgba(0, 0, 0, 0.08); }
.cs-karta .cs-slowo { font-weight: 800; font-size: 1.05rem; line-height: 1.2; word-break: break-word; }
.cs-karta .cs-tlum { color: var(--grigio); font-size: 0.86rem; margin-top: 4px; line-height: 1.3; word-break: break-word; }
.cs-karta .cs-poziom {
  position: absolute; top: -9px; left: 50%; transform: translateX(-50%);
  font-size: 0.64rem; font-weight: 800; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  background: var(--card-bg); border: 1px solid var(--border-2); color: var(--grigio);
}
.cs-karta .cs-poziom.latwe   { color: var(--verde); border-color: var(--verde); }
.cs-karta .cs-poziom.srednie { color: var(--cs-akcent); border-color: var(--cs-akcent); }
.cs-karta .cs-poziom.trudne  { color: var(--rosso); border-color: var(--rosso); }
.cs-karta .cs-fajka { position: absolute; top: 6px; right: 8px; color: var(--verde); font-size: 1rem; }
@keyframes csWjazd {
  0%   { transform: translateX(-140%) rotate(-14deg) scale(0.7); opacity: 0; }
  60%  { transform: translateX(6%) rotate(3deg) scale(1.06); opacity: 1; }
  100% { transform: none; opacity: 1; }
}
.cs-nie { background: none; border: 0; color: var(--muted-light); font-size: 0.8rem; margin-top: 8px; cursor: pointer;
  text-decoration: underline dotted; padding: 4px 8px; font-family: inherit; }
/* BLOKADA NA WJAZD KART: od 2026-09-27 wspólne zamrożenie plansz (.polmetek.zamrozona przy .polmetek-hint wyżej) -
   przyciski głuche i przygaszone, dopóki karty nie wylądują, a stuknięcie z poprzedniego ekranu przechodzi obok. */
.polmetek.cel-slowek .cs-glowny, .cs-nie { transition: background 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease, opacity 0.25s ease; }
.cs-nie:hover { color: var(--grigio); }
.cs-nie.hidden { display: none; }
/* Chip „powtórka celu” nad pytaniem w ZWYKŁYM quizie (słówko z celu sprzed 1–2 dni). */
.quiz-cel-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 0.74rem; font-weight: 700;
  color: #D97706; background: color-mix(in srgb, #D97706 12%, transparent); border-radius: 999px;
  padding: 3px 10px; margin: -14px 0 14px; }
.quiz-cel-chip.hidden { display: none; }
/* Plakietka „premium" / „quiz dla konta premium" przy pytaniach głosowych. Stoi w tej samej linii co
   odznaka testu (oba są inline-flex), więc na wąskim ekranie zawija się pod nią zamiast ją ściskać. */
.quiz-premium-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 0.7rem; font-weight: 800;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--oro); background: var(--bg-gold-soft);
  border: 1px solid color-mix(in srgb, var(--oro) 35%, transparent); border-radius: 999px;
  padding: 3px 10px; margin: -14px 0 14px 8px; line-height: 1.3; font-family: inherit; }
.quiz-premium-chip.hidden { display: none; }
button.quiz-premium-chip { cursor: pointer; text-transform: none; letter-spacing: 0; font-weight: 700; }
button.quiz-premium-chip:hover { background: color-mix(in srgb, var(--oro) 20%, transparent); }
button.quiz-premium-chip:focus-visible { outline: 2px solid var(--oro); outline-offset: 2px; }
/* Pasek po serii zajawki w podsumowaniu quizu (POPUPY_ADMIN 'quiz_premium_zajawka'). */
.quiz-zajawka-pasek { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; text-align: left;
  margin: 14px 0 2px; padding: 12px 14px; border-radius: 14px; background: var(--bg-gold-soft);
  border: 1px solid color-mix(in srgb, var(--oro) 30%, transparent); }
.quiz-zajawka-pasek > .ico { font-size: 1.3rem; color: var(--oro); margin-right: 0; }
.qzp-tekst { flex: 1 1 200px; display: flex; flex-direction: column; gap: 3px; font-size: 0.85rem; color: var(--testo); }
.qzp-tekst b { font-weight: 800; }
.quiz-zajawka-pasek .qzp-cta { width: auto; flex: 0 0 auto; margin: 0; padding: 8px 16px; font-size: 0.85rem; }
/* Historia celów (Ustawienia -> Historia): wiersz = data, status, pasek, słówka, przycisk. */
.csh-wiersz { border: 1px solid var(--border-2); border-radius: 14px; padding: 12px 14px; margin-bottom: 10px; background: var(--bg-soft); }
.csh-naglowek { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 0.9rem; }
.csh-status { font-size: 0.68rem; font-weight: 800; padding: 2px 8px; border-radius: 999px; background: var(--card-bg); border: 1px solid var(--border-2); color: var(--grigio); text-transform: uppercase; letter-spacing: 0.03em; }
.csh-status.ukonczony { color: var(--verde); border-color: var(--verde); }
.csh-status.aktywny { color: #D97706; border-color: #D97706; }
.csh-pct { margin-left: auto; font-weight: 800; font-size: 0.82rem; color: var(--grigio); }
.csh-pasek { height: 6px; border-radius: 999px; background: var(--card-bg); border: 1px solid var(--border-2); margin: 8px 0; overflow: hidden; }
.csh-pasek > div { height: 100%; background: var(--marka-zielony); border-radius: 999px; transition: width 0.4s; }
.csh-slowka { display: flex; flex-wrap: wrap; gap: 6px; }
.csh-slowo { font-size: 0.8rem; padding: 3px 9px; border-radius: 999px; background: var(--card-bg); border: 1px solid var(--border-2); color: var(--grigio); }
.csh-slowo b { color: var(--testo); }
.csh-slowo.ok { border-color: var(--verde); }
.csh-slowo.ok .ico { color: var(--verde); }
.csh-slowo.brak { opacity: 0.55; text-decoration: line-through; }
.csh-btn { width: auto; margin: 10px 0 0; font-size: 0.85rem; padding: 7px 14px; }
@media (max-width: 600px) { .cs-karta { width: calc(50% - 5px); } }
@media (prefers-reduced-motion: reduce) { .cs-karta { animation: none; } .polmetek.cel-slowek.huk .polmetek-tresc { animation: none; } }
/* NOWY REKORD COMBO - ta sama nakładka, inna paleta (złoto zamiast zieleni) i więcej huku:
   wolno obracające się promienie, biały błysk na wjeździe liczby, liczba pulsuje, pioruny
   combo po bokach. Wyłącznie transform/opacity - żadnego filter na animowanym tekście
   (lekcja z banera combo: filter przeliczany co klatkę ciął klatki). */
.polmetek.rekord { background: color-mix(in srgb, #F59E0B 16%, var(--card-bg)); box-shadow: inset 0 0 0 3px #F59E0B; }
.polmetek.rekord::before { background: radial-gradient(circle at 50% 45%, rgba(245, 158, 11, 0.38) 0, transparent 55%); }
.polmetek.rekord::after {
  content: ''; position: absolute; inset: -60%;
  background: repeating-conic-gradient(from 0deg at 50% 50%, rgba(245, 158, 11, 0.18) 0deg 10deg, transparent 10deg 30deg);
  animation: rekordPromienie 16s linear infinite; pointer-events: none;
}
@keyframes rekordPromienie { to { transform: rotate(360deg); } }
.polmetek.rekord .polmetek-tresc { z-index: 1; }
.polmetek.rekord .polmetek-pct {
  color: #F59E0B; text-shadow: 0 6px 24px rgba(245, 158, 11, 0.5);
  animation: rekordPuls 0.8s ease-in-out infinite alternate;
}
@keyframes rekordPuls { from { transform: scale(1); } to { transform: scale(1.07); } }
.rekord-blysk { position: absolute; inset: 0; z-index: 2; background: #fff; pointer-events: none; animation: rekordBlysk 0.75s ease-out forwards; }
@keyframes rekordBlysk { from { opacity: 0.9; } to { opacity: 0; } }
.rekord-piorun {
  position: absolute; top: 50%; z-index: 1; width: 46px; height: 62px; margin-top: -31px;
  color: var(--nak-kolor, #F59E0B); pointer-events: none; animation: rekordPiorun 0.7s ease-in-out infinite alternate;
}
.rekord-piorun svg { width: 100%; height: 100%; }
.rekord-piorun.lewy { left: 5%; }
.rekord-piorun.prawy { right: 5%; transform: scaleX(-1); }
@keyframes rekordPiorun { from { opacity: 0.45; } to { opacity: 1; } }
/* Na waskim ekranie pioruny wchodzily na tekst opisu (zrzut z panelu 2026-09-07) - ida wyzej,
   obok liczby, i mniejsze. */
@media (max-width: 600px) { .rekord-piorun { top: 34%; width: 34px; height: 46px; margin-top: -23px; } }

/* PANEL PROGU SERII (5 i 10 z rzędu) - krótka nakładka w barwie progu (--nak-kolor ustawia JS z COMBO_PANEL_BARWY:
   niebieski przy 5, czerwony przy 10; wygląd planszy marki w sekcji „PANEL COMBO W BARWACH MARKI” niżej). Sama znika:
   pasek pod przyciskiem kurczy się przez czas autoprzewijania (--auto-ms), żeby było widać, że zaraz pójdzie dalej. */
.polmetek.combo { background: color-mix(in srgb, var(--nak-kolor, #8B5CF6) 14%, var(--card-bg)); box-shadow: inset 0 0 0 3px var(--nak-kolor, #8B5CF6); }
.polmetek.combo::before { background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--nak-kolor, #8B5CF6) 32%, transparent) 0, transparent 55%); }
.polmetek.combo .polmetek-pct { color: var(--nak-kolor, #8B5CF6); text-shadow: 0 6px 24px color-mix(in srgb, var(--nak-kolor, #8B5CF6) 45%, transparent); }
.polmetek.auto .polmetek-tresc::after {
  content: ''; display: block; height: 4px; width: 56%; margin: 14px auto 0; border-radius: 999px;
  background: var(--nak-kolor, var(--verde)); transform-origin: left center;
  animation: polmetekOdliczanie var(--auto-ms, 5s) linear forwards;
}
@keyframes polmetekOdliczanie { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Trzęsienie ziemi: cała treść strony drży przez niecałą sekundę (patrz trzesienieZiemi w JS).
   Klasa ląduje na kontenerze treści, NIE na body - transform na body zmieniłby punkt
   odniesienia elementów position: fixed (nagłówek, powiadomienia) i te skoczyłyby na górę
   dokumentu na czas animacji. */
@keyframes trzesienieZiemi {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  10% { transform: translate(-10px, 5px) rotate(-0.7deg); }
  20% { transform: translate(9px, -6px) rotate(0.6deg); }
  30% { transform: translate(-8px, 4px) rotate(-0.5deg); }
  40% { transform: translate(8px, -4px) rotate(0.4deg); }
  50% { transform: translate(-6px, 4px) rotate(-0.3deg); }
  60% { transform: translate(5px, -2px) rotate(0.25deg); }
  70% { transform: translate(-4px, 2px) rotate(-0.15deg); }
  80% { transform: translate(2px, -1px) rotate(0.1deg); }
  90% { transform: translate(-1px, 1px) rotate(0); }
}
.trzesienie-ziemi { animation: trzesienieZiemi 0.9s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@media (prefers-reduced-motion: reduce) {
  .trzesienie-ziemi, .polmetek::before, .polmetek.wjazd .polmetek-tresc,
  .polmetek.rekord::after, .polmetek.rekord .polmetek-pct, .rekord-piorun, .rekord-blysk { animation: none; }
}

/* Rozsypanka literowa: wielkie odliczanie 3-2-1 na środku, potem kafelki liter
   i pasek 6 sekund (współdzielony .pf-czas wyżej). */
.anagram-karta { text-align: center; }
.anagram-odliczanie {
  font-size: 4.6rem; font-weight: 900; color: var(--primary); padding: 38px 0;
  line-height: 1;
}
.anagram-odliczanie.puls, .anagram-odliczanie { animation: anagramPuls 0.7s ease; }
@keyframes anagramPuls { 0% { transform: scale(1.35); opacity: 0.35; } 70% { transform: scale(1); opacity: 1; } }
.anagram-litery {
  display: flex; gap: 6px; justify-content: center; align-items: center; flex-wrap: wrap;
  margin: 8px 0 4px;
}
.anagram-litera {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 44px; padding: 0 7px; background: var(--bg-soft);
  border: 1px solid var(--border-2); border-radius: 11px;
  font-size: 1.35rem; font-weight: 800;
}
.anagram-przedrostek { font-size: 1.2rem; font-weight: 800; color: var(--grigio); margin-right: 5px; }
.anagram-definicja { font-size: 1.35rem; font-weight: 800; margin: 4px 0 2px; }
.anagram-litera.klik { cursor: pointer; font: inherit; font-size: 1.35rem; font-weight: 800; transition: var(--transition); }
.anagram-litera.klik:hover { transform: translateY(-2px); border-color: var(--primary); }
.anagram-litera.zuzyta { visibility: hidden; }
.anagram-litera.klaw-wybor { outline: 3px solid var(--oro); outline-offset: 3px; }
.anagram-litera.ulozona { background: var(--bg-success-soft); border-color: var(--verde); }
.anagram-odpowiedz { min-height: 48px; margin-top: 2px; }
.anagram-slot {
  display: inline-flex; min-width: 34px; height: 44px;
  border: 2px dashed var(--border-2); border-radius: 11px; background: transparent;
}
/* ZAMROŻENIE NA START. Pytanie wchodzi zaraz po kliknięciu „Dalej" w poprzednim kroku -
   kciuk bywa jeszcze w drodze i drugie tknięcie w to samo miejsce trafiało w ✓/✕, zanim
   ktokolwiek zdążył przeczytać parę. Przez pierwszą sekundę przyciski są więc martwe,
   a ODLICZANIE STOI: trzy sekundy na decyzję ruszają dopiero po zamrożeniu, więc blokada
   nie zabiera czasu na odpowiedź (patrz PF_ZAMROZENIE_MS).
   pointer-events, a nie `disabled`: przyciski mają onclick w znaczniku i zostają w układzie
   dokładnie tam, gdzie były - nic nie drga w chwili odmrożenia. */
.pf-przyciski.zamrozone { pointer-events: none; }

/* --- Znajdź intruza --- */
.intruz-siatka { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (max-width: 420px) { .intruz-siatka { grid-template-columns: 1fr; } }
.intruz-opcja {
  padding: 18px 12px; border-radius: 14px; cursor: pointer;
  border: 2px solid var(--border-warm); background: var(--card-bg);
  font: inherit; font-size: 1.05rem; font-weight: 700; color: var(--testo);
  transition: var(--transition);
}
.intruz-opcja:hover { border-color: var(--oro); transform: translateY(-2px); }
.intruz-siatka.zablokowane .intruz-opcja { cursor: default; transform: none; }
.intruz-opcja.poprawna { border-color: var(--zielen-gleboka); background: var(--bg-success-soft); }
.intruz-opcja.bledna   { border-color: var(--rosso); background: var(--bg-error-soft); }
.intruz-opcja small { display: block; font-size: 0.72rem; font-weight: 600; color: var(--grigio); margin-top: 3px; }

/* Wyjście z pytań na słuch. Dyskretne - to furtka na "jestem w pociągu", nie zachęta. */
.bez-audio-btn {
  display: block; margin: 8px auto 0; cursor: pointer;
  border: none; background: transparent; color: var(--grigio);
  font: inherit; font-size: 0.74rem; font-weight: 600; text-decoration: underline;
  text-underline-offset: 3px; padding: 4px 8px; border-radius: 8px;
}
.bez-audio-btn:hover { color: var(--testo); background: var(--crema); text-decoration: none; }
/* Ten sam napis pod polem odpowiedzi. Odstęp daje już gap kolumny, więc własny margines
   zerujemy - inaczej „nie wiem" odjeżdża od przycisku na dwie odległości naraz. */
.mini-exam-input-row .quiz-nie-wiem { margin-top: 0; }

/* Rozwijane metody dodawania słówek. Zwinięty panel zostaje w drzewie (display:none psułoby
   animację), ale nie łapie kliknięć ani tabulatora. */
.metoda-panel {
  overflow: hidden; max-height: 0; opacity: 0;
  transition: max-height 0.3s cubic-bezier(.22,1,.36,1), opacity 0.22s ease;
}
.metoda-panel.otwarty { opacity: 1; }
.metoda-panel:not(.otwarty) { visibility: hidden; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .metoda-panel { transition: none; } }

/* Koło form zeszło 2026-10-03 (kanwa „Uzupełnij zdanie”): formy to kafle w siatce, wygląd w sekcji 16 (.quiz-kafel). */

/* --- Tabela odmiany: nagłówek kroku quizu (stary układ, używany w modalu) --- */
.odmiana-podpowiedz { font-size: 0.72rem; color: var(--grigio); margin-top: 8px; }


.mail-status {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 0.7rem; font-weight: 800; white-space: nowrap;
}
.mail-status.ok   { background: var(--bg-success-soft); color: var(--zielen-gleboka); }
.mail-status.blad { background: var(--bg-error-soft);   color: var(--rosso); }
/* Ani zielony, ani czerwony - bo to ani wysylka, ani awaria: wiadomosc leży w pliku na
   maszynie deweloperskiej (patrz send_email w mailer.php). Zielony klamalby, ze ktos ja
   dostal, czerwony kazalby szukac usterki, ktorej nie ma. */
.mail-status.lokalnie { background: var(--bg-warning-soft, #FEF3C7); color: #92400E; }
.mail-rodzaj { font-size: 0.72rem; font-weight: 700; color: var(--grigio); }
.mail-blad { display: block; font-size: 0.72rem; color: var(--rosso); margin-top: 2px; }

.usun-jezyk-lista li.zostaje { color: var(--grigio); font-size: 0.78rem; border-top: 1px solid var(--border-2); margin-top: 6px; padding-top: 6px; }
.header-lang-item.active { background: var(--bg-gold-soft); color: var(--testo); cursor: default; }
.header-lang-divider { height: 1px; background: var(--border-warm-soft); margin: 6px 4px; }
.header-lang-add {
  display: flex; align-items: center; gap: 7px; padding: 7px 10px;
  border-radius: 8px; cursor: pointer; color: var(--testo); font-size: 0.8rem;
  white-space: nowrap;
}
.header-lang-add:hover { background: var(--crema); }
.header-lang-picker {
  max-height: 200px; overflow-y: auto; margin: 3px -1px -1px;
}
/* #headerLangSwitcher (i cały dropdown) siedzi wewnątrz .header-title w HTML - bez tego
   ".header-title span { font-size: 2rem; }" (myślana wyłącznie dla logo "Lingaria.com")
   nadpisywała rozmiar KAŻDEGO spana w dropdownie, bo bezpośrednia reguła zawsze wygrywa
   z dziedziczeniem, niezależnie od tego, co ustawię na .header-lang-menu wyżej. */
.header-lang-menu span { font-size: inherit; }

/* ===== NAWIGACJA TRYBÓW ===== */
.mode-tabs {
  display: flex;
  gap: 6px;
  background: var(--bg-soft);
  padding: 5px;
  border-radius: 50px;
}
.mode-tab {
  padding: 8px 20px;
  border-radius: 50px;
  border: none;
  background: transparent;
  color: var(--grigio);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
  white-space: nowrap;
}
.mode-tab:hover { background: var(--border); color: var(--testo); }
.mode-tab.locked { opacity: 0.55; cursor: not-allowed; }
.mode-tab.locked:hover { background: transparent; color: var(--grigio); }
.mode-tab.locked::after { content: ' 🔒'; }
/* Aktywna zakładka wypełniona akcentem, a nie kolorem karty: --card-bg i --bg-soft
   w trybie ciemnym mają DOKŁADNIE tę samą wartość (#1E293B), więc "biały pill na szarym
   pasku" był tam po prostu niewidoczny. Wypełnienie akcentem czyta się w obu motywach. */
.mode-tab.active { background: var(--oro); color: var(--na-akcencie); box-shadow: 0 2px 10px color-mix(in srgb, var(--oro) 34%, transparent); }
.mode-tab.active:hover { background: var(--oro); color: var(--na-akcencie); }

/* =========================================================
   STRONA GŁÓWNA (to, co widzi ktoś BEZ konta)
   =========================================================
   Plansza „Strona główna - desktop" (Alek, 2026-09-26): ta sama paleta i te same kroje, co
   aplikacja mobilna i nowy lejek - granat #17183B, niebieski #2463E9, żółty #FFC83D, czerwony
   #DB2727 i zielony #35A64D z logo, nagłówki Outfit 800, tekst Figtree. Formularz logowania
   nie stoi na środku ekranu, tylko w oknie (#authModal) - pierwsza rzecz, jaką widzi ktoś,
   kto jeszcze nie wie, czy chce tu zostać, nie może być polem na hasło.

   DWA RODZAJE BARW i to jest cała obsługa motywów:
   - --lp-tlo, --lp-tekst, --lp-karta, --lp-linia… odwracają się w ciemnym motywie (bloki niżej,
     tym samym mechanizmem co paleta aplikacji: prefers-color-scheme ALBO data-theme="dark");
   - barwy marki (niebieskie hero, żółte pasy, granatowa metoda, kolorowe karty trybów, zielona
     karta na końcu, granatowa stopka) są STAŁE - marka nie zmienia koloru razem z motywem,
     a biały napis na niebieskim jest czytelny w obu.
   Stary zestaw tokenów aplikacji (--verde, --crema…) nie jest tu używany: ma zielony akcent
   i granat #0F172A, których na planszy nie ma. */
.auth-screen {
  position: relative; z-index: 3000;
  background: var(--lp-tlo);
  --lp-max: 1200px;
  --lp-granat: #17183B;
  --lp-granat-2: #24265A;      /* kafle kroków na granatowej sekcji */
  --lp-granat-kreska: #2E3068; /* kreska w stopce i obwódki na granacie */
  --lp-niebieski: #2463E9;
  --lp-niebieski-2: #204EB8;
  --lp-zolty: #FFC83D;
  --lp-czerwony: #DB2727;
  --lp-zielony: #35A64D;
  --lp-lawenda: #C9CAE8;       /* drugi tekst na granacie */
  --lp-font: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --lp-font-nag: 'Outfit', 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --lp-pion: clamp(64px, 7.2vw, 104px);  /* pionowy oddech sekcji: 104 px na planszy */
  --lp-tlo: #FFFFFF;
  --lp-tlo-2: #F3F5FB;
  --lp-karta: #FFFFFF;
  --lp-tekst: #17183B;
  --lp-tekst-2: #4A4B6B;
  --lp-tekst-3: #6B6D8A;
  --lp-linia: #E3E4EF;
  --lp-szary: #9A9CB8;
  --lp-mocna: #17183B;          /* obrys „Zaloguj się", otwarte pytanie, hover kart */
  --lp-akcent-tekst: #204EB8;   /* hover pozycji menu */
  --lp-obwodka-granat: transparent;
  /* Granatowa pigułka z żółtym kółkiem. W ciemnym motywie granat na granatowym tle znika,
     więc przechodzi w wariant „na granacie" z planszy: żółta pigułka, granatowe kółko. */
  --lp-cta-tlo: #17183B; --lp-cta-tekst: #FFFFFF; --lp-cta-kolko: #FFC83D; --lp-cta-strzalka: #17183B;
  --lp-tag-tlo: #D9F0DE; --lp-tag-tekst: #1F7A35;
  --lp-cien-karty: 0 22px 40px -26px rgba(23, 24, 59, 0.5);
}
/* Ciemny motyw. Tło granatowe zamiast grafitowego #0F172A aplikacji: strona ma granatowe
   sekcje marki i stopkę, a grafit obok granatu czytał się jak dwie różne strony sklejone
   w jedną. Tekst jasny z lawendowym drugim planem - ten sam, co na granacie w jasnym motywie. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .auth-screen {
    --lp-tlo: #111230; --lp-tlo-2: #0B0C24; --lp-karta: #1B1D45;
    --lp-tekst: #F3F5FB; --lp-tekst-2: #C9CAE8; --lp-tekst-3: #A3A5C6;
    --lp-linia: #2E3068; --lp-szary: #5E608F; --lp-mocna: #F3F5FB; --lp-akcent-tekst: #FFC83D;
    --lp-obwodka-granat: #2E3068;
    --lp-cta-tlo: #FFC83D; --lp-cta-tekst: #17183B; --lp-cta-kolko: #17183B; --lp-cta-strzalka: #FFC83D;
    --lp-tag-tlo: rgba(53, 166, 77, 0.22); --lp-tag-tekst: #8CD9A0;
    --lp-cien-karty: 0 22px 40px -26px rgba(0, 0, 0, 0.9);
  }
}
:root[data-theme="dark"] .auth-screen {
  --lp-tlo: #111230; --lp-tlo-2: #0B0C24; --lp-karta: #1B1D45;
  --lp-tekst: #F3F5FB; --lp-tekst-2: #C9CAE8; --lp-tekst-3: #A3A5C6;
  --lp-linia: #2E3068; --lp-szary: #5E608F; --lp-mocna: #F3F5FB; --lp-akcent-tekst: #FFC83D;
  --lp-obwodka-granat: #2E3068;
  --lp-cta-tlo: #FFC83D; --lp-cta-tekst: #17183B; --lp-cta-kolko: #17183B; --lp-cta-strzalka: #FFC83D;
  --lp-tag-tlo: rgba(53, 166, 77, 0.22); --lp-tag-tekst: #8CD9A0;
  --lp-cien-karty: 0 22px 40px -26px rgba(0, 0, 0, 0.9);
}

/* =========================================================================================
   RUCH STRONY GŁÓWNEJ - odsłony przy przewijaniu i światło pod kursorem.
   =========================================================================================
   Wszystko pod bramką html.lp-ruch (patrz skrypt w <head>): tylko precyzyjny kursor, tylko
   bez prefers-reduced-motion. Bez tej klasy strona jest w 100% statyczna - robot wyszukiwarki
   i telefon dostają pełną treść bez żadnego stanu przejściowego.

   Lista odsłanianych elementów MUSI być ta sama, co w silniku w JS (szukaj „RUCH STRONY
   GŁÓWNEJ - silnik"): element ukryty tutaj, a nieznany silnikowi, zostałby przezroczysty na
   zawsze. Animowane są WYŁĄCZNIE transform i opacity (kompozytor; zero przeliczeń układu).
   Światło zostało tylko na BIAŁYCH kartach (artykuły, zestawy): na kolorowych kartach trybów
   poświata w innej barwie brudziła kolor marki. */
html.lp-ruch :is(.lp-sek-glowa, .lp-tryb, .lp-upusc, .lp-krok, .lp-art, .lp-art-wszystkie, .lp-zestaw2, .lp-nowosci-info, .lp-plan, .lp-faq-poz):not(.lp-widoczne) {
  opacity: 0;
  transform: translateY(18px);
}
html.lp-ruch :is(.lp-sek-glowa, .lp-tryb, .lp-upusc, .lp-krok, .lp-art, .lp-art-wszystkie, .lp-zestaw2, .lp-nowosci-info, .lp-plan, .lp-faq-poz) {
  transition: opacity 0.55s ease, transform 0.55s cubic-bezier(.22,1,.36,1), box-shadow 0.2s ease;
}
/* Sąsiedzi w siatkach wchodzą jeden po drugim - pół uderzenia różnicy, nie sekwencja. */
html.lp-ruch :is(.lp-tryby-siatka, .lp-metoda-kroki, .lp-art-siatka, .lp-zestawy2, .lp-cennik) > :nth-child(2) { transition-delay: 0.07s; }
html.lp-ruch :is(.lp-tryby-siatka, .lp-metoda-kroki, .lp-art-siatka, .lp-zestawy2, .lp-cennik) > :nth-child(3) { transition-delay: 0.14s; }
html.lp-ruch :is(.lp-tryby-siatka, .lp-metoda-kroki, .lp-art-siatka, .lp-zestawy2, .lp-cennik) > :nth-child(n+4) { transition-delay: 0.21s; }
/* ŚWIATŁO POD KURSOREM. Pozycję podaje JS zmiennymi --mx/--my (jeden delegowany nasłuch,
   dawkowany rAF-em). ::after ma stałe rozmiary i rysuje się na kompozytorze: zmienia się tylko
   pozycja gradientu i opacity. pointer-events: none, żeby poświata nie zasłaniała odnośnika. */
html.lp-ruch :is(.lp-art, .lp-zestaw2) { position: relative; }
html.lp-ruch :is(.lp-art, .lp-zestaw2)::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0; transition: opacity 0.25s ease;
  background: radial-gradient(190px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--lp-niebieski) 11%, transparent), transparent 68%);
}
html.lp-ruch :is(.lp-art, .lp-zestaw2).lp-swiatlo::after { opacity: 1; }

/* --- wspólne cegiełki --- */
/* PŁYNNE PRZEWIJANIE DO KOTWIC („Jak to działa", „Ucz się"). scroll-padding-top: nagłówek jest
   position:sticky, więc bez tego docelowa sekcja lądowała pod nim i pierwsze, co widać po
   skoku, to jej ucięty tytuł. Wyłączone przy prefers-reduced-motion. */
html { scroll-padding-top: 84px; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

.lp-header, .lp-sek { font-family: var(--lp-font); color: var(--lp-tekst); }
.lp-kontener { width: min(var(--lp-max), 100% - 48px); margin-inline: auto; }
.lp-sek-srodek { display: flex; flex-direction: column; gap: 40px; padding-block: var(--lp-pion); }
.lp-sek--biala { background: var(--lp-tlo); }
.lp-sek--szara { background: var(--lp-tlo-2); }
.lp-sek--granat { background: var(--lp-granat); color: #FFFFFF; }
.lp-sek--zolta { background: var(--lp-zolty); color: var(--lp-granat); }

.lp-h1, .lp-h2 {
  margin: 0; font-family: var(--lp-font-nag); font-weight: 800; text-wrap: balance;
}
.lp-h2 { font-size: clamp(2.1rem, 1.2rem + 2.6vw, 3.25rem); line-height: 1.02; letter-spacing: -0.03em; color: inherit; }
.lp-h2--duzy { font-size: clamp(2.3rem, 1.2rem + 3.2vw, 3.75rem); line-height: 1; }
.lp-sek-glowa { display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; }
/* Wąska kolumna nagłówka tylko przy trybach, jak na planszy: tam obok stoi akapit. „Artykuły"
   i „Najczęściej zadawane pytania" mają się zmieścić w jednym wierszu. */
.lp-tryby .lp-sek-glowa > .lp-h2 { max-width: 40rem; }
.lp-sek-glowa--srodek { justify-content: center; text-align: center; }
.lp-sek-glowa--kolumna { flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: 22px; }
.lp-sek-glowa-tekst { display: flex; flex-direction: column; gap: 14px; max-width: 44rem; }
.lp-sek-opis { margin: 0; max-width: 26rem; font-size: 17px; font-weight: 500; line-height: 1.55; color: var(--lp-tekst-2); }
.lp-sek-glowa-tekst .lp-sek-opis { max-width: none; }
.lp-pigulka {
  align-self: flex-start; display: inline-flex; align-items: center;
  min-height: 28px; padding: 0 12px; border-radius: 999px;
  background: #FFFFFF; color: var(--lp-granat); font-size: 13px; font-weight: 800; line-height: 1;
}
/* Flagi są rysowane (flaga_svg), a nie emotką - ten sam powód, co w aplikacji: Windows
   nie ma emoji flag w żadnym systemowym foncie. */
.lp-flaga-svg { border-radius: 4px; display: block; flex: none; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08); }
.lp-strzalka { display: block; }
[dir="rtl"] .lp-strzalka { transform: scaleX(-1); }

/* GŁÓWNY PRZYCISK PLANSZY: pigułka z napisem po lewej i kółkiem ze strzałką po prawej.
   Barwy przez zmienne wariantu, rozmiar przez zmienne rozmiaru - jeden przepis na siedem
   przycisków w czterech kolorach. */
.lp-cta {
  --cta-tlo: var(--lp-cta-tlo); --cta-tekst: var(--lp-cta-tekst);
  --cta-kolko: var(--lp-cta-kolko); --cta-strzalka: var(--lp-cta-strzalka);
  --cta-wys: 58px; --cta-kolko-r: 44px; --cta-font: 17px;
  display: inline-flex; align-items: center; justify-content: space-between; gap: 18px;
  min-height: var(--cta-wys); padding-block: 0; padding-inline: 26px 7px; box-sizing: border-box;
  border: 0; border-radius: 999px; background: var(--cta-tlo); color: var(--cta-tekst);
  font-family: var(--lp-font); font-size: var(--cta-font); font-weight: 800; line-height: 1.2;
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.lp-cta:hover { color: var(--cta-tekst); transform: translateY(-1px); box-shadow: 0 12px 26px -12px rgba(23, 24, 59, 0.6); }
.lp-cta:focus-visible { outline: 3px solid var(--lp-niebieski); outline-offset: 3px; }
.lp-cta-kolko {
  width: var(--cta-kolko-r); height: var(--cta-kolko-r); flex: none; border-radius: 999px;
  background: var(--cta-kolko); color: var(--cta-strzalka);
  display: flex; align-items: center; justify-content: center; transition: transform 0.18s ease;
}
.lp-cta:hover .lp-cta-kolko { transform: translateX(3px); }
[dir="rtl"] .lp-cta:hover .lp-cta-kolko { transform: translateX(-3px); }
.lp-cta--granat-stala { --cta-tlo: #17183B; --cta-tekst: #FFFFFF; --cta-kolko: #FFC83D; --cta-strzalka: #17183B; }
.lp-cta--zolta   { --cta-tlo: #FFC83D; --cta-tekst: #17183B; --cta-kolko: #17183B; --cta-strzalka: #FFC83D; }
.lp-cta--zielona { --cta-tlo: #35A64D; --cta-tekst: #17183B; --cta-kolko: #17183B; --cta-strzalka: #35A64D; }
.lp-cta--duza    { --cta-wys: 62px; --cta-kolko-r: 48px; --cta-font: 18px; }
.lp-cta--srednia { --cta-wys: 56px; --cta-kolko-r: 42px; --cta-font: 16px; }
.lp-cta--mala    { --cta-wys: 52px; --cta-kolko-r: 38px; --cta-font: 15px; }

/* Obrysowana pigułka („Zaloguj się") i szara („Plik Excel") - dwa przyciski drugiego planu. */
.lp-btn-kontur {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 22px; border: 0; border-radius: 999px;
  background: transparent; box-shadow: inset 0 0 0 2px var(--lp-mocna); color: var(--lp-tekst);
  font-family: var(--lp-font); font-size: 15px; font-weight: 800; line-height: 1.2;
  white-space: nowrap; cursor: pointer; transition: background 0.15s ease;
}
.lp-btn-kontur:hover { background: color-mix(in srgb, var(--lp-mocna) 8%, transparent); }
.lp-btn-szary {
  min-height: 48px; padding: 0 20px; border: 0; border-radius: 999px;
  background: var(--lp-tlo-2); box-shadow: inset 0 0 0 1.5px var(--lp-linia); color: var(--lp-tekst);
  font-family: var(--lp-font); font-size: 15px; font-weight: 800; line-height: 1.2; cursor: pointer;
  transition: box-shadow 0.15s ease;
}
.lp-btn-szary:hover { box-shadow: inset 0 0 0 1.5px var(--lp-mocna); }
:is(.lp-btn-kontur, .lp-btn-szary, .lp-nav a, .lp-nav button, .lp-link-dalej, .lp-art, .lp-zestaw2, .lp-art-wszystkie):focus-visible {
  outline: 3px solid var(--lp-niebieski); outline-offset: 3px;
}

/* --- NAGŁÓWEK --- */
/* Przyklejony do góry, bo strona jest długa, a „Zacznij za darmo" ma być pod ręką na każdej
   jej wysokości. Pełne tło (bez przezroczystości z rozmyciem jak dawniej): pod paskiem
   przejeżdżają teraz pełne kolory marki i przez mgłę wyglądały jak zabrudzenie. */
.lp-header {
  position: sticky; top: 0; z-index: 40;
  background: var(--lp-tlo); box-shadow: 0 1px 0 var(--lp-linia);
}
.lp-header-inner {
  width: min(var(--lp-max), 100% - 48px); margin-inline: auto; min-height: 84px;
  display: flex; align-items: center; gap: 40px;
}
.lp-header-marka { display: flex; flex-shrink: 0; }
/* Wymiary z planszy (172 × 41) zgadzają się z prawdziwymi proporcjami pliku (1196 × 285).
   Atrybuty width/height w znaczniku podają TE proporcje, żeby przeglądarka zarezerwowała
   właściwe miejsce przed wczytaniem obrazka. */
.lp-header-logo { height: 41px; width: auto; display: block; }
/* Logo śledzi motyw regułą [data-theme="dark"] .logo-marka.wg-motywu - ta zna tylko ręczny
   wybór. Ciemny motyw z samego ustawienia systemu zostawiał czarne logo na granacie. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .lp-header-logo { content: url('../../assets/img/logo-biale.png'); }
}
.lp-nav { display: flex; align-items: center; gap: 28px; }
/* Pozycja „Ucz się" jest <button> (jej cel zależy od stanu konta), reszta to zwykłe linki.
   W menu mają być NIE DO ODRÓŻNIENIA, więc styl opisuje oba. */
.lp-nav a, .lp-nav button {
  padding: 10px 4px; border: 0; border-radius: 8px; background: none; cursor: pointer;
  font-family: var(--lp-font); font-size: 15px; font-weight: 700; line-height: 1.2;
  color: var(--lp-tekst); text-decoration: none; white-space: nowrap;
}
.lp-nav a:hover, .lp-nav button:hover { color: var(--lp-akcent-tekst); }
.lp-header-akcje { margin-inline-start: auto; display: flex; align-items: center; gap: 12px; }
.lp-header-narzedzia, .lp-header-konto { display: flex; align-items: center; gap: 12px; }
/* Kółko motywu i pigułka języka w jednym rzędzie z przyciskami - 44 px, obwódka jak na
   planszy. Specyficzność z .lp-header, żeby wygrać ze wspólną regułą 40 px dla .header-theme
   na ekranach dotykowych. */
.lp-header .lp-header-theme {
  width: 44px; height: 44px; font-size: 1.05rem; color: var(--lp-tekst);
  background: var(--lp-karta); border: 0; box-shadow: 0 0 0 1.5px var(--lp-linia);
}
.lp-header .lp-header-theme:hover { background: var(--lp-tlo-2); }
.lp-header .lp-header-theme:focus-visible { outline: 3px solid var(--lp-niebieski); outline-offset: 3px; }
.lp-lang-picker { margin-bottom: 0; }
.lp-lang-picker .lang-picker-btn {
  width: auto; min-height: 44px; padding-block: 0; padding-inline: 10px 14px; gap: 8px;
  border: 0; border-radius: 999px; background: var(--lp-karta); box-shadow: 0 0 0 1.5px var(--lp-linia);
  font-family: var(--lp-font); font-size: 14px; font-weight: 700; color: var(--lp-tekst);
}
.lp-lang-picker .lang-picker-btn:hover { box-shadow: 0 0 0 1.5px var(--lp-mocna); }
.lp-lang-picker .lang-picker-btn:focus-visible { outline: 3px solid var(--lp-niebieski); outline-offset: 3px; }
.lp-lang-picker .lang-picker-flag .lp-flaga-svg { width: 24px; height: 16px; }
.lp-lang-picker .lang-picker-name { flex: none; }
.lp-lang-picker .lang-picker-caret { display: flex; color: var(--lp-tekst); }
.lp-lang-picker .lang-picker-list {
  left: auto; right: auto; inset-inline-end: 0; min-width: 220px; max-height: 60vh;
  background: var(--lp-karta); border: 1px solid var(--lp-linia);
  font-family: var(--lp-font); color: var(--lp-tekst);
}
/* Opcje są odsyłaczami <a> (wersje językowe jako zwykłe linki, 2026-10-02): bez tego dostałyby kolor i podkreślenie linku. */
.lp-lang-picker a.lang-picker-opt { color: inherit; text-decoration: none; }
.lp-lang-picker a.lang-picker-opt:focus-visible { outline: 3px solid var(--lp-niebieski); outline-offset: -3px; }
.lp-lang-picker .lang-picker-opt:hover { background: var(--lp-tlo-2); }
.lp-lang-picker .lang-picker-opt.aktywny { font-weight: 800; }
/* Podgląd strony głównej z zalogowanej aplikacji (klik w logo): chowamy logowanie
   i rejestrację, a pokazujemy „Wróć do nauki". Sesja zostaje - to tylko przełączenie widoku. */
.lp-wroc-do-apki { display: none; }
body.podglad-glownej .lp-wroc-do-apki { display: inline-flex; }
body.podglad-glownej .lp-header-zaloguj,
body.podglad-glownej .lp-header-cta { display: none; }
/* Szyny przyklejone do okna (ranking dla wszystkich, reklama kont darmowych) stoją POZA #appShell, więc podgląd
   strony głównej ich nie chował. Sekcje strony (#authScreen, z-index 3000) je zasłaniały, a wspólna stopka pod nimi
   już nie: Alek 2026-09-26, przewinięcie na sam dół = w prawym dolnym rogu wyjeżdżała tabela rankingu na granatowej
   stopce (zmierzone w oknie 1600×700: #rankRail 230×584 px, fixed, z-index 5, widoczny tylko nad .app-stopka). */
body.podglad-glownej .rank-rail,
body.podglad-glownej .ad-rail { display: none; }
/* Wybrano jezyk, nowa strona w drodze - przygaszamy od razu, zeby klik mial widoczny skutek. */
html.lp-jezyk-w-drodze body { opacity: .45; transition: opacity .25s ease; pointer-events: none; }

/* --- HERO --- */
.lp-hero { background: var(--lp-niebieski); color: #FFFFFF; overflow: hidden; }
/* NOWY UKŁAD (Alek 2026-09-29: „MP4 w 16:9, nowy układ hero”). Film 16:9 w prawej kolumnie miał ~600 px szerokości
   i napisy filmu czytało się w nim z trudem, więc idzie POD tekst na całą szerokość kontenera, a tekst staje u góry
   w siatce dwóch kolumn: nagłówek po lewej, opis i nota naprzeciw niego po prawej (kończą się na wysokości ostatniego
   wiersza nagłówka), przyciski pod spodem w jednym rzędzie przez całą szerokość - w lewej kolumnie drugi przycisk
   po niemiecku („Sieh dir ein Beispiel an: 113 Vokabeln aus einem Lied”, 458 px) spadał pod pierwszy. Kolejność
   w HTML zostaje ta sama (chip, h1, opis, przyciski, nota), więc czytnik ekranu i układ w jednej kolumnie na
   telefonie czytają ją jak dawniej.
   Po co tak ciasno: film rusza sam dopiero przy 60% na ekranie. Tekst w jednej kolumnie zajmował ~380 px, opis
   z dwoma przyciskami jeden pod drugim w prawej kolumnie ~290 px (z dziurą nad chipem); siatka ~270 px, czyli przy
   oknie 1536 × 864 (Windows 125% na ekranie 1920 × 1080) film widać w ~64% od wejścia, a przy 1440 × 900 w ~69%. */
.lp-hero-uklad { display: flex; flex-direction: column; gap: 36px; padding: 40px 0 80px; }
.lp-hero-tekst {
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: 64px; row-gap: 22px;
  grid-template-areas: "chip ." "h1 opis" "h1 nota" "akcje akcje"; min-width: 0;
}
.lp-hero-tekst > .lp-hero-chip { grid-area: chip; justify-self: start; }
.lp-hero-tekst > .lp-h1 { grid-area: h1; align-self: end; }
.lp-hero-tekst > .lp-hero-opis { grid-area: opis; align-self: end; }
.lp-hero-tekst > .lp-hero-akcje { grid-area: akcje; }
/* Nota tuż pod opisem: odstęp wierszy siatki (22 px) między zdaniem a jego dopiskiem rozrywał je wizualnie. */
.lp-hero-tekst > .lp-hero-nota { grid-area: nota; align-self: start; margin-top: -10px; }
.lp-hero-chip {
  display: inline-flex; align-items: center; gap: 10px; min-height: 36px;
  padding-block: 6px; padding-inline: 8px 16px; box-sizing: border-box; border-radius: 999px;
  background: rgba(255, 255, 255, 0.16); font-size: 14px; font-weight: 700; line-height: 1.3;
}
.lp-hero-kropki { display: flex; gap: 4px; flex: none; }
.lp-hero-kropki i { width: 12px; height: 12px; border-radius: 999px; background: var(--lp-zielony); }
.lp-hero-kropki i:nth-child(2) { background: var(--lp-zolty); }
.lp-hero-kropki i:nth-child(3) { background: var(--lp-czerwony); }
.lp-h1 { font-size: clamp(2.6rem, 1.2rem + 4.9vw, 5rem); line-height: 0.96; letter-spacing: -0.035em; color: #FFFFFF; }
.lp-hero-opis { margin: 0; max-width: 34rem; font-size: 19px; font-weight: 500; line-height: 1.5; padding-bottom: 6px; }
/* Nagłówek w lewej kolumnie (7/12 kontenera, 663 px przy pełnym kontenerze) mniejszy niż w dawnym układzie: przy 80 px
   polskie „Wklej piosenkę. Naucz się z niej słówek.” łamało się na trzy wiersze, a przy 70 px (okno 1440 × 900) też,
   i tekst hero rósł z 273 do 351 px, a film schodził pod 60% widoczności. Sufit 65 px trzyma dwa wiersze. */
.lp-hero .lp-h1 { font-size: clamp(2.6rem, 1.15rem + 3.7vw, 4.05rem); line-height: 0.98; }
.lp-hero-akcje { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 2px; }
.lp-hero .lp-cta:focus-visible, .lp-hero-przyklad:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 4px; }
.lp-hero-przyklad {
  display: inline-flex; align-items: center; gap: 10px; min-height: 62px;
  padding-block: 8px; padding-inline: 18px 24px; box-sizing: border-box; border: 0; border-radius: 999px;
  background: transparent; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.7); color: #FFFFFF;
  font-family: var(--lp-font); font-size: 16px; font-weight: 800; line-height: 1.25;
  text-align: start; text-decoration: none; cursor: pointer; transition: background 0.15s ease, box-shadow 0.15s ease;
}
.lp-hero-przyklad:hover { color: #FFFFFF; background: rgba(255, 255, 255, 0.08); box-shadow: inset 0 0 0 2px #FFFFFF; }
.lp-hero-przyklad-ikona { flex: none; display: block; }
.lp-hero-nota { margin: 2px 0 0; font-size: 14px; font-weight: 600; line-height: 1.45; }

/* FILM PROMOCYJNY pod tekstem, na całą szerokość kontenera (komponenty/film_promo.php, film_promo_wideo): plik MP4
   w języku strony z plakatem klatki końcowej. Kontener ma aspect-ratio 16:9 już w HTML-u, więc zanim przyjdzie plik,
   miejsce filmu stoi: układ nie skacze. Barwy filmu są stałe w obu motywach, jak ekrany marki.
   Szerokość nie większa niż okno pod przyklejonym nagłówkiem (84 px) z oddechem 48 px, przeliczone na 16:9: po
   przewinięciu do filmu cały kadr mieści się na ekranie (laptop 1366 × 768, okno ~650 px: 1131 px zamiast 1200,
   a przy 100% szerokości dół filmu z przyciskiem finału leżałby pod krawędzią okna). Na telefonie warunek nie
   gryzie (pion), a poziomo film maleje do wysokości okna. */
.lp-hero-film { position: relative; min-width: 0; width: min(100%, calc((100svh - 132px) * 16 / 9)); margin-inline: auto; }
/* Poświata pod kartą filmu: biała mgła na niebieskim hero odrywa kartę od tła tak, jak światło w samym filmie. */
.lp-hero-film::before { content: ""; position: absolute; inset: 6% 3% -5%; z-index: 0; pointer-events: none;
  border-radius: 40px; background: radial-gradient(closest-side, rgba(255, 255, 255, 0.30), rgba(255, 255, 255, 0) 100%);
  filter: blur(28px); }
.lp-hero-film .fp { z-index: 1; border-radius: 30px; }
/* =========================================================================================
   FILM PROMOCYJNY (komponenty/film_promo.php). Barwy stałe w obu motywach: film to „okładka"
   na niebieskim hero, jak ekrany marki w aplikacji. Ruch filmu robi silnik w JS przez
   transform/opacity/filter; przejścia CSS są tu tylko na sterowaniu (hover), nie na klatkach.
   ========================================================================================= */
.fp {
  --fp-granat: #17183B; --fp-niebieski: #2463E9; --fp-zolty: #FFC83D; --fp-czerwony: #DB2727;
  --fp-zielony: #35A64D; --fp-tlo: #F3F5FB; --fp-bialy: #FFFFFF; --fp-lawenda: #C9CAE8;
  --fp-font: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --fp-font-nag: 'Outfit', 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --fp-u: calc(100cqw / 1280);
  position: relative; width: 100%; aspect-ratio: 16 / 9; container-type: inline-size;
  border-radius: 28px; overflow: hidden; isolation: isolate; contain: layout paint;
  background: var(--fp-granat); color: var(--fp-bialy); font-family: var(--fp-font);
  /* Rama widoczna NA NIEBIESKIM hero: jasny pierścień i ciemny cień pod spodem. Krytyka ruchu: scena
     Czytania ma tło w barwie hero i przez 4,5 s film tracił krawędź (karta czytanki „wisiała” w hero). */
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.22), 0 30px 60px -20px rgba(10, 12, 40, 0.55),
    0 40px 80px -36px rgba(8, 14, 60, 0.85);
  -webkit-tap-highlight-color: transparent; user-select: none;
}
.fp-plotno { position: absolute; left: 0; top: 0; width: 1280px; height: 720px; overflow: hidden;
  transform: scale(var(--fp-k, 1)); transform-origin: 0 0; cursor: pointer; }
.fp-sceny, .fp-scena, .fp-scena-tlo, .fp-scena-tresc, .fp-kamera-okno, .fp-kamera { position: absolute; inset: 0; }
/* Perspektywa warstwy scen: przejście „klapka” obraca całą scenę na zawiasie u góry kadru. */
.fp-sceny { perspective: 1500px; perspective-origin: 50% 0%; }
.fp-scena { perspective: 1400px; perspective-origin: 50% 45%; contain: layout paint style; }
/* Pierścień na krawędzi koła przejścia (silnik, rysujPierscien): nad scenami, pod plakatem. */
.fp-pierscien { position: absolute; left: 0; top: 0; width: 1280px; height: 720px; pointer-events: none; opacity: 0; overflow: visible; }
.fp-scena-tlo { overflow: hidden; }
/* Światło w szerokim kadrze: plama ~900 × 900 px (koło, nie elipsa rozciągnięta na 16:9) nad lewą kolumną
   napisu, przesuwana przez silnik w poziomie; winieta przyciemnia prawy dół, gdzie kadr kończy się ekranem. */
.fp-blask { position: absolute; left: -12%; top: -45%; width: 70%; height: 125%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.07) 55%, transparent); }
.fp-winieta { position: absolute; inset: 0;
  background: radial-gradient(120% 115% at 30% 22%, transparent 52%, rgba(8, 10, 40, 0.30)); }
.fp-scena-tresc { transform-origin: 50% 50%; }
/* Punkt zaczepienia kamery ustawia silnik przy budowie sceny (środek ekranu albo kadru, kamO w silnik.js). */
.fp-kamera { transform-origin: 68.75% 50%; }

/* --- PLAKAT: klatka końcowa. Własne tło bez JS i wtedy, gdy scena finału nie przejęła jego
   geometrii (klasa fp-plakat-przejety z silnika). --- */
.fp-plakat { position: absolute; inset: 0; z-index: 20; text-align: center; }
.fp:not(.fp-plakat-przejety) .fp-plakat {
  background: radial-gradient(120% 90% at 30% 10%, #2A2C66 0%, var(--fp-granat) 60%);
}
/* Geometria = FilmPromo.PLAKAT (silnik.js), płótno 1280 × 720: logo 460/132 × 360, zdanie 160/250 × 960 (krój
   z --fp-zd, domyślnie 72), kółka trybów od 426 (50 px, odstęp 18), przycisk od 508 wysokości 80. Grupa 132–588
   stoi w środku kadru (środek 360), przycisk jest ostatni i największy (krytyka ruchu: finał był słabszy od
   otwarcia). Wszystko w polu bezpiecznym (64 / 48 px od krawędzi, STREFA.bezpieczne). */
.fp-plakat-logo { position: absolute; left: calc(var(--fp-u) * 460); top: calc(var(--fp-u) * 132);
  width: calc(var(--fp-u) * 360); height: auto; display: block; }
/* Pole zdania: stała wysokość dwóch linijek (150), tekst wyśrodkowany w pionie (PLAKAT.zdanie.h w silnik.js). */
.fp-plakat-zdanie { position: absolute; left: calc(var(--fp-u) * 160); top: calc(var(--fp-u) * 250);
  width: calc(var(--fp-u) * 960); height: calc(var(--fp-u) * 150); display: flex; align-items: center; justify-content: center;
  margin: 0; font-family: var(--fp-font-nag); font-weight: 800;
  font-size: calc(var(--fp-u) * var(--fp-zd, 72)); line-height: 1.04; letter-spacing: -0.025em; color: var(--fp-bialy); text-wrap: balance; }
.fp-plakat-tryby { position: absolute; left: 0; right: 0; top: calc(var(--fp-u) * 426); display: flex; justify-content: center;
  gap: calc(var(--fp-u) * 18); pointer-events: none; }
.fp-plakat-tryb { width: calc(var(--fp-u) * 50); height: calc(var(--fp-u) * 50); border-radius: 999px; flex: none;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.8); }
.fp-plakat-tryb svg { width: calc(var(--fp-u) * 24); height: calc(var(--fp-u) * 24); display: block; }
.fp-plakat-cta { position: absolute; left: 50%; top: calc(var(--fp-u) * 508); transform: translateX(-50%);
  display: inline-flex; align-items: center; justify-content: space-between; gap: calc(var(--fp-u) * 24);
  height: calc(var(--fp-u) * 80); padding: 0 calc(var(--fp-u) * 8) 0 calc(var(--fp-u) * 34); box-sizing: border-box;
  border: 0; border-radius: 999px; background: var(--fp-zolty); color: var(--fp-granat);
  font-family: var(--fp-font); font-size: calc(var(--fp-u) * 25); font-weight: 800; line-height: 1.2;
  white-space: nowrap; cursor: pointer; }
.fp-plakat-cta-kolko { width: calc(var(--fp-u) * 64); height: calc(var(--fp-u) * 64); flex: none; border-radius: 999px;
  background: var(--fp-granat); color: var(--fp-zolty); display: flex; align-items: center; justify-content: center; }
.fp-plakat-cta-kolko svg { width: calc(var(--fp-u) * 28); height: calc(var(--fp-u) * 28); display: block; }
/* Pole dotyku przycisku nie mniejsze niż 48 × 44 px. Zmierzone 2026-10-02 na telefonie 390 px: film ma 358 px szerokości,
   a przycisk w skali filmu 54 × 22 px (poniżej 24 px z WCAG 2.5.8 i daleko od 44 pt palca). Obraz zostaje ten sam (ten
   sam przycisk jest narysowany w pliku), rośnie tylko niewidoczne pole wokół niego; odtwarzacz liczy klik w obraz po tych
   samych liczbach (POLE_CTA w film_promo_wideo_js). */
.fp-plakat-cta::after { content: ""; position: absolute; left: 50%; top: 50%; width: max(100%, 48px); height: max(100%, 44px);
  transform: translate(-50%, -50%); border-radius: 999px; }
.fp-plakat-cta:hover { box-shadow: 0 12px 26px -12px rgba(0, 0, 0, 0.6); }
.fp-plakat-cta:focus-visible, .fp-ster:focus-visible, .fp-rozdzial:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 3px; }

/* --- STEROWANIE --- */
.fp-sterowanie { display: none; }
.fp[data-silnik] .fp-sterowanie { display: block; }
/* Narzędzie klatek (scripts/film_promo_klatki.js) zrzuca sam film, bez przycisków i paska. */
.fp.fp-klatki .fp-sterowanie { display: none; }
/* ...i bez zaokrąglenia i cienia ramki: klatka idzie do pliku MP4, a zaokrąglenie da odtwarzacz w hero. Z rogami
   zaokrąglonymi w samym pliku każdy róg klatki 1920 × 1080 niósł tło podglądu (promień 28 px × skala 1,5 = 42 px, widać na zrzucie). */
.fp.fp-klatki { border-radius: 0; box-shadow: none; }
/* Krycie siedzi na PRZYCISKACH, nie na pasku: wyciszony dźwięk zostaje na widoku sam (niżej), a dziecko nie może
   być bardziej widoczne niż rodzic z opacity 0. */
.fp-przyciski { position: absolute; left: 14px; right: 14px; bottom: 16px; z-index: 30; display: flex; gap: 8px;
  align-items: center; pointer-events: none; }
.fp-przyciski > .fp-ster { opacity: 0; pointer-events: none; transition: opacity 0.25s ease; }
.fp:hover .fp-przyciski > .fp-ster, .fp:focus-within .fp-przyciski > .fp-ster, .fp[data-stan="pauza"] .fp-przyciski > .fp-ster,
.fp[data-stan="koniec"] .fp-przyciski > .fp-ster { opacity: 1; pointer-events: auto; }
@media (hover: none) { .fp .fp-przyciski > .fp-ster { opacity: 1; pointer-events: auto; } }
/* DŹWIĘK (Alek 2026-09-29: „popraw jeszcze audio w odtwarzaczu”). Wyciszony przycisk stoi na widoku zawsze, także
   bez najazdu myszą: to jedyne zaproszenie do muzyki, a schowany w rogu ruchomego obrazu ginął. Przy pierwszym
   odtworzeniu obok ikony stoi napis (ten sam, co nazwa przycisku), który po kilku sekundach zwija się do ikony
   (silnik: klasa fp-dzwiek-napis). Pigułka rośnie w stronę środka kadru, bo przycisk stoi przy prawej krawędzi. */
.fp-przyciski > .fp-ster-dzwiek[aria-pressed="false"], .fp-przyciski > .fp-ster-dzwiek[data-laduje] { opacity: 1; pointer-events: auto; }
.fp-ster.fp-ster-dzwiek { position: relative; width: auto; min-width: 40px; padding: 0 10px; box-sizing: border-box;
  transition: opacity 0.25s ease, background 0.25s ease, box-shadow 0.25s ease; }
.fp-ster-napis { display: block; order: -1; max-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  opacity: 0; margin-inline-end: 0; font-family: var(--fp-font); font-size: 14px; font-weight: 800; line-height: 40px;
  letter-spacing: 0.01em; color: #FFFFFF;
  transition: max-width 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.3s ease, margin 0.45s cubic-bezier(0.2, 0.8, 0.2, 1); }
.fp.fp-dzwiek-napis .fp-ster-dzwiek { background: rgba(23, 24, 59, 0.9); box-shadow: 0 0 0 1.5px var(--fp-zolty), 0 10px 24px -12px rgba(0, 0, 0, 0.8); }
.fp.fp-dzwiek-napis .fp-ster-dzwiek .fp-ster-napis { max-width: min(240px, calc(100cqw - 150px)); opacity: 1; margin-inline: 6px 8px; }
.fp.fp-dzwiek-napis .fp-ster-dzwiek svg { color: var(--fp-zolty); }
/* Wczytywanie po kliknięciu: ikona już pokazuje „włączone”, żółta obwódka i pulsujące fale mówią „zaraz zagra”.
   Z opóźnieniem, żeby skok po wczytanym pliku (~20-80 ms) nie mrugał. */
.fp-ster-dzwiek[data-laduje] { box-shadow: 0 0 0 2px var(--fp-zolty); transition-delay: 0.2s; }
.fp-ster-dzwiek[data-laduje] .fp-i-dzwiek { animation: fp-dzwiek-laduje 0.9s ease-in-out 0.2s infinite alternate; }
@keyframes fp-dzwiek-laduje { from { opacity: 1; } to { opacity: 0.35; } }
.fp-ster { width: 40px; height: 40px; border: 0; border-radius: 999px; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  background: rgba(23, 24, 59, 0.74); color: #FFFFFF; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16); }
.fp-ster:hover { background: rgba(23, 24, 59, 0.92); }
.fp-ster[hidden] { display: none; }
.fp-ster-dzwiek { margin-inline-start: auto; }
.fp-ster svg { display: none; }
.fp-ster[data-ikona="graj"] .fp-i-graj, .fp-ster[data-ikona="pauza"] .fp-i-pauza,
.fp-ster[data-ikona="od-nowa"] .fp-i-od-nowa, .fp-ster[data-fp-od-nowa] .fp-i-od-nowa,
.fp-ster[data-ikona="dzwiek"] .fp-i-dzwiek, .fp-ster[data-ikona="cisza"] .fp-i-cisza { display: block; }
.fp[data-stan="koniec"] [data-fp-od-nowa] { display: none; }
.fp-postep { position: absolute; left: 0; right: 0; bottom: 0; height: 14px; z-index: 31; cursor: pointer; }
.fp-postep-tor { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(255, 255, 255, 0.22); }
.fp-postep-wypelnienie { position: absolute; inset: 0; background: var(--fp-zolty); transform-origin: 0 50%; transform: scaleX(0); }
.fp-rozdzialy { position: absolute; inset: 0; pointer-events: none; }
.fp-rozdzial { position: absolute; bottom: -3px; width: 10px; height: 10px; margin-left: -5px; padding: 0; border: 0;
  border-radius: 999px; background: #FFFFFF; box-shadow: 0 0 0 2px var(--fp-granat); cursor: pointer;
  pointer-events: auto; opacity: 0; transition: opacity 0.2s ease, transform 0.2s ease; }
.fp:hover .fp-rozdzial, .fp:focus-within .fp-rozdzial, .fp[data-stan="pauza"] .fp-rozdzial { opacity: 1; }
.fp-rozdzial:hover { transform: scale(1.35); }
@media (hover: none) { .fp .fp-rozdzial { opacity: 1; } }
.fp-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Ograniczony ruch (systemowy albo wymuszony data-ogranicz, klasa fp-ogranicz): napis zwija się bez animacji,
   wskaźnik wczytywania stoi (sama obwódka i przygaszona ikona). */
@media (prefers-reduced-motion: reduce) {
  .fp-przyciski > .fp-ster, .fp-rozdzial, .fp-ster.fp-ster-dzwiek, .fp-ster-napis { transition: none; }
  .fp-ster-dzwiek[data-laduje] .fp-i-dzwiek { animation: none; opacity: 0.55; }
}
.fp.fp-ogranicz .fp-przyciski > .fp-ster, .fp.fp-ogranicz .fp-ster.fp-ster-dzwiek, .fp.fp-ogranicz .fp-ster-napis { transition: none; }
.fp.fp-ogranicz .fp-ster-dzwiek[data-laduje] .fp-i-dzwiek { animation: none; opacity: 0.55; }
/* =========================================================================================
   ODTWARZACZ Z PLIKU (film_promo_wideo, strona główna od 2026-10-02). Plik 16:9 wypełnia kontener 16:9,
   a plakat i sterowanie leżą na nim tak samo, jak na płótnie wersji z kodu. Przejścia CSS są tu dozwolone:
   to nie są klatki filmu (te dekoduje karta graficzna), tylko warstwa nad nim.
   ========================================================================================= */
.fp-wideo-el { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover;
  background: var(--fp-granat); cursor: pointer; }
.fp[data-odtwarzacz] .fp-sterowanie { display: block; }
/* Plakat: przed pierwszym odtworzeniem i na końcu. Schodzi przenikaniem (0,45 s, jak zejście plakatu w silniku),
   wraca szybciej (0,3 s) na ostatniej klatce, która wygląda tak samo, jak on. */
.fp-wideo .fp-plakat { opacity: 1; visibility: visible; transition: opacity 0.3s ease; }
.fp-wideo.fp-plakat-schowany .fp-plakat { opacity: 0; visibility: hidden; transition: opacity 0.45s ease, visibility 0s linear 0.45s; }
.fp-wideo[data-odtwarzacz]:not([data-zagral]) .fp-plakat { cursor: pointer; }
.fp-wideo:not([data-zagral]) [data-fp-od-nowa] { display: none; }
/* Przycisk odtworzenia z napisem „Odtwórz film”, gdy film nie ruszył sam (ograniczony ruch, oszczędzanie danych,
   odmowa przeglądarki): sama ikona w rogu nie mówi, że to jest film. Napis rośnie w stronę środka kadru. */
.fp-ster.fp-ster-graj { width: auto; min-width: 40px; padding: 0 10px; box-sizing: border-box;
  transition: opacity 0.25s ease, background 0.25s ease, box-shadow 0.25s ease; }
.fp-ster-graj .fp-ster-napis { order: 1; }
.fp-wideo[data-stan="pauza"]:not([data-zagral]) .fp-ster-graj { background: rgba(23, 24, 59, 0.9);
  box-shadow: 0 0 0 1.5px var(--fp-zolty), 0 10px 24px -12px rgba(0, 0, 0, 0.8); }
.fp-wideo[data-stan="pauza"]:not([data-zagral]) .fp-ster-graj .fp-ster-napis { max-width: min(240px, calc(100cqw - 150px));
  opacity: 1; margin-inline: 8px 6px; }
.fp-wideo[data-stan="pauza"]:not([data-zagral]) .fp-ster-graj svg { color: var(--fp-zolty); }
@media (prefers-reduced-motion: reduce) {
  .fp-wideo .fp-plakat, .fp-wideo.fp-plakat-schowany .fp-plakat, .fp-ster.fp-ster-graj { transition: none; }
}
/* WĄSKI FILM (telefon: plik 16:9 ma ~360 × 200 px, zmierzone zrzutem 390 × 844): przyciski 40 px z napisem „Włącz muzykę”
   zasłaniały dół kadru, czyli rząd trybów w otwarciu i przycisk finału. Mniejsze i bliżej krawędzi, a „od nowa” w trakcie
   znika (na końcu wraca jako główny przycisk, a środek filmu przewija pasek). Wersja z kodu też na tym korzysta (podgląd). */
@container (max-width: 560px) {
  .fp-przyciski { left: 8px; right: 8px; bottom: 9px; gap: 6px; }
  .fp-ster { width: 30px; height: 30px; }
  .fp-ster svg { width: 15px; height: 15px; }
  .fp-ster.fp-ster-dzwiek, .fp-ster.fp-ster-graj { min-width: 30px; padding: 0 7px; }
  .fp-ster-napis { font-size: 12px; line-height: 30px; }
  .fp-wideo [data-fp-od-nowa] { display: none; }
  .fp-postep { height: 10px; }
  .fp-postep-tor { height: 3px; }
  .fp-rozdzial { width: 8px; height: 8px; margin-left: -4px; bottom: -2.5px; }
}
/* --- LICZBY (żółty pas) --- */
.lp-liczby { background: var(--lp-zolty); color: var(--lp-granat); }
.lp-liczby-uklad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; padding: 38px 0; }
.lp-liczba { display: flex; align-items: center; gap: 18px; }
.lp-liczba-ile {
  font-family: var(--lp-font-nag); font-size: 64px; font-weight: 800; line-height: 1;
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.lp-liczba-co { max-width: 15rem; font-size: 16px; font-weight: 700; line-height: 1.35; }

/* --- TRYBY NAUKI --- */
.lp-tryby .lp-sek-srodek { gap: 44px; padding-bottom: calc(var(--lp-pion) + 6px); }
.lp-tryby-siatka { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.lp-tryb {
  --lp-tryb-obrys: #FFFFFF;
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  border-radius: 28px; background: var(--lp-czerwony); color: #FFFFFF;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.lp-tryb:hover { transform: translateY(-4px); box-shadow: var(--lp-cien-karty); }
.lp-tryb--niebieski { background: var(--lp-niebieski); }
.lp-tryb--zielony   { background: var(--lp-zielony); color: #17183B; --lp-tryb-obrys: #17183B; }
.lp-tryb--zolty     { background: var(--lp-zolty);   color: #17183B; --lp-tryb-obrys: #17183B; }
.lp-tryb--granat    { background: var(--lp-granat); box-shadow: inset 0 0 0 1.5px var(--lp-obwodka-granat); }
.lp-tryb-ilu { display: block; width: 200px; height: 200px; margin: 22px auto 0; }
.lp-tryb-tresc { display: flex; flex-direction: column; gap: 10px; padding: 8px 28px 30px; }
.lp-tryb-tytul { margin: 0; font-family: var(--lp-font-nag); font-size: 26px; font-weight: 800; line-height: 1.1; }
/* Przycisk w tytule rozciągnięty ::after na całą kartę - klikalna jest cała karta, a w drzewie
   dostępności zostaje nagłówek z przyciskiem w środku. */
.lp-tryb-akcja {
  padding: 0; border: 0; background: none; cursor: pointer; text-align: inherit;
  font: inherit; color: inherit; text-decoration: none;
}
.lp-tryb-akcja:hover { color: inherit; }
.lp-tryb-akcja::after { content: ''; position: absolute; inset: 0; z-index: 1; border-radius: 28px; }
.lp-tryb-akcja:focus-visible { outline: none; }
.lp-tryb-akcja:focus-visible::after { outline: 3px solid var(--lp-tryb-obrys); outline-offset: -6px; }
.lp-tryb-opis { margin: 0; font-size: 16px; font-weight: 500; line-height: 1.5; }

.lp-upusc {
  display: flex; flex-direction: column; gap: 14px; padding: 28px; border-radius: 28px;
  border: 2px dashed var(--lp-szary); background: var(--lp-karta); color: var(--lp-tekst);
  transition: border-color 0.15s ease, background 0.15s ease;
}
/* Ten sam sygnał „upuść tutaj", co przy prawdziwym ekranie talii w aplikacji (.dragover). */
.lp-upusc.dragover { border-color: var(--lp-niebieski); background: color-mix(in srgb, var(--lp-niebieski) 9%, var(--lp-karta)); }
.lp-upusc-ikona {
  width: 64px; height: 64px; border-radius: 20px; background: var(--lp-zolty); color: #17183B;
  display: flex; align-items: center; justify-content: center;
}
.lp-upusc-tytul { margin: 0; font-family: var(--lp-font-nag); font-size: 26px; font-weight: 800; line-height: 1.1; }
.lp-upusc-opis { margin: 0; font-size: 16px; font-weight: 500; line-height: 1.5; color: var(--lp-tekst-2); }
.lp-upusc-przyciski { margin-top: auto; display: flex; flex-wrap: wrap; gap: 10px; padding-top: 6px; }

/* --- METODA (granat) --- */
.lp-metoda-uklad {
  display: grid; grid-template-columns: 470px minmax(0, 1fr); gap: 64px; align-items: center;
  padding-block: calc(var(--lp-pion) + 6px);
}
.lp-metoda-lewa { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
.lp-metoda-znak {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 0.45em;
  min-height: 32px; padding: 6px 14px; box-sizing: border-box; border-radius: 999px;
  background: var(--lp-zolty); color: #17183B;
  font-size: 13px; font-weight: 800; line-height: 1.2; letter-spacing: 0.06em; text-transform: uppercase;
}
.lp-metoda-opis { margin: 0; font-size: 17px; font-weight: 500; line-height: 1.6; color: var(--lp-lawenda); }
.lp-stos { position: relative; width: 470px; max-width: 100%; height: 330px; margin-top: 22px; }
.lp-stos-karta {
  --k: #2463E9; --k-tlo: #E6EDFC; --k-tekst: #FFFFFF;
  position: absolute; width: 240px; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 12px; padding: 16px;
  border-radius: 26px; border: 3px solid var(--k); background: #FFFFFF; color: #17183B;
  box-shadow: 0 26px 50px -28px rgba(0, 0, 0, 0.8);
}
.lp-stos-karta--srednie { inset-inline-start: 0;     top: 0;     z-index: 1; transform: rotate(-7deg); }
.lp-stos-karta--latwe   { inset-inline-start: 228px; top: 24px;  z-index: 2; transform: rotate(6deg);
                          --k: #35A64D; --k-tlo: #E4F3E7; --k-tekst: #17183B; }
.lp-stos-karta--trudne  { inset-inline-start: 112px; top: 150px; z-index: 3; transform: rotate(-2deg);
                          --k: #DB2727; --k-tlo: #FBE6E6; --k-tekst: #FFFFFF; }
.lp-stos-poziom {
  align-self: flex-end; display: inline-flex; align-items: center; min-height: 24px; padding: 0 10px;
  border-radius: 999px; background: var(--k); color: var(--k-tekst);
  font-size: 11px; font-weight: 800; line-height: 1; letter-spacing: 0.06em; text-transform: uppercase;
}
.lp-stos-slowo { font-family: var(--lp-font-nag); font-size: 28px; font-weight: 800; line-height: 1.05; letter-spacing: -0.02em; text-align: center; }
.lp-stos-zdanie {
  padding: 10px 14px; border-radius: 12px; border-inline-start: 4px solid var(--k); background: var(--k-tlo);
  font-size: 14px; font-weight: 500; font-style: italic; line-height: 1.4;
}
.lp-metoda-kroki { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.lp-krok { display: flex; flex-direction: column; gap: 12px; padding: 24px; border-radius: 24px; background: var(--lp-granat-2); }
.lp-krok-ikona { width: 48px; height: 48px; border-radius: 15px; display: flex; align-items: center; justify-content: center; }
.lp-krok-ikona--zolta     { background: var(--lp-zolty);     color: #17183B; }
.lp-krok-ikona--czerwona  { background: var(--lp-czerwony);  color: #FFFFFF; }
.lp-krok-ikona--zielona   { background: var(--lp-zielony);   color: #17183B; }
.lp-krok-ikona--niebieska { background: var(--lp-niebieski); color: #FFFFFF; }
.lp-krok-tytul { margin: 0; font-family: var(--lp-font-nag); font-size: 23px; font-weight: 800; line-height: 1.15; color: #FFFFFF; }
.lp-krok-opis { margin: 0; font-size: 15px; font-weight: 500; line-height: 1.55; color: var(--lp-lawenda); }

/* --- ARTYKUŁY --- */
.lp-link-dalej {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  font-size: 16px; font-weight: 800; color: var(--lp-tekst); text-decoration: none; white-space: nowrap;
}
.lp-link-dalej:hover { color: var(--lp-tekst); text-decoration: underline; text-underline-offset: 4px; }
/* Strzałka w kółku z kanwy (ta sama, co w .lp-cta-kolko) zamiast znaku „→" z czcionki (Alek 2026-09-27: „ohydne to jest
   jako tekst"). W RTL obraca się sama .lp-strzalka, więc kółko już nie. */
.lp-link-dalej-strzalka {
  flex: none; width: 32px; height: 32px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--lp-cta-tlo); color: var(--lp-cta-tekst); transition: transform 0.18s ease;
}
.lp-link-dalej-strzalka .lp-strzalka { width: 18px; height: 18px; }
.lp-link-dalej:hover .lp-link-dalej-strzalka { transform: translateX(3px); }
[dir="rtl"] .lp-link-dalej:hover .lp-link-dalej-strzalka { transform: translateX(-3px); }
.lp-art-siatka { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.lp-art-siatka--2 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.lp-art {
  display: flex; flex-direction: column; overflow: hidden; border-radius: 28px;
  background: var(--lp-karta); color: var(--lp-tekst); text-decoration: none;
  box-shadow: 0 0 0 1.5px var(--lp-linia);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.lp-art:hover { color: var(--lp-tekst); transform: translateY(-4px); box-shadow: 0 0 0 1.5px var(--lp-mocna), var(--lp-cien-karty); }
.lp-art-foto {
  aspect-ratio: 16 / 10; overflow: hidden; background: var(--lp-linia);
  display: flex; align-items: center; justify-content: center;
}
.lp-art-foto img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lp-art-bezfoto { font-size: 2rem; opacity: 0.45; }
.lp-art-tresc { flex: 1; display: flex; flex-direction: column; gap: 12px; padding: 22px 24px 26px; }
.lp-art-tag {
  align-self: flex-start; display: inline-flex; align-items: center; min-height: 26px; padding: 0 11px;
  border-radius: 999px; background: var(--lp-tag-tlo); color: var(--lp-tag-tekst);
  font-size: 12.5px; font-weight: 800; line-height: 1;
}
.lp-art-tytul { margin: 0; font-family: var(--lp-font-nag); font-size: 25px; font-weight: 800; line-height: 1.12; text-wrap: balance; }
.lp-art-opis { margin: 0; font-size: 15px; font-weight: 500; line-height: 1.55; color: var(--lp-tekst-2); }
.lp-art-meta { margin-top: auto; font-size: 13px; font-weight: 700; color: var(--lp-tekst-3); }
.lp-art-wszystkie {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 12px;
  min-height: 320px; padding: 26px; box-sizing: border-box; overflow: hidden; border-radius: 28px;
  background: var(--lp-niebieski); color: #FFFFFF; text-decoration: none;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.lp-art-wszystkie:hover { color: #FFFFFF; transform: translateY(-4px); box-shadow: var(--lp-cien-karty); }
.lp-art-wszystkie-ilu { position: absolute; top: -6px; inset-inline-end: -24px; width: 250px; height: 250px; pointer-events: none; }
.lp-art-wszystkie-tytul { position: relative; font-family: var(--lp-font-nag); font-size: 34px; font-weight: 800; line-height: 1.02; letter-spacing: -0.02em; }
.lp-art-wszystkie-opis { position: relative; font-size: 15px; font-weight: 500; line-height: 1.55; }
.lp-kolko {
  position: relative; align-self: flex-start; width: 52px; height: 52px; margin-top: 6px; border-radius: 999px;
  background: var(--lp-zolty); color: #17183B; display: flex; align-items: center; justify-content: center;
}

/* --- ZESTAWY ZE SPOŁECZNOŚCI --- */
.lp-zestawy2 { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(0, 1fr); gap: 20px; }
.lp-zestaw2 {
  display: flex; flex-direction: column; overflow: hidden; border-radius: 26px;
  background: var(--lp-karta); color: var(--lp-tekst); text-decoration: none;
  box-shadow: 0 0 0 1.5px var(--lp-linia);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.lp-zestaw2:hover { color: var(--lp-tekst); transform: translateY(-4px); box-shadow: 0 0 0 1.5px var(--lp-mocna), var(--lp-cien-karty); }
.lp-zestaw2--duzy { grid-row: span 2; }
.lp-zestaw2-foto { position: relative; height: 132px; overflow: hidden; background: var(--lp-linia); flex: none; }
.lp-zestaw2--duzy .lp-zestaw2-foto { flex: 1; height: auto; min-height: 360px; }
.lp-zestaw2-foto img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.lp-zestaw2-swieze {
  position: absolute; top: 16px; inset-inline-start: 16px;
  display: inline-flex; align-items: center; min-height: 30px; padding: 0 12px; border-radius: 999px;
  background: var(--lp-zolty); color: #17183B; font-size: 13px; font-weight: 800; line-height: 1;
}
.lp-zestaw2-opis { display: flex; align-items: center; gap: 12px; padding: 12px 16px 14px; }
.lp-zestaw2--duzy .lp-zestaw2-opis { padding: 18px 22px 20px; }
.lp-zestaw2-teksty { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lp-zestaw2-tytul {
  margin: 0; font-family: var(--lp-font-nag); font-size: 18px; font-weight: 800; line-height: 1.15;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lp-zestaw2--duzy .lp-zestaw2-tytul { font-size: 24px; white-space: normal; }
.lp-zestaw2-meta { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--lp-tekst-3); }
.lp-nowosci-info {
  display: flex; flex-direction: column; justify-content: center; gap: 14px; padding: 22px;
  border-radius: 26px; background: var(--lp-karta); box-shadow: 0 0 0 1.5px var(--lp-linia);
}
.lp-nowosci-info-ikona {
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 14px; background: var(--lp-zielony); color: #17183B;
  display: flex; align-items: center; justify-content: center;
}
.lp-nowosci-info-tekst { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.5; color: var(--lp-tekst-2); }
.lp-nowosci-info-tekst strong { color: var(--lp-tekst); font-weight: 800; }
/* Świeża tablica bywa uboga. Trzy zestawy zostawiały w drugim rzędzie dziurę po czwartym,
   więc karta „Bez konta" zajmuje wtedy dwie komórki; przy jednym–dwóch duży kafelek
   przestaje zajmować dwa rzędy i wszystko staje w jednym. */
.lp-zestawy2--3 .lp-nowosci-info { grid-column: span 2; }
.lp-zestawy2--2 .lp-zestaw2--duzy, .lp-zestawy2--1 .lp-zestaw2--duzy { grid-row: auto; }
.lp-zestawy2--1 { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }

/* --- JĘZYKI (żółty) --- */
.lp-jezyki-uklad {
  display: grid; grid-template-columns: 400px minmax(0, 1fr); gap: 56px; align-items: center;
  padding-block: calc(var(--lp-pion) - 8px);
}
.lp-jezyki-uklad--film { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.lp-jezyki-ilu { display: block; width: 400px; max-width: 100%; height: auto; aspect-ratio: 1; }
/* Ramka filmu: proporcje trzyma aspect-ratio (iframe dostaje sztywne width/height, które przy
   zmianie szerokości kolumny rozjeżdżałyby się z kontenerem). Czarne tło, bo przez ułamek
   sekundy przed wczytaniem ramki widać właśnie je. */
.lp-jezyki-film { position: relative; aspect-ratio: 16 / 9; border-radius: 24px; overflow: hidden; background: #000; }
.lp-jezyki-film iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.lp-jezyki-tresc { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.lp-jezyki-opis { margin: 0; max-width: 36rem; font-size: 18px; font-weight: 600; line-height: 1.5; }
.lp-flagi { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.lp-flaga {
  display: inline-flex; align-items: center; gap: 9px; min-height: 44px;
  padding-block: 0; padding-inline: 10px 16px; box-sizing: border-box; border: 0; border-radius: 999px;
  background: #FFFFFF; color: #17183B; font-family: var(--lp-font); font-size: 15px; font-weight: 700;
  white-space: nowrap; cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.lp-flaga:hover { transform: translateY(-2px); box-shadow: 0 0 0 2px #17183B; }
.lp-flaga:focus-visible { outline: 3px solid #17183B; outline-offset: 3px; }
.lp-flaga .lp-flaga-svg { width: 26px; height: 17px; }
.lp-swiat { margin: 6px 0 0; font-size: 15px; font-weight: 700; line-height: 1.4; }

/* --- CENNIK --- */
.lp-cennik { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.lp-plan {
  position: relative; display: flex; flex-direction: column; gap: 22px; padding: 36px;
  border-radius: 32px; overflow: hidden;
}
.lp-plan > :not(.lp-plan-ilu) { position: relative; }
.lp-plan--darmowy { background: var(--lp-karta); color: var(--lp-tekst); box-shadow: 0 0 0 1.5px var(--lp-linia); }
.lp-plan--premium { background: var(--lp-granat); color: #FFFFFF; box-shadow: inset 0 0 0 1.5px var(--lp-obwodka-granat); }
.lp-plan-ilu { position: absolute; top: -6px; inset-inline-end: -10px; width: 200px; height: 200px; pointer-events: none; }
.lp-plan-nazwa {
  margin: 0; font-family: var(--lp-font); font-size: 14px; font-weight: 800; line-height: 1.2;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--lp-tekst-2);
}
.lp-plan--premium .lp-plan-nazwa { color: var(--lp-zolty); }
.lp-plan-cena { margin: 0; display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.lp-plan-kwota { font-family: var(--lp-font-nag); font-size: 72px; font-weight: 800; line-height: 1; letter-spacing: -0.03em; white-space: nowrap; }
.lp-plan--premium .lp-plan-kwota { color: var(--lp-zolty); }
.lp-plan-okres { font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--lp-tekst-2); }
.lp-plan--premium .lp-plan-okres { color: #FFFFFF; }
.lp-plan-cena-blok { display: flex; flex-direction: column; gap: 6px; }
.lp-plan-opcje { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.4; color: var(--lp-lawenda); }
.lp-plan-lista { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 14px; }
.lp-plan-lista li { display: flex; align-items: flex-start; gap: 12px; font-size: 16px; font-weight: 600; line-height: 1.45; }
.lp-ptaszek {
  width: 26px; height: 26px; flex-shrink: 0; border-radius: 999px; background: var(--lp-zielony); color: #17183B;
  display: flex; align-items: center; justify-content: center;
}
.lp-plan--premium .lp-ptaszek { background: var(--lp-zolty); }
.lp-plan-stopka { margin-top: auto; display: flex; flex-direction: column; align-items: flex-start; gap: 14px; padding-top: 8px; }
.lp-plan-nota { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.5; color: var(--lp-lawenda); }

/* --- PYTANIA --- */
.lp-faq { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 24px; align-items: start; }
.lp-faq-kolumna { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.lp-faq-poz { border-radius: 22px; background: var(--lp-karta); box-shadow: 0 0 0 1.5px var(--lp-linia); }
.lp-faq-poz[open] { box-shadow: 0 0 0 2px var(--lp-mocna); }
.lp-faq-poz summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 64px;
  padding-block: 14px; padding-inline: 22px 16px; box-sizing: border-box; border-radius: 22px;
  list-style: none; cursor: pointer; font-size: 17px; font-weight: 800; line-height: 1.35; color: var(--lp-tekst);
}
.lp-faq-poz summary::-webkit-details-marker { display: none; }
.lp-faq-poz summary::marker { content: ''; }
.lp-faq-poz summary:focus-visible { outline: 3px solid var(--lp-niebieski); outline-offset: 3px; }
.lp-faq-plus {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 999px; background: var(--lp-zolty); color: #17183B;
  display: flex; align-items: center; justify-content: center; transition: transform 0.2s ease;
}
.lp-faq-poz[open] .lp-faq-plus { transform: rotate(45deg); }
.lp-faq-poz p { margin: 0; padding: 0 22px 20px; font-size: 16px; font-weight: 500; line-height: 1.6; color: var(--lp-tekst-2); }

/* --- KONIEC STRONY: zielona karta --- */
.lp-final-sek .lp-kontener { padding-bottom: var(--lp-pion); }
.lp-final {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 40px; align-items: center;
  padding: 56px 64px; border-radius: 40px; overflow: hidden;
  background: var(--lp-zielony); color: #17183B;
}
.lp-final-tekst { display: flex; flex-direction: column; align-items: flex-start; gap: 36px; min-width: 0; }
.lp-final .lp-h2 { color: #17183B; }
.lp-final .lp-cta:focus-visible { outline-color: #17183B; }
.lp-final-ilu { width: 340px; height: 340px; margin: -24px 0 -56px; justify-self: end; }

/* STOPKA: pod stroną główną wspólna stopka prawna z końca <body> (.app-stopka) przebiera się
   w granatowy pas z planszy - logo po lewej, odnośniki po prawej, pod kreską zdanie
   o regulaminie i znak własności. Te same odnośniki i te same klucze, co na każdym innym
   ekranie; zmienia się tylko ułożenie. Logo jest tłem ::before (nie osobnym <img>), bo ta
   stopka stoi też pod aplikacją i tam logo mieć nie powinna. Kolejność robi `order`:
   ::before (logo) → odnośniki → ::after (kreska na całą szerokość łamie wiersz) → zdanie
   o regulaminie → znak własności. :has() nieobsługiwane = zwykła, jasna stopka. */
body:has(#authScreen:not(.hidden)) > .app-stopka {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 12px 26px;
  margin-top: 0; padding: 48px max(24px, calc((100% - 1200px) / 2)) 44px;
  border-top: 0; background: #17183B; color: #C9CAE8; text-align: start;
  font-family: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif; font-size: 13px; font-weight: 600;
}
body:has(#authScreen:not(.hidden)) > .app-stopka::before {
  content: ''; order: -1; width: 172px; height: 41px; margin-inline-end: auto;
  background: url('../../assets/img/logo-biale.png') center / contain no-repeat;
}
body:has(#authScreen:not(.hidden)) > .app-stopka a { order: 0; color: #FFFFFF; font-size: 14px; font-weight: 700; }
body:has(#authScreen:not(.hidden)) > .app-stopka a:hover { color: #FFC83D; }
body:has(#authScreen:not(.hidden)) > .app-stopka::after {
  content: ''; order: 1; flex-basis: 100%; height: 1px; margin: 14px 0 10px; background: #2E3068;
}
body:has(#authScreen:not(.hidden)) > .app-stopka > span:first-child { order: 2; flex: 1 1 auto; }
body:has(#authScreen:not(.hidden)) > .app-stopka .app-stopka-marka {
  order: 3; flex-basis: auto; margin: 0; color: #C9CAE8; font-weight: 600;
}

/* --- reklama na stronie głównej --- */
/* Podpis „Reklama" jest obowiązkowy, a nie kosmetyczny: blok wstawiony między sekcje bez
   podpisu czyta się jak ich część, a reklama udająca treść łamie zasady AdSense. */
.lp-reklama { max-width: var(--lp-max); margin: 0 auto; padding: 32px 20px; }
/* Bez doładowanej reklamy (konto w ocenie, brak dopasowania, blokada) blok znika razem
   z podpisem - strona główna ma wyglądać jak strona, nie jak szkielet na reklamy. */
.lp-reklama:has(ins.adsbygoogle:not([data-ad-status="filled"])) { display: none; }
.lp-reklama-etykieta {
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--lp-tekst-3); margin-bottom: 6px; text-align: center;
}

/* --- okno logowania --- */
.lp-modal {
  position: fixed; inset: 0; z-index: 4200;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  /* BEZ backdrop-filter - dokładnie z tego samego powodu, dla którego nie ma go mapa słówek
     (patrz .wordmap-overlay i pomiar w komentarzu przy niej). Rozmywanie tła każe
     przeglądarce przerysowywać CAŁĄ stronę pod spodem w każdej klatce, a pod tym oknem stoi
     strona główna z dwudziestoma pięcioma pigułkami języków, z których każda ma nieskończoną
     animację `lp-plyw`. Tło zmienia się więc bez przerwy, blur liczy się od nowa bez przerwy
     - i pisanie w polu hasła konkuruje o klatki z ozdobą, której i tak nie widać zza okna.
     Ciemniejsze tło daje to samo oddzielenie za darmo. Pigułki nie pływają od przebudowy
     z 2026-09-26, ale powód zostaje: rozmycie całej długiej strony to koszt bez zysku. */
  background: rgba(15, 23, 42, 0.68);
  overflow-y: auto;
}
.lp-modal .auth-card { margin: auto; }

.lp-modal-zamknij {
  position: absolute; top: 14px; inset-inline-end: 14px;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--border-warm); background: var(--card-bg); color: var(--grigio);
  font-size: 1rem; cursor: pointer; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.lp-modal-zamknij:hover { color: var(--testo); border-color: var(--border-2); }

/* --- logowanie kontem Google --- */
/* Kontener na przycisk renderowany przez skrypt Google. Wysokość rezerwujemy z góry, żeby
   po jego doładowaniu formularz nie podskoczył. */
.lp-google { margin-top: 6px; min-height: 44px; display: flex; justify-content: center; }
.lp-google-lub {
  display: flex; align-items: center; gap: 12px; margin: 16px 0 12px;
  font-size: 0.78rem; color: var(--muted-light);
}
.lp-google-lub::before, .lp-google-lub::after {
  content: ''; flex: 1; height: 1px; background: var(--border-warm);
}
.lp-google-zgoda { margin-top: 10px; font-size: 0.74rem; line-height: 1.45; color: var(--muted-light); text-align: center; }
.lp-google-zgoda a { color: var(--grigio); font-weight: 600; }
/* Blok „potwierdź kodem z e-maila" w miejscu pola hasła (konto z Google bez hasła) -
   patrz przygotujPotwierdzenie w JS. */
.potwierdz-kodem { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }
.potwierdz-kodem.hidden { display: none; }
.potwierdz-kodem-opis { font-size: 0.82rem; color: var(--grigio); line-height: 1.55; margin: 0 0 4px; }
.potwierdz-kodem .btn { width: 100%; }
/* Przycisk „Zaloguj się przez Google" - wg wytycznych marki Google („Sign in with Google"
   branding): jasny - białe tło, ramka #747775, tekst #1F1F1F; ciemny - tło #131314, ramka
   #8E918F, tekst #E3E3E3; Roboto 500 14 px, 40 px wysokości, logo „G" 20 px z lewej, pigułka.
   Ciemny wariant włącza się obiema drogami motywu aplikacji (prefers-color-scheme i data-theme). */
.btn-google {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-width: 240px; max-width: 400px; height: 40px; padding: 0 12px; box-sizing: border-box;
  border-radius: 20px; border: 1px solid #747775; background: #FFFFFF; color: #1F1F1F;
  font-family: 'Roboto', 'Segoe UI', Arial, sans-serif; font-size: 14px; font-weight: 500; letter-spacing: 0.25px;
  text-decoration: none; cursor: pointer; transition: background 0.15s ease, box-shadow 0.15s ease;
}
.btn-google:hover { background: #F2F2F2; box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15); }
.btn-google:focus-visible { outline: 2px solid #4285F4; outline-offset: 2px; }
.btn-google .btn-google-logo { flex-shrink: 0; display: block; }
:root[data-theme="dark"] .btn-google { background: #131314; border-color: #8E918F; color: #E3E3E3; }
:root[data-theme="dark"] .btn-google:hover { background: #1F1F20; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn-google { background: #131314; border-color: #8E918F; color: #E3E3E3; }
  :root:not([data-theme="light"]) .btn-google:hover { background: #1F1F20; }
}

/* --- węższe ekrany (strona główna) --- */
/* Plansza ma 1440 px i kontener 1200. Nagłówek z planszy potrzebuje ok. 1190 px, a przycisk
   motywu dokłada swoje - poniżej 1320 px język zostaje samą flagą, a menu gęstnieje. */
@media (max-width: 1320px) {
  .lp-header-inner { gap: 28px; }
  .lp-nav { gap: 20px; }
  .lp-lang-picker .lang-picker-name { display: none; }
}
/* Karta Premium węższa niż na planszy (poniżej ok. 1250 px): „/mies. przy płatności za rok"
   wjeżdżało pod skrzynię z ilustracji. Cena ustępuje ilustracji miejsca i zawija się pod kwotę,
   a sama ilustracja maleje. */
@media (max-width: 1250px) {
  .lp-plan-ilu { width: 160px; height: 160px; }
  .lp-plan--premium .lp-plan-cena-blok { max-width: calc(100% - 140px); }
}
/* Poniżej 1120 px menu nie mieści się obok przycisków. Znika - jak w poprzedniej wersji
   strony - bo każda jego pozycja jest też na samej stronie: tryby i metoda to sekcje niżej,
   Artykuły i Społeczność mają własne sekcje z przyciskiem, a Artykuły jeszcze w stopce. */
@media (max-width: 1120px) {
  .lp-nav { display: none; }
  /* Tablet i wąskie okno: tekst hero w jednej kolumnie (chip, nagłówek, opis, przyciski, nota), film pod nim. W dwóch
     kolumnach przy 1024 px nagłówek miał trzy wiersze, przyciski stały jeden pod drugim, a nota wisiała sama
     w prawej kolumnie (zmierzone zrzutem 1024 × 768: tekst 385 px). */
  .lp-hero-uklad { gap: 36px; padding: 40px 0 64px; }
  .lp-hero-tekst { grid-template-columns: minmax(0, 1fr); grid-template-areas: "chip" "h1" "opis" "akcje" "nota"; row-gap: 20px; }
  .lp-hero-opis { padding-bottom: 0; max-width: 40rem; }
  .lp-hero-tekst > .lp-hero-nota { margin-top: 0; }
  .lp-metoda-uklad { grid-template-columns: minmax(0, 1fr); gap: 48px; }
  .lp-metoda-lewa { display: grid; grid-template-columns: minmax(0, 1fr) 470px; gap: 40px; align-items: center; }
  .lp-stos { margin-top: 0; }
  /* Trzy liczby w trzech wąskich kolumnach: liczba nad opisem, bo obok niego opis
     „pełnego Premium dla każdego nowego konta" łamał się na pięć wierszy po jednym słowie. */
  .lp-liczba { flex-direction: column; align-items: flex-start; gap: 8px; }
  .lp-liczba-ile { font-size: 56px; }
}
@media (max-width: 980px) {
  .lp-tryby-siatka { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lp-metoda-lewa { grid-template-columns: minmax(0, 1fr); }
  .lp-stos { justify-self: center; }
  .lp-art-siatka, .lp-art-siatka--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Karta „Wszystkie artykuły" idzie na całą szerokość pod dwa artykuły; tekst trzyma się
     z dala od ilustracji w prawym górnym rogu, inaczej wchodził na postać. */
  .lp-art-siatka .lp-art-wszystkie { grid-column: 1 / -1; min-height: 240px; padding-inline-end: 250px; }
  .lp-art-siatka--2 .lp-art-wszystkie { grid-column: auto; min-height: 320px; padding-inline-end: 26px; }
  .lp-zestawy2, .lp-zestawy2--1 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lp-zestaw2--duzy { grid-row: auto; grid-column: 1 / -1; }
  .lp-zestaw2--duzy .lp-zestaw2-foto { min-height: 300px; }
  .lp-zestawy2--3 .lp-nowosci-info { grid-column: auto; }
  .lp-jezyki-uklad, .lp-jezyki-uklad--film { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .lp-jezyki-ilu { width: 260px; justify-self: center; }
  .lp-cennik, .lp-faq { grid-template-columns: minmax(0, 1fr); }
  .lp-final { grid-template-columns: minmax(0, 1fr) 260px; padding: 44px 40px; gap: 24px; }
  .lp-final-ilu { width: 260px; height: 260px; margin: -20px 0 -44px; }
}
@media (max-width: 860px) {
  .lp-sek-glowa { flex-direction: column; align-items: flex-start; gap: 16px; }
  .lp-sek-glowa--srodek { align-items: center; }
  .lp-sek-opis { max-width: 40rem; }
  /* Trzy liczby jedna pod drugą w JEDNEJ siatce (display: contents na wierszu): kolumna liczb
     ma szerokość najszerszej (do 2026-10-11 „60 min", dziś „160” albo „0 zł”), więc opisy zaczynają się w jednej linii. Osobne
     wiersze flex dawały poszarpany lewy brzeg opisów, a minimalna szerokość na liczbie
     pozwalała „60 min" wjechać pod opis obok. */
  .lp-liczby-uklad { grid-template-columns: max-content minmax(0, 1fr); column-gap: 18px; row-gap: 14px; align-items: center; padding: 30px 0; }
  .lp-liczba { display: contents; }
  .lp-liczba-ile { font-size: 52px; }
  .lp-liczba-co { max-width: none; }
  .lp-metoda-kroki { grid-template-columns: minmax(0, 1fr); }
  .lp-final { grid-template-columns: minmax(0, 1fr); text-align: start; }
  .lp-final-ilu { order: -1; width: 200px; height: 200px; margin: -8px 0 -16px; justify-self: center; }
  body:has(#authScreen:not(.hidden)) > .app-stopka { justify-content: flex-start; gap: 10px 20px; padding: 40px 20px 36px; }
  body:has(#authScreen:not(.hidden)) > .app-stopka::before { flex-basis: 100%; margin: 0 0 8px; background-position: left center; }
  [dir="rtl"] body:has(#authScreen:not(.hidden)) > .app-stopka::before { background-position: right center; }
  body:has(#authScreen:not(.hidden)) > .app-stopka > span:first-child,
  body:has(#authScreen:not(.hidden)) > .app-stopka .app-stopka-marka { flex-basis: 100%; }
}
/* TELEFON. Nagłówek w dwóch rzędach, jak w poprzedniej wersji strony: logo z kółkami motywu
   i języka u góry, „Zaloguj się" i „Zacznij za darmo" pod nimi. Trzy przyciski i dwa kółka
   w jednym rzędzie potrzebują ok. 520 px, a telefon ma 360-390; ścinanie napisów po kilka
   pikseli zrobiłoby z nich zagadkę. .lp-header-akcje znika z układu (display: contents),
   żeby obie grupy przycisków mogły stanąć w różnych rzędach. */
@media (max-width: 640px) {
  .auth-screen { --lp-pion: 60px; }
  /* Dwurzędowy nagłówek jest wyższy niż 84 px. Tylko pod stroną główną - scroll-padding
     działa też na scrollIntoView() w aplikacji, która ma własny, niższy nagłówek. */
  html:has(#authScreen:not(.hidden)) { scroll-padding-top: 120px; }
  .lp-kontener, .lp-header-inner { width: min(var(--lp-max), 100% - 32px); }
  .lp-header-inner { flex-wrap: wrap; gap: 10px 8px; min-height: 0; padding: 10px 0 12px; }
  .lp-header-logo { height: 30px; }
  .lp-header-akcje { display: contents; }
  .lp-header-narzedzia { margin-inline-start: auto; gap: 8px; }
  .lp-header-konto { flex-basis: 100%; gap: 8px; }
  .lp-header .lp-header-theme { width: 40px; height: 40px; }
  .lp-lang-picker .lang-picker-btn { min-height: 40px; padding-inline: 9px 10px; }
  .lp-header-konto .lp-btn-kontur { min-height: 44px; padding: 0 16px; font-size: 14px; }
  .lp-header-konto .lp-cta { flex: 1; --cta-wys: 44px; --cta-kolko-r: 34px; --cta-font: 14px; padding-inline-start: 18px; gap: 10px; }
  .lp-hero-uklad { padding: 32px 0 48px; gap: 28px; }
  .lp-hero-tekst { row-gap: 18px; }
  .lp-hero-chip { font-size: 13px; }
  .lp-hero-opis { font-size: 17px; }
  .lp-hero-akcje { flex-direction: column; align-items: stretch; width: 100%; margin-top: 0; gap: 10px; }
  .lp-hero-akcje .lp-cta, .lp-hero-przyklad { width: 100%; }
  .lp-hero-przyklad { min-height: 56px; font-size: 15px; }
  .lp-hero-film .fp { border-radius: 18px; }
  .lp-hero-film::before { inset: 4% 2% -4%; filter: blur(18px); }
  .lp-liczba-ile { font-size: 44px; }
  .lp-liczba-co { font-size: 15px; }
  .lp-tryby-siatka { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .lp-tryb-ilu { width: 160px; height: 160px; margin-top: 16px; }
  .lp-tryb-tresc { padding: 6px 22px 24px; }
  .lp-tryb-tytul, .lp-upusc-tytul { font-size: 23px; }
  .lp-tryb-opis, .lp-upusc-opis { font-size: 15px; }
  .lp-upusc { padding: 22px; }
  .lp-metoda-uklad { gap: 36px; }
  .lp-metoda-opis { font-size: 16px; }
  /* Stos trzech fiszek ma układ w pikselach (karty obrócone, zachodzące na siebie) i 470 px
     szerokości. Na telefonie zmniejszamy go w całości przez `zoom`, który - w odróżnieniu
     od transform: scale() - zmniejsza też miejsce w układzie, więc pod stosem nie zostaje
     pusty pas wysokości oryginału. */
  .lp-stos { zoom: 0.72; }
  .lp-krok { padding: 20px; }
  .lp-krok-tytul { font-size: 21px; }
  .lp-art-siatka, .lp-art-siatka--2 { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  /* Na telefonie ilustracja stoi NAD tekstem (padding od góry), a nie obok - na 358 px nie ma
     „obok", a tekst na postaci był nieczytelny. */
  .lp-art-siatka .lp-art-wszystkie, .lp-art-siatka--2 .lp-art-wszystkie {
    grid-column: auto; min-height: 0; padding: 168px 22px 24px;
  }
  .lp-art-tytul { font-size: 22px; }
  .lp-art-wszystkie-tytul { font-size: 30px; }
  .lp-art-wszystkie-ilu { width: 180px; height: 180px; top: -4px; inset-inline-end: -6px; }
  .lp-zestawy2, .lp-zestawy2--1 { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .lp-zestaw2--duzy { grid-column: auto; }
  .lp-zestaw2--duzy .lp-zestaw2-foto { min-height: 240px; }
  .lp-zestaw2-foto { height: 150px; }
  .lp-zestaw2--duzy .lp-zestaw2-tytul { font-size: 21px; }
  .lp-jezyki-ilu { width: 220px; }
  .lp-jezyki-opis { font-size: 16px; }
  .lp-flagi { gap: 8px; }
  .lp-flaga { min-height: 40px; font-size: 14px; padding-inline: 9px 13px; }
  .lp-plan { padding: 26px 22px; gap: 18px; border-radius: 26px; }
  .lp-plan-ilu { width: 130px; height: 130px; top: -4px; inset-inline-end: -8px; }
  .lp-plan-kwota { font-size: 56px; }
  .lp-plan-lista li { font-size: 15px; }
  .lp-plan-stopka .lp-cta { width: 100%; white-space: normal; text-align: start; }
  .lp-faq-poz summary { font-size: 16px; padding-inline: 18px 12px; }
  .lp-faq-poz p { padding: 0 18px 18px; font-size: 15px; }
  .lp-final { padding: 32px 22px 30px; border-radius: 28px; gap: 12px; }
  .lp-final-tekst { gap: 24px; }
  .lp-final-tekst .lp-cta { width: 100%; }
  .lp-final-ilu { width: 170px; height: 170px; }
}
@media (max-width: 380px) {
  .lp-stos { zoom: 0.66; }
  .lp-header-logo { height: 26px; }
}
@media (prefers-reduced-motion: reduce) {
  .lp-cta:hover, .lp-tryb:hover, .lp-art:hover, .lp-art-wszystkie:hover, .lp-zestaw2:hover,
  .lp-flaga:hover { transform: none; }
  .lp-cta:hover .lp-cta-kolko, .lp-link-dalej:hover .lp-link-dalej-strzalka { transform: none; }
  .lp-faq-plus { transition: none; }
}
.auth-card {
  position: relative; z-index: 3;
  background: var(--card-bg);
  border-radius: 24px;
  width: 100%; max-width: 380px;
  padding: 32px 28px;
  box-shadow: 0 24px 80px rgba(0,0,0,0.35);
}
.auth-brand { text-align: center; margin-bottom: 24px; }
/* Znak marki na karcie logowania jest wiekszy niz w naglowku - to pierwsza rzecz, ktora widzi
   ktos, kto trafil tu z reklamy albo z linku, i musi od razu powiedziec, gdzie jest.
   margin:auto, bo .logo-marka jest display:block, a karta wysrodkowuje tekstem. */
.auth-logo { height: 55px; margin: 0 auto 6px; max-width: 100%; }
.auth-subtitle { font-size: 0.85rem; color: var(--grigio); margin-top: 2px; }
.auth-input {
  width: 100%;
  padding: 12px 16px;
  border-radius: 12px;
  border: 2px solid var(--border-warm);
  background: var(--crema);
  font-size: 0.95rem;
  font-family: inherit;
  margin-bottom: 12px;
  outline: none;
  transition: var(--transition);
}
.auth-input:focus { border-color: var(--oro); }
.auth-label { display: block; font-size: 0.8rem; color: var(--grigio); margin: -4px 0 8px 2px; }
.auth-info {
  font-size: 0.78rem; color: var(--muted-dark); line-height: 1.55; margin: 0 0 12px;
  background: var(--bg-soft); border: 1px solid var(--border); border-radius: 12px; padding: 10px 13px;
}

/* Powitalne pytania o język - dwa kroki tuż po założeniu konta. Bez przycisku zamykania:
   bez tych odpowiedzi aplikacja nie wie, w jakim języku mówić ani czego uczyć. */
.onboarding-overlay {
  position: fixed; inset: 0; z-index: 300; background: rgba(2,6,23,0.88);
  display: flex; align-items: center; justify-content: center; padding: 22px;
}
.onboarding-karta {
  background: var(--card-bg); border-radius: 22px; padding: 30px 28px; max-width: 460px;
  width: 100%; max-height: 90vh; overflow-y: auto; box-shadow: var(--shadow-hover); text-align: center;
}
.onboarding-krok { font-size: 0.72rem; font-weight: 800; color: var(--oro); letter-spacing: 0.08em; text-transform: uppercase; }
.onboarding-karta h2 { font-size: 1.3rem; margin: 8px 0 8px; }
.onboarding-karta p { font-size: 0.88rem; color: var(--grigio); line-height: 1.6; margin: 0 0 18px; }
.onboarding-uwaga {
  font-size: 0.76rem; color: var(--muted-dark); background: var(--bg-warn-soft);
  border-radius: 12px; padding: 10px 13px; margin: 0 0 18px; line-height: 1.5;
}
.onboarding-lista { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 8px; margin-bottom: 20px; }
.onboarding-jezyk {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px; cursor: pointer;
  border: 2px solid var(--border); border-radius: 14px; background: var(--card-bg);
  font-family: inherit; font-size: 0.85rem; font-weight: 700; color: var(--testo);
  transition: var(--transition); text-align: left;
}
.onboarding-jezyk:hover { border-color: var(--border-2); transform: translateY(-1px); }
.onboarding-jezyk.wybrany { border-color: var(--oro); background: var(--bg-highlight); }
.onboarding-jezyk.polecany { border-color: var(--oro); box-shadow: 0 0 0 3px color-mix(in srgb, var(--oro) 18%, transparent); }
.onboarding-podpowiedz {
  font-size: 0.78rem; color: var(--muted-dark); background: var(--bg-info-soft);
  border-radius: 12px; padding: 10px 13px; margin: 0 0 14px; line-height: 1.5;
}
.onboarding-jezyk svg, .onboarding-jezyk img { flex-shrink: 0; }

/* =========================================================
   LEJEK STARTOWY - pierwsze wejście na stronę, jeszcze bez konta
   (patrz api/start.php i sekcja "LEJEK STARTOWY" w JS niżej)

   Kolejność ekranów jest odwrócona względem klasycznej rejestracji: najpierw język, potem
   po co komu ten język, potem krótka lekcja z pięcioma słówkami - a konto dopiero na końcu.
   Dlatego przez CAŁY lejek na górze stoi jeden pasek postępu: bez niego człowiek nie wie,
   czy jest w połowie drogi, czy dopiero na jej początku, i porzuca lejek w lekcji.
   ========================================================= */
.start-overlay {
  position: fixed; inset: 0; z-index: 3200; background: var(--crema);
  display: flex; flex-direction: column; overflow-y: auto;
}
.start-top {
  position: sticky; top: 0; z-index: 2; flex-shrink: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px 12px; background: var(--crema);
}
.start-wyjscie {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
  border: none; background: transparent; color: var(--grigio);
  font-size: 1.1rem; line-height: 1; font-family: inherit; transition: var(--transition);
}
.start-wyjscie:hover { background: var(--bg-soft); color: var(--testo); }
/* Krzyżyk i strzałka z kreski (LK_SVG w JS) zamiast znaków „✕" / „←" z czcionki. */
.start-wyjscie svg { display: block; width: 18px; height: 18px; margin: auto; }
[dir="rtl"] .start-wyjscie svg { transform: scaleX(-1); }
/* Pasek postępu ZAKŁADANIA KONTA - jedyny element widoczny na każdym ekranie lejka. */
.start-pasek {
  flex: 1; height: 14px; border-radius: 999px; overflow: hidden;
  background: var(--bg-soft); border: 1px solid var(--border);
}
.start-pasek-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel));
  transition: width 0.55s cubic-bezier(.4,0,.2,1);
}
.start-krok-etykieta {
  flex-shrink: 0; font-size: 0.72rem; font-weight: 800; color: var(--grigio);
  letter-spacing: 0.04em; white-space: nowrap;
}
.start-scena { flex: 1; display: flex; justify-content: center; padding: 8px 18px 40px; }
.start-panel { width: 100%; max-width: 560px; text-align: center; animation: startWejdz 0.32s cubic-bezier(.4,0,.2,1); }
@keyframes startWejdz { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .start-panel { animation: none; } }

.start-h { font-size: 1.42rem; font-weight: 800; color: var(--testo); margin: 10px 0 6px; line-height: 1.3; }
.start-p  { font-size: 0.9rem; color: var(--grigio); line-height: 1.6; margin: 0 0 20px; }
.start-blad { background: var(--bg-error-soft); color: var(--rosso); border-radius: 10px; padding: 9px 12px; font-size: 0.82rem; margin: 0 0 14px; }

/* Pigułka „Mówię po…", siatka języków (.start-lista, .start-jezyk) i logo nad nimi (.start-marka) zeszły
   2026-09-26 razem ze starym krokiem 1 - krok 1 i 2 rysuje dziś sekcja „LEJEK W STYLU KANWY" niżej. */

/* Kafle wyboru jednej kolumny. Niesie je już tylko okno celów dla konta, które je zmienia (#celePanelKafelki):
   cele lejka przeszły 2026-09-26 do siatki kafli w stylu kanwy (.lk-kafel-cel), a poziom 2026-09-27
   (.lk-kafel-poziom). */
.start-cele { display: grid; gap: 10px; margin-bottom: 22px; }
.start-cel {
  display: flex; align-items: center; gap: 13px; padding: 14px 16px; cursor: pointer;
  border: 2px solid var(--border); border-radius: 16px; background: var(--card-bg);
  font-family: inherit; color: var(--testo);
  transition: var(--transition); text-align: left; position: relative;
}
.start-cel:hover { border-color: var(--border-2); transform: translateY(-2px); }
.start-cel.wybrany { border-color: var(--oro); background: var(--bg-highlight); }
.start-cel-ico { font-size: 1.6rem; line-height: 1; flex-shrink: 0; }
.start-cel-tresc { min-width: 0; }
.start-cel-tresc b { font-size: 0.94rem; font-weight: 700; line-height: 1.4; }
.start-cel-ptak { margin-left: auto; color: var(--oro); font-weight: 900; font-size: 1.1rem; opacity: 0; transition: var(--transition); flex-shrink: 0; }
.start-cel.wybrany .start-cel-ptak { opacity: 1; }

/* Duży zielony przycisk „dalej" - ten sam kształt na każdym ekranie lejka, żeby po dwóch
   krokach ręka wiedziała, gdzie go szukać. */
.start-cta {
  width: 100%; padding: 15px 20px; border: none; border-radius: 999px; cursor: pointer;
  background: var(--oro); color: var(--na-akcencie);
  font-family: inherit; font-size: 1rem; font-weight: 800; letter-spacing: 0.01em;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--oro) 65%, black);
  transition: transform 0.08s ease, box-shadow 0.08s ease, opacity var(--transition);
}
.start-cta:hover:not(:disabled) { transform: translateY(1px); box-shadow: 0 3px 0 color-mix(in srgb, var(--oro) 65%, black); }
.start-cta:active:not(:disabled)  { transform: translateY(4px); box-shadow: none; }
.start-cta:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.start-link { display: block; margin: 16px auto 0; background: none; border: none; cursor: pointer;
  font-family: inherit; font-size: 0.84rem; font-weight: 700; color: var(--grigio); }
.start-link:hover { color: var(--oro); text-decoration: underline; }

/* --- Lekcja próbna ---
   Sama fiszka i samo pytanie quizu NIE mają tu własnych stylów: lekcja składa się z tych
   samych komponentów, które dostaje osoba zalogowana (.flip-container z .flip-front/.flip-back
   oraz .mini-exam-card z .quiz-slowo-opcja). To nie jest oszczędność kodu, tylko obietnica:
   to, co ktoś zobaczy przed rejestracją, ma być tym, co zastanie po niej - inaczej lejek
   sprzedaje aplikację, której nie ma. Poniżej zostaje wyłącznie to, czego w aplikacji nie ma. */
/* Karta w lekcji stoi sama na środku, bez paska filtrów i statystyk, więc dostaje trochę
   powietrza z góry - inaczej klei się do paska postępu. */
.start-panel .flip-container { margin-top: 6px; }
/* Podpowiedź „kliknij kartę" znika, gdy karta zostanie obrócona - dalej prowadzi już przycisk. */

/* --- Ekran wyniku --- */

/* --- Ostatni krok: konto --- */
.start-form { text-align: left; margin-bottom: 4px; }
.start-form .auth-input { margin-bottom: 10px; }

@media (max-width: 560px) {
  .start-scena { padding: 8px 14px 32px; }
  .start-h { font-size: 1.24rem; }
  .start-krok-etykieta { display: none; } /* na wąskim ekranie liczy się sam pasek */
}
/* Kolumna sceny lejka. Dawniej style="max-width:560px" wprost w znaczniku #startScena - styl w atrybucie
   wygrywa z każdym selektorem, a kroki w stylu kanwy (niżej) potrzebują na komputerze szerszej kolumny. */
.start-scena-in { width: 100%; max-width: 560px; }

/* =========================================================
   LEJEK W STYLU KANWY - krok 1 (język nauki) i krok 2 (cele) jak w aplikacji mobilnej (2026-09-26)

   Alek: „zrobi onboarding aplikacji w desktop, czyli ten LEVEL 1 i LEVEL 2 dla nowego użytkownika,
   dosłownie odgapi się od naszej aplikacji mobilnej, jak to wygląda, i przeniesie na desktop … bo jeszcze
   jest stare". WZÓR: lingaria-app/src/app/(gosc)/index.tsx (krok 1) i cele.tsx (krok 2) z klockami
   z komponenty/marka.tsx - kolor marki na cały ekran (krok 1 niebieski #2463E9, krok 2 żółty #FFC83D),
   cienki pasek postępu na górze, nadtytuł „KROK N Z 4" nad tytułem Outfit 800, ilustracja z Higgsfielda
   w prawym górnym rogu, białe kafle (wybrany granatowy z żółtym ptaszkiem), granatowa pigułka „Dalej"
   z żółtym kółkiem (.btn-strzalka w .na-kolorze). Numeracja kroków jak w aplikacji: „z 3” dla trzech pytań
   (START_NUMER_KROKU), a próba aplikacji i konto bez numeru, z „Prawie gotowe” (2026-09-27, „byle było spójnie”).
   Od 2026-09-27 tak samo wygląda krok 3 - POZIOM (plansza „Krok 3", zielony #35A64D z granatowym tekstem,
   kafle z plakietką CEFR w barwach logo; niżej „Poziom").

   UKŁAD: do 720 px wymiary 1:1 z aplikacji (tytuł 40 px w kolumnie 232 px, ilustracja 204 px wystająca
   za prawą krawędź, kafle w dwóch kolumnach, licznik z „Dalej" przyklejony na dole). Na komputerze ten sam
   język w kolumnie 1040 px: ilustracja obok tytułu zamiast nad kaflami, kafle języków w czterech kolumnach -
   24 języki po dwa to dwanaście rzędów przewijania na ekranie, który ma miejsce na cztery kafle w rzędzie.

   BARWY STAŁE W OBU MOTYWACH (jak ekrany marki w aplikacji i sekcje strony głównej): niebieski krok jest
   niebieski także w ciemnym motywie, dlatego tokeny --lk-* mają wartości wpisane, a nie --primary czy
   --marka-niebieski, które w ciemnym jaśnieją. Kontrast policzony wzorem WCAG: biały na #2463E9 5,2 : 1,
   żółte „Zmień" na #204EB8 4,8 : 1, granat na #FFC83D 11 : 1, żółta obwódka fokusu na niebieskim 3,4 : 1
   i granatowa na żółtym 11 : 1 (próg dla obwódki 3 : 1).

   WŁĄCZNIK: atrybut data-kolor na #startOverlay (ustawia go startUstawPostep z START_KOLOR_KROKU). Ekrany
   poziomu, ładowania, próby aplikacji i konta go nie mają, więc zostają w dotychczasowym wyglądzie.
   ========================================================= */
.start-overlay[data-kolor] {
  --lk-niebieski: #2463E9;
  --lk-niebieski-ciemny: #204EB8;
  --lk-zolty: #FFC83D;
  --lk-granat: #17183B;
  --lk-bialy: #FFFFFF;
  --lk-kolumna: 1040px;
  --lk-tlo: var(--lk-niebieski);
  --lk-tekst: var(--lk-bialy);
  --lk-tor: rgba(255, 255, 255, 0.3);
  --lk-fokus: var(--lk-zolty);
  background: var(--lk-tlo); color: var(--lk-tekst);
  /* Ilustracja wystaje za prawą krawędź jak na planszy (right −28 pt): zmierzone na 390 px, że treść nakładki
     ma wtedy 398 px szerokości (w kroku 2: 410 px). Nakładka przewija się w pionie, więc overflow-x liczyłby
     się jako auto i telefon dostałby przewijanie w bok - stąd hidden. */
  overflow-x: hidden;
}
.start-overlay[data-kolor="zolty"] {
  --lk-tlo: var(--lk-zolty);
  --lk-tekst: var(--lk-granat);
  --lk-tor: rgba(23, 24, 59, 0.2);
  --lk-fokus: var(--lk-granat);
}
/* Krok 3 (poziom): zieleń z logo i granat, jak plansza „Krok 3" i EkranMarki tlo="zielony" w aplikacji. Biały na tej
   zieleni ma 3,1 : 1 (za mało na drobny tekst), granat 5,6 : 1 - stąd granatowy tekst, pasek i obwódka fokusu. */
.start-overlay[data-kolor="zielony"] {
  --lk-tlo: #35A64D;
  --lk-tekst: var(--lk-granat);
  --lk-tor: rgba(23, 24, 59, 0.2);
  --lk-fokus: var(--lk-granat);
}
/* Pasek zakładania konta zostaje TEN SAM element (rośnie, nie przeskakuje - patrz #startOverlay), zmienia się
   wygląd: cienka kreska w barwie tekstu ekranu jak PasekKrokow w aplikacji, w szerokości kolumny treści.
   Strzałka i etykieta z procentem chowają się: wyjście stoi w wierszu pod paskiem (krzyżyk w kroku 1,
   strzałka w kroku 2), a numer kroku nad tytułem. */
.start-overlay[data-kolor] .start-top {
  background: var(--lk-tlo);
  padding: 16px max(20px, calc((100% - var(--lk-kolumna)) / 2)) 6px;
}
.start-overlay[data-kolor] .start-wyjscie,
.start-overlay[data-kolor] .start-krok-etykieta { display: none; }
.start-overlay[data-kolor] .start-pasek { height: 6px; border: none; background: var(--lk-tor); }
.start-overlay[data-kolor] .start-pasek-fill { background: var(--lk-tekst); }
.start-overlay[data-kolor] .start-scena { padding: 12px 20px 0; }
.start-overlay[data-kolor] .start-scena-in { max-width: var(--lk-kolumna); }
.start-panel.lk-panel {
  max-width: none; text-align: start; color: var(--lk-tekst);
  display: flex; flex-direction: column; gap: 18px; padding-bottom: 40px;
}
.start-panel.lk-panel-cele { padding-bottom: 0; }
.lk-panel :is(button, a):focus-visible { outline: 3px solid var(--lk-fokus); outline-offset: 3px; }

/* Wiersz pod paskiem: po lewej wyjście (i sygnet w kroku 1), po prawej pigułki. Na telefonie język
   aplikacji schodzi do własnego wiersza, jak na planszy „Krok 1". */
.lk-gora {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas: "lewa . ui prawa"; align-items: center; gap: 12px;
}
.lk-gora-lewa { grid-area: lewa; display: flex; align-items: center; gap: 12px; }
.lk-gora .lk-ui { grid-area: ui; }
.lk-gora .lk-prawa { grid-area: prawa; }
/* Okrągły przycisk 44 px (PrzyciskKolowy): granatowy z białą ikoną. */
.lk-kolo {
  flex: none; width: 44px; height: 44px; padding: 0; border: none; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--lk-granat); color: var(--lk-bialy); transition: transform 0.15s ease;
}
.lk-kolo svg { width: 22px; height: 22px; }
[dir="rtl"] .lk-kolo-wstecz svg { transform: scaleX(-1); }
/* Sygnet na białym kwadracie (LogoMarki) - jedyny znak marki na kolorowym ekranie. */
.lk-logo {
  flex: none; width: 44px; height: 44px; border-radius: 14px; background: var(--lk-bialy);
  display: inline-flex; align-items: center; justify-content: center;
}
.lk-logo img { width: 32px; height: 32px; display: block; }
/* Biała pigułka 44 px („Mam już konto", język nauki w kroku 2 - PigulkaMarki). */
.lk-pigulka {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; max-width: 100%;
  padding: 0 18px; border: none; border-radius: 999px; cursor: pointer;
  background: var(--lk-bialy); color: var(--lk-granat);
  font-family: var(--font-tekst); font-size: 15px; font-weight: 700; line-height: 1.2; white-space: nowrap;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.lk-pigulka.z-flaga { padding-inline-start: 8px; }
/* Język APLIKACJI: ciemniejsza niebieska pigułka z żółtym „Zmień". */
.lk-ui {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; max-width: 100%;
  padding-block: 6px; padding-inline: 8px 16px; border: none; border-radius: 999px; cursor: pointer;
  background: var(--lk-niebieski-ciemny); color: var(--lk-bialy); text-align: start;
  font-family: var(--font-tekst); font-size: 14px; font-weight: 600; line-height: 1.2;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.lk-ui-tekst { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk-ui-zmien { flex: none; color: var(--lk-zolty); font-weight: 800; }
/* Flaga w kółku (FlagaWKolku): prostokąt 3:2 przycięty do koła - szerokość 150% średnicy. */
.lk-flaga-kolo {
  flex: none; width: 30px; height: 30px; border-radius: 999px; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 1.5px rgba(23, 24, 59, 0.16);
}
.lk-pigulka .lk-flaga-kolo { width: 28px; height: 28px; }
.lk-ui .lk-flaga-kolo { box-shadow: 0 0 0 2px var(--lk-bialy); }
.lk-flaga-kolo .flag-icon { flex: none; width: 150%; height: 100%; border-radius: 0; box-shadow: none; }

/* NAGŁÓWEK Z ILUSTRACJĄ (NaglowekMarki): nadtytuł i tytuł w wąskiej kolumnie, ilustracja w rogu. Wysokość
   kolumny tytułu bierze się z ilustracji (min-height), żeby opis pod spodem nie wjechał pod jej dół. */
.lk-glowa { position: relative; margin-top: 2px; }
.lk-ilustracja {
  position: absolute; top: -6px; inset-inline-end: -28px; width: min(204px, 52vw); height: auto;
  pointer-events: none; user-select: none;
}
.lk-krok2 .lk-ilustracja { top: -24px; inset-inline-end: -40px; width: min(212px, 54vw); }
.lk-glowa-tekst {
  position: relative; width: 232px; max-width: calc(100% - 110px); min-height: 190px;
  display: flex; flex-direction: column; gap: 10px;
}
.lk-krok2 .lk-glowa-tekst { min-height: 180px; }
.lk-glowa.bez-ilustracji .lk-glowa-tekst { width: auto; max-width: none; min-height: 0; }
.lk-nadtytul { font-size: 13px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1.3; }
.lk-tytul {
  margin: 0; color: inherit; font-family: var(--font-naglowek); font-weight: 800;
  font-size: min(40px, 10.3vw); line-height: 1.02; letter-spacing: -0.02em;
}
/* Tytuł dostaje fokus programowo przy zmianie ekranu (startNaPoczatekEkranu) - to nie jest element
   do klikania, więc bez obwódki. */
.lk-tytul:focus { outline: none; }
.lk-opis { margin: 16px 0 0; max-width: 340px; color: inherit; font-size: 15px; font-weight: 500; line-height: 1.5; }

/* KAFLE (KafelMarki): białe na kolorze, wybrany granatowy z żółtym ptaszkiem. */
.lk-siatka { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 4px; }
.lk-kafel {
  position: relative; display: flex; align-items: center; gap: 12px; min-width: 0; min-height: 58px;
  padding-block: 10px; padding-inline: 14px 12px; border: none; border-radius: 18px; cursor: pointer;
  background: var(--lk-bialy); color: var(--lk-granat); text-align: start;
  font-family: var(--font-tekst); font-size: 16px; font-weight: 700; line-height: 1.25;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}
.lk-kafel.wybrany { background: var(--lk-granat); color: var(--lk-bialy); }
.lk-kafel-nazwa { flex: 1; min-width: 0; overflow-wrap: break-word; }
.lk-flaga {
  flex: none; display: inline-flex; border-radius: 5px; overflow: hidden;
  box-shadow: 0 0 0 1.5px rgba(23, 24, 59, 0.16);
}
.lk-flaga .flag-icon { width: 30px; height: 20px; border-radius: 0; box-shadow: none; }
.lk-znak {
  flex: none; width: 26px; height: 26px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--lk-zolty); color: var(--lk-granat);
}
.lk-znak svg { width: 15px; height: 15px; }
/* Ostrzeżenie „język interfejsu na stałe" w liście języków aplikacji (Notka wariant złoty). */
.lk-notka {
  display: flex; align-items: flex-start; gap: 10px; max-width: 640px; padding: 12px 14px; border-radius: 16px;
  background: #FFF6DC; color: var(--lk-granat); font-size: 14px; font-weight: 500; line-height: 1.5;
}
.lk-notka svg { flex: none; width: 20px; height: 20px; margin-top: 1px; color: #8A5A00; }
.lk-notka strong { font-weight: 800; }

/* Cele: kwadrat z dwubarwną ikoną w barwie celu, krótka nazwa jako tytuł i pełne zdanie pod nią;
   ptaszek w rogu. Po wybraniu czterech pozostałe kafle gasną (aria-disabled) zamiast odrzucać klik bez słowa. */
.lk-kafel-cel { flex-direction: column; align-items: flex-start; gap: 10px; min-height: 164px; padding: 14px; border-radius: 20px; }
.lk-kafel-cel .lk-znak { position: absolute; top: 12px; inset-inline-end: 12px; }
.lk-cel-ikona {
  flex: none; width: 44px; height: 44px; border-radius: 14px;
  display: inline-flex; align-items: center; justify-content: center;
}
.lk-cel-ikona svg { width: 28px; height: 28px; }
.lk-cel-tytul { font-family: var(--font-naglowek); font-size: 19px; font-weight: 800; line-height: 1.1; padding-inline-end: 28px; }
.lk-cel-opis { font-size: 13px; font-weight: 500; line-height: 1.38; color: #4A4B6B; }
.lk-kafel-cel.wybrany .lk-cel-opis { color: #D4D5F0; }
.lk-kafel[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
/* Licznik i „Dalej" przyklejone na dole (stopka EkranMarki): siedem kafli po dwa nie mieści się na telefonie. */
.lk-stopka {
  position: sticky; bottom: 0; z-index: 1; margin: 0 -20px;
  padding: 12px 20px max(22px, env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 10px; background: var(--lk-tlo);
}
.lk-licznik { font-size: 14px; font-weight: 700; line-height: 1.3; text-align: center; color: var(--lk-tekst); }
.lk-stopka .btn-strzalka { margin-top: 0; min-height: 58px; font-size: 17px; padding-block: 6px; padding-inline: 24px 6px; }
/* Kółko na strzałkę przy krawędzi KOŃCOWEJ, a nie prawej: wspólne .btn-strzalka ma margin-left: auto i padding
   liczony od lewej, więc po arabsku (dir="rtl") kółko stawało tuż przy napisie, a „Dalej" dotykało krawędzi -
   zmierzone na zrzucie z dir="rtl". Tu tylko dla przycisku lejka; reguła wspólna ma ten sam kłopot. */
.lk-stopka .btn-strzalka::after { margin-left: 0; margin-inline-start: auto; }
.lk-stopka .btn:disabled:hover { box-shadow: none; }

/* Poziom (plansza „Krok 3"): białe kafle na całą szerokość, po lewej plakietka CEFR 54 px w barwie logo (A0 żółta,
   A1 zielona, A2 niebieska, B1 czerwona, B2 granatowa - barwy wpisuje JS z START_POZIOMY), obok nazwa Outfit
   i zdanie o umiejętności; wybrany kafel granatowy z żółtym ptaszkiem na końcu. Wymiary 1:1 z planszy i z poziom.tsx. */
.lk-krok3 .lk-ilustracja { top: -18px; inset-inline-end: -34px; }
.lk-krok3 .lk-glowa-tekst { min-height: 180px; }
.lk-poziomy { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin-top: 4px; }
.lk-kafel-poziom { gap: 14px; min-height: 78px; padding-block: 12px; padding-inline: 14px 12px; border-radius: 20px; }
.lk-cefr {
  flex: none; width: 54px; height: 54px; border-radius: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-naglowek); font-size: 22px; font-weight: 800; line-height: 1;
}
/* Granatowa plakietka B2 na granatowym (wybranym) kaflu zlałaby się z tłem - dostaje wtedy białą obwódkę. */
.lk-kafel-poziom.wybrany .lk-cefr-b2 { box-shadow: 0 0 0 2px var(--lk-bialy); }
.lk-poziom-tresc { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.lk-poziom-nazwa { font-family: var(--font-naglowek); font-size: 18px; font-weight: 800; line-height: 1.15; overflow-wrap: break-word; }
.lk-poziom-opis { font-size: 13px; font-weight: 500; line-height: 1.38; color: #4A4B6B; }
.lk-kafel-poziom.wybrany .lk-poziom-opis { color: #D4D5F0; }

@media (hover: hover) {
  .lk-kolo:hover { transform: scale(1.06); }
  .lk-pigulka:hover, .lk-ui:hover { transform: translateY(-1px); box-shadow: 0 10px 22px -14px rgba(23, 24, 59, 0.75); }
  .lk-kafel:not([aria-disabled="true"]):hover { transform: translateY(-2px); box-shadow: 0 14px 26px -18px rgba(23, 24, 59, 0.8); }
}
.lk-kafel:not([aria-disabled="true"]):active { transform: scale(0.98); }
@media (prefers-reduced-motion: reduce) {
  .lk-kolo, .lk-pigulka, .lk-ui, .lk-kafel { transition: none; }
  .lk-kolo:hover, .lk-pigulka:hover, .lk-ui:hover, .lk-kafel:hover, .lk-kafel:active { transform: none; }
}
/* Telefon: język aplikacji w drugim wierszu (plansza „Krok 1"). Bardzo wąski telefon: jedna kolumna kafli -
   zmierzone na 320 px: w dwóch kolumnach po 135 px 12 z 24 nazw języków łamało się w pół słowa („Angielski",
   „Niderlandzki"). Aplikacja przechodzi na jedną kolumnę tak samo, przy dużym tekście systemu. */
@media (max-width: 720px) {
  .lk-gora.z-ui { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "lewa . prawa" "ui ui ui"; }
  .lk-gora.z-ui .lk-ui { justify-self: start; }
}
@media (max-width: 359px) {
  .lk-siatka { grid-template-columns: minmax(0, 1fr); }
  .lk-kafel-cel { min-height: 0; }
}
/* Komputer: ilustracja obok tytułu, większa typografia, kafle w czterech kolumnach, stopka w jednym rzędzie
   (licznik przy przycisku, po prawej - tam kończy się czytanie). */
@media (min-width: 721px) {
  .start-overlay[data-kolor] .start-scena { padding-top: 20px; }
  .start-panel.lk-panel { gap: 22px; }
  .lk-glowa {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "tekst ilu" "opis ilu"; column-gap: 40px; margin-top: 0;
  }
  .lk-glowa.bez-ilustracji { grid-template-columns: minmax(0, 1fr); grid-template-areas: "tekst" "opis"; }
  /* 260 px przy 1440, nie 300: zmierzone w oknie 1440×900 - przy ilustracji 300 px i kaflach celów 176 px
     krok 2 wymagał przewinięcia o 42 px, a dolny rząd celów wchodził pod przyklejoną stopkę; przy 260 px
     i 164 px (wysokość z aplikacji) mieści się cały, bez przewijania. */
  .lk-ilustracja, .lk-krok2 .lk-ilustracja {
    position: static; grid-area: ilu; align-self: center; width: clamp(200px, 18vw, 260px);
  }
  .lk-glowa-tekst, .lk-krok2 .lk-glowa-tekst {
    grid-area: tekst; align-self: end; width: auto; max-width: none; min-height: 0; gap: 14px;
  }
  .lk-nadtytul { font-size: 14px; }
  /* Wyrównanie wierszy tylko tu: zmierzone na 1440 px, że bez niego zostaje sierota („Jakiego języka chcesz się
     / uczyć?"), z nim „Jakiego języka / chcesz się uczyć?". Na telefonie aplikacja łamie tytuł zwyczajnie
     („chcesz się / uczyć?") i tak ma zostać. */
  .lk-tytul { font-size: clamp(44px, 4.6vw, 64px); max-width: 13em; text-wrap: balance; }
  .lk-opis { grid-area: opis; align-self: start; max-width: 560px; font-size: 17px; }
  .lk-siatka { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
  .lk-siatka-cele { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
  .lk-kafel-cel { min-height: 164px; padding: 16px; }
  .lk-cel-tytul { font-size: 21px; }
  .lk-cel-opis { font-size: 14px; }
  .lk-stopka { margin: 0; padding: 16px 0 24px; flex-direction: row; align-items: center; justify-content: flex-end; gap: 20px; }
  .lk-licznik { text-align: end; }
  .lk-stopka .btn-strzalka { width: auto; min-width: 320px; }
  /* Poziom na komputerze: kafle po trzy w rzędzie (1040 px kolumny), jak cele - pięć pasków na całą szerokość
     zostawiało pod tytułem długie białe wstęgi z krótkim zdaniem po lewej. */
  .lk-krok3 .lk-ilustracja { top: auto; inset-inline-end: auto; }
  .lk-krok3 .lk-glowa-tekst { min-height: 0; }
  .lk-poziomy { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
  .lk-kafel-poziom { min-height: 96px; padding-block: 16px; padding-inline: 16px 14px; }
  .lk-poziom-nazwa { font-size: 20px; }
  .lk-poziom-opis { font-size: 14px; }
}

/* Znacznik „dziś / wczoraj" przy tytule w historii czytanek. Ma wpadać w oko na tyle,
   żeby po dodaniu tekstu ze Społeczności od razu było widać, który wiersz właśnie przybył. */
.tekst-swiezosc {
  /* margin-left:auto dosuwa plakietkę do prawej krawędzi wiersza - wcześniej kleiła się
     do uciętego tytułu, przez co wyglądała jak jego część. */
  flex-shrink: 0; margin-left: auto; padding: 2px 8px; border-radius: 999px;
  background: var(--bg-success-soft); color: var(--verde);
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase;
  vertical-align: middle; white-space: nowrap;
}

/* Pasek zakładania konta nad aplikacją w trybie demo (patrz #startPasekDemo w markupie).
   position: sticky, nie fixed - ma przewijać się razem z nagłówkiem aplikacji zamiast
   zasłaniać go przy przewijaniu w dół. */
.start-pasek-demo {
  position: sticky; top: 0; z-index: 900;
  display: flex; align-items: center; gap: 16px;
  padding: 10px 18px;
  background: var(--card-bg); border-bottom: 1px solid var(--border);
  box-shadow: 0 2px 12px rgba(15,23,42,0.06);
}
.spd-tresc { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.spd-etykieta { font-size: 0.7rem; font-weight: 800; color: var(--grigio); letter-spacing: 0.05em; }
.spd-tor { height: 10px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--border); overflow: hidden; }
.spd-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel));
  transition: width 0.55s cubic-bezier(.4,0,.2,1);
}
/* Przycisk założenia konta jest JEDYNYM wyjściem z dema do przodu - i ma tak wyglądać.
   Duży, zawsze pulsujący, z własnym poświatowym pierścieniem: reszta paska to informacja,
   to jest akcja. */
.spd-cta {
  flex-shrink: 0; border: none; border-radius: 16px; cursor: pointer;
  padding: 14px 30px; background: var(--oro); color: var(--na-akcencie);
  font-family: inherit; font-size: 1.05rem; font-weight: 900; letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--oro) 62%, black);
  animation: spdPuls 2s ease-in-out infinite;
  transition: transform 0.08s ease;
}
.spd-cta:hover  { transform: translateY(1px) scale(1.02); }
.spd-cta:active { transform: translateY(4px); }
@keyframes spdPuls {
  0%, 100% { box-shadow: 0 4px 0 color-mix(in srgb, var(--oro) 62%, black), 0 0 0 0 color-mix(in srgb, var(--oro) 55%, transparent); }
  55%      { box-shadow: 0 4px 0 color-mix(in srgb, var(--oro) 62%, black), 0 0 0 16px transparent; }
}
@media (prefers-reduced-motion: reduce) { .spd-cta { animation: none; } }
@media (max-width: 700px) {
  .start-pasek-demo { flex-wrap: wrap; gap: 10px; padding: 10px 14px; }
  .spd-tresc  { flex-basis: 100%; }
  .spd-cta    { flex: 1; padding: 13px 18px; font-size: 0.98rem; }
}

/* W demie znikają wyłącznie te elementy, które bez konta nie mają czego zrobić. Zakładki
   ZOSTAJĄ (inaczej nie dałoby się zajrzeć do Tekstów i Społeczności, a to połowa aplikacji),
   podobnie flaga języka i statystyki - one pokazują, o co w tym wszystkim chodzi.
   Uwaga: .tryb-demo chodzi w parze z .tryb-goscia, więc trzeba ODKRĘCIĆ to, co tamta klasa
   chowa gościowi z linku do zdjęcia - tamten scenariusz to sama tablica, ten to cała apka. */
/* Podwójna klasa (.tryb-goscia.tryb-demo) nie jest ozdobnikiem: reguły dla samego
   .tryb-goscia stoją NIŻEJ w tym pliku i przy równej wadze wygrywają. Bez podbicia
   szczegółowości zakładki i flaga języka zostawały ukryte mimo tej reguły. */
body.tryb-goscia.tryb-demo .mode-tabs,
body.tryb-goscia.tryb-demo #headerLangSwitcher { display: flex !important; }
body.tryb-demo #kartaDodajSlowka,
body.tryb-demo #streakWrap,
body.tryb-demo .card-delete-btn,
body.tryb-demo .header-lang-caret,
/* Usuwanie z mapy słówek: bez konta nie ma czego skasować, a przycisk, który tylko rzuca
   błędem, jest gorszy niż jego brak. Sama mapa ZOSTAJE - to jedna z lepszych rzeczy
   do pokazania komuś, kto się jeszcze zastanawia. */
body.tryb-demo .wordmap-kat-delall,
body.tryb-demo .wordmap-paczka-usun,
body.tryb-demo .chip-del { display: none !important; }

.auth-hint { font-size: 0.82rem; color: var(--grigio); margin-bottom: 14px; line-height: 1.5; }
.auth-error {
  background: var(--bg-error-soft); color: var(--rosso);
  border-radius: 10px; padding: 8px 12px;
  font-size: 0.82rem; margin-bottom: 12px;
}
/* Adres w kroku 2 resetu: długi e-mail bez spacji łamie się w środku, zamiast rozpychać kartę w bok na telefonie.
   Pod .auth-error, a nie zaraz pod .auth-hint: tam sąsiaduje z regułami samouczka, które rosną w osobnej gałęzi. */
.auth-kod-adres { margin-top: -6px; overflow-wrap: anywhere; }
.auth-kod-adres:empty { display: none; }
/* Zgoda na regulamin - pole wyboru musi być odznaczone domyślnie i zaznaczane świadomie,
   inaczej zgoda nie jest zgodą (RODO wprost wyklucza domyślnie zaznaczone okienka) */
.auth-consent {
  display: flex; align-items: flex-start; gap: 9px; margin: 4px 0 14px;
  font-size: 0.82rem; color: var(--grigio); line-height: 1.5; cursor: pointer;
}
.auth-consent input { margin-top: 3px; flex-shrink: 0; width: 16px; height: 16px; accent-color: var(--oro); }
.auth-consent a { color: var(--oro); font-weight: 700; }
/* Blok zgód przy rejestracji (Alek, 2026-09-11): „Zaznacz wszystko" na górze, gwiazdka przy
   jedynej WYMAGANEJ zgodzie, marketingowa mniejsza i wyszarzona - ma być do znalezienia,
   a nie rzucać się w oczy. Kolor gwiazdki taki jak błędów, bo mówi o tym samym: bez tego nie przejdziesz. */
.auth-consent-wszystko { font-weight: 800; color: var(--testo); margin-bottom: 10px; }
.auth-consent-mala { font-size: 0.74rem; color: var(--muted-light); }
.auth-consent-mala input { width: 14px; height: 14px; accent-color: var(--muted-light); }
.auth-wymagane { color: var(--rosso); font-weight: 800; margin-right: 1px; }
.auth-legal, .settings-legal {
  display: flex; gap: 14px; justify-content: center; margin-top: 18px;
  padding-top: 14px; border-top: 1px solid var(--border-warm-soft);
  font-size: 0.75rem;
}
.auth-legal a, .settings-legal a { color: var(--grigio); text-decoration: none; font-weight: 600; }
.auth-legal a:hover, .settings-legal a:hover { color: var(--oro); text-decoration: underline; }
/* Atrybucja cudzych licencji (dziś Uicons by Flaticon). Osobna linia pod odnośnikami prawnymi,
   bo to nie jest dokument nasz, tylko wymóg cudzej licencji. Do 2026-10-03 stała tu też linijka
   OpenMoji (CC BY-SA 4.0) dla quizów obrazkowych - zeszła razem z nimi. */
.settings-credits {
  margin-top: 10px; text-align: center; font-size: 0.72rem; color: var(--grigio); line-height: 1.6;
}
.settings-credits a { color: var(--grigio); font-weight: 600; text-decoration: underline; }
.settings-credits a:hover { color: var(--oro); }
.auth-switch { text-align: center; font-size: 0.85rem; color: var(--grigio); margin-top: 14px; }
.auth-switch a { color: var(--oro); font-weight: 800; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.auth-switch a:hover { text-decoration: underline; }

/* Style strony głównej stoją wyżej, przy .auth-screen - patrz sekcja STRONA GŁÓWNA. */

/* ===== FLAGI / WYBÓR JĘZYKA ===== */
.flag-icon { border-radius: 3px; box-shadow: 0 0 0 1px rgba(15,23,42,0.12); flex-shrink: 0; display: block; }
.lang-picker { position: relative; margin-bottom: 12px; }
.lang-picker-btn {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-radius: 12px; border: 2px solid var(--border);
  background: var(--crema); font-family: inherit; font-size: 0.95rem; font-weight: 600;
  color: var(--testo); cursor: pointer; transition: var(--transition);
}
.lang-picker-btn:hover { border-color: var(--oro); }
.lang-picker-name { flex: 1; text-align: left; }
.lang-picker-caret { color: var(--grigio); font-size: 0.8rem; }
.lang-picker-list {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 50;
  background: var(--card-bg); border-radius: 14px; box-shadow: var(--shadow-hover);
  max-height: 260px; overflow-y: auto; padding: 6px;
}
.lang-picker-opt {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 9px; cursor: pointer; font-size: 0.9rem; font-weight: 600;
}
.lang-picker-opt:hover { background: var(--crema); }
/* Flaga jezyka na kafelku tablicy - widoczna tylko w miksie jezykow. */
.community-tile-jezyk {
  display: inline-flex; align-items: center; padding: 3px; border-radius: 6px;
  background: color-mix(in srgb, var(--card-bg) 86%, transparent); backdrop-filter: blur(3px);
}
.community-tile-jezyk svg { border-radius: 3px; display: block; }
/* Przelacznik miksu - widoczny wylacznie dla admina i moderatora. */
#cmtyMixBtn.wlaczony { border-color: var(--oro); color: var(--oro); font-weight: 800; }
/* ===== OKNO WYBORU PACZKI DO CWICZENIA ===== */
/* KAFELKI ZAMIAST PASKOW (2026-09-25, Alek: „Ćwicz słowa z paczki powinno być ładnymi kafelkami, a nie paskami,
   miejsce wyboru ma być duże i prostokątne, (większe miniaturki też, jeśli istnieją) … 3–4 na szerokość").
   Siatka auto-fill: w oknie 1080 px wychodza 4 kolumny, na wezszym ekranie 3, na telefonie 2 (media query nizej).
   OKLADKA 16:9: kadr filmu (mqdefault z YouTube'a - 320×180, dokladnie 16:9; hqdefault ma czarne pasy),
   zdjecie z tablicy (community_photos) albo barwna plansza z ikona rodzaju - kolor mowi, skad zbior, zanim
   przeczyta sie tytul. Zielona fala opanowania z wiersza zostala paskiem na dole okladki (--postep). */
#wyborPaczkiOverlay .wordmap-modal { max-width: 1080px; }
.wybor-paczki-lista {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px;
  padding: 16px 20px 22px; overflow-y: auto; align-content: start;
  /* WIERSZE NA WYSOKOŚĆ TREŚCI. Kafelek ma overflow: hidden, a taki element ma w siatce minimum ZERO - przy niskim
     oknie (zmierzone 2026-09-25 w 754×428: trzy rzędy w 300 px) siatka dzieliła wysokość między rzędy i kafelki
     ścinało do 80 px, bez tytułu. max-content trzyma pełny kafelek, a nadmiar się przewija. */
  grid-auto-rows: max-content;
}
.wybor-paczki-lista > .wordmap-empty { grid-column: 1 / -1; }
.wybor-paczki-wiersz {
  position: relative; display: flex; flex-direction: column; min-width: 0; isolation: isolate;
  border-radius: 16px; border: 2px solid var(--border-warm); background: var(--card-bg); color: var(--testo);
  overflow: hidden; transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.wybor-paczki-wiersz:hover, .wybor-paczki-wiersz:focus-within {
  border-color: var(--oro); transform: translateY(-3px); box-shadow: var(--shadow-hover);
}
/* Wejscie w cwiczenie = CALY kafelek poza akcjami (okladka + opis). Akcje to osobne przyciski obok,
   nie w srodku: przycisk w przycisku to niepoprawny HTML, a klik w kosz wchodzilby wtedy tez w cwiczenie. */
.wp-wejdz {
  flex: 1; display: flex; flex-direction: column; align-items: stretch; width: 100%; padding: 0;
  background: none; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.wp-wejdz:focus-visible { outline: 3px solid var(--fokus); outline-offset: -3px; border-radius: 14px; }
.wp-okladka {
  --k: var(--oro);
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 100%; aspect-ratio: 16 / 9; overflow: hidden;
  background: linear-gradient(135deg, color-mix(in srgb, var(--k) 32%, var(--card-bg)), color-mix(in srgb, var(--k) 8%, var(--card-bg)));
}
.wp-okladka-tekst   { --k: var(--marka-niebieski); }
.wp-okladka-plik    { --k: var(--verde); }
.wp-okladka-zdjecie { --k: var(--marka-czerwony); }
.wp-okladka-film    { --k: var(--testo); }
/* Rozmowa w barwie Mówienia (zieleń logo), artykuł jak czytanie (2026-10-07). */
.wp-okladka-rozmowa { --k: var(--marka-zielony, #35A64D); }
.wp-okladka-artykul { --k: var(--marka-niebieski); }
.wp-mini {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  background: var(--bg-soft); transition: transform .35s ease;
}
.wybor-paczki-wiersz:hover .wp-mini { transform: scale(1.05); }
.wp-ikona { display: flex; }
.wp-ikona .ico { font-size: 2.6rem; margin: 0; color: var(--k); transition: transform .25s ease; }
.wybor-paczki-wiersz:hover .wp-ikona .ico { transform: scale(1.12) rotate(-4deg); }
.wp-pasek { position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: rgba(15, 23, 42, .28); }
.wp-pasek > span { display: block; height: 100%; width: var(--postep, 0%); background: var(--marka-zielony); transition: width .35s ease; }
/* Zbior opanowany w calosci - zielona pieczatka w rogu okladki: nagroda widoczna z daleka. */
.wp-komplet {
  position: absolute; left: 8px; top: 8px; width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--verde); color: var(--na-akcencie); box-shadow: 0 2px 8px rgba(15, 23, 42, .3);
}
.wp-komplet .ico { margin: 0; font-size: .9rem; }
.wp-tresc { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px 12px; min-width: 0; }
/* Okładka z materiałem - osobny przycisk (wpMaterial): pigułka „Otwórz film / tekst" mówi, dokąd prowadzi, a „Ćwicz
   tylko to" w opisie - że opis to fiszki. */
.wp-material { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; font: inherit; color: inherit; }
.wp-material:focus-visible { outline: 3px solid var(--fokus); outline-offset: -3px; border-radius: 14px; }
.wp-otworz {
  position: absolute; left: 8px; bottom: 14px; display: inline-flex; align-items: center; gap: 6px; max-width: calc(100% - 16px);
  padding: 5px 10px; border-radius: 999px; background: rgba(15, 23, 42, .74); color: #fff;
  font-size: .76rem; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  backdrop-filter: blur(4px); transition: background .15s ease, transform .15s ease;
}
.wp-otworz .ico { margin: 0; font-size: .8rem; }
.wp-material:hover .wp-otworz, .wp-material:focus-visible .wp-otworz { background: var(--oro); color: var(--na-akcencie); transform: scale(1.05); }
.wp-cwicz { display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; font-size: .78rem; font-weight: 800; color: var(--oro); }
.wp-cwicz .ico { margin: 0; font-size: .75rem; }
.wybor-paczki-wiersz.z-materialem .wp-wejdz:hover .wp-cwicz { text-decoration: underline; }
.wp-nazwa {
  font-weight: 800; line-height: 1.25; overflow: hidden; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.wp-meta { font-size: 0.78rem; color: var(--grigio); }
/* „Otwierano N dni temu" - drobna adnotacja pod nazwa, w tym samym rejestrze co reszta meta. */
.wp-otwarto { font-size: 0.74rem; color: var(--muted-light); }
/* KŁÓDKA LIMITU (2026-09-22): chip „N słówek pod kłódką" w kafelku, a zbiór w całości za limitem jest
   przygaszony i zamiast wejścia otwiera ścianę Premium - patrz wpUstawKlodke / wpZamknieta w JS. Ten sam
   chip stoi na pasku trybu paczki (.ppt-zamek). Kłódka w kolorze błędów, bo to jest to, co uczeń ma zauważyć. */
.wp-zamek, .ppt-zamek {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.74rem; font-weight: 700; color: var(--muted-dark);
}
.wp-zamek .ico, .ppt-zamek .ico { font-size: 0.85rem; margin: 0; color: var(--rosso); }
.ppt-zamek { border: none; background: transparent; cursor: pointer; font-family: inherit; padding: 0; }
.ppt-zamek:hover { text-decoration: underline; }
.wybor-paczki-wiersz.zamknieta .wp-okladka { filter: grayscale(.85); opacity: .75; }
.wybor-paczki-wiersz.zamknieta .wp-nazwa { color: var(--grigio); }
/* AKCJE (słówka zbioru, ołówek, kosz) - pigułka na okładce w prawym górnym rogu, ZAWSZE widoczna: na
   telefonie nie ma najechania, które by ją odsłoniło. Tło półprzezroczyste, żeby nie zakrywało kadru filmu. */
.wp-akcje {
  position: absolute; top: 8px; right: 8px; z-index: 2; display: flex; gap: 2px; padding: 3px;
  border-radius: 12px; background: color-mix(in srgb, var(--card-bg) 86%, transparent);
  backdrop-filter: blur(6px); box-shadow: 0 2px 10px rgba(15, 23, 42, .18);
}
.wp-akcja {
  width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 9px; background: transparent; color: var(--grigio); cursor: pointer; font-size: .95rem;
}
.wp-akcja .ico { margin: 0; }
.wp-akcja:hover, .wp-akcja:focus-visible { background: var(--bg-soft); color: var(--testo); }
.wp-akcja:focus-visible { outline: 2px solid var(--fokus); outline-offset: 1px; }
.wp-akcja-usun:hover, .wp-akcja-usun:focus-visible { color: var(--rosso); }
.wp-akcja-ok { color: var(--verde); }
.wp-akcja:disabled { opacity: .5; cursor: default; }
/* Tryb zmiany nazwy: okładka zostaje (widać, KTÓRY zbiór się nazywa), opis i akcje schowane KLASĄ kafelka,
   nie atrybutem hidden - ten przegrywa z display:flex klasy (pułapka z CLAUDE.md), a formularz wstawia
   i zdejmuje JS (wpZmienNazwe dokleja go na koniec kafelka, czyli pod okładkę). */
.wybor-paczki-wiersz.edytuje > .wp-akcje, .wybor-paczki-wiersz.edytuje .wp-tresc { display: none; }
.wybor-paczki-wiersz.edytuje > .wp-wejdz, .wybor-paczki-wiersz.edytuje > .wp-material { flex: none; pointer-events: none; }
.wp-edycja { display: flex; align-items: center; gap: 4px; padding: 10px 8px 10px 10px; min-width: 0; }
.wp-edycja-pole {
  flex: 1; min-width: 0; padding: 9px 12px; border-radius: 10px; border: 2px solid var(--border-2);
  background: var(--bg-soft); color: var(--testo); font: inherit; font-weight: 700;
}
.wp-edycja-pole:focus { outline: none; border-color: var(--oro); }
@media (max-width: 560px) {
  .wybor-paczki-lista { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 12px; }
  .wp-tresc { padding: 8px 10px 4px; }
  .wp-nazwa { font-size: .9rem; }
  .wp-ikona .ico { font-size: 2rem; }
  /* Na wąskim kafelku trzy ikony zakryłyby pół okładki - schodzą pod opis, do prawej. */
  .wp-akcje {
    position: static; justify-content: flex-end; padding: 0 4px 6px;
    background: none; box-shadow: none; backdrop-filter: none;
  }
  .wp-akcja { width: 36px; height: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  .wybor-paczki-wiersz, .wp-mini, .wp-ikona .ico, .wp-pasek > span { transition: none; }
  .wybor-paczki-wiersz:hover, .wybor-paczki-wiersz:focus-within { transform: none; }
  .wybor-paczki-wiersz:hover .wp-mini, .wybor-paczki-wiersz:hover .wp-ikona .ico { transform: none; }
}

/* Potwierdzenie usuniecia zbioru - nad oknem wyboru (.wordmap-overlay ma 2000). */
.zakres-usun-okno {
  position: fixed; inset: 0; z-index: 2100; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(15, 23, 42, .55);
}
.zakres-usun-karta {
  width: min(460px, 100%); max-height: calc(100vh - 32px); overflow-y: auto; background: var(--card-bg);
  color: var(--testo); border-radius: 18px; box-shadow: var(--shadow-hover);
}
.zakres-usun-glowa {
  display: flex; align-items: flex-start; gap: 10px; padding: 18px 18px 10px; font-weight: 800;
  font-size: 1.05rem; line-height: 1.35; overflow-wrap: anywhere;
}
.zakres-usun-glowa .ico { color: var(--rosso); margin: 3px 0 0; flex: none; }
.zakres-usun-tresc { padding: 0 18px 8px; font-size: 0.9rem; line-height: 1.55; color: var(--muted-dark); }
.zakres-usun-tresc p { margin: 0 0 8px; }
/* Zdanie „z archiwum zniknie też N słówek" przy „na zawsze" - to jest ta część, której człowiek się nie
   spodziewa (nagłówek liczy tylko talię), więc stoi w kolorze przycisku „Usuń na zawsze", a nie szarym tłem. */
#zakresUsunArchiwum { color: var(--rosso); font-weight: 700; }
.zakres-usun-zawsze input:disabled { cursor: default; }
.zakres-usun-zawsze {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 12px; padding: 11px 12px; border-radius: 12px;
  background: var(--bg-soft); cursor: pointer; font-weight: 700; color: var(--testo);
}
.zakres-usun-zawsze input { width: 18px; height: 18px; margin: 1px 0 0; flex: none; accent-color: var(--rosso); }
/* Hasło przy „na zawsze" - pod polem wyboru, bo pojawia się dopiero po jego zaznaczeniu. */
.zakres-usun-tozsamosc { margin-top: 12px; }
.zakres-usun-tozsamosc > label { display: block; margin-bottom: 6px; font-weight: 700; color: var(--testo); }
.zakres-usun-tozsamosc .auth-input { margin-bottom: 6px; }
.zakres-usun-stopka { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 10px; padding: 10px 18px 18px; }
.zakres-usun-stopka .btn { width: auto; margin: 0; padding: 9px 18px; }
/* Edycja słówka - ta sama karta, co usuwanie zbioru, tylko z polami. Ikona w nagłówku zielona: to nie jest ostrzeżenie. */
.slowko-edycja .zakres-usun-glowa .ico { color: var(--oro); }
.slowko-edycja .zakres-usun-tresc label { display: block; margin: 10px 0 4px; font-weight: 700; color: var(--testo); font-size: 0.85rem; }
.slowko-edycja .auth-input { width: 100%; margin: 0; box-sizing: border-box; }
.slowko-edycja textarea.auth-input { resize: vertical; min-height: 54px; font: inherit; line-height: 1.45; }
.slowko-edycja-uwaga { margin: 12px 0 0 !important; color: var(--grigio); font-size: 0.82rem; }
.slowko-edycja .auth-error { margin-top: 10px; }
/* Domyslnie obrys (do archiwum, da sie cofnac), po zaznaczeniu „na zawsze" - pelna czerwien. Dwie
   klasy, bo .btn stoi w arkuszu nizej i przy rownej wadze wygralby kolejnoscia. */
.btn.zakres-usun-btn { background: transparent; color: var(--rosso); border: 2px solid var(--rosso); }
.btn.zakres-usun-btn.na-zawsze { background: var(--rosso); color: #fff; }
.btn.zakres-usun-btn:disabled { opacity: .6; cursor: default; }

/* Nazwa zbioru po wgraniu zdjecia i Excela (pole + „Zaproponuj nazwe (AI)"). Uklad pola z przyciskiem
   i wyglad przycisku pozyczone od nazwy zbioru na tablicy (.pole-z-przyciskiem, .btn-auto-nazwa). */
.zakres-nazwa { margin: 14px auto 4px; max-width: 520px; text-align: left; }
.zakres-nazwa-etykieta { display: block; margin-bottom: 6px; font-size: 0.8rem; font-weight: 700; color: var(--muted-dark); }
.zakres-nazwa input {
  width: 100%; box-sizing: border-box; padding: 10px 13px; border-radius: 12px; border: 2px solid var(--border-2);
  background: var(--bg-soft); color: var(--testo); font: inherit; font-size: 0.9rem;
}
.zakres-nazwa input:focus { outline: none; border-color: var(--oro); }
.zakres-nazwa .btn-auto-nazwa { min-height: 42px; }
.zakres-nazwa .btn-auto-nazwa[aria-busy="true"] { cursor: progress; }
.zakres-nazwa-podpowiedz { margin: 6px 0 0; font-size: 0.74rem; line-height: 1.45; color: var(--muted-light); }
.zakres-nazwa-stan { margin-left: 6px; font-weight: 700; color: var(--verde); }
@media (max-width: 520px) {
  .zakres-nazwa .pole-z-przyciskiem { flex-wrap: wrap; }
  .zakres-nazwa .pole-z-przyciskiem input { flex: 1 1 100%; }
  .zakres-nazwa .btn-auto-nazwa { flex: 1 1 auto; }
}

/* Kafelek filmu na ekranie dodawania: albo zacheta do zrobienia fiszek, albo informacja,
   ze slowka juz sa. Jedno miejsce, dwa stany - zeby po samej liscie bylo widac, z czym
   jeszcze jest robota. Kafelek JEST przyciskiem, wiec zacheta to <span role="button">:
   przycisk w przycisku to niepoprawny HTML. */
.film-kafelek-fiszki {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 6px;
  padding: 5px 10px; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--oro) 10%, transparent);
  color: var(--oro); font-size: 0.76rem; font-weight: 700;
  transition: var(--transition);
}
.film-kafelek-fiszki:hover { background: color-mix(in srgb, var(--oro) 20%, transparent); }
.film-kafelek-fiszki .ico { font-size: 0.9rem; }
.film-kafelek-ma {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
  font-size: 0.74rem; font-weight: 600; color: var(--grigio);
}
/* „Umiesz X%" za meta kafelka (patrz filmUmieszHtml): ile slowek z tego filmu, ktore uczen ma w talii,
   jest juz opanowanych. Kropka przed napisem ciagnie dalej separator z film_meta („42 linijek · 58 slowek
   w talii · umiesz 50%"), zeby procent czytal sie jako czesc tej samej linijki, a nie osobna plakietka.
   Szaro jak „masz w zestawie", ZIELONO OD POLOWY - ta sama granica, co „znasz X%" na mapie Mowienia
   (.mow-kafelek-znasz.duzo); jedna regula koloru dla obu list materialow. */
.film-kafelek-umiesz {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
  font-size: 0.74rem; font-weight: 700; color: var(--grigio);
}
.film-kafelek-umiesz::before { content: '·'; font-weight: 400; color: var(--grigio); }
.film-kafelek-umiesz.duzo { color: var(--verde); }
/* Czysciec odrzuconych zgloszen w panelu Moderacji. */
.czysciec-wiersz {
  display: flex; gap: 12px; align-items: flex-start; padding: 10px 0;
  border-bottom: 1px solid var(--border-warm);
}
.czysciec-mini {
  width: 84px; height: 62px; object-fit: cover; border-radius: 10px; flex-shrink: 0;
  border: 1px solid var(--border-warm); cursor: zoom-in; background: var(--bg-soft);
}
.czysciec-brak { display: flex; align-items: center; justify-content: center; font-size: 1.4rem; cursor: default; }
.czysciec-info { flex: 1; min-width: 0; font-size: 0.85rem; }
.czysciec-powody { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0; }
.czysciec-powod {
  background: var(--bg-soft); border: 1px solid var(--border-warm); border-radius: 999px;
  padding: 2px 10px; font-size: 0.78rem;
}
.czysciec-opisy { font-size: 0.8rem; color: var(--grigio); margin: 2px 0; }
.czysciec-usun {
  width: 26px; height: 26px; border-radius: 50%; border: none; background: var(--rosso);
  color: #fff; cursor: pointer; flex-shrink: 0; line-height: 1;
}

/* ===== SZYNY REKLAMOWE (AdSense, konta darmowe) =====
   .app-body ma max-width:1100px i jest wycentrowana, więc krawędź treści siedzi
   (100vw - 1100px)/2 od brzegu ekranu. Rezerwujemy 24px odstępu od krawędzi viewportu -
   Prog 1500px, nie 1600: w drzewie została już tylko LEWA szyna (prawą zajął ranking), więc
   liczy się jeden margines, nie dwa. Przy 1500px wolne miejsce po lewej to (1500-1100)/2 = 200px,
   czyli 24px odstępu + 160px reklamy + 16px luzu - dokładnie tyle, ile trzeba. To nie jest
   kosmetyka: laptopy raportujące 1536px (1920px przy skalowaniu 125%, najpospolitszy układ
   w Windows) mieszczą się w nowym progu, a w starym nie mieściły.
   Niżej szyny nie da się opuścić bez nachodzenia na treść - dlatego POD nią stoi osobna
   jednostka w panelu bocznym (patrz #adSidebar), która działa na każdej szerokości. */
.ad-rail {
  display: none;
  position: fixed; top: 96px;
  width: 160px; max-height: calc(100vh - 116px);
  z-index: 5;
}
.ad-rail-left  { left: 24px; }
.ad-rail-right { right: 24px; }
@media (min-width: 1500px) {
  .ad-rail:not(.hidden) { display: block; }
}

/* Reklama w panelu bocznym - dla wszystkich szerokości, w tym telefonów.
   Podpis "Reklama" nad jednostką jest obowiązkowy: bez niego blok w kolumnie aplikacji
   wygląda na jej część, a reklama udająca treść łamie zasady AdSense. Górna kreska
   oddziela ją od przycisków nauki, żeby nie czytało się jej jako kolejnego z nich. */
.ad-sidebar {
  margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--border-warm);
  min-height: 100px;
}
.ad-sidebar-label {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--grigio); opacity: 0.65; margin-bottom: 6px; text-align: center;
}

/* Szyna rankingu - TA SAMA prawa pozycja co .ad-rail-right (stąd JS wygasza prawą reklamę,
   patrz refreshAdRails(): ranking dla wszystkich jest ważniejszy niż drugi slot AdSense, który
   i tak dotyczy tylko darmowych kont). Osobny (niższy niż ad-rail) próg szerokości - to funkcja,
   nie reklama, więc pokazuje się większej części użytkowników, i to WSZYSTKIM (też Premium). */
.rank-rail {
  display: none; position: fixed; top: 96px; right: 24px;
  width: 230px; max-height: calc(100vh - 116px); overflow-y: auto;
  z-index: 5; background: var(--bianco); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px;
}
@media (min-width: 1400px) {
  .rank-rail:not(.hidden) { display: block; }
}
body.focus-mode .rank-rail { display: none; } /* pełny ekran fiszek ma usuwać rozpraszacze, ranking też */
/* Ikona jest RODZENSTWEM tlumaczonego <span> - dzieki temu applyDomTranslations moze
   nadpisac sam tekst, nie kasujac glifu (patrz bezWiodacejEmotki). */
.rank-rail-title {
  display: flex; align-items: center; gap: 7px;
  font-size: 0.8rem; font-weight: 800; color: var(--grigio);
  text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 10px;
}
.rank-row {
  display: flex; align-items: center; gap: 8px; padding: 7px 6px; border-radius: 12px;
  cursor: pointer; transition: var(--transition);
}
.rank-row:hover { background: var(--crema); }
.rank-row.me { background: var(--bg-success-soft); }
/* Przełącznik okresu nad listą rankingu - ten sam kształt co przełącznik 7/30 dni
   w profilu, żeby dwa sąsiadujące ze sobą wybory nie wyglądały jak dwa różne pomysły. */
.rank-okres { display: flex; gap: 6px; justify-content: center; margin: 0 0 8px; }
.rank-okres-btn {
  flex: 1; padding: 5px 10px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-warm); background: transparent; color: var(--grigio);
  font: inherit; font-size: 0.72rem; font-weight: 800; transition: var(--transition);
}
.rank-okres-btn:hover { border-color: var(--oro); color: var(--oro); }
.rank-okres-btn.active { background: var(--zolty); border-color: var(--zolty); color: var(--granat); }

.rank-row-num { width: 20px; text-align: center; font-size: 0.78rem; font-weight: 800; color: var(--grigio); flex-shrink: 0; }
.rank-row-name { flex: 1; min-width: 0; font-size: 0.82rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-row-xp { font-size: 0.78rem; font-weight: 800; color: var(--primary); white-space: nowrap; }
.rank-row-flag { display: inline-flex; flex-shrink: 0; line-height: 0; }
.rank-row-trend {
  font-size: 0.75rem; width: 16px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.rank-row-trend .ico { margin-right: 0; }
.rank-row-trend.up { color: var(--verde); }
.rank-row-trend.down { color: var(--rosso); }
.rank-row-trend.flat { color: var(--grigio); }

/* ===== LAYOUT ===== */
.app-body {
  max-width: 1100px;
  margin: 0 auto;
  padding: 28px 20px;
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 24px;
  align-items: start;
}
@media (max-width: 768px) {
  .app-body { grid-template-columns: 1fr; }
  .sidebar { order: 2; }
}
/* Tryb pełnoekranowy fiszek: chowa tylko boczny panel (konto/postęp/dodawanie), zostawia
   nagłówek i pasek narzędzi karty - to wystarcza, żeby zniknęły rozpraszacze, a jednocześnie
   zawsze da się łatwo wyjść (ten sam przełącznik). Celowo NIE dotyka .ad-rail-* - te stoją
   na position:fixed względem całego viewportu, więc miejsce na reklamy zostaje nietknięte
   niezależnie od układu .app-body. Na wąskich ekranach panel i tak jest pod treścią (patrz
   wyżej), więc ukrycie go działa identycznie dobrze na telefonie. */
body.focus-mode .sidebar { display: none; }
body.focus-mode .app-body { grid-template-columns: 1fr; }
body.focus-mode .app-header { display: none; }
body.focus-mode .ad-rail { top: 24px; } /* nagłówek zniknął, szyny reklamowe podjeżdżają pod sam wierzch */

/* ===== SIDEBAR ===== */
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.card {
  background: var(--card-bg);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow);
  border: 1px solid rgba(0,0,0,0.06);
}
.card-title {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--grigio);
  margin-bottom: 14px;
}

/* ---- MENU POD TRZEMA KROPKAMI W NAGŁÓWKU KARTY ----
   Miejsce na polecenia, które karta ma udostępniać, ale które nie są tym, po co się do niej
   przychodzi. Eksport do Excela stał jako pełnej szerokości przycisk na samym dole „Dodaj
   słówka" - ostatnia i najbardziej rzucająca się w oczy rzecz w panelu, którego zadaniem jest
   DODAWANIE słówek. Pod kropkami zajmuje zero miejsca, a nadal jest tam, gdzie go szukać.
   Nagłówek zostaje zwykłym nagłówkiem: flex włącza się dopiero klasą .z-menu. */
.card-title.z-menu { display: flex; align-items: center; gap: 6px; }
.card-menu-wrap { position: relative; margin-left: auto; }
.card-menu-btn {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: none; border-radius: 8px;
  background: transparent; color: var(--grigio); cursor: pointer;
  font: inherit; font-size: 1.1rem; line-height: 1; letter-spacing: 0;
  transition: var(--transition);
}
.card-menu-btn:hover, .card-menu-btn[aria-expanded="true"] { background: var(--bg-soft); color: var(--testo); }
.card-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 200;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft);
  border-radius: 12px; box-shadow: var(--shadow-hover);
  min-width: 210px; padding: 6px;
}
.card-menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 9px 11px; border: none; border-radius: 9px; background: transparent;
  color: var(--testo); font: inherit; font-size: 0.84rem; font-weight: 700;
  text-align: left; text-transform: none; letter-spacing: 0; cursor: pointer;
}
.card-menu-item:hover { background: var(--bg-soft); }

/* ===== STATYSTYKI ===== */
.stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.stat-box {
  background: var(--crema);
  border-radius: 12px;
  padding: 12px;
  text-align: center;
  border: 2px solid transparent;
  cursor: pointer;
  transition: var(--transition);
}
.stat-box:hover { border-color: var(--oro); transform: scale(1.03); }
.stat-box.active-filter { border-color: var(--oro); background: var(--bg-highlight); }
.stat-box .count { font-size: 1.6rem; font-weight: 800; line-height: 1; }
.stat-box .label { font-size: 0.7rem; font-weight: 600; color: var(--grigio); margin-top: 2px; }
.stat-nowe  .count { color: var(--muted-dark); }
.stat-latwe .count { color: var(--chart-latwe); }
.stat-srednie .count { color: var(--primary); }
.stat-trudne .count { color: var(--rosso); }
/* Kropka poziomu jako prawdziwy element CSS zamiast emoji 🟢🟡🔴 - inaczej nie da się
   jej pokolorować (emoji ma stały, niesterowalny kolor), więc kropka i liczba obok
   zawsze się rozjeżdżały. Ten sam schemat co wszędzie indziej: zielony/niebieski/czerwony. */
/* .lvl-dot - patrz komponenty/fiszka.php (nalezy do przyciskow oceny). */

/* ===== WYBÓR METODY DODAWANIA SŁÓWEK ===== */
/* Dwa duże wybory zamiast trzech wąskich zakładek: każdy niesie nazwę I krótkie wyjaśnienie,
   bo „Plik Excel" vs „Zdjęcie" samo w sobie nie mówi, co się właściwie stanie. */
.add-method-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
.add-method-tab {
  display: flex; align-items: center; gap: 10px; text-align: left;
  flex: 1; padding: 8px 6px; border-radius: 10px; border: 2px solid var(--border);
  background: var(--crema); font-family: inherit; font-size: 0.72rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; transition: var(--transition); text-align: center;
}
.add-method-tab:hover { border-color: var(--oro); }
.add-method-tab.active { background: var(--oro); border-color: var(--oro); color: var(--na-akcencie); }
.add-method-tab .ico { font-size: 1.15rem; margin-right: 0; flex-shrink: 0; }
.add-method-tab b { display: block; font-size: 0.82rem; font-weight: 800; line-height: 1.2; }
.add-method-tab small { display: block; font-size: 0.68rem; opacity: 0.75; line-height: 1.3; margin-top: 1px; }
.add-method-tab > span { min-width: 0; }

/* Pomoc zwinięta domyślnie. Przykładowa tabelka Excela i regulaminowe warunki zdjęcia to
   treść, którą czyta się RAZ - rozwinięta na stałe robiła z karty ścianę tekstu i to przez
   nią „Dodaj słówka" wyglądało na najdłuższą sekcję w panelu. */
.pomoc-rozwijana { margin-top: 12px; }
.pomoc-rozwijana > summary {
  display: flex; align-items: center; gap: 8px; cursor: pointer; list-style: none;
  font-size: 0.78rem; font-weight: 700; color: var(--grigio);
  padding: 8px 10px; border-radius: 10px; background: var(--bg-soft);
  transition: var(--transition);
}
.pomoc-rozwijana > summary::-webkit-details-marker { display: none; }
.pomoc-rozwijana > summary:hover { color: var(--testo); background: var(--border); }
.pomoc-rozwijana > summary .ico { margin-right: 0; }
.pomoc-rozwijana[open] > summary { margin-bottom: 10px; }

/* Skok z pustego ekranu do karty: krótkie tętnienie obramowania, żeby było widać, DOKĄD
   właśnie przewinęliśmy. Bez tego na wysokim ekranie klik wyglądał jak brak reakcji. */
.card.podswietlona { animation: kartaTetno 1.5s cubic-bezier(.22,1,.36,1); }
@keyframes kartaTetno {
  0%, 100% { box-shadow: var(--shadow); }
  20%, 60% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--oro) 45%, transparent), var(--shadow); }
}
@media (prefers-reduced-motion: reduce) { .card.podswietlona { animation: none; } }

/* ===== UPLOAD ===== */
.upload-zone {
  border: 2px dashed var(--border-warm-dash);
  border-radius: 12px;
  padding: 20px;
  text-align: center;
  cursor: pointer;
  transition: var(--transition);
  background: var(--crema);
}
.upload-zone:hover, .upload-zone.dragover {
  border-color: var(--oro);
  background: var(--bg-highlight);
}
.upload-zone input { display: none; }
.upload-icon { font-size: 2rem; margin-bottom: 8px; }
.upload-text { font-size: 0.85rem; color: var(--grigio); }

/* ===== PRZYKŁAD FORMATU PLIKU EXCEL / PODPOWIEDŹ ZDJĘCIA ===== */
.upload-hint-note {
  font-size: 0.78rem; color: var(--grigio); line-height: 1.5;
  background: var(--bg-info-soft); border-radius: 10px; padding: 9px 12px; margin-top: 10px;
}
.upload-hint-note strong { color: var(--testo); }
.excel-example {
  margin-top: 12px; border-radius: 14px; overflow: hidden;
  border: 1px solid var(--border); background: var(--card-bg);
  box-shadow: var(--shadow);
}
.excel-example-titlebar {
  background: var(--bg-soft); padding: 10px 14px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; position: relative;
}
.excel-example-dots { display: flex; gap: 6px; }
.excel-example-dots span { width: 10px; height: 10px; border-radius: 50%; display: block; }
.excel-example-dots span:nth-child(1) { background: #ff5f56; }
.excel-example-dots span:nth-child(2) { background: #ffbd2e; }
.excel-example-dots span:nth-child(3) { background: #27c93f; }
.excel-example-filename {
  position: absolute; left: 0; right: 0; text-align: center;
  font-size: 0.72rem; font-weight: 700; color: var(--grigio);
}
.excel-example-banner {
  background: var(--bg-info-soft); padding: 8px 14px; border-bottom: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.72rem; color: var(--primary); font-weight: 600;
}
.excel-example table { width: 100%; border-collapse: collapse; text-align: left; font-size: 0.78rem; }
.excel-example th {
  padding: 7px 12px; color: var(--testo); font-weight: 700;
  border-right: 1px solid var(--border); border-bottom: 2px solid var(--border);
  background: var(--bg-soft);
}
.excel-example th:last-child { border-right: none; }
.excel-example th small { font-weight: 400; color: var(--grigio); }
.excel-example td {
  padding: 7px 12px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border-warm-2);
}
.excel-example td:last-child { border-right: none; color: var(--testo); }
.excel-example td:first-child:not(.excel-example-num) { font-weight: 700; color: var(--primary); }
.excel-example-num {
  width: 30px; text-align: center; color: var(--muted-light); font-size: 0.7rem;
  background: var(--bg-soft) !important; font-weight: 400 !important;
}

/* PRZYCISKI W STYLU KANWY (2026-09-26): pigułka i Figtree 800. Wysokość bez sztywnego minimum - zwarte przyciski
   w panelach i oknie twórcy mają własny, mniejszy padding; pełne 56 px dostaje główny przycisk z kółkiem (.btn-strzalka). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 22px;
  border-radius: 999px;
  border: none;
  font-size: 0.92rem;
  font-weight: 800;
  cursor: pointer;
  transition: var(--transition);
  width: 100%;
  margin-top: 8px;
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-hover); }
.btn:active { transform: translateY(0); }
/* .btn-verde to od lat nazwa GŁÓWNEGO przycisku (kilkadziesiąt miejsc w HTML i JS), więc klasa zostaje,
   a wypełnienie idzie za akcentem interfejsu: granatowa pigułka, w ciemnym motywie żółta. Zielony główny
   przycisk obok zielonego „dobrze" w quizie czytał się jak jeden sygnał (patrz --oro / --verde w :root). */
.btn-verde  { background: var(--oro);    color: var(--na-akcencie); }
.btn-rosso  { background: var(--rosso);  color: white; }
.btn-oro    { background: var(--oro);    color: var(--na-akcencie); }
/* Drugi przycisk = biała pigułka z obwódką („Wróć do nauki", „Wyślij kod jeszcze raz" na planszach). */
.btn-grigio { background: var(--card-bg); color: var(--testo); box-shadow: inset 0 0 0 1.5px var(--border-2); }
.btn-grigio:hover { box-shadow: inset 0 0 0 1.5px var(--oro), var(--shadow-hover); }
/* GŁÓWNY PRZYCISK Z KÓŁKIEM NA STRZAŁKĘ - znak rozpoznawczy plansz („Rozpocznij pierwszą naukę", „Wróć do nauki",
   „Kup Premium"): napis po lewej, żółte kółko 44 px z granatową strzałką po prawej. W ciemnym motywie (i na
   granatowych ekranach marki) odwrotnie: żółta pigułka, granatowe kółko, żółta strzałka. Kółko rysuje ::after,
   więc wystarczy dodać klasę - HTML przycisku i jego JS zostają, jakie były. Ikonę z przodu chowamy, bo przy
   kółku po prawej byłaby drugą strzałką. */
/* .cs-glowny (główny przycisk planszy celu dnia) dostaje ten sam kształt przez selektor, a nie przez klasę w HTML -
   testy_cel_slowek pilnuje dosłownego zestawu klas tego przycisku. */
.btn-strzalka, .polmetek.cel-slowek .cs-glowny {
  --kolko-tlo: var(--przycisk-kolko);
  --kolko-strzalka: var(--przycisk-kolko-strzalka);
  justify-content: flex-start; min-height: 56px; padding: 6px 6px 6px 24px;
  font-size: 1rem; text-align: left;
}
.btn-strzalka > .ico:first-child, .polmetek.cel-slowek .cs-glowny > .ico:first-child { display: none; }
.btn-strzalka::after, .polmetek.cel-slowek .cs-glowny::after {
  content: ''; flex: none; width: 44px; height: 44px; margin-left: auto; border-radius: 999px;
  background: var(--kolko-tlo) var(--kolko-strzalka) center / 22px 22px no-repeat;
}
[dir="rtl"] .btn-strzalka::after { transform: scaleX(-1); }
/* Na ekranach marki barwy są STAŁE w obu motywach (marka nie zmienia koloru razem z motywem):
   na granacie żółta pigułka z granatowym kółkiem, na żółtym/zielonym/niebieskim/czerwonym granatowa z żółtym. */
.na-granacie .btn-strzalka { background: var(--zolty); color: var(--granat); --kolko-tlo: var(--granat); --kolko-strzalka: var(--strzalka-zolta); }
.na-kolorze .btn-strzalka, .polmetek.cel-slowek .cs-glowny { background: var(--granat); color: #FFFFFF; --kolko-tlo: var(--zolty); --kolko-strzalka: var(--strzalka-granatowa); }
/* WARIANT KRESKOWANY - ten sam znak, co kafelki w „Dodaj słówka" (.empty-state-method):
   przerywana ramka na tle strony. Czyta się jako „miejsce, w które można wejść", a nie jako
   główny ruch. Dwa przyciski pod Postępem są właśnie tym: wejściem w inny tryb nauki, a nie
   następnym krokiem w tym, co użytkownik robi teraz - wypełniony kolorem konkurowały
   z „Przygotuj do nauki" nad kartą. */
.btn-kreskowany {
  background: var(--crema); color: var(--testo);
  border: 2px dashed var(--border-warm-dash);
}
.btn-kreskowany .ico { color: var(--grigio); }
.btn-kreskowany:hover { border-color: var(--oro); color: var(--oro); }
.btn-kreskowany:hover .ico { color: var(--oro); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

/* ===== KARTA KONTA (sidebar) ===== */
.account-row { display: flex; align-items: center; gap: 12px; }
.account-avatar {
  width: 48px; height: 48px; border-radius: 50%;
  background: #78828C; color: white;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 1.1rem; flex-shrink: 0;
  overflow: hidden; text-transform: uppercase;
}
.account-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* Pierścień zajętości talii wokół awatara - tylko na koncie darmowym (patrz odswiezPierscien).
   Zamiast licznika "12/160", który straszy pułapem, zanim ten pułap kogokolwiek dotyczy,
   stan konta widać kątem oka: dopóki pierścień jest ledwie napoczęty, nie ma o czym myśleć.
   conic-gradient, nie SVG: to jedno tło na elemencie, który i tak już istnieje. */
.awatar-pierscien {
  position: relative; flex-shrink: 0; border-radius: 50%; padding: 3px;
  background: var(--border-warm);
  transition: background 0.4s ease;
}
.awatar-pierscien::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--pierscien-kolor, var(--verde)) calc(var(--pierscien-pct, 0) * 1%), transparent 0);
  transition: background 0.4s ease;
}
.awatar-pierscien > * { position: relative; }

/* Premium: pełny pierścień, który powoli oddycha. Nie ma tu procentu do pokazania - konto
   bez sufitu nie ma czego zapełniać - więc pierścień przestaje być miarą i staje się
   znakiem. Gradient jedzie po dwóch zieleniach, które NIE zmieniają się z motywem, żeby
   w ciemnym trybie nie wyszedł z tego jednolity pasek.
   Obrót jest na ::before (samym kolorze), a pulsowanie na kontenerze - inaczej jedna
   animacja nadpisywałaby transform drugiej. */
.awatar-pierscien.premium { background: transparent; animation: awatarOddech 3.6s ease-in-out infinite; }
.awatar-pierscien.premium::before {
  background: conic-gradient(from 0deg,
    var(--zielen-gleboka), var(--zielen-pastel), var(--zielen-gleboka),
    var(--zielen-pastel), var(--zielen-gleboka));
  animation: awatarObrot 6s linear infinite;
}
@keyframes awatarObrot { to { transform: rotate(360deg); } }
@keyframes awatarOddech {
  0%, 100% { box-shadow: 0 0 0 0 rgba(140, 208, 166, 0.0); }
  50%      { box-shadow: 0 0 0 5px rgba(140, 208, 166, 0.28); }
}
/* Ruch w nieskończonej pętli tuż przy twarzy jest dla części ludzi męczący, a dla części
   wywołuje zawroty głowy. Znak zostaje, ruch znika. */
@media (prefers-reduced-motion: reduce) {
  .awatar-pierscien.premium, .awatar-pierscien.premium::before { animation: none; }
}
/* Przerwa między pierścieniem a zdjęciem - inaczej kolor dotyka twarzy i wygląda jak obwódka. */
.awatar-pierscien .account-avatar { box-shadow: 0 0 0 2px var(--card-bg); }
.header-konto .awatar-pierscien .account-avatar { box-shadow: 0 0 0 2px var(--bg-soft); }

/* Awatar w nagłówku jest teraz przyciskiem - otwiera panel konta. */
.awatar-przycisk { cursor: pointer; border: none; background: none; padding: 3px; }
.awatar-przycisk:hover { transform: scale(1.06); }
.awatar-przycisk { transition: transform var(--transition); }

/* LICZNIK POWIADOMIEŃ - przyklejony do zdjęcia profilowego, nie osobna ikona w pasku.
   Nagłówek ma już cztery rzeczy do kliknięcia (awatar, ustawienia, wylogowanie, tryby);
   piąta, stojąca luzem, kazałaby ich wszystkich szukać od nowa. Przy awatarze licznik jest
   tam, gdzie i tak pada wzrok szukający „moich rzeczy", a mały dzwonek mówi, czym ta liczba
   jest - bez niego cyfra przy zdjęciu wygląda na poziom albo na liczbę wiadomości.
   PRZY ZERZE ZNIKA CAŁY. Wyszarzone „0" to informacja, że nic się nie dzieje, podana tak,
   jakby się działo: zabiera uwagę dokładnie tyle samo razy co prawdziwe powiadomienie. */
.pw-kotwica { position: relative; display: inline-flex; flex-shrink: 0; }
.pw-licznik {
  position: absolute; top: -3px; right: -5px; z-index: 3;
  display: flex; align-items: center; gap: 3px;
  min-width: 22px; height: 22px; padding: 0 6px;
  border: 2px solid var(--bg-soft); border-radius: 50px;
  background: var(--rosso); color: #fff;
  font-family: inherit; font-size: 0.68rem; font-weight: 800; line-height: 1;
  cursor: pointer; transition: transform var(--transition);
}
.pw-licznik .ico { font-size: 0.6rem; margin: 0; }
.pw-licznik:hover { transform: scale(1.12); }

/* Lista w panelu. Wiersz jest przyciskiem, bo każdy prowadzi w KONKRETNE miejsce: profil
   obserwującego albo materiał, o którym mowa. Powiadomienie, którego nie da się kliknąć,
   zostawia człowieka z wiadomością „coś się stało" i zadaniem znalezienia tego samemu. */
.pw-naglowek { font-weight: 800; font-size: 1.05rem; padding-top: 26px; margin-bottom: 2px; }
.pw-wiersz {
  display: flex; align-items: flex-start; gap: 11px; width: 100%; cursor: pointer;
  padding: 11px 12px; border: none; border-radius: 14px; background: none;
  font-family: inherit; color: inherit; text-align: left;
}
.pw-wiersz:hover { background: var(--bg-soft); }
/* Nieprzeczytane mają tło, a nie kropkę z boku: panel otwiera się właśnie po to, żeby je
   przeczytać, więc „które są nowe" jest pytaniem o CAŁY wiersz, a nie o znacznik przy nim. */
.pw-wiersz.nowe { background: var(--zielen-tlo); }
.pw-wiersz.nowe:hover { background: var(--zielen-tlo); filter: brightness(1.15); }
.pw-ikona {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--card-bg); border: 1px solid var(--border-2); font-size: 0.85rem;
}
.pw-ikona.serce { color: var(--rosso); }
.pw-ikona.obserwuje { color: var(--zielen-gleboka); }
/* Ten sam bursztyn, co plomyk i baner COMBO w samej grze (--combo-akcent): wiersz ma sie
   kojarzyc z tym, co sie widzialo na ekranie po dziesiatej dobrej odpowiedzi z rzedu. */
.pw-ikona.combo { color: #F59E0B; }
.pw-tresc { min-width: 0; flex: 1; }
.pw-tekst { font-size: 0.87rem; line-height: 1.45; }
.pw-tytul-postu { font-weight: 700; }
.pw-kiedy { font-size: 0.74rem; color: var(--grigio); margin-top: 2px; }

/* ŚWIEŻE OD OBSERWOWANYCH - pasek nad tablicą.
   Zielona ramka, a nie kolejny rząd kafelków: te materiały mają być rozpoznawalne jako INNA
   kategoria niż reszta tablicy, zanim ktokolwiek przeczyta nagłówek. Bez obwódki pierwszy rząd
   wyglądałby po prostu na początek siatki i cała różnica („to są ludzie, których śledzisz")
   byłaby do wyczytania dopiero z podpisów pod kafelkami.
   Pasek przewija się w poziomie zamiast zawijać: ma zajmować stałą, przewidywalną wysokość
   u góry, a nie spychać tablicę o trzy rzędy w dół, gdy ktoś obserwuje dziesięciu twórców. */
.cmty-obserwowani {
  border: 2px solid var(--zielen-gleboka); border-radius: 18px;
  padding: 14px 16px 16px; margin-bottom: 18px;
  background: var(--zielen-tlo);
}
.cmty-obs-glowa { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.cmty-obs-tytul {
  font-weight: 800; font-size: 0.95rem; color: var(--zielen-gleboka);
  display: flex; align-items: center; gap: 7px;
}
.cmty-obs-opis { font-size: 0.76rem; color: var(--grigio); }
.cmty-obs-pas { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px; }
.cmty-obs-kafelek {
  flex: 0 0 210px; display: flex; flex-direction: column; gap: 6px;
  padding: 10px; border: 1px solid var(--border-2); border-radius: 14px;
  background: var(--card-bg); cursor: pointer; text-align: left;
  font-family: inherit; color: inherit;
}
.cmty-obs-kafelek:hover { border-color: var(--zielen-gleboka); transform: translateY(-2px); }
.cmty-obs-kafelek { transition: transform var(--transition), border-color var(--transition); }
.cmty-obs-obraz {
  width: 100%; height: 88px; border-radius: 10px; object-fit: cover; background: var(--bg-soft);
  display: flex; align-items: center; justify-content: center; color: var(--grigio); font-size: 1.5rem;
}
.cmty-obs-tytul-mat { font-weight: 700; font-size: 0.84rem; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cmty-obs-autor { font-size: 0.74rem; color: var(--grigio); display: flex; align-items: center; gap: 5px; }
.account-info { min-width: 0; }
.account-nick { font-weight: 700; font-size: 0.95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.account-plan { font-size: 0.75rem; color: var(--grigio); }

/* Konto w prawym rogu nagłówka. Awatar jest tu mniejszy niż w dawnym kafelku sidebara,
   więc nadpisujemy rozmiar - reszta stylów (kadrowanie zdjęcia, inicjał) zostaje wspólna. */
.header-konto {
  display: flex; align-items: center; gap: 9px; padding: 4px 6px 4px 4px;
  border-radius: 999px; background: var(--bg-soft);
}
.header-konto .account-avatar { width: 34px; height: 34px; font-size: 0.85rem; }
.header-konto-opis { max-width: 150px; color: var(--testo); line-height: 1.25; }
.header-konto .account-nick { font-size: 0.82rem; }
.header-konto .account-plan { font-size: 0.68rem; color: var(--grigio); }
.header-konto-akcje { display: flex; align-items: center; gap: 9px; }
.header-konto-akcja {
  width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
  border: none; background: var(--border); color: var(--testo); font-size: 0.85rem;
  line-height: 1; transition: var(--transition);
}
.header-konto-akcja:hover { background: var(--border-2); transform: translateY(-1px); }

@media (max-width: 1000px) {
  /* Nick i plan idą pierwsze - awatar i tak je zastępuje, a miejsce w nagłówku jest cenne */
  .header-konto-opis { display: none; }
}

/* ===== USTAWIENIA ===== */
/* .settings-tab zostaje: uzywa go jeszcze przelacznik 7/30 dni na wykresie w profilu gracza
   (patrz renderPlayerProfile). Sam pasek zakladek Ustawien zastapila pionowa lista w szufladzie. */
.settings-tab {
  flex: 0 0 auto; padding: 9px 14px; border-radius: 50px; border: 2px solid var(--border);
  background: var(--crema); font-family: inherit; font-size: 0.78rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; transition: var(--transition); white-space: nowrap;
}
.settings-tab:hover { border-color: var(--oro); color: var(--testo); }
.settings-tab.active { background: var(--zolty); border-color: var(--zolty); color: var(--granat); }
.theme-switch { display: flex; gap: 10px; }
.theme-switch-btn:focus-visible { outline: 2px solid var(--oro); outline-offset: 2px; }
/* Przełącznik motywu w nagłówku, po lewej od flagi - jedna ikona zamiast trzech etykiet */
.header-theme {
  background: var(--bg-soft); border: 1px solid var(--border); border-radius: 50%;
  width: 32px; height: 32px; flex-shrink: 0; cursor: pointer; font-size: 0.95rem;
  line-height: 1; display: flex; align-items: center; justify-content: center;
  transition: var(--transition);
}
.header-theme:hover { background: var(--border); transform: rotate(-18deg) scale(1.1); }

.theme-switch-btn {
  flex: 1; padding: 10px 8px; border-radius: 12px; border: 2px solid var(--border);
  background: var(--crema); font-family: inherit; font-size: 0.78rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; transition: var(--transition);
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
/* Ikona nad podpisem - .ico ma line-height:0 (patrz sekcja IKONY), wiec w ukladzie
   kolumnowym musi dostac wlasna wysokosc, inaczej podpis wjezdza na nia. */
.theme-switch-btn .ico { font-size: 1.3rem; margin-right: 0; line-height: 1; height: 1.3rem; }
.theme-switch-btn:hover { border-color: var(--primary); color: var(--testo); }
/* Akcent panelu Ustawien jest pomaranczowy (wskaznik listy, ikony sekcji, aktywna zakladka)
   - niebieski kafelek motywu byl tu jedynym elementem z innej palety. */
.theme-switch-btn.active { background: var(--oro); border-color: var(--oro); color: var(--na-akcencie); }
.settings-pane { display: none; }
.settings-pane.active { display: block; }
.settings-section { padding: 18px 0; border-bottom: 1px solid var(--border-warm-soft); }
/* Poziom i cele w zakładce Nauka (rysujUstPreferencje): kafel poziomu z plakietką w barwach lejka (START_POZIOMY.barwy),
   wybrany w kolorze akcentu jak kafelki celów (.start-cel.wybrany). */
.ust-pref-opis { margin: 0 0 12px; }
.ust-pref-naglowek { margin: 14px 0 8px; font-size: 0.82rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--grigio); }
.ust-poziomy { display: grid; gap: 8px; }
.ust-poziom {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px 14px; border: 2px solid var(--border); border-radius: 14px;
  background: var(--card-bg); color: var(--testo); font: inherit; text-align: start; cursor: pointer;
}
.ust-poziom:hover { border-color: var(--border-2); }
.ust-poziom[aria-checked="true"] { border-color: var(--oro); background: var(--bg-highlight); }
/* Obwódka, bo granatowa plakietka B2 w ciemnym motywie zlewała się z kartą (zrzut z podglądu 2026-10-09). */
.ust-poziom-kod {
  flex-shrink: 0; min-width: 40px; padding: 4px 8px; border-radius: 9px; font-family: var(--font-naglowek); font-weight: 800; text-align: center;
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--testo) 22%, transparent);
}
.ust-poziom-tresc { display: flex; flex-direction: column; min-width: 0; }
.ust-poziom-tresc b { font-size: 0.94rem; line-height: 1.3; }
.ust-poziom-tresc span { font-size: 0.85rem; line-height: 1.35; color: var(--grigio); }
.ust-poziom-ptak { margin-inline-start: auto; color: var(--oro); font-size: 1.1rem; opacity: 0; flex-shrink: 0; }
.ust-poziom[aria-checked="true"] .ust-poziom-ptak { opacity: 1; }
.ust-cele { margin-bottom: 0; }
.settings-section:last-child { border-bottom: none; padding-bottom: 4px; }
.settings-section:first-child { padding-top: 0; }
/* Szara ramka informacyjna. Zakładka Premium już jej nie używa (ma kontener .pk), ale stoi
   w karcie startowej Gry w pary. */
.settings-plan-box {
  background: var(--crema);
  border-radius: 14px;
  padding: 14px 16px;
  font-size: 0.88rem;
  line-height: 1.6;
}

/* ===== USTAWIENIA - SZUFLADA WYSUWANA Z PRAWEJ =====
   Wcześniej było to okno na środku ekranu z POZIOMYM paskiem zakładek. Zakładek zrobiło się
   osiem, pasek trzeba było przewijać w bok i nie dało się jednym spojrzeniem sprawdzić, co
   w ustawieniach w ogóle jest. Szuflada dostaje pełną wysokość ekranu, więc wszystkie sekcje
   mieszczą się w pionowej liście po lewej - widać je naraz, a treść ma własne przewijanie. */
/* Podwojna klasa, nie sama .ustawienia-overlay: .wordmap-overlay (padding:20px, wysrodkowanie)
   jest zdefiniowana NIZEJ w pliku, wiec przy rownej specyficznosci wygrywalaby kolejnoscia
   i szuflada wisiala 20 px od kazdej krawedzi zamiast siedziec przy brzegu ekranu. */
.wordmap-overlay.ustawienia-overlay { justify-content: flex-end; padding: 0; }
/* min-width: 0 jest KONIECZNE: panel jest elementem flexa (nakładki), więc domyślne
   min-width: auto nie pozwala mu zejść poniżej szerokości najszerszego dziecka - na telefonie
   siatka korzyści Premium rozpychała go wtedy poza ekran i połowa panelu była nie do obejrzenia. */
.ustawienia-panel {
  background: var(--crema);
  width: min(780px, 100%);
  min-width: 0;
  height: 100%;
  display: flex; flex-direction: column;
  box-shadow: -24px 0 70px rgba(0,0,0,0.30);
  animation: ustawieniaWjazd 0.34s cubic-bezier(.22,1,.36,1);
}
@keyframes ustawieniaWjazd { from { transform: translateX(100%); } to { transform: translateX(0); } }
/* Zamknięcie musi być OSOBNĄ animacją, a nie odwróceniem wjazdu: .hidden dokładamy dopiero
   po jej zakończeniu (patrz closeSettings), inaczej panel po prostu znikałby w jednej klatce. */
.ustawienia-overlay.zamykanie { animation: ustawieniaZanik 0.24s ease forwards; }
.ustawienia-overlay.zamykanie .ustawienia-panel { animation: ustawieniaZjazd 0.24s cubic-bezier(.4,0,1,1) forwards; }
@keyframes ustawieniaZanik { to { opacity: 0; } }
@keyframes ustawieniaZjazd { to { transform: translateX(100%); } }

.ustawienia-head {
  display: flex; align-items: center; gap: 12px; flex-shrink: 0;
  padding: 16px 20px; background: var(--card-bg);
  border-bottom: 1px solid var(--border-warm-soft);
}
.ustawienia-osoba { display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1; }
.ustawienia-osoba .account-avatar { width: 46px; height: 46px; font-size: 1.05rem; }
.ustawienia-nick { font-weight: 800; font-size: 1.02rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ustawienia-podpis { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 3px; }
/* Czesc plakietek to <button> (prowadza do zakladki), czesc to <span> - bez wyzerowania
   ramki i czcionki te pierwsze mialy domyslny wyglad przycisku przegladarki i odcinaly sie
   od pozostalych. */
.ustawienia-plakietka {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 999px;
  border: none; font-family: inherit;
  background: var(--bg-soft); color: var(--grigio); font-size: 0.7rem; font-weight: 800;
}
button.ustawienia-plakietka { cursor: pointer; transition: var(--transition); }
button.ustawienia-plakietka:hover { filter: brightness(0.95); }
.ustawienia-plakietka .ico { font-size: 0.72rem; margin-right: 0; }
.ustawienia-plakietka.premium { background: var(--bg-gold-soft); color: var(--oro); }
.ustawienia-plakietka.xp { background: var(--bg-info-soft); color: var(--muted-dark); }
.ustawienia-zamknij {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 50%; border: none;
  background: var(--bg-soft); color: var(--grigio); font-size: 1rem; cursor: pointer;
  transition: var(--transition);
}
.ustawienia-zamknij:hover { background: var(--bg-error-soft); color: var(--rosso); transform: rotate(90deg); }

.ustawienia-korpus { display: flex; flex: 1; min-height: 0; min-width: 0; }
.ustawienia-rail {
  position: relative; flex: 0 0 196px; padding: 14px 12px; overflow-y: auto;
  background: var(--card-bg); border-right: 1px solid var(--border-warm-soft);
  display: flex; flex-direction: column; gap: 2px; scrollbar-width: thin;
}
.ustawienia-poz {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 11px 13px; border: none; border-radius: 12px; background: transparent;
  font-family: inherit; font-size: 0.86rem; font-weight: 700; color: var(--grigio);
  cursor: pointer; text-align: left; white-space: nowrap;
  transition: color 0.22s ease, transform 0.22s ease;
}
.ustawienia-poz .ico { font-size: 1rem; margin-right: 0; }
.ustawienia-poz:hover { color: var(--testo); transform: translateX(2px); }
.ustawienia-poz.active { color: var(--oro); }
/* Wskaźnik jeżdżący za aktywną pozycją: JEDEN element, którego pozycję i wysokość ustawia
   JS (patrz przesunWskaznikUstawien). Podświetlenie przesuwa się płynnie zamiast przeskakiwać
   - to jedyne miejsce w tym panelu, gdzie JS jest potrzebny do samego wyglądu. */
.ustawienia-wskaznik {
  position: absolute; left: 12px; right: 12px; top: 0; height: 0; z-index: 0;
  border-radius: 12px; background: var(--bg-highlight); pointer-events: none; opacity: 0;
  transition: transform 0.34s cubic-bezier(.22,1,.36,1), height 0.34s cubic-bezier(.22,1,.36,1), opacity 0.2s ease;
}
.ustawienia-wskaznik.widoczny { opacity: 1; }

.ustawienia-tresc { flex: 1; min-width: 0; overflow-y: auto; padding: 22px 26px 40px; }
/* Wejście sekcji kaskadą: po kliknięciu zakładki treść układa się z góry na dół, zamiast
   pojawiać się całą planszą naraz. backwards, bo bez tego sekcja mignęłaby przed opóźnieniem. */
.settings-pane.active > .settings-section { animation: ustawieniaSekcja 0.4s cubic-bezier(.22,1,.36,1) backwards; }
.settings-pane.active > .settings-section:nth-child(1) { animation-delay: 0.02s; }
.settings-pane.active > .settings-section:nth-child(2) { animation-delay: 0.07s; }
.settings-pane.active > .settings-section:nth-child(3) { animation-delay: 0.12s; }
.settings-pane.active > .settings-section:nth-child(4) { animation-delay: 0.17s; }
.settings-pane.active > .settings-section:nth-child(n+5) { animation-delay: 0.22s; }
@keyframes ustawieniaSekcja { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* Tytuł sekcji z ikoną - ikona nie ma prawa podskakiwać przy zawijaniu tekstu, stąd flex. */
.settings-title { font-weight: 800; font-size: 0.95rem; margin-bottom: 12px; display: flex; align-items: center; gap: 9px; }
.settings-title .ico { color: var(--oro); font-size: 1rem; margin-right: 0; }

/* Wiersz "etykieta + opis po lewej, przełącznik po prawej" - powtarza się w kilku zakładkach. */
.ustawienia-wiersz {
  display: flex; align-items: center; gap: 16px; justify-content: space-between;
  padding: 13px 0; border-bottom: 1px dashed var(--border-warm-soft);
}
.ustawienia-wiersz:last-child { border-bottom: none; padding-bottom: 0; }
.ustawienia-wiersz:first-child { padding-top: 0; }
.ustawienia-wiersz-txt { min-width: 0; }
.ustawienia-wiersz-tytul { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 0.88rem; }
.ustawienia-wiersz-tytul .ico { color: var(--grigio); font-size: 0.92rem; margin-right: 0; }
.ustawienia-wiersz-opis { font-size: 0.76rem; color: var(--grigio); line-height: 1.5; margin-top: 3px; }
.ustawienia-wiersz-akcja { flex-shrink: 0; }
/* Suwak w wierszu ustawień - wartość nad suwakiem, żeby nie skakała szerokość wiersza. */
.ustawienia-suwak { display: flex; flex-direction: column; gap: 6px; min-width: 210px; }
.ustawienia-suwak-wartosc { font-weight: 800; font-size: 0.82rem; color: var(--oro); text-align: right; }
.ustawienia-suwak input[type="range"] { width: 100%; accent-color: var(--oro); cursor: pointer; }

/* ===== KONTENER ZAKUPU PREMIUM (Ustawienia → Premium i ściana nad aplikacją) =====
   Jeden komponent w dwóch miejscach (premiumKontenerHtml w JS): baner, stan konta, wybór planu,
   akordeony, kafelki korzyści - układ z makiety, którą Alek pokazał 2026-09-18. Kolory są
   z MOTYWU aplikacji, nie z makiety, więc ten sam kontener działa w jasnym i ciemnym.
   Szerokość liczymy od KONTENERA (container query), nie od okna: w szufladzie Ustawień na
   szerokim monitorze kontener ma ~500 px, a na ścianie ~700 px - media query po szerokości
   ekranu nie odróżniłoby tych dwóch miejsc i kafelki ściskałyby się w szufladzie. */
.pk { container-type: inline-size; container-name: pk; display: grid; gap: 16px; min-width: 0; overflow-wrap: break-word; }
.pk-sekcja { min-width: 0; }
.pk-sekcja-tytul { margin: 0 0 10px; font-size: 0.95rem; font-weight: 800; color: var(--testo); }

/* Baner: pełna GŁĘBOKA zieleń z białym napisem w OBU motywach. --zielen-gleboka nie zmienia się
   z motywem, więc napis też nie może: biel ma na niej 5.1:1. Dawny gradient kończył się pastelem,
   na którym jasny napis ciemnego motywu miał 1.8:1. */
.pk-baner {
  border-radius: 18px; padding: 18px 20px;
  background: var(--zielen-gleboka); color: #FFFFFF;
  box-shadow: 0 10px 30px rgba(27,126,65,0.22);
}
.pk-baner-tytul { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 1.1rem; }
.pk-baner-tytul .ico { font-size: 1.2rem; margin-right: 0; }
.pk-baner-zdanie { margin: 8px 0 0; font-size: 0.88rem; line-height: 1.55; }
.pk-baner-platnosc {
  display: flex; gap: 8px; align-items: flex-start; margin: 10px 0 0; padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.25); font-size: 0.8rem; line-height: 1.5;
}
.pk-baner-platnosc .ico { margin: 2px 0 0; flex-shrink: 0; }

/* Stan konta: ile z limitu, pasek, archiwum i granice konta darmowego. */
.pk-stan { padding: 14px 16px; border-radius: 14px; background: var(--card-bg); border: 1px solid var(--border-warm-soft); }
.pk-stan-glowa {
  display: flex; justify-content: space-between; align-items: baseline; gap: 4px 10px; flex-wrap: wrap;
  font-size: 0.85rem; font-weight: 700; color: var(--grigio);
}
.pk-stan-glowa b { color: var(--testo); font-size: 1rem; font-weight: 800; }
.pk-pasek { height: 8px; border-radius: 999px; background: var(--border); overflow: hidden; margin-top: 8px; }
.pk-pasek > span { display: block; height: 100%; border-radius: 999px; background: var(--marka-zielony); transition: width 0.4s ease; }
/* Od 80% bursztyn. Wpisany wprost, bo paleta motywu ma tylko zieleń, błękit i czerwień, a czerwień
   przy pełnej talii czytałaby się jak błąd - to okno świadomie NIE jest karą (patrz limit_spokoj).
   Bursztyn jest tu wypełnieniem, nie tekstem, więc wystarcza mu kontrast z torem w obu motywach. */
.pk-pasek.ostrzezenie > span { background: #D97706; }
.pk-archiwum { display: flex; gap: 8px; align-items: flex-start; margin: 10px 0 0; font-size: 0.82rem; line-height: 1.5; font-weight: 600; color: var(--muted-dark); }
.pk-archiwum .ico { color: var(--verde); flex-shrink: 0; margin: 2px 0 0; }
.pk-darmowe { margin-top: 12px; font-size: 0.8rem; line-height: 1.5; color: var(--grigio); }
.pk-darmowe b { color: var(--testo); }
.pk-darmowe ul { margin: 4px 0 0; padding: 0 0 0 18px; display: grid; gap: 2px; }
.pk-stan-premium { margin: 10px 0 0; font-size: 0.82rem; line-height: 1.5; font-weight: 700; color: var(--testo); }

/* Wybór planu: PRAWDZIWE radio w etykiecie - klawiatura (Tab + strzałki) i czytnik ekranu dostają
   to, co znają. Zaznaczenie widać po ramce całego kafelka, fokus - po obrysie. */
.pk-plany-lista { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding-top: 6px; }
.pk-plan {
  position: relative; display: flex; flex-direction: column; gap: 3px; min-width: 0;
  padding: 18px 14px 14px 42px; border-radius: 14px; border: 2px solid var(--border); background: var(--card-bg);
  cursor: pointer; transition: border-color 0.15s ease, background-color 0.15s ease;
}
.pk-plan:hover { border-color: var(--oro); }
.pk-plan.wybrany, .pk-plan:has(.pk-plan-radio:checked) { border-color: var(--zolty); background: var(--bg-highlight); }
.pk-plan:has(.pk-plan-radio:focus-visible) { outline: 3px solid var(--fokus); outline-offset: 2px; }
.pk-plan-radio { position: absolute; left: 14px; top: 19px; width: 18px; height: 18px; margin: 0; accent-color: var(--oro); cursor: pointer; }
.pk-plan-nazwa { font-size: 0.78rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--grigio); }
.pk-plan-cena { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; }
.pk-cena { font-size: 1.6rem; font-weight: 800; line-height: 1.15; color: var(--testo); }
.pk-cena-sufiks { font-size: 0.78rem; font-weight: 700; color: var(--grigio); }
/* Cena sprzed rabatu - przekreślona, żeby od razu było widać, ile kod realnie ścina */
.pk-cena-stara { font-size: 0.85rem; font-weight: 700; color: var(--grigio); text-decoration: line-through; }
.pk-plan-nota { font-size: 0.74rem; line-height: 1.4; color: var(--grigio); }
.pk-wstazka {
  position: absolute; top: -10px; right: 12px; white-space: nowrap;
  padding: 3px 10px; border-radius: 999px; font-size: 0.66rem; font-weight: 800;
  background: var(--verde); color: var(--na-akcencie);
}
.pk-zaplac { margin-top: 14px; padding: 13px 20px; font-size: 0.98rem; font-weight: 800; }
.pk-zaplac.loading { opacity: 0.75; }
.pk-zaplac:focus-visible, .pk-akordeon > summary:focus-visible, .currency-opt:focus-visible,
.pk .limit-droga-cta:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
.pk-blad { margin-top: 10px; }
.pk-zaplac-nota { margin-top: 8px; font-size: 0.74rem; line-height: 1.5; text-align: center; color: var(--grigio); }

/* Akordeony „Masz kod rabatowy?" i „Chcę fakturę na firmę". Strzałka to ikona z fontu, obraca ją
   CSS przy [open] - bez znaku w ::before (tam przez zjedzony backslash świeciło „B8"). */
.pk-akordeony { margin-top: 12px; display: grid; gap: 8px; }
.pk-akordeon { border: 1px solid var(--border-warm); border-radius: 12px; background: var(--card-bg); }
.pk-akordeon > summary {
  display: flex; align-items: center; gap: 9px; padding: 11px 14px; border-radius: 12px;
  font-size: 0.85rem; font-weight: 700; color: var(--testo); cursor: pointer; list-style: none; user-select: none;
}
.pk-akordeon > summary::-webkit-details-marker { display: none; }
.pk-akordeon > summary .ico { margin-right: 0; color: var(--grigio); }
.pk-strzalka { margin-left: auto; transition: transform 0.2s ease; }
.pk-akordeon[open] > summary .pk-strzalka { transform: rotate(180deg); }
.pk-akordeon-tresc { padding: 0 14px 14px; }
.pk-akordeon .auth-input { margin: 8px 0 0; }
.pk-akordeon .promo-row .auth-input { margin: 0; }

/* Korzyści: osiem kafelków, dwa w rzędzie, na wąskim kontenerze jeden. */
.pk-kafelki { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.pk-kafelek {
  display: flex; gap: 11px; align-items: flex-start; min-width: 0; padding: 13px 15px;
  border-radius: 14px; background: var(--card-bg); border: 1px solid var(--border-warm-soft);
}
.pk-kafelek > .ico { flex-shrink: 0; margin: 2px 0 0; font-size: 1.1rem; color: var(--verde); }
.pk-kafelek b { display: block; margin-bottom: 2px; font-size: 0.84rem; color: var(--testo); }
.pk-kafelek span { display: block; font-size: 0.76rem; line-height: 1.5; color: var(--grigio); }

/* Konto z Premium i godzina próbna: informacja zamiast oferty. */
.pk-info { padding: 14px 16px; border-radius: 14px; background: var(--crema); font-size: 0.88rem; line-height: 1.6; }
.pk-info-tytul { display: flex; align-items: center; gap: 8px; font-weight: 800; }
.pk-info-tytul .ico { margin-right: 0; }
.pk-info-opis { margin-top: 6px; font-size: 0.84rem; color: var(--grigio); }

@container pk (max-width: 480px) { .pk-kafelki { grid-template-columns: 1fr; } }
@container pk (max-width: 330px) { .pk-plany-lista { grid-template-columns: 1fr; } }
/* Zapas dla przeglądarek bez zapytań o kontener: wąski ekran = jedna kolumna. */
@media (max-width: 480px) {
  .pk-kafelki { grid-template-columns: 1fr; }
  .pk-baner { padding: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .pk-strzalka, .pk-pasek > span, .pk-plan { transition: none; }
}

@media (max-width: 860px) {
  /* Na wąskim ekranie pionowa lista zjadłaby połowę szerokości - kładziemy ją na płask
     nad treścią. Wskaźnik znika: przy przewijaniu w poziomie i tak nie trafiałby w miejsce. */
  .ustawienia-panel { width: 100%; }
  .ustawienia-korpus { flex-direction: column; }
  .ustawienia-rail {
    flex: 0 0 auto; flex-direction: row; overflow-x: auto; overflow-y: hidden;
    border-right: none; border-bottom: 1px solid var(--border-warm-soft);
    padding: 10px; scrollbar-width: none;
  }
  .ustawienia-rail::-webkit-scrollbar { display: none; }
  .ustawienia-poz { width: auto; flex: 0 0 auto; padding: 9px 13px; }
  .ustawienia-poz:hover { transform: none; }
  .ustawienia-poz.active { background: var(--bg-highlight); }
  .ustawienia-wskaznik { display: none; }
  .ustawienia-tresc { padding: 18px 18px 32px; }
  .ustawienia-suwak { min-width: 150px; }
}

@media (prefers-reduced-motion: reduce) {
  .ustawienia-panel,
  .ustawienia-overlay.zamykanie .ustawienia-panel,
  .settings-pane.active > .settings-section { animation: none; }
  .ustawienia-wskaznik { transition: opacity 0.2s ease; }
  .ustawienia-poz:hover { transform: none; }
}


/* =========================================================================
   TELEFONY - OSOBNE REGUŁY
   Do tej pory na wąskie ekrany szło kilka luźnych @media rozsianych po pliku i głównie
   zwężały kolumny. Poniżej jeden blok, który zajmuje się dwiema rzeczami zgłoszonymi
   wprost: STABILNOŚCIĄ widoku nauki (nic nie ma prawa skakać przy przewijaniu fiszek
   i przy wejściu quizu) oraz ciasnotą w Społeczności.
   ========================================================================= */

/* ---- 1. NAUKA BEZ SKAKANIA (wszystkie szerokości) ----
   Trzy różne rzeczy dzielą to samo miejsce: pusty ekran, fiszka i quiz. Każda ma inną
   wysokość, więc przełączenie między nimi przesuwało wszystko pod spodem i wyrzucało
   stronę w innym miejscu przewinięcia. Wspólna wysokość minimalna zdejmuje ten skok -
   quiz startuje dokładnie tam, gdzie stała fiszka. */
#flashcard-area { min-height: 620px; position: relative; }   /* relative: nakładka półmetka (.polmetek) */

/* Wiersz z licznikiem i filtrami zawija się przy dłuższej nazwie kategorii. Rezerwacja
   wysokości dwóch wierszy sprawia, że zawinięcie nie przesuwa karty w dół. */
.fiszka-nav { min-height: 40px; align-content: flex-start; }
/* To samo z rzędem przełączników - na wąskim ekranie łamie się na dwa wiersze zależnie
   od długości tłumaczeń. */
.fiszka-toggles { min-height: 34px; }
/* Przyciski oceny pojawiają się dopiero po obróceniu karty. Zamiast wskakiwać (i pchać
   stronę), miejsce na nie jest zarezerwowane od początku - .hidden zostaje, bo kliknięcia
   mają nie działać przed obróceniem, ale wysokość już się nie zmienia. */
.ocena-row.hidden { display: grid; visibility: hidden; pointer-events: none; }
/* PACZKA (każdy tryb): rzędu ocen nie ma wcale (nie „niewidoczny z zachowanym miejscem" jak wyżej -
   tam chodzi o to, żeby karta nie skakała przy obrocie, a tu przyciski nie pokażą się nigdy).
   Zamiast nich jedno zdanie po obróceniu, skąd ta różnica - patrz ocenyWylaczone() w JS. */
.ocena-row.bez-ocen { display: none !important; }
.ocena-poziom-hint { text-align: center; font-size: 0.8rem; color: var(--grigio); margin-top: 12px; line-height: 1.45; }
.ocena-poziom-hint.hidden { display: none; }

@media (max-width: 768px) {
  /* ---- 2. NAUKA NA TELEFONIE ----
     dvh, nie vh: pasek adresu w mobilnym Chrome/Safari chowa się przy przewijaniu i przy
     vh cała sekcja zmieniałaby wtedy wysokość - czyli dokładnie ten skok, który mamy
     wyeliminować. */
  #flashcard-area { min-height: 74dvh; }
  /* Reguly telefonu dla samej karty przeniosly sie do komponenty/fiszka.php - jada razem
     z jej wygladem, zeby artykul dostal je tak samo jak aplikacja. */
  /* Filtry na całą szerokość, po dwa w rzędzie - przy 150 px maksymalnej szerokości nazwy
     kategorii i tak się nie mieściły. */
  .fiszka-nav { gap: 8px; }
  .fiszka-nav .custom-select { flex: 1 1 45%; }
  .fiszka-nav-select { max-width: none; width: 100%; }

  /* ---- 3. SPOŁECZNOŚĆ NA TELEFONIE ----
     Pasek narzędzi łamał się na trzy–cztery poziomy: wyszukiwarka, filtr, zakładki, konto.
     Tu składamy go w dwa czytelne rzędy: wyszukiwarka na całą szerokość, pod nią jeden
     wiersz z akcjami dosuniętymi do prawej. */
  /* Trzy przewidywalne wiersze zamiast czterech przypadkowych: wyszukiwarka na całą
     szerokość, pod nią filtr z kafelkami, a nawigacja i konto jako osobny blok dosunięty
     do prawej. Kluczowe jest, żeby SAMA nawigacja się nie łamała - inaczej motyw, flaga,
     zakładki i konto rozłaziły się po dwóch poziomach i pasek wyglądał na rozsypany. */
  .community-topbar { gap: 8px; }
  .community-search-wrap { flex: 1 1 100%; max-width: none; }
  .community-filters { flex: 1 1 100%; gap: 8px; flex-wrap: wrap; }
  .cmty-nawigacja { flex-wrap: nowrap !important; margin-left: auto; gap: 8px; }
  /* Chip filtra bierze resztę wiersza i skraca się wielokropkiem - „Moja biblioteka" jest
     dwa razy dłuższe niż „Popularne", a pasek nie może przez to zmieniać wysokości. */
  #communitySortBtn { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* Nazwy zakładek zjadały cały wiersz - na telefonie zostaje sama ikona, a co jest czym,
     mówi kolor aktywnej pigułki (tej samej co w nagłówku Fiszek). */
  .cmty-nawigacja .mode-tab span { display: none; }
  .cmty-nawigacja .mode-tab { padding: 8px 12px; }
  .cmty-nawigacja .mode-tab .ico { margin-right: 0; font-size: 1rem; }
  /* Wysokość filtra, dwie kolumny tablicy i dopełnienie stoją w sekcji 16 stylu kanwy (2026-10-03): tu przegrywały
     kaskadę z regułami bazowymi, które stoją niżej w arkuszu (filtr miał 31 px, a siatka auto-fill z minmax 150 px). */

  /* Powiększenie karty: kolumny jedna pod drugą i zdjęcie ograniczone do połowy ekranu,
     żeby lista słówek i komentarze były widoczne bez przewijania przez całą grafikę. */
  .community-detail-karta.w-siatce { flex-direction: column; }
  .community-detail-karta.w-siatce .community-detail-obraz img { max-height: 48dvh; }
  .community-detail-panel { padding: 16px 14px; min-width: 0; min-height: 0; }
  .community-detail-karta.paczka .community-detail-obraz { padding: 54px 14px 16px; }
  .community-zdania { max-height: 46dvh; }
  /* Akcje na zdjęciu są na dotyku widoczne od razu (patrz @media (hover:none)) - tu tylko
     odsuwamy je od krawędzi. Pole 44 px i szerokość panelu kategorii (min(300px, 86vw)) mają dziś wszystkie
     ekrany, w sekcji 16 stylu kanwy: stąd przegrywały kaskadę. */
  .community-detail-akcje-gora { top: 10px; right: 10px; gap: 6px; }

  /* ---- PASEK SPOŁECZNOŚCI: TEN SAM ZABIEG CO W NAGŁÓWKU FISZEK ----
     Miał 177 px i trzy rzędy: wyszukiwarka, pod nią filtr z motywem, flagą i zakładkami,
     a panel konta spadał do trzeciego. Ta sama przyczyna: .cmty-nawigacja była osobnym
     pudełkiem, które jako całość nie mieściło się w wierszu i schodziło niżej z całą
     zawartością. display: contents rozpuszcza je, a wtedy jego dzieci układają się razem
     z filtrem i kafelkami. Zakładki dostają własny, wyśrodkowany wiersz.

     Przedrostek `body` NIE jest ozdobnikiem: reguły bazowe .cmty-nawigacja i .community-filters
     stoją w tym pliku NIŻEJ niż ten blok telefonowy, a zapytanie @media nie podnosi swoistości
     - bez tego jednego elementu więcej przegrywają samą kolejnością i nic się nie dzieje
     (sprawdzone: display zostawał `flex`, a flex-wrap `nowrap`). */
  body .cmty-nawigacja { display: contents; }
  /* flex i min-width też muszą tu być, i też z `body`: bazowe `.community-filters { flex: 1;
     min-width: min-content }` stoi niżej w pliku. Po rozpuszczeniu nawigacji jej zawartość
     przestała podpierać szerokość minimalną, więc filtr skurczył się do 146 px i wszystko
     ustawiło się w wąską kolumnę przy prawej krawędzi. */
  /* Rozpuszczamy TAKŻE .community-filters - wtedy wszystkie kontrolki paska są dziećmi
     jednego kontenera (.community-topbar) i da się je ułożyć w dwa wiersze zamiast trzech.
     Zakładki wskakują obok wyszukiwarki, która i tak nie potrzebuje całej szerokości. */
  body .community-filters { display: contents; }
  /* column-gap 6, nie 8: drugi wiersz (filtr + kafelki + motyw + flaga + konto) wychodził
     na 362 px przy 360 dostępnych i konto spadało do trzeciego rzędu przez DWA piksele.
     Cztery odstępy po 2 px mniej załatwiają sprawę bez ruszania samych kontrolek. */
  /* row-gap 4, nie 8: łamanie wiersza (::before niżej) jest osobną linią o zerowej wysokości, więc odstęp między
     rzędami liczy się dwa razy; 2 x 4 px daje te same 8 px, co odstęp w poziomie. */
  body .community-topbar { row-gap: 4px; column-gap: 6px; align-items: center; }

  /* DWA RZĘDY, NIE TRZY (2026-10-03). Zmierzone przy 390 x 844: pasek miał 184 px (22% ekranu), bo aparat nie miał
     tu miejsca w kolejności, a zawijanie flexa liczy szerokość z flex-basis: auto PRZED kurczeniem: filtr z napisem
     106 px wypychał konto do trzeciego rzędu, choć sam mógłby się skurczyć.
     wiersz 1: wyszukiwarka, aparat, kafelki i zakładki */
  /* Podstawa 80 px, nie 120: przy 360 px zakładki (117 px) spadały do drugiego rzędu, a filtr i konto do trzeciego. */
  body .community-topbar .community-search-wrap { order: 0; flex: 1 1 80px; min-width: 0; max-width: none; }
  body .community-topbar .community-aparat      { order: 1; }
  body .community-topbar .community-kafelki     { order: 2; }
  body .community-topbar .mode-tabs             { order: 3; flex: 0 0 auto; }
  /* wiersz 2: filtr, „Wszystkie języki”, motyw, flaga i konto dosunięte do prawej */
  /* Filtr ustępuje pierwszy i skraca się wielokropkiem (ma już overflow/ellipsis wyżej) -
     jego etykieta zmienia się z „Najnowsze" na „Moja biblioteka" i bez tego dłuższa nazwa
     znów rozbijałaby wiersz. flex-basis 0 sprawia, że przy łamaniu wiersza liczy się jako zero (nie wypycha
     konta), a max-width: max-content, że rośnie najwyżej do swojego napisu, więc resztę bierze margines konta. */
  body .community-topbar .community-chip     { order: 5; flex: 1 1 0; min-width: 0; max-width: max-content; }
  body .community-topbar #cmtyMixBtn         { order: 6; flex: 0 1 auto; }
  body .community-topbar .header-theme       { order: 7; }
  body .community-topbar .header-lang        { order: 8; }
  body .community-topbar .header-konto       { order: 9; margin-left: auto; }
  /* Łamanie wiersza dokładnie po zakładkach - element o zerowej wysokości i pełnej
     szerokości. Bez niego kontrolki wchodziłyby na pierwszy wiersz w kolejności, w jakiej
     się zmieszczą, i pasek wyglądałby inaczej przy każdej długości nazwy filtra. */
  body .community-topbar::before { content: ''; order: 4; flex: 1 1 100%; height: 0; }
  /* Gość zamiast panelu konta ma wezwanie do założenia konta - cały wiersz na dole paska,
     bo to jedyna rzecz, którą ma tam zrobić. */
  body .community-topbar .gosc-cta { order: 10; flex: 1 1 100%; }

  /* ---- 4. NAGŁÓWEK ----
     #headerActions to element flex bez prawa do kurczenia (domyślne min-width: auto), więc
     przy wąskim ekranie zjadał prawy margines paska i wystawał kilkaset setnych piksela poza
     krawędź. To wystarczy, żeby telefon uznał stronę za szerszą niż ekran i pozwolił nią
     ruszać w bok. */
  /* Sygnatura LINGARIA.COM zajmowala caly wiersz nagłówka (185 px szerokosci), a adres
     i tak stoi w pasku przegladarki tuz nad nia. Bez niej pasek schodzi z trzech rzedow
     na dwa. */
  #headerBrand { display: none; }
  .header-inner { padding: 8px 14px; gap: 8px; }
  #headerActions { gap: 8px; row-gap: 8px; justify-content: flex-end; }
  .header-title { gap: 8px; }

  /* UKŁAD DWURZĘDOWY ZAMIAST TRZYRZĘDOWEGO.
     Przy koncie zalogowanym w pasku stoi pięć rzeczy: motyw, flaga, passa, zakładki i panel
     konta. Razem to ok. 440 px przy 362 dostępnych, więc jeden rząd nie wchodzi w grę bez
     usunięcia którejś z nich. Bez wymuszenia łamały się jednak w najgorszym miejscu: passa
     zostawała przy zakładkach, a panel konta spadał do TRZECIEGO rzędu - stąd 171 px, czyli
     20% ekranu.
     Zakładki dostają własny, wyśrodkowany wiersz (flex-basis: 100%), a passa i konto mieszczą
     się obok motywu i flagi. Dwa rzędy zamiast trzech, ok. 120 px.
     Reguły są przypięte do #headerActions, bo w trybie Społeczności te same elementy
     przenoszą się do pionowego paska po prawej (patrz przeniesDoPaska) i tam mają zostać
     ułożone po swojemu. */
  /* display: contents rozpuszcza kontener akcji - jego dzieci stają się bezpośrednimi
     elementami paska i mogą układać się w jednym wierszu razem z motywem i flagą. Dopóki
     był osobnym pudełkiem, nie mieścił się obok tytułu W CAŁOŚCI i schodził niżej, ciągnąc
     za sobą wszystko. */
  .header-actions { display: contents; }
  .header-inner { row-gap: 8px; justify-content: flex-start; }
  .header-inner > .header-title { order: 0; }
  .header-inner .streak-wrap    { order: 1; }
  /* Konto dosunięte do prawej krawędzi - to samo miejsce, co na dużym ekranie. */
  .header-inner .header-konto   { order: 2; margin-left: auto; }
  /* Zakładki dostają własny, wyśrodkowany wiersz: razem z resztą byłoby ok. 440 px przy 362
     dostępnych, a ich rozbicie w środku wiersza wyglądałoby przypadkowo. */
  .header-inner .mode-tabs      { order: 3; flex: 1 1 100%; justify-content: center; }
  /* Etykieta zostaje przy AKTYWNEJ zakładce, nieaktywna schodzi do samej ikony. Sama etykieta
     aktywnej niesie informację, w którym podwidoku się jest („Fiszki" czy „Teksty") - to jedyne
     miejsce, gdzie to widać. Dwie pełne etykiety zajmowały 289 px z 347 dostępnych i spychały
     panel konta do osobnego rzędu. */
  .mode-tab:not(.active) span:not(.mode-tab-caret) { display: none; }
  .mode-tab:not(.active) { padding-left: 14px; padding-right: 14px; }
  .mode-tab:not(.active) .ico { margin-right: 0; }

  /* Pasek nad czytanka: tytul dostaje wlasny wiersz zamiast walczyc o piksele z ikonami. */
  .kartka-pasek { flex-wrap: wrap; row-gap: 8px; }
  .kartka-tytul-blok { flex: 1 1 150px; }
  .kartka-akcje { flex-shrink: 1; flex-wrap: wrap; }

  @supports (padding: env(safe-area-inset-left)) {
    .header-inner {
      padding-left:  max(14px, env(safe-area-inset-left));
      padding-right: max(14px, env(safe-area-inset-right));
    }
  }
  #headerActions { min-width: 0; flex-wrap: wrap; justify-content: flex-end; }

  /* ---- 5. MAPA SŁÓWEK ----
     Nagłówek mapy to jeden nierozrywalny wiersz: tytuł po lewej, wyszukiwarka i przełącznik
     po prawej. Przy 320 px wyszukiwarka zaczynała się na 224 px i kończyła na 404 - czyli
     w całości poza modalem. Na telefonie dajemy jej własny wiersz pod tytułem. */
  .wordmap-header { flex-wrap: wrap; gap: 10px; padding: 16px 16px 12px; }
  .wordmap-controls { flex: 1 1 100%; justify-content: space-between; gap: 10px; }
  .wordmap-search { max-width: none; }
}

/* ---- POLA TRAFIENIA POD KCIUK ----
   Warunek celowo po RODZAJU WSKAŹNIKA, nie po szerokości: liczy się to, czy ekran jest
   dotykowy, a nie ile ma pikseli. Tablet w poziomie ma 1024 px i też potrzebuje większych
   przycisków, a wąskie okno na laptopie z myszką - nie.
   Wytyczne Apple i Google mówią o 44 px. Przyciski „pokaż mapę" pod licznikami miały 23 px
   wysokości, czyli połowę tego, i leżały jeden pod drugim - trafienie w sąsiedni było
   łatwiejsze niż we właściwy. */
@media (hover: none) and (pointer: coarse) {
  .stat-map-btn { min-height: 38px; padding-top: 9px; padding-bottom: 9px; }
  .mode-tab { min-height: 44px; }
  .header-theme { width: 40px; height: 40px; }
  .kartka-ikona, .kartka-przelacznik, .kartka-wroc { min-height: 40px; min-width: 40px; }
  /* Strzałka rozwijająca podwidok jest osobnym, 13-pikselowym celem wewnątrz zakładki -
     powiększamy samo pole kliknięcia, nie rysunek. */
  .mode-tab-caret { padding: 12px 8px; margin: -12px -8px; }
}

/* ---- BARDZO WĄSKIE TELEFONY (iPhone SE i podobne) ----
   Przy 320 px pasek Społeczności w trybie gościa nie mieścił się w żadnej konfiguracji:
   samo CTA „Załóż darmowe konto" ma 182 px, a `flex-wrap: nowrap` wyżej zabraniało wiersza
   złamać. Efekt był poważniejszy niż estetyka - zakładki Fiszki/Społeczność lądowały
   w całości POZA ekranem (x 320–424) i nie dało się ich kliknąć.
   Poniżej tego progu odwracamy tamten kompromis: lepiej dwa czytelne wiersze niż jeden,
   z którego połowa jest niedostępna. */
@media (max-width: 480px) {
  .cmty-nawigacja { flex-wrap: wrap !important; justify-content: flex-end; row-gap: 8px; }
  .community-filters { min-width: 0; }
  /* CTA bierze cały wiersz i skraca się wielokropkiem zamiast rozpychać pasek. */
  .cmty-nawigacja .gosc-cta { flex: 1 1 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* PASEK SPOŁECZNOŚCI W TRZECH RZĘDACH (2026-10-03, po recenzji). Dwa rzędy z bloku telefonu wyżej mieszczą się tylko
     kosztem wyszukiwarki: miała 147 px przy 390 i 117 px przy 360, czyli 71 i 41 px na tekst („ristorante” widać było
     jako „ristor”, podpowiedź jako „Szukaj słć”), a filtr ucinał się bez wielokropka („Popul”, u moderatora „Do wery”).
     Pasek chowa się przy przewijaniu, więc trzeci rząd mało kosztuje (3 x 44 + 2 x 8 + 20 = 168 px; przed zmianą 184).
     wiersz 1: wyszukiwarka z aparatem i kafelkami (266 px przy 390, 236 przy 360),
     wiersz 2: filtr, „Wszystkie języki”, motyw i flaga,
     wiersz 3: zakładki i konto dosunięte do prawej.
     Szerokości zmierzone przy 390: filtr 104-143 px, „Wszystkie języki” 151, zakładki 113 (137 w Słuchaniu), konto 136,
     flaga 68. Moderator ma o pigułkę więcej i drugi rząd by się nie zmieścił, więc u niego flaga schodzi do trzeciego
     (wtedy 350 i 329 px przy 366). Gość nie ma filtra, zakładek ani konta: motyw zostaje przy wyszukiwarce. */
  body .community-topbar .community-search-wrap { flex: 1 1 0; }
  body .community-topbar .community-chip        { flex: 0 1 auto; max-width: 100%; }
  body .community-topbar .mode-tabs             { order: 12; }
  body .community-topbar .header-konto          { order: 13; }
  body .community-topbar .gosc-cta              { order: 14; }
  body .community-topbar::after { content: ''; order: 10; flex: 1 1 100%; height: 0; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .header-lang { order: 11; }
  body.tryb-goscia .community-topbar .header-theme { order: 3; }
  body.tryb-goscia .community-topbar::after { display: none; }
}
/* Przy 360 px moderator mieści drugi rząd (filtr, „Wszystkie języki”, motyw) dopiero z węższymi pigułkami: 334 px przy 336. */
@media (max-width: 400px) {
  body .community-topbar .community-chip { padding-inline: 12px; }
}
/* Moderatorowi dwa rzędy z bloku telefonu wystarczają dopiero od ok. 590 px: drugi rząd (filtr, „Wszystkie języki”, motyw,
   flaga, konto) ma 566 px, a filtr kurczył się do kilkudziesięciu pikseli. Do 620 px dostaje te same trzy rzędy, co wyżej. */
@media (min-width: 481px) and (max-width: 620px) {
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .community-search-wrap { flex: 1 1 0; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .community-chip        { flex: 0 1 auto; max-width: 100%; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .mode-tabs             { order: 12; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .header-lang           { order: 11; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden)) .header-konto          { order: 13; }
  body .community-topbar:has(#cmtyMixBtn:not(.hidden))::after { content: ''; order: 10; flex: 1 1 100%; height: 0; }
}

/* Bardzo wąskie telefony. Tablica Społeczności zostaje tu przy dwóch kolumnach, jak w aplikacji (reguła z jedną
   kolumną i tak przegrywała z blokiem 720 px niżej w arkuszu; usunięta 2026-10-03). */
@media (max-width: 400px) {
  /* .empty-state-methods to flex, nie grid - kolumna, a nie grid-template-columns. */
  .empty-state-methods { flex-direction: column; }
  .empty-state-method { width: 100%; }
  .add-method-tabs { grid-template-columns: 1fr; }
}


/* =========================================================================
   TRYB "TEKSTY" - czytanka na kartce w kratkę
   ========================================================================= */

/* --- Rozwinięcie pod zakładką Fiszek --- */
.mode-tab-wrap { position: relative; display: inline-flex; }
.mode-tab-caret { font-size: 0.7em; opacity: 0.75; margin-left: 5px; padding: 0 2px; }
.mode-tab-caret:hover { opacity: 1; }
.mode-tab-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 200;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft);
  border-radius: 12px; box-shadow: var(--shadow-hover);
  min-width: 210px; padding: 6px;
}
.mode-tab-item {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 11px;
  border-radius: 9px; cursor: pointer; color: var(--testo);
}
.mode-tab-item:hover { background: var(--bg-soft); }
.mode-tab-item.active { background: var(--bg-highlight); color: var(--oro); }
.mode-tab-item .ico { margin-right: 0; margin-top: 2px; }
.mode-tab-item b { display: block; font-size: 0.84rem; font-weight: 700; }
.mode-tab-item small { display: block; font-size: 0.7rem; color: var(--grigio); margin-top: 1px; }

/* Panel boczny w trybie "Teksty": historia na górze, dodawanie słówek na dole.
   Przez order, nie przez przenoszenie w DOM - panel jest flex-kolumną, więc kolejność
   wizualna zmienia się bez ruszania znaczników i bez utraty stanu formularza w środku. */
#kartaHistoriaTekstow, #kartaHistoriaFilmow, #kartaHistoriaMowienia { display: none; }
body.tryb-teksty   #kartaHistoriaTekstow  { display: block; }
body.tryb-filmy    #kartaHistoriaFilmow   { display: block; }
body.tryb-mowienie #kartaHistoriaMowienia { display: block; }
body.tryb-teksty   #kartaDodajSlowka,
body.tryb-filmy    #kartaDodajSlowka,
body.tryb-mowienie #kartaDodajSlowka { order: 3; }
/* Długa historia nie może wypchnąć postępu poza ekran - po kilkunastu tekstach panel
   przewija się w środku. */
/* overflow-x jawnie: samo overflow-y:auto zamienia drugą oś na "auto" i w wąskim panelu
   pod listą wyskakiwał poziomy pasek przewijania. */
/* Bez własnego paska przewijania: panel pokazuje najwyżej PANEL_HISTORII pozycji, więc jest
   z natury krótki. Wcześniej wchodziła tu cała historia i pasek w pasku - przewijanie listy
   wewnątrz przewijanej strony - sprawiał, że dolne pozycje trzeba było wyłuskiwać. Reszta
   jest jedno kliknięcie dalej, w „Wszystkie". */
#tekstyHistoria, #filmyHistoria, #mowienieMapaBok { overflow-x: hidden; }
#kartaHistoriaTekstow  .tekst-wiersz,
#kartaHistoriaFilmow   .tekst-wiersz,
#kartaHistoriaMowienia .tekst-wiersz { padding: 10px 11px; margin-bottom: 6px; }
#kartaHistoriaTekstow  .tekst-wiersz:last-child,
#kartaHistoriaFilmow   .tekst-wiersz:last-child,
#kartaHistoriaMowienia .tekst-wiersz:last-child { margin-bottom: 0; }
/* Miniatura zamiast poziomu (A1/B2): film nie ma poziomu, a klatka z YouTube'a rozpoznaje się
   szybciej niż tytuł - po to właśnie się do listy wraca. */
.film-wiersz-mini {
  flex: none; width: 46px; height: 26px; object-fit: cover; border-radius: 5px;
  background: var(--bg-soft);
}

/* --- Lista i formularz --- */
.tekst-intro { color: var(--grigio); font-size: 0.86rem; line-height: 1.6; margin: 0 0 14px; }
.tekst-licznik { text-align: right; font-size: 0.72rem; color: var(--grigio); margin: -6px 0 10px; }
.tekst-licznik.blisko { color: var(--rosso); font-weight: 700; }

.tekst-wiersz {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 12px 14px; margin-bottom: 8px; cursor: pointer;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft); border-radius: 14px;
  font-family: inherit; color: var(--testo); transition: var(--transition);
}
.tekst-wiersz:hover { border-color: var(--oro); transform: translateX(2px); }
/* PASEK POSTĘPU JAKO TŁO WIERSZA. Bardzo jasna zieleń wypełnia wiersz od lewej dokładnie
   w tylu procentach, w ilu zdania są zrobione - całą listę czyta się wtedy jednym rzutem
   oka, bez czytania liczb. Warstwa ::before (nie gradient na tle) trzyma zaokrąglenie
   wiersza i nie rusza kolorów tekstu; z-index 0 kładzie ją POD treść, a dzieci wiersza
   dostają position:relative, żeby zostały na wierzchu. */
.tekst-wiersz { position: relative; overflow: hidden; isolation: isolate; }
.tekst-wiersz::before {
  content: ''; position: absolute; inset: 0 auto 0 0; z-index: 0;
  width: var(--postep, 0%);
  background: color-mix(in srgb, var(--verde) 14%, transparent);
  transition: width .35s ease;
  pointer-events: none;
}
.tekst-wiersz > * { position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) { .tekst-wiersz::before { transition: none; } }
.tekst-wiersz-txt { flex: 1; min-width: 0; }
/* display:block, bo to są <span>-y: bez tego ani skracanie wielokropkiem, ani margines
   nie działają, a tytuł i opis sklejają się w jedną linijkę w wąskim panelu bocznym. */
/* Tytuł i odznaka „DZIŚ" leżą obok siebie we WSPÓLNYM wierszu, ale skraca się wyłącznie
   tytuł. Gdy odznaka siedziała w środku tytułu, wielokropek zjadał najpierw ją i zostawało
   „W…" - czyli ucinała się dokładnie ta informacja, dla której ją dodaliśmy. */
/* Tytuł i plakietka „2 DNI TEMU" dzielą jedną linijkę, ale w wąskim panelu bocznym
   plakietka (nieściśliwa, ~90 px) zjadała prawie całą szerokość i z tytułu zostawało
   „Dit…". Dlatego: wrap na wierszu + gwarantowane minimum dla tytułu - gdy na sensowny
   tytuł brakuje miejsca, to PLAKIETKA schodzi do drugiej linii, a nie tytuł znika.
   W szerokiej liście (pełny ekran) nic się nie zmienia: wszystko mieści się jak dotąd. */
.tekst-wiersz-glowa { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.tekst-wiersz-tytul { flex: 1 1 auto; min-width: 14ch; font-weight: 700; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tekst-wiersz-meta { display: block; font-size: 0.72rem; color: var(--grigio); margin-top: 3px; }
.tekst-poziom {
  flex-shrink: 0; min-width: 34px; text-align: center; padding: 3px 8px; border-radius: 999px;
  background: var(--bg-info-soft); color: var(--primary); font-size: 0.7rem; font-weight: 800;
}
.tekst-pusto { color: var(--grigio); font-size: 0.85rem; line-height: 1.6; }
.proba-wyjscie-info {
  font-size: 0.78rem; font-weight: 600; color: var(--grigio); line-height: 1.5;
}
/* Kosz w wierszu historii. Wychodzi z cienia dopiero pod kursorem - lista jest do czytania
   i otwierania, a nie do kasowania, więc kasowanie nie ma prawa rzucać się w oczy. */
.tekst-wiersz-usun {
  flex-shrink: 0; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; color: var(--muted-light); opacity: 0; transition: var(--transition);
}
.tekst-wiersz:hover .tekst-wiersz-usun { opacity: 1; }
.tekst-wiersz-usun:hover { background: var(--bg-soft); color: var(--rosso); }
/* Ta sama plakietka jako wejście do paletki fiszek w panelu „Rozmowy” - nie kasuje, więc pod kursorem w akcencie, nie w czerwieni. */
.tekst-wiersz-usun.tekst-wiersz-fiszki:hover { color: var(--oro); }
/* Na dotyku nie ma najechania - tam kosz jest widoczny od razu, tylko przygaszony. */
@media (hover: none) and (pointer: coarse) { .tekst-wiersz-usun { opacity: 0.55; } }

/* Tytuł własnego tekstu daje się kliknąć i zmienić - podkreślenie kropkowane mówi to
   bez dokładania kolejnej ikony do i tak gęstego paska. */
.kartka-tytul.do-zmiany { cursor: text; text-decoration: underline dotted var(--border-warm); text-underline-offset: 4px; }
.kartka-tytul.do-zmiany:hover { color: var(--primary); }
/* W trakcie pisania tytuł przestaje być etykietą, a staje się polem: ramka pokazuje, dokąd
   sięga, a zdjęte przycięcie wielokropkiem pozwala zobaczyć koniec własnej nazwy - inaczej
   dłuższa chowałaby się pod „…" dokładnie tam, gdzie stoi kursor. */
.kartka-tytul.w-edycji {
  text-decoration: none; overflow: visible; text-overflow: clip; outline: none; cursor: text;
  padding: 2px 8px; margin: -2px -8px; border-radius: 8px;
  background: var(--card-bg); box-shadow: 0 0 0 2px var(--primary);
}

/* Przyciski w pasku kartki (Brudnopis, Kolory) nie mają przełącznika, więc stan „włączony"
   muszą pokazać sobą - inaczej po otwarciu brudnopisu pasek wygląda tak samo jak przed. */
.kartka-przelacznik.aktywny { border-color: var(--oro); color: var(--oro); background: var(--bg-highlight); }

/* ===== BRUDNOPIS - druga kartka obok tekstu ===== */
.kartka-obszar { display: flex; align-items: flex-start; gap: 16px; }
.kartka-obszar .kartka { flex: 1; min-width: 0; }
.brudnopis {
  /* flex-start, NIE stretch: rozciagniety na cala wysokosc kartki brudnopis nie mialby po
     czym jechac (sticky rusza sie tylko w obrebie wlasnego bloku) i przy dlugim tekscie pole
     do pisania zostawaloby na samej gorze - trzeba by przewijac do niego w druga strone. */
  flex: 0 0 300px; align-self: flex-start; position: sticky; top: 12px;
  max-height: calc(100vh - 24px);
  display: flex; flex-direction: column; gap: 10px;
  border-radius: 16px; padding: 16px 16px 14px;
  /* Ta sama kratka co na kartce - brudnopis ma wyglądać jak druga strona tego samego zeszytu,
     a nie jak panel aplikacji doklejony z boku. */
  background-color: var(--card-bg);
  background-image:
    linear-gradient(var(--kratka-linia) 1px, transparent 1px),
    linear-gradient(90deg, var(--kratka-linia) 1px, transparent 1px);
  background-size: 26px 26px;
  border: 1px solid var(--border-warm-soft);
  box-shadow: var(--shadow);
}
.brudnopis-naglowek { display: flex; align-items: center; gap: 6px; }
.brudnopis-tytul {
  flex: 1; font-size: 1.15rem; font-weight: 700; color: var(--grigio);
  letter-spacing: 0.02em; opacity: 0.75;
}
.brudnopis-x {
  width: 26px; height: 26px; flex-shrink: 0; border: none; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--grigio); font-size: 0.85rem; transition: var(--transition);
}
.brudnopis-x:hover { background: var(--bg-soft); color: var(--testo); }
/* Kartka do pisania. Bez obwódki i bez tła - ma wyglądać jak miejsce na kratce, a nie jak
   pole formularza wstawione w zeszyt. Wysokość rośnie z treścią, do rozsądnego maksimum. */
.brudnopis-kartka {
  flex: 1 1 auto; min-height: 220px; overflow-y: auto;
  font-size: 0.9rem; line-height: 26px;   /* równo z kratką w tle (26px) */
  color: var(--testo); outline: none; word-break: break-word;
}
.brudnopis-kartka:empty::before {
  content: attr(data-pusty); color: var(--muted-light); pointer-events: none;
}
.brudnopis-kartka .cytat {
  display: block; border-left: 3px solid var(--oro); padding-left: 9px; margin: 2px 0;
}
.brudnopis-kartka .cytat .tlum { display: block; font-size: 0.82rem; color: var(--grigio); }

/* Słowo, w które właśnie kliknięto, a tłumaczenia jeszcze lecą. */
.context-word.glosy-czekaja { opacity: 0.5; cursor: progress; }

/* Zdanie źródłowe pod rozstrzygnięciem rozsypanki - te same klikalne słowa, co w trybie
   "uzupełnij zdanie", więc i ten sam rozmiar tekstu. */
.quiz-zdanie-glosy { margin-top: 6px; font-size: 0.95rem; line-height: 1.7; }

/* Pasek formatowania nad zaznaczeniem w brudnopisie. */
.brudnopis-pasek {
  position: fixed; z-index: 1200; display: flex; align-items: center; gap: 4px;
  padding: 5px 7px; border-radius: 10px;
  background: var(--testo); box-shadow: 0 6px 18px rgba(0,0,0,0.28);
}
.bp-narzedzie {
  min-width: 26px; height: 26px; border: none; border-radius: 6px; cursor: pointer;
  background: transparent; color: var(--card-bg); font-family: inherit; font-size: 0.85rem;
}
.bp-narzedzie:hover { background: rgba(255,255,255,0.16); }
.bp-kolor {
  width: 20px; height: 20px; border: none; border-radius: 50%; cursor: pointer; background: var(--k);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.35);
}
.bp-kolor:hover { transform: scale(1.12); }
.bp-kreska { width: 1px; height: 18px; background: rgba(255,255,255,0.25); margin: 0 2px; }

/* Tryb przenoszenia: kartka zamarza - nie da się otworzyć zdania do tłumaczenia, zostaje
   samo zaznaczanie. Bez tego pierwsze kliknięcie w zdanie otwierałoby panel próby i zjadało
   zaznaczenie, które właśnie się robi. */
.przenoszenie-pasek {
  display: flex; align-items: center; gap: 10px; margin: 0 0 12px;
  padding: 10px 14px; border-radius: 12px;
  background: var(--bg-warn-soft); color: var(--muted-dark);
  font-size: 0.82rem; font-weight: 600; line-height: 1.45;
}
.przenoszenie-pasek .ico { color: var(--primary); flex-shrink: 0; }
.przenoszenie-pasek button {
  margin-left: auto; flex-shrink: 0; border: none; border-radius: 9px; cursor: pointer;
  padding: 7px 14px; background: var(--primary); color: #fff;
  font-family: inherit; font-size: 0.78rem; font-weight: 800;
}
body.tryb-przenoszenia #kartkaTresc .kartka-segment { cursor: text; }
body.tryb-przenoszenia #kartkaTresc .kartka-proba { display: none !important; }
body.tryb-przenoszenia #kartkaTresc .kartka-segment:hover { background: transparent; }
body.tryb-przenoszenia .brudnopis-przenies { background: var(--primary); color: #fff; }
@media (max-width: 900px) {
  .kartka-obszar { flex-direction: column; }
  .brudnopis { flex: 1 1 auto; width: 100%; position: static; max-height: none; }
}

/* Ściąga: wiersz = próbka koloru + nazwa + jedno zdanie wyjaśnienia. Próbki są tymi SAMYMI
   elementami co na kartce (to samo .kartka-zrodlo w tej samej ocenie, ta sama .znane-slowo),
   więc legenda nie może rozjechać się z rzeczywistością przy zmianie któregokolwiek koloru. */

.sciaga-grupa { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--grigio); margin: 16px 0 8px; }
.sciaga-grupa:first-child { margin-top: 0; }
.sciaga-wiersz { display: flex; align-items: flex-start; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--border); }
.sciaga-wiersz:last-child { border-bottom: none; }
.sciaga-probka { flex-shrink: 0; width: 74px; display: flex; align-items: center; justify-content: center; padding-top: 2px; }
.sciaga-probka .kartka-zrodlo { font-size: 0.95rem; font-weight: 600; color: var(--testo); }
.sciaga-opis b { display: block; font-size: 0.86rem; color: var(--testo); }
/* Wiersz, o który konkretnie zapytano klikając kolor na kartce. */
.sciaga-wskazany { animation: sciagaMrug 2.1s ease-out; border-radius: 10px; }
@keyframes sciagaMrug {
  0%, 100% { background: transparent; }
  15%, 55% { background: var(--bg-success-soft); }
}
@media (prefers-reduced-motion: reduce) { .sciaga-wskazany { animation: none; background: var(--bg-success-soft); } }
/* Oznaczenia, w które da się kliknąć po zdaniu - kursor mówi, że to nie jest sam kolor. */
.kartka-segment.zrobione .znane-slowo,
.kartka-segment .trudne-fraza, .kartka-segment .ai-wstawka { cursor: help; }
.sciaga-opis span { font-size: 0.79rem; color: var(--grigio); line-height: 1.5; }

/* ===== ŚCIANA PREMIUM NAD APLIKACJĄ (#premiumScianaOverlay) =====
   Jedno okno na siedem powodów (talia pełna, cztery przydziały, quiz głosowy, budżet AI) - patrz
   ŚCIANA PREMIUM w JS. Świadomie NIE wygląda jak blokada: najpierw zdanie „co się stało" i zielona
   ramka „co zostaje", dopiero pod nimi kontener zakupu. Przy pełnej talii między płatnością
   a korzyściami stoi druga droga, bez płacenia, tej samej szerokości - okno, w którym jedyne
   wyjście kosztuje, jest ultimatum, choćby było napisane najuprzejmiej. */
.limit-opis { font-size: 0.9rem; color: var(--muted-dark); line-height: 1.6; margin: 0 0 10px; }
.limit-spokoj {
  font-size: 0.86rem; line-height: 1.6; margin: 0 0 18px; padding: 10px 14px;
  border-radius: 12px; background: var(--bg-success-soft); color: var(--muted-dark);
}
.limit-spokoj b { color: var(--testo); }
.sciana-powod { margin-bottom: 18px; }
.sciana-powod > :last-child { margin-bottom: 0; }
.limit-droga {
  display: flex; flex-direction: column; padding: 15px 16px; border-radius: 16px;
  border: 1px solid var(--border-warm-soft); background: var(--card-bg); min-width: 0;
}
.limit-droga-tytul { font-weight: 800; font-size: 0.95rem; margin-bottom: 6px; }
.limit-droga-opis { font-size: 0.82rem; color: var(--grigio); line-height: 1.55; margin: 0 0 12px; }
.limit-droga-cta { margin: auto 0 0; width: 100%; padding: 10px 14px; font-size: 0.84rem; }
.plan-archiwum { margin-top: 10px; font-size: 0.85rem; line-height: 1.55; color: var(--muted-dark); }
.plan-archiwum-btn { width: 100%; padding: 10px 14px; font-size: 0.84rem; }
.plan-archiwum-opis { margin-top: 6px; font-size: 0.78rem; color: var(--grigio); }
.locked-banner-archiwum { margin-top: 6px; font-weight: 600; }
/* TWARDA ŚCIANA (Krok 3): okno zajmuje cały ekran. To nie jest dymek do odklikania w drodze do
   czegoś innego, tylko moment decyzji - treść zostaje w kolumnie do czytania. z-index nad zwykłymi
   oknami (2000) i nad oknami Mówienia (twórca 2500, paletka fiszek 2600): ściana za kliknięcie
   staje także nad oknem, z którego to kliknięcie przyszło, i nie może się pod nim schować. */
#premiumScianaOverlay { padding: 0; z-index: 2700; }
#premiumScianaOverlay .sciana-okno { max-width: none; width: 100%; height: 100%; max-height: none; border-radius: 0; }
#premiumScianaOverlay .wordmap-header,
#premiumScianaOverlay .wordmap-body { width: 100%; max-width: 720px; margin: 0 auto; }
#premiumScianaOverlay .wordmap-body { overflow-y: auto; }
#premiumScianaOverlay .wordmap-close:focus-visible { outline: 3px solid var(--zolty); outline-offset: 2px; border-radius: 8px; }
@media (max-width: 480px) {
  #premiumScianaOverlay .wordmap-header { padding: 14px 16px 12px; }
  #premiumScianaOverlay .wordmap-body { padding: 16px; }
  #premiumScianaOverlay .wordmap-title { font-size: 1.02rem; }
}
/* MIĘKKA ŚCIANA (Krok 3): panel nad fiszką, w kolorach okna Premium - ma wyglądać jak
   propozycja, nie jak błąd. Obok treści stoi ilustracja „Premium” (wygląd w sekcji STYL KANWY, 13). */
.paywall-miekki {
  display: flex; gap: 14px; align-items: flex-start; margin: 0 0 14px;
  padding: 14px 16px; border-radius: 16px;
  background: var(--bg-success-soft); border: 1px solid var(--zielen-pastel);
}
.paywall-miekki-tresc { flex: 1; min-width: 0; }
.paywall-miekki-tytul { font-weight: 800; font-size: 0.98rem; margin-bottom: 4px; }
.paywall-miekki-opis { font-size: 0.84rem; color: var(--grigio); line-height: 1.55; }
.paywall-miekki-akcje { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.paywall-miekki-akcje .btn { width: auto; padding: 8px 14px; font-size: 0.82rem; }

.limit-pozniej { width: 100%; margin: 14px 0 0; padding: 11px 16px; font-size: 0.84rem; }

/* Termin czyta sie jako pierwszy - to jedyna informacja w oknie przydzialu, z ktora da sie cos
   zrobic bez placenia. Stad zegar obok, a nie sam tekst w akapicie opisu. */
.przydzial-kiedy { display: flex; align-items: flex-start; gap: 8px; }
.przydzial-kiedy .ico { color: var(--oro); flex-shrink: 0; margin-top: 2px; }
/* Dzienny przydzial wypowiedzi nad mapa rozmow: informacja, nie ostrzezenie - dopoki cos zostalo,
   ma byc ledwo widoczna. Zerowy stan dostaje kolor ostrzezenia, bo wtedy tlumaczy pusty ekran. */
.mow-mapa-przydzial {
  display: flex; align-items: center; gap: 7px; justify-content: center;
  font-size: 0.78rem; color: var(--grigio); margin: 0 0 10px;
}
.mow-mapa-przydzial.pusty { color: var(--arancio); font-weight: 700; }
/* Uprzedzenie na karcie tekstu w Społeczności: „to będzie Twój tekst na ten tydzień". Ton
   informacyjny, nie ostrzegawczy - to jeszcze nie jest odmowa, tylko cena wyboru. */
.cmty-przydzial-notka {
  display: flex; align-items: flex-start; gap: 7px; margin-top: 10px;
  font-size: 0.78rem; line-height: 1.5; color: var(--grigio);
}
.cmty-przydzial-notka .ico { color: var(--arancio); flex-shrink: 0; margin-top: 2px; }
/* ===== PISMO OD PRAWEJ (arabski) =====
   Uklad opiera sie na flexboksie i gridzie, ktore same odwracaja sie przy dir="rtl".
   Poprawiamy to, co jest przypiete do konkretnej strony ekranu na sztywno: wyrownania
   tekstu, akcenty na krawedzi karty i elementy pozycjonowane absolutnie. */
[dir="rtl"] { text-align: right; }
[dir="rtl"] ol, [dir="rtl"] ul { padding-left: 0; padding-right: 22px; }
[dir="rtl"] .kartka-akapit { padding-left: 0; padding-right: 36px; }
[dir="rtl"] .kartka-segment.aktywny {
  padding-left: 0; padding-right: 13px; box-shadow: inset -3px 0 0 var(--oro);
}
[dir="rtl"] .settings-legal, [dir="rtl"] .settings-credits { text-align: right; }
[dir="rtl"] .lang-picker-caret { margin-left: 0; margin-right: auto; }
/* Liczby, kody jezykow i skroty klawiszowe zostaja od lewej - to nie jest tekst arabski. */
[dir="rtl"] .mono, [dir="rtl"] code, [dir="rtl"] .kpi-value { direction: ltr; unicode-bidi: embed; }

.cookie-baner {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 16px; z-index: 100000;
  width: min(760px, calc(100vw - 24px));
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  background: var(--card-bg); border: 1px solid var(--border-warm); border-radius: 18px;
  box-shadow: 0 18px 48px rgba(15, 23, 42, .22); padding: 18px 22px;
}
.cookie-baner-tresc { flex: 1 1 320px; min-width: 0; }
.cookie-baner-tytul { font-weight: 800; font-size: 1rem; margin-bottom: 6px; }
.cookie-baner-opis { margin: 0 0 8px; font-size: 0.84rem; line-height: 1.6; color: var(--muted-dark); }
.cookie-baner-link { font-size: 0.8rem; font-weight: 700; color: var(--primary); }
/* Oba przyciski tej samej wielkosci i wagi - rowny wybor, nie podpowiedz. */
.cookie-baner-akcje { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; min-width: 210px; }
.cookie-baner-akcje .btn { margin: 0; width: 100%; padding: 12px 16px; font-size: 0.88rem; }
@media (max-width: 640px) {
  .cookie-baner { bottom: 0; border-radius: 18px 18px 0 0; width: 100vw; padding: 16px; }
  .cookie-baner-akcje { flex-direction: row; width: 100%; min-width: 0; }
}
.przypomnienie-pasek { height: 10px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--border); overflow: hidden; }
.przypomnienie-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel)); }
.przypomnienie-podpis { margin-top: 8px; font-size: 0.8rem; color: var(--grigio); }
.kartka-podpis-marki {
  margin-top: 14px; text-align: center;
  font-size: 0.68rem; letter-spacing: 0.06em; color: var(--muted-light);
}
.kartka-podpis-marki a { color: inherit; text-decoration: none; font-weight: 700; }
.kartka-podpis-marki a:hover { color: var(--oro); text-decoration: underline; }
.kartka-cwicz { margin-top: 14px; }
.kartka-cwicz .btn { width: auto; margin: 0; padding: 11px 18px; font-size: 0.86rem; }
.limit-opis b { color: var(--testo); }
.tekst-lista-otworz {
  margin-left: auto; border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: 0.74rem; font-weight: 800; color: var(--oro);
  letter-spacing: 0.02em; padding: 2px 0;
}
.tekst-lista-otworz:hover { text-decoration: underline; }
/* „Wszystkie (12)" z ikoną zamiast znaku „→" na końcu (2026-09-27, Alek: „ohydne to jest jako tekst"). */
.tekst-lista-otworz .ico { margin: 0 0 0 1px; vertical-align: -0.2em; }
[dir="rtl"] .tekst-lista-otworz .ico { transform: scaleX(-1); }
.tekst-lista-otworz.hidden { display: none; }
.tekst-lista-ile { font-size: 0.8rem; font-weight: 700; color: var(--grigio); margin-left: 6px; }
/* W pełnej liście wiersze mają więcej miejsca niż w wąskim panelu bocznym. */
#tekstyListaBody .tekst-wiersz { padding: 13px 16px; }

/* --- Pasek nad kartką --- */
.kartka-pasek { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.kartka-wroc {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  font-size: 1rem; line-height: 1; transition: var(--transition);
}
.kartka-wroc:hover { border-color: var(--oro); transform: translateX(-2px); }
.kartka-tytul-blok { flex: 1; min-width: 0; }
/* Jedna linia z wielokropkiem, nie zawijanie. Blok tytulu jest elementem flex z
   min-width: 0, wiec przy ciasnym pasku (przycisk powrotu + dwie ikony + akcje tekstu
   ze Spolecznosci) kurczyl sie niemal do zera - a wtedy tekst lamal sie PO JEDNEJ
   LITERZE i „(bez punktow)" rozciagalo sie na kilkaset pikseli w pionie. */
.kartka-tytul, .kartka-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kartka-tytul { font-weight: 800; font-size: 1.05rem; }
.kartka-meta { font-size: 0.75rem; color: var(--grigio); margin-top: 2px; }
.pochodzenie-pytanie { font-size: 0.78rem; font-weight: 800; color: var(--grigio); }
.pochodzenie-btn { width: auto; margin: 0; padding: 7px 12px; font-size: 0.76rem; }
.kartka-akcje { display: flex; gap: 8px; flex-shrink: 0; }
.kartka-postep { height: 5px; border-radius: 999px; background: var(--border); overflow: hidden; margin-bottom: 16px; }
.kartka-postep-fill {
  height: 100%; width: 0%; border-radius: 999px;
  background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel));
  transition: width 0.45s cubic-bezier(.22,1,.36,1);
}

/* --- Sama kartka ---
   Kratka jest rysowana gradientem, nie obrazkiem: skaluje się bez rozmycia, działa w obu
   motywach (linie biorą kolor z tokena) i nie kosztuje ani jednego żądania sieciowego. */
.kartka {
  position: relative; border-radius: 16px; padding: 34px 30px;
  background-color: var(--card-bg);
  background-image:
    linear-gradient(var(--kratka-linia) 1px, transparent 1px),
    linear-gradient(90deg, var(--kratka-linia) 1px, transparent 1px);
  /* Krok kratki jedzie razem ze stopniem pisma (patrz zastosujWielkoscPisma): przy mniejszej
     czcionce papier ma drobniejszą linijkę, więc tekst dalej siada NA liniach, a nie pływa
     w co drugiej kratce. Bez zmiennej - dokładnie tyle, co dotąd. */
  background-size: var(--kartka-krok, 26px) var(--kartka-krok, 26px);
  box-shadow: var(--shadow);
  border: 1px solid var(--border-warm-soft);
}
/* Delikatny margines jak w prawdziwym zeszycie - czysto dekoracyjny, stąd aria-hidden
   przez pseudoelement (nie ma go w drzewie dostępności). */
.kartka::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 52px; width: 1px;
  background: color-mix(in srgb, var(--rosso) 35%, transparent);
}

/* --- Kartka czyta się jak STRONA, nie jak lista zdań ---
   Zdania są elementami INLINE i płyną jedno za drugim w wierszu, dokładnie tak, jak stoją
   w tekście wklejonym do okna dodawania. Wcześniej każde zdanie było osobnym blokiem
   z własnym marginesem i ołówkiem pod spodem: czterowyrazowe „Ici, il fait toujours chaud."
   zajmowało cały wiersz plus dwie przerwy, przez co ta sama czytanka po przetworzeniu
   rozciągała się na trzy ekrany i przestawała wyglądać jak tekst do czytania.
   Krój, waga i interlinia są TE SAME co w .kartka-textarea (26 px = krok kratki), żeby
   przejście „wklejam → czytam" nie zmieniało wyglądu tekstu. */
.kartka-akapit {
  /* 36 + 30 px paddingu kartki = 66 px, czyli tyle samo, ile ma pole do wklejania: tekst
     zaczyna się 14 px za czerwonym marginesem, jak w zeszycie. */
  padding-left: 36px;
  font-size: var(--kartka-pismo, 1.02rem); font-weight: 600;
  line-height: var(--kartka-krok, 26px); color: var(--testo);
}
/* Przerwa między akapitami to jedna kratka - dokładnie jedna pusta linia, jak w oryginale. */
.kartka-akapit + .kartka-akapit { margin-top: 26px; }

.kartka-segment {
  cursor: pointer; border-radius: 4px; transition: background 0.2s ease;
  /* Tło powtarza się na KAŻDYM wierszu przełamanego zdania, zamiast rozlać się w jeden
     prostokąt obejmujący pół akapitu. */
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
/* Zdanie już przerobione nie jest do klikania - kursor mówi to, zanim ktoś spróbuje. */
.kartka-segment.zrobione { cursor: default; }
/* Zaproszenie zamiast ołówka: pod kursorem zdanie podnosi się z papieru. Ołówek przy KAŻDYM
   zdaniu był tą samą podpowiedzią powtórzoną trzydzieści razy - teraz stoi raz, nad kartką. */
.kartka-segment:not(.zrobione):hover { background: color-mix(in srgb, var(--oro) 18%, transparent); }

/* Zdanie, nad którym się właśnie pracuje, WYCHODZI z akapitu i staje się własnym blokiem:
   dostaje miejsce na linijkę do pisania, a reszta tekstu opływa je z góry i z dołu. */
.kartka-segment.aktywny {
  display: block; border-radius: 0;
  margin: 13px 0; padding-left: 13px;
  background: transparent; box-shadow: inset 3px 0 0 var(--oro);
}
.kartka-segment.aktywny .kartka-zrodlo,
.kartka-segment.aktywny .kartka-tlumaczenie { display: block; }
.kartka-segment.aktywny .kartka-tlumaczenie::before { display: none; }
/* Zdanie, które właśnie tłumaczysz, cofa się o pół tonu - wtedy najciemniejszą rzeczą na
   kartce jest to, co piszesz, a nie to, z czego piszesz. */
.kartka-segment.aktywny .kartka-zrodlo { color: var(--tekst-neutralny); }

/* Źródło zostaje w kolorze tekstu, nie w szarości: to materiał do CZYTANIA i ma się czytać
   tak samo dobrze jak przed przetworzeniem. Kolor niesie wyłącznie OCENĘ - a ta siedzi
   w podkreśleniu (niżej), więc nie musi już rozjaśniać całego zdania. */
.kartka-zrodlo { transition: color 0.4s ease; }

/* Tłumaczenie jest GLOSĄ dopisaną między zdaniami, nie drugim wierszem pod każdym z nich:
   mniejsze, przygaszone i poprzedzone cienką kreską, więc oko samo je omija przy czytaniu
   oryginału, a znajduje, gdy go szuka. Kto chce czysty tekst, gasi je przełącznikiem
   „Tłumaczenia" - i dopiero teraz ten przełącznik coś naprawdę zmienia. */
.kartka-tlumaczenie {
  /* Lżejsza waga niż zdanie obok, nie tylko mniejszy stopień: przy tej samej grubości oba
     języki walczyły o pierwszy plan i akapit czytał się jak lista, a nie jak tekst z glosą. */
  /* em, nie rem: glosa ma zostać o tyle samo mniejsza od zdania także wtedy, gdy czytelnik
     zmieni stopień pisma. 0.843 to ta sama proporcja co dotąd (0.86rem przy 1.02rem). */
  font-size: 0.843em; font-weight: 500; color: var(--grigio); margin-right: 3px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.kartka-tlumaczenie::before {
  content: ''; display: inline-block; width: 2px; height: 0.9em;
  margin: 0 6px -1px 4px; border-radius: 1px;
  background: color-mix(in srgb, var(--primary) 40%, transparent);
}
/* Piosenka i wiersz mają własny podział na wersy i to on jest treścią - tam zdania NIE płyną,
   bo sklejone w akapit przestają być piosenką. */
.kartka.wersami .kartka-segment { display: block; }
.kartka.wersami .kartka-tlumaczenie { display: block; }
.kartka.wersami .kartka-tlumaczenie::before { display: none; }

/* Jedna podpowiedź nad całą kartką zamiast ołówka przy każdym zdaniu. */
.kartka-wskazowka {
  display: flex; align-items: center; gap: 7px; margin: -6px 0 12px 2px;
  font-size: 0.76rem; font-weight: 600; color: var(--muted-light);
}
.kartka-wskazowka .ico { margin: 0; font-size: 0.85rem; }
.kartka-wskazowka.hidden { display: none; }

/* Zdania NIE są kolorowane w całości i NIE dostają już koloru za ocenę.
   Cztery kolory kresek pod czterema rodzajami wyniku (zielony, niebieski, czerwony,
   przerywany) dawały pod niemal każdym wersem inną barwę - na przerobionej kartce robiła się
   z tego tęcza, w której nie dało się niczego wypatrzeć. Do tego różnica „dobrze" od „prawie"
   nie zmienia niczego, co można w tej chwili z tym zdaniem zrobić.
   Została JEDNA zasada, ta sama po obu stronach zdania:
       CZERWONA KRESKA = to nie Twoje, dopisała to AI,
       brak czerwonej kreski = całe Twoje.
   Zdanie przerobione ma pod spodem tylko cienką, szarą kreskę, która mówi wyłącznie
   „to masz już za sobą" - także wtedy, gdy glosy są schowane. */

/* Człon oceniony jako zły W TRWAJĄCEJ próbie - czerwona FALA, bo to ten sam odruch co
   podkreślenie w edytorze tekstu: „tu popatrz jeszcze raz". Informacja zwrotna ważna przez
   najbliższe kilka sekund, a nie ślad zostający na kartce (od tego jest .trudne-fraza). */
.czesc-zle {
  text-decoration: underline wavy var(--rosso);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}
/* CZERWONA KRESKA - jedyne kolorowe oznaczenie na przerobionym zdaniu. Znaczy dokładnie
   jedno: „tego kawałka nie napisałeś sam". Stoi po OBU stronach zdania, bo po obu trzeba jej
   szukać wzrokiem: .trudne-fraza pod fragmentem oryginału, .ai-wstawka pod tym samym
   fragmentem w tłumaczeniu. Jedno znaczenie, jeden wygląd, dwa miejsca - dlatego obie klasy
   mają wspólną regułę, a nie dwie podobne.
   Od czerwonej FALI przy błędzie w trwającej próbie (.czesc-zle) odróżnia ją prosta linia:
   fala to polecenie „popraw teraz", prosta kreska to ślad, który zostaje. */
.trudne-fraza, .ai-wstawka {
  text-decoration: underline;
  text-decoration-color: var(--rosso);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-skip-ink: none;
}
/* Świeżo oceniony błąd dostaje jeszcze delikatne tło - znika po przemalowaniu kartki,
   zostaje samo podkreślenie. */
.czesc-zle { background: color-mix(in srgb, var(--rosso) 9%, transparent); border-radius: 4px; }

/* --- Zdanie przerobione: jedna cienka, szara kreska ---
   Podkreślenie zamiast paska na marginesie, bo w tekście, który płynie, zdanie zaczyna się
   w połowie wiersza i nie ma przy czym postawić paska.
   Kreska jest NIEKOLOROWA i cienka: niesie jedną informację („zrobione"), a nie ocenę. Ocenę
   niesie czerwień na fragmentach dopisanych przez AI - patrz .trudne-fraza / .ai-wstawka.
   Offset 6 px zostawia miejsce na czerwoną kreskę (3 px) pod tym samym zdaniem: obie linie
   nigdy nie zlewają się w jedną i dalej widać, która co znaczy. */
.kartka-segment.zrobione .kartka-zrodlo {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
  text-decoration-color: var(--border-2);
  text-decoration-skip-ink: none;
}

/* Kawałek dopisany przez AI w tłumaczeniu ucznia. Wcześniej było to czerwone TŁO - i to ono
   razem z kolorowymi kreskami pod zdaniami robiło z kartki plamiasty patchwork. Teraz jest to
   ta sama kreska co po stronie oryginału (reguła wyżej), więc oko szuka jednej rzeczy zamiast
   dwóch różnych.

   Gwiazdka na końcu niesie to samo bez udziału koloru - i tylko dzięki niej ktoś, kto
   czerwieni od różu nie odróżnia, w ogóle zobaczy, gdzie kończy się jego własne zdanie.
   Jest pseudoelementem, więc nie wchodzi do zaznaczenia ani do skopiowanego tekstu.

   display:inline-block NIE jest tu ozdobnikiem: to jedyny sposób, żeby czerwona kreska pod
   zdaniem NIE przeszła pod samą gwiazdką. Podkreślenie rysuje element nadrzędny i rysuje je
   pod całą swoją treścią, także pod pseudoelementem - samo `text-decoration: none` tego nie
   cofa, bo kreska nie należy do gwiazdki. Pudełko blokowe w linii jest dla podkreślenia
   nieprzenikalne, więc kreska kończy się na ostatniej literze, tam gdzie kończy się słowo. */
.ai-wstawka::after {
  content: '✦';
  font-size: 0.58em; vertical-align: 0.55em; margin-left: 2px;
  color: var(--ai-wstawka-znak); opacity: 0.9;
  display: inline-block; text-decoration: none;
}
/* --- Próba tłumaczenia: pisze się WPROST NA KARTCE ---
   Wcześniej pod zdaniem otwierało się pudełko: obwódka, pole formularza i dwa pełne przyciski.
   Na kartce w kratkę wyglądało to jak wklejony formularz z innej strony i rozbijało rytm
   czytania. Teraz jest jedna linijka bez ramki, w tym samym kroju i na tej samej kratce co
   tekst, a decyzje to dwie małe ikony na końcu: ptaszek (sprawdź) i krzyżyk (nie wiem). */
.kartka-proba { margin-top: 0; display: flex; flex-direction: column; gap: 8px; }
/* Linijka jest zwykłym tekstem, nie układem flex: pole i ikony mają płynąć jak wyrazy
   w zdaniu, żeby ikony stały tuż za ostatnim słowem i przesuwały się razem z nim. */
.proba-linia { line-height: 26px; }
.proba-pole {
  outline: none; border: none; background: transparent; color: var(--testo);
  /* Ten sam rozmiar i ta sama waga co tekst na kartce: to, co piszesz, ma być kolejnym
     wierszem tej samej strony, a nie treścią wpisaną do pola. */
  font-family: inherit; font-size: 1.02rem; font-weight: 600; line-height: 26px;
  caret-color: var(--oro);
  /* break-word, bo długie tłumaczenie musi zawijać się na kartce, a nie rozpychać jej w bok */
  overflow-wrap: anywhere;
}
/* Puste pole = migający kursor i ledwie widoczna podpowiedź, dokładnie jak niezapisana
   linijka w zeszycie. Kursor jest pseudoelementem, bo przeglądarka rysuje swój dopiero po
   kliknięciu - a to właśnie on ma powiedzieć "tu się pisze", ZANIM ktokolwiek kliknie.
   Po wejściu w pole znika, żeby nie mrugały dwa naraz. */
.proba-pole:empty::before {
  content: ''; display: inline-block; width: 2px; height: 15px; margin-right: 5px;
  vertical-align: -2px; background: var(--oro);
  animation: kursorProby 1.05s step-end infinite;
}
/* Pusty wiersz pokazuje TYLKO nasz pasek: kursor przeglądarki bywa w pustym contenteditable
   niewidoczny albo stoi gdzie indziej, więc go wyciszamy i wracamy do niego dopiero, gdy jest
   przy czym stanąć - czyli od pierwszej litery. */
.proba-pole:empty { caret-color: transparent; }
.proba-pole:empty::after {
  content: attr(data-pusty);
  color: var(--testo); font-weight: 500; opacity: 0.3;
}
@keyframes kursorProby { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .proba-pole:empty::before { animation: none; } }
.proba-ikony { white-space: nowrap; }   /* ptaszek i krzyżyk nigdy nie rozjeżdżają się na dwie linie */
.proba-ikona {
  width: 24px; height: 24px; margin-left: 6px; vertical-align: -6px; border-radius: 50%; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; font-size: 0.7rem;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--grigio);
  transition: var(--transition);
}
.proba-ikona .ico { margin: 0; }
.proba-ikona.ok:hover  { border-color: var(--verde); color: var(--verde); transform: scale(1.1); }
.proba-ikona.nie:hover { border-color: var(--rosso); color: var(--rosso); transform: scale(1.1); }
.proba-ikona:disabled { opacity: 0.5; cursor: default; transform: none; }
/* Mikrofon dyktowania (patrz dyktujProbe): w nasłuchu czerwony i oddychający głośnością
   (--moc z analizy sygnału), w trakcie rozpoznawania na serwerze pulsuje na niebiesko. */
.proba-ikona.mik:hover { border-color: var(--primary); color: var(--primary); transform: scale(1.1); }
.proba-ikona.mik.slucha, .proba-ikona.mik.slucha:hover {
  background: var(--rosso); border-color: var(--rosso); color: #FFFFFF;
  transform: scale(calc(1 + var(--moc, 0) * 0.35));
  box-shadow: 0 0 0 calc(var(--moc, 0) * 8px) color-mix(in srgb, var(--rosso) 25%, transparent);
}
.proba-ikona.mik.mysli { border-color: var(--primary); color: var(--primary); animation: dyktandoPuls 0.8s ease-in-out infinite; }
@keyframes dyktandoPuls { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }
.proba-pole.dyktando-niepewne { color: var(--grigio); }
@media (prefers-reduced-motion: reduce) { .proba-ikona.mik.mysli { animation: none; } .proba-ikona.mik.slucha { transform: none; } }
/* Człon zaliczony NIE dostaje koloru. Podświetlanie tego, co poszło dobrze, zamieniało zdanie
   w dwukolorowy pasek i gubiło jedyną rzecz, na którą trzeba patrzeć - miejsce błędu. */
.czesc { border-radius: 4px; padding: 1px 2px; }
.proba-czesci { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font-size: 0.78rem; }
.czesci-licznik { font-weight: 800; color: var(--zielen-gleboka); }
.czesc-wiersz { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; }
.czesc-wiersz .ico { margin: 0; font-size: 0.72rem; }
.czesc-wiersz.ok  { color: var(--zielen-gleboka); }
.czesc-wiersz.zle { color: var(--rosso); }

/* Wyjście awaryjne po nieudanej próbie. Stoi w miejscu, gdzie kiedyś AI opisywało słowami,
   co poszło nie tak - opis znikł, bo czerwone podkreślenie pod złym członem mówi to samo
   szybciej. Zostało jedno zdanie, które da się KLIKNĄĆ. */
.proba-wyjscie { font-size: 0.78rem; }
.proba-wyjscie-koszt { font-weight: 800; opacity: 0.75; }
/* Znacznik przy zdaniu, które dokończyła AI - bo po samym podkreśleniu wstawek trudno
   odróżnić "dopisałem sam po poprawce" od "oddałem to maszynie". Dwie litery przy
   tłumaczeniu zamiast wiersza pod zdaniem: pełne zdanie wyjaśnienia zostaje w tooltipie,
   bo czyta się je raz, a wiersz zabierałby miejsce przy każdym spojrzeniu na kartkę. */
.kartka-dociagniete {
  margin-left: 5px; padding: 0 4px; border-radius: 4px; cursor: help;
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.04em; vertical-align: 0.35em;
  color: var(--muted-light); background: var(--bg-soft);
}

/* --- Stopka: fiszki tymczasowe --- */
.kartka-stopka { margin-top: 18px; }

/* --- Fiszki tymczasowe --- */
.tmp-postep { height: 5px; border-radius: 999px; background: var(--border); overflow: hidden; margin-bottom: 18px; }
.tmp-postep-fill {
  height: 100%; width: 0%; border-radius: 999px;
  background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel));
  transition: width 0.35s cubic-bezier(.22,1,.36,1);
}
.tmp-karta {
  text-align: center; padding: 30px 20px; border-radius: 16px;
  background: var(--bg-soft); border: 2px solid var(--border-warm-soft); cursor: pointer;
  transition: var(--transition);
}
.tmp-karta:hover { border-color: var(--oro); }
.tmp-karta-slowo { font-size: 1.7rem; font-weight: 800; color: var(--primary); line-height: 1.3; }
.tmp-karta-tlum { font-size: 1.25rem; font-weight: 700; margin-top: 12px; color: var(--testo); }
.tmp-karta-hint { font-size: 0.75rem; color: var(--muted-light); margin-top: 12px; }
.tmp-licznik { text-align: center; font-size: 0.78rem; color: var(--grigio); margin-top: 14px; }
.tmp-koniec { text-align: center; padding: 20px 10px; }
.tmp-koniec-ikona { font-size: 2.6rem; line-height: 1; margin-bottom: 10px; }

@media (max-width: 768px) {
  .kartka { padding: 22px 16px; background-size: 22px 22px; }
  .kartka::before { left: 30px; }
  /* 16 + 28 = 44 px, czyli 14 px za czerwonym marginesem - tak samo jak na dużym ekranie
     i tak samo jak w polu do wklejania (patrz .kartka-textarea niżej). */
  .kartka-akapit { padding-left: 28px; font-size: 0.98rem; }
  [dir="rtl"] .kartka-akapit { padding-left: 0; padding-right: 28px; }
  .kartka-tlumaczenie { font-size: 0.85rem; }
  .mode-tab-menu { min-width: 180px; }
}


/* ===== TRYB MÓWIENIE =====
   Wygląd z prototypu „Opisz swój dzień" (test-diary.html, 2026-09-04), który Alek chciał
   zachować: JEDNA SCENA BEZ RAMEK, dużo powietrza, cienka typografia, mikrofon na środku.
   Kolor pojawia się WYŁĄCZNIE tam, gdzie coś się dzieje. Reszta jest szara, żeby ruch był
   jedyną rzeczą przyciągającą wzrok.
   Od 2026-09-15 scena gra SCENARIUSZE (sekcja MÓWIENIE w JS): najpierw mapa kafelków (.wybor chowa
   resztę), potem w pionie - instrukcja nad dymkami, dymki z wzorami odpowiedzi, mikrofon, kwestia
   sprzedawcy w linijce pod nim, karta z tłumaczeniem na dole. Alek: „ma to wyglądać nadal w taki
   sposób, jak obecnie to się prezentuje".
   Wszystko, co się tu rusza, idzie jedną krzywą (--mow-ease): różne krzywe na jednym ekranie
   czyta się jako niedbalstwo. */
#widokMowienia { --mow-ease: cubic-bezier(.42, 0, .58, 1); }
.mow-uklad { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px; align-items: start; }
.mow-scena {
  position: relative; min-height: 560px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 64px 16px 40px; overflow: hidden;
}
/* MAPA SCENARIUSZY: póki stoi, scena pokazuje tylko ją (.wybor chowa resztę, także nagłówek i „od nowa"). */
.mow-scena.wybor { justify-content: flex-start; padding-top: 28px; }
.mow-scena.wybor > :not(.mow-mapa) { display: none !important; }
.mow-mapa { width: 100%; max-width: 760px; animation: mowWejscie .5s var(--mow-ease); }
/* Powrót nad głową mapy (mowMapaPowrot): pigułka „Moje filmy" ze Słuchania, przy krawędzi początkowej - scena
   wyśrodkowuje tekst, więc zwykły inline-flex stałby na środku. Od 2026-09-28 ta sama pigułka stoi nad głowami Czytania
   i Słuchania (.tryb-powrot, widokPowrot) - jedna reguła, żeby trzy tryby miały ją w tym samym miejscu. */
.mow-mapa-powrot, .tryb-powrot { display: flex; width: fit-content; margin: 0 0 12px; margin-inline-end: auto; }
[dir="rtl"] .mow-mapa-powrot .ico, [dir="rtl"] .tryb-powrot .ico { transform: scaleX(-1); }
.mow-mapa-tytul { font-size: clamp(1.15rem, 2.6vw, 1.45rem); font-weight: 500; color: var(--testo); margin-bottom: 6px; }
.mow-mapa-opis { font-size: 0.92rem; line-height: 1.5; color: var(--grigio); margin-bottom: 22px; }
.mow-mapa-lista { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; text-align: left; }
@media (max-width: 640px) { .mow-mapa-lista { grid-template-columns: minmax(0, 1fr); } }
/* Kafelek = wybór, więc musi wyglądać na klikalny (jedyny wyjątek od „bez ramek"). */
.mow-kafelek {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px; text-align: left;
  padding: 16px 16px 14px; border-radius: 16px; cursor: pointer; font: inherit;
  background: var(--card-bg); color: var(--testo); border: 1px solid var(--border-warm-soft);
  transition: border-color .2s var(--mow-ease), transform .15s var(--mow-ease), box-shadow .2s var(--mow-ease);
}
.mow-kafelek:hover, .mow-kafelek:focus-visible { border-color: var(--primary); box-shadow: var(--shadow-hover); transform: translateY(-2px); outline: none; }
/* OKŁADKA KAFELKA (2026-09-16). Zdjęcie albo obraz z generatora wychodzi poza padding kafelka (ujemne marginesy),
   bo półkowy obrazek z ramką wygląda jak załącznik, a nie jak okładka. Stała wysokość i object-fit: cover, żeby
   dwadzieścia rozmów obok siebie miało równą siatkę niezależnie od proporcji wgranego zdjęcia. */
.mow-kafelek-foto { position: relative; display: block; margin: -16px -16px 2px; height: 128px; overflow: hidden; border-radius: 15px 15px 0 0; background: var(--bg-soft); }
.mow-kafelek-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Znak obrazu z generatora jest dla OGLĄDAJĄCEGO - ta sama zasada, co ai_generowane przy zdjęciach na tablicy. Od 2026-10-08
   to mały znak „SI” z dymkiem (wygląd: sekcja 19a, .znak-si); tu tylko miejsce w prawym dolnym rogu okładki, więc dymek
   rośnie od prawej krawędzi znaku w lewo. Dwie klasy, bo .znak-si (dalej w arkuszu) stawia position: relative. */
.znak-si.mow-znak-ai { position: absolute; right: 8px; bottom: 8px; }
.znak-si.mow-znak-ai .znak-si-dymek { left: auto; right: 0; }
.mow-kafelek-glowa { display: flex; align-items: center; gap: 10px; }
.mow-kafelek-glowa .ico { font-size: 1.35rem; color: var(--primary); margin: 0; }
.mow-kafelek-glowa b { font-size: 1.02rem; font-weight: 600; line-height: 1.3; flex: 1; min-width: 0; }
.mow-cefr { font-size: 0.68rem; font-weight: 700; letter-spacing: .05em; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--verde); color: var(--verde); }
.mow-kafelek-t { font-size: 0.86rem; color: var(--grigio); margin-top: -4px; }
.mow-kafelek-opis { font-size: 0.85rem; line-height: 1.45; color: var(--grigio); }
.mow-kafelek-slowka { display: flex; flex-wrap: wrap; gap: 5px; }
.mow-chip { font-size: 0.76rem; padding: 2px 9px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--border-warm-soft); color: var(--grigio); }
.mow-chip.cichy { border-style: dashed; }
/* POZIOM ZNAJOMOŚCI NA CHIPIE (Alek 2026-09-16: „podświetlaj na odpowiednie kolory słówka, które już znasz,
   bo są w łatwe, średnie lub trudne - tak samo jak w Słuchaniu i Czytaniu"). Barwimy OBWÓDKĘ i kropkę, a nie
   tło: globalne klasy `.p-latwe/.p-srednie/.p-trudne` wypełniają tło kolorem i na chipie zjadłyby napis.
   Kolory te same, co w legendzie czytanki: zielony / niebieski / czerwony. */
.mow-chip.zn { border-width: 1.5px; font-weight: 600; }
.mow-chip.zn::before { content: ""; width: 7px; height: 7px; border-radius: 50%; display: inline-block; margin-right: 5px; vertical-align: 1px; }
.mow-chip.zn-latwe   { border-color: var(--chart-latwe); color: var(--testo); }
.mow-chip.zn-latwe::before   { background: var(--chart-latwe); }
.mow-chip.zn-srednie { border-color: var(--primary); color: var(--testo); }
.mow-chip.zn-srednie::before { background: var(--primary); }
.mow-chip.zn-trudne  { border-color: var(--rosso); color: var(--testo); }
.mow-chip.zn-trudne::before  { background: var(--rosso); }
.mow-chip.zn-nowe    { border-color: var(--border-2); }
.mow-chip.zn-nowe::before    { background: var(--border-2); }
/* Legenda pod paletką fiszek i w oknie twórcy - ten sam zestaw kropek, co przy czytance. */
.mow-legenda { display: flex; flex-wrap: wrap; gap: 12px; font-size: 0.72rem; color: var(--grigio); padding: 2px 0; }
.mow-legenda span { display: inline-flex; align-items: center; gap: 5px; }
.mow-legenda i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.mow-legenda i.legenda-latwe { background: var(--chart-latwe); }
.mow-legenda i.legenda-srednie { background: var(--primary); }
.mow-legenda i.legenda-trudne { background: var(--rosso); }
.mow-legenda i.legenda-nowe { background: var(--border-2); }
.mow-kafelek-stopka { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 0.78rem; color: var(--muted-light); margin-top: 2px; }
.mow-kafelek-meta { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* „Znasz 40%" - po słówkach kluczowych rozmowy (mowienie_scen_znane). Zielono dopiero od połowy, bo wcześniej
   ta liczba ma zachęcać do wejścia, a nie chwalić. */
.mow-kafelek-znasz { font-weight: 700; color: var(--grigio); }
.mow-kafelek-znasz.duzo { color: var(--verde); }
.mow-kafelek-fiszki {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-2); background: transparent; color: var(--grigio); font: inherit; font-size: 0.72rem; font-weight: 600;
}
.mow-kafelek-fiszki:hover { border-color: var(--oro); color: var(--oro); }
.mow-kafelek-fiszki .ico { margin: 0; font-size: 0.78rem; }
/* CO DALEJ - sugerowane rozmowy po ostatnim poziomie (Alek 2026-09-23). Kafelki są celowo małe i poziome:
   to zaproszenie na dalszą drogę, a nie druga mapa - mapa jest o kliknięcie dalej. */
.mow-sugestie { display: none; flex-direction: column; align-items: center; gap: 10px; margin-top: 18px; width: 100%; }
.mow-sugestie.wl { display: flex; }
.mow-sugestie-tytul { font-size: 0.82rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--grigio); }
.mow-sugestie-lista { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.mow-sugestia {
  display: flex; align-items: center; gap: 10px; max-width: 280px; padding: 9px 14px 9px 10px;
  border: 1px solid var(--border-warm-soft); border-radius: 14px; background: var(--card-bg); color: var(--testo);
  font: inherit; text-align: left; cursor: pointer; transition: var(--transition);
}
.mow-sugestia:hover { border-color: var(--oro); transform: translateY(-2px); }
.mow-sugestia .ico { margin: 0; font-size: 1.1rem; color: var(--primary); }
.mow-sugestia-txt { display: flex; flex-direction: column; min-width: 0; }
.mow-sugestia-tytul { font-weight: 700; font-size: 0.92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mow-sugestia-meta { font-size: 0.74rem; color: var(--grigio); }
.mow-sugestia-meta b { color: var(--verde); }
/* STOPKA CZYTANIA („Co czytać dalej”). Kafelki są TE SAME, co pod mapą Mówienia, więc markup używa
   klas .mow-sugestie* i .mow-tworca-btn - drugi komplet identycznych reguł rozjechałby się przy
   pierwszej poprawce wyglądu. Nazwa klas została historyczna; dzieli je dziś Czytanie i Mówienie. */
.tekst-stopka { display: none; flex-direction: column; align-items: center; gap: 10px; margin-top: 28px; }
.tekst-stopka.wl { display: flex; }
/* Różdżka przy nagłówku „Rozmowy" - jedyne wejście do kreatora z panelu bocznego (Alek 2026-09-23).
   `margin-left: auto` spycha ją na prawy koniec wiersza nagłówka, jak „Wszystkie" w historii czytanek. */
.mow-bok-rozdzka {
  margin-left: auto; width: 26px; height: 26px; padding: 0; border: none; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--primary);
  display: inline-flex; align-items: center; justify-content: center; transition: var(--transition);
}
.mow-bok-rozdzka:hover { background: var(--bg-soft); }
.mow-bok-rozdzka .ico { margin: 0; font-size: 0.95rem; }
/* „Pokaż jeszcze N” / „Zwiń” pod listą rozmów w panelu bocznym (mowRysujMapeBok, 2026-10-06). Pigułka na całą szerokość
   jak wiersze nad nią, żeby trafić w nią kciukiem i żeby nie udawała kolejnej rozmowy (bez ikony z lewej, tekst na środku). */
.mow-bok-wiecej {
  display: flex; align-items: center; justify-content: center; gap: 4px; width: 100%;
  padding: 10px 14px; margin-top: 2px; cursor: pointer;
  background: var(--bg-soft); border: 1.5px solid var(--border-warm-soft); border-radius: 999px;
  font-family: inherit; font-size: 0.82rem; font-weight: 700; color: var(--testo); transition: var(--transition);
}
.mow-bok-wiecej:hover { border-color: var(--oro); }
.mow-bok-wiecej:focus-visible { outline: 2px solid var(--oro); outline-offset: 2px; }
.mow-bok-wiecej .ico { margin: 0; font-size: 1rem; }
/* Licznik sytuacji w nagłówku sceny: poziom kończy się po przejściu WSZYSTKICH gałęzi drzewa, więc uczeń
   musi widzieć, ile ich zostało - inaczej dowiadywałby się o tym dopiero przy zakończeniu przebiegu. */
.mow-naglowek-pokrycie {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--border-2); color: var(--grigio); font-size: 0.72rem; font-weight: 700;
}
.mow-naglowek-pokrycie .ico { margin: 0; font-size: 0.76rem; }
.mow-naglowek-pokrycie.pelne { border-color: var(--verde); color: var(--verde); }
/* Pigułki poziomów 1·2·3 - kafelek na mapie i nagłówek sceny. Kłódka = najpierw poprzedni poziom. */
.mow-poziomy-pills { display: inline-flex; gap: 5px; }
.mow-poziom-pill {
  width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--border-2); background: var(--card-bg);
  color: var(--grigio); font: inherit; font-size: 0.8rem; font-weight: 700; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; transition: background .2s var(--mow-ease), color .2s var(--mow-ease), border-color .2s var(--mow-ease);
}
.mow-poziom-pill .ico { margin: 0; font-size: 0.75rem; }
.mow-poziom-pill:hover { border-color: var(--primary); color: var(--testo); }
.mow-poziom-pill.ukonczony { border-color: var(--verde); color: var(--verde); }
.mow-poziom-pill.aktywny { background: var(--primary); border-color: var(--primary); color: #fff; }
.mow-poziom-pill.zablokowany { opacity: .55; cursor: not-allowed; }
/* Nagłówek sceny: mapa ← · tytuł · „Poziom 1 z 3 · Podgląd” · pigułki. Po lewej, „Zacznij od nowa" po prawej. */
.mow-naglowek {
  position: absolute; top: 12px; left: 8px; right: 150px; z-index: 2;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; text-align: left;
  font-size: 0.82rem; color: var(--grigio);
}
.mow-naglowek-mapa {
  display: inline-flex; align-items: center; gap: 2px; padding: 6px 10px 6px 6px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-warm-soft); background: var(--card-bg); color: var(--grigio); font: inherit; font-size: 0.8rem; font-weight: 600;
}
.mow-naglowek-mapa:hover { color: var(--testo); border-color: var(--primary); }
.mow-naglowek-mapa .ico { margin: 0; }
.mow-naglowek-tytul { font-weight: 600; color: var(--testo); }
.mow-naglowek-tytul .ico { color: var(--primary); margin: 0 2px 0 0; }
/* SLOT NAD DYMKAMI - instrukcja („Poproś o chleb"), poprawka do przeczytania i transkrypcja na żywo.
   Stała minimalna wysokość i treść dociśnięta do DOŁU: gdy transkrypcja rośnie z linijki na trzy,
   mikrofon pod spodem nie przesuwa się ani o piksel (kliknięcie w niego trafiałoby w pustkę). */
.mow-srodek {
  width: 100%; min-height: 6rem; margin-bottom: 12px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
}
/* TRANSKRYPCJA NA ŻYWO - szara, bez ramki. Najwyżej trzy linijki: starsze słowa znikają za krawędzią. */
.mow-gora {
  max-width: 680px; max-height: 4.8em; overflow: hidden; padding: 0 18px;
  display: flex; align-items: flex-end; justify-content: center;
  font-size: 1.1rem; line-height: 1.6; color: var(--grigio);
}
.mow-gora-txt { max-width: 680px; }
/* Krzyzyk kasujacy odczyt: maly i blady, zeby nie konkurowal z tekstem, ale z obszarem dotyku na telefon. */
.mow-gora-x { flex: 0 0 auto; margin-left: 6px; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--grigio); opacity: .55; cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; line-height: 1; }
.mow-gora-x:hover, .mow-gora-x:focus-visible { opacity: 1; background: var(--muted-light); }
.mow-gora-x .ico { margin: 0; font-size: 0.85rem; }
.mow-cwiczenie-slot:empty { display: none; }
/* Poprawka nad mikrofonem: slot rośnie, żeby zmieścić zdanie i JEDNĄ linijkę transkrypcji pod nim. */
.mow-cwiczenie-slot .mow-cwiczenie { margin-bottom: 8px; padding: 0 12px; }
.mow-srodek.z-cwiczeniem { min-height: 8.5rem; }
.mow-srodek.z-cwiczeniem .mow-gora { max-height: 1.6em; font-size: 0.95rem; width: 100%; min-width: 0; }
/* JEDNA LINIJKA PRZY POPRAWCE = TAŚMA, nie zawijanie (Alek 2026-09-13, telefon: „algorytm kasuje sam
   zdanie, gdy mówię" - tekst był zawijany, na wąskim ekranie widać było prawie pustą nową linijkę). */
.mow-srodek.z-cwiczeniem .mow-gora-txt { white-space: nowrap; max-width: none; }
.mow-gora.przewija {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 1.4em);
          mask-image: linear-gradient(to bottom, transparent, #000 1.4em);
}
.mow-srodek.z-cwiczeniem .mow-gora.przewija {
  justify-content: flex-end;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 22%);
          mask-image: linear-gradient(to right, transparent, #000 22%);
}
.mow-gora .niepewne { color: var(--muted-light); }
/* Cisza przed pierwszym słowem: zamiast tekstu trzy oddychające kropki. */
.mow-gora-cisza { display: inline-flex; gap: 5px; align-items: center; padding-top: 6px; }
.mow-gora-cisza i { width: 4px; height: 4px; border-radius: 50%; background: var(--muted-light); animation: mowTetno 1.4s var(--mow-ease) infinite; }
.mow-gora-cisza i:nth-child(2) { animation-delay: .2s; }
.mow-gora-cisza i:nth-child(3) { animation-delay: .4s; }
@keyframes mowTetno { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
/* INSTRUKCJA NAD DYMKAMI (Alek 2026-09-15: „mała instrukcja nad: Zapytaj: Ile to kosztuje?"; „gdy brakuje
   kontekstu, napisz po polsku »Poproś o chleb«"). Etykieta drobna, treść wyraźna - to jest polecenie. */
.mow-zaczep { max-width: 560px; margin-bottom: 0; line-height: 1.5; animation: mowWejscie .6s var(--mow-ease); }
.mow-zaczep.znika { animation: mowGasnie .28s var(--mow-ease) forwards; }
.mow-zaczep:empty { display: none; }
.mow-instrukcja-etykieta { display: block; font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-light); margin-bottom: 4px; }
/* Zdanie na pamięć: który z dwóch kroków trwa (powtórz za mną / z pamięci). Pigułka jak pozostałe na scenie, bez wersalików. */
.mow-krok { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; font-size: 0.7rem; letter-spacing: normal; text-transform: none;
  background: color-mix(in srgb, var(--oro) 14%, transparent); color: var(--testo); font-weight: 600; vertical-align: 1px; }
.mow-instrukcja { font-size: clamp(1.05rem, 2.3vw, 1.3rem); font-weight: 500; color: var(--testo); }
/* OKO PRZY INSTRUKCJI - poziom 3, gdzie polecenie jest w języku nauki („Ringrazia ed esci."). Wiersz
   jest flexem w linii bazowej, żeby ikonka stała przy zdaniu, a nie pod nim, i żeby długa instrukcja
   mogła się złamać bez odrywania oka od ostatniego wiersza. */
.mow-instrukcja-wiersz { display: inline; }
.mow-instrukcja-wiersz .mow-glos { margin-left: 4px; }
.mow-zaczep-tlum { display: block; margin-top: 4px; font-size: 0.9rem; line-height: 1.4; color: var(--grigio); animation: mowWejscie .2s var(--mow-ease); }
@keyframes mowWejscie { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes mowGasnie  { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-6px); } }
/* DYMKI NAD MIKROFONEM - wzory odpowiedzi do przeczytania na głos: tekst w języku nauki (klikane
   słowa), głośnik, pod spodem tłumaczenie (poziomy 1–2). Stała minimalna wysokość obszaru: dymki nie
   mogą przesunąć mikrofonu pod kursorem. */
.mow-dymki {
  min-height: 62px; display: flex; align-items: flex-end; justify-content: center;
  gap: 8px 14px; flex-wrap: wrap; padding: 0 8px;
}
.mow-dymek {
  position: relative;
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--bg-soft); border: none; padding: 7px 12px; border-radius: 999px; font: inherit;
  font-size: 0.98rem; line-height: 1.35; color: var(--testo); max-width: 260px;
  animation: mowPrzylot .45s var(--mow-ease) both; transition: background .25s var(--mow-ease);
}
/* Gwiazdka = tym dymkiem uczeń już odpowiadał (mowienie_scen_galezie); siedzi w rogu pigułki, nie w tekście. */
.mow-dymek.uzyty { box-shadow: inset 0 0 0 1px color-mix(in srgb, #f5b800 55%, transparent); }
.mow-gwiazda { position: absolute; top: -7px; right: 6px; color: #f5b800; font-size: .78rem; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
.mow-gwiazda::before { margin: 0; }
/* „+N" = ile jeszcze NIEPRZEĆWICZONYCH wypowiedzi czeka w tę stronę (Alek 2026-09-23: „powinienem dostać małą
   wskazówkę, gdzie się udać, aby spotkać element, którego jeszcze nie odblokowałem - np. przy gwiazdce zrobić »+1«
   czy »+2«"). Siedzi w drugim rogu pigułki niż gwiazdka, żeby oba znaczki mogły stać na jednym dymku. */
.mow-plus {
  position: absolute; top: -8px; left: 6px; padding: 1px 6px; border-radius: 999px;
  background: var(--verde); color: var(--na-akcencie); font-size: .68rem; font-weight: 700; line-height: 1.5;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}
/* POMIŃ (Alek 2026-09-25: „gdy przeszedłem już jakiś etap, to można go pominąć”): przycisk w DOLNYM rogu dymka z gwiazdką,
   żeby gwiazdka, „+N” i on mogły stać na jednym dymku. Pominięty dymek na chwilę świeci złotem - widać, którą drogą poszła
   scena. Bez transform: animacja wejścia dymka trzyma swoją klatkę końcową (fill-mode both) i przykryłaby przesunięcie. */
.mow-pomin {
  position: absolute; bottom: -9px; right: 6px; width: 22px; height: 22px; padding: 0; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; font: inherit; font-size: .72rem; line-height: 1;
  background: var(--card-bg); color: var(--muted-dark); border: 1px solid color-mix(in srgb, #f5b800 60%, transparent);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .16); transition: transform .15s var(--mow-ease), color .15s, background .15s;
}
.mow-pomin:hover, .mow-pomin:focus-visible { color: var(--testo); background: color-mix(in srgb, #f5b800 22%, var(--card-bg)); transform: scale(1.12); }
.mow-dymek.pominiety { background: color-mix(in srgb, #f5b800 24%, var(--bg-soft)); box-shadow: inset 0 0 0 2px color-mix(in srgb, #f5b800 70%, transparent); }
.mow-klawisz { font: inherit; font-size: .72rem; font-weight: 700; line-height: 1.3; padding: 0 5px; margin-left: 2px; border-radius: 4px;
  border: 1px solid var(--border); color: var(--muted-dark); }
.mow-dymek:nth-child(2) { animation-delay: .07s; }
.mow-dymek:nth-child(3) { animation-delay: .14s; }
.mow-dymek:nth-child(4) { animation-delay: .21s; }
/* Zwykły tekst, nie flex: przy flex każde słowo i znak interpunkcyjny stawały się osobnym elementem
   z odstępem („Buongiorno , vorrei del pane .” - zmierzone w podglądzie 2026-09-15). */
.mow-dymek-tekst { display: inline; }
.mow-dymek .mow-glos { padding: 0 4px; font-size: 0.85em; }
/* Tłumaczenie dymka (poziomy 1–2) SCHOWANE, dopóki uczeń nie kliknie w dymek (Alek 2026-09-15 wieczór: „tłumaczenia
   niech wyświetlają się dopiero po kliknięciu w dymek, a tak niech zostanie tylko język nauki"). Klik w słowo też odsłania. */
.mow-dymek-pl { display: none; font-size: 0.78rem; color: var(--muted-light); line-height: 1.3; }
.mow-dymek.pokaz-pl .mow-dymek-pl { display: block; animation: mowWejscie .2s var(--mow-ease); }
/* Cały dymek to przycisk (czyta na głos + tłumaczenie) - bez osobnego głośnika. */
.mow-dymek, .mow-dymek.slowa { cursor: pointer; }
.mow-dymek:hover { background: color-mix(in srgb, var(--primary) 10%, var(--bg-soft)); }
/* POZIOM 2 (dymki_ui, Alek 2026-09-22: „zamiast luk … zrób jednak dymki wyboru, ale tylko z językiem interfejsu"): dymek
   niesie SAMO zdanie w języku interfejsu, które uczeń ma powiedzieć w języku nauki. Nie jest przyciskiem - głos i klikane
   słowa zdradzałyby odpowiedź - więc bez wskaźnika i bez podświetlenia po najechaniu; kursywa odróżnia „powiedz to po
   swojemu" od wzorów poziomu 1, które się czyta. Do 2026-09-22 stały tu luki (.mow-luka) - tag luki-poziom2-porzucone. */
.mow-dymek.po-naszemu { cursor: default; }
.mow-dymek.po-naszemu:not(.trafiony):hover { background: var(--bg-soft); }
.mow-dymek.po-naszemu .mow-dymek-tekst { font-style: italic; }
/* Trafiony dymek zielenieje na czas werdyktu, a na poziomie 2 wychodzi pod nim zdanie w języku nauki - widać, jak to się
   mówi (w tym samym miejscu do 2026-09-22 luki odsłaniały się na zielono). */
.mow-dymek.trafiony { background: color-mix(in srgb, var(--verde) 18%, var(--bg-soft)); }
.mow-dymek-cel { display: block; font-style: normal; font-weight: 600; color: var(--verde); animation: mowWejscie .2s var(--mow-ease); }
/* PUSTE DYMKI (poziom 3, 2026-09-25): przerywany kontur bez tekstu - tyle odpowiedzi ma pytanie. Gwiazdka, „+N” i pominięcie
   siedzą w rogach jak zawsze. Dotknięcie odsłania znaczenie po naszemu (kursywa jak poziom 2 + „jak to powiedzieć?”), drugie -
   zdanie w języku nauki. `.cicho` = przerysowanie po odsłonięciu bez animacji wejścia; wjeżdża tylko świeżo odsłonięty. */
.mow-dymek.duch { background: transparent; box-shadow: inset 0 0 0 1.5px var(--border); color: var(--muted-light); min-width: 118px; }
.mow-dymek.duch.uzyty { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, #f5b800 55%, transparent); }
.mow-dymek.duch:hover, .mow-dymek.duch:focus-visible { background: var(--bg-soft); color: var(--muted-dark); outline: none; }
.mow-duch-tekst { display: inline-flex; align-items: center; gap: 6px; font-size: .84rem; letter-spacing: .02em; }
.mow-duch-tekst .ico, .mow-duch-dalej .ico { margin: 0; font-size: .9em; }
.mow-dymek.po-naszemu.odkryty { cursor: pointer; }
.mow-dymek.po-naszemu.odkryty:hover, .mow-dymek.po-naszemu.odkryty:focus-visible { background: color-mix(in srgb, var(--primary) 10%, var(--bg-soft)); outline: none; }
.mow-duch-dalej { display: inline-flex; align-items: center; gap: 4px; font-size: .72rem; font-style: normal; color: var(--muted-light); }
.mow-dymki.cicho .mow-dymek { animation: none; }
.mow-dymki.cicho .mow-dymek.odslona { animation: mowWejscie .25s var(--mow-ease); }
/* Miejsce na własną odpowiedź ucznia (pytania otwarte, 2026-09-25): przerywana pigułka „twój wybór” w dymku, a po odpowiedzi
   jej treść wyróżniona w tym samym miejscu (dymek po trafieniu, kwestia rozmówcy, która ją powtarza). */
.mow-wybor { display: inline-block; padding: 0 8px; margin: 0 2px; border: 1.5px dashed var(--verde); border-radius: 999px;
  color: var(--verde); font-weight: 800; font-size: .82em; line-height: 1.55; white-space: nowrap; vertical-align: baseline; font-style: normal; }
.mow-wybor-wartosc { font-weight: 800; color: var(--verde); }
.mow-dymki.znika .mow-dymek { animation: mowGasnie .22s var(--mow-ease) forwards; }
@keyframes mowPrzylot { from { opacity: 0; transform: translateY(14px) scale(.94); } to { opacity: 1; transform: none; } }
/* MIKROFON: jedyny przycisk na ekranie. Szare koło, w nasłuchu odwrócone (ciemne z jasną ikoną)
   i „oddychające" cieniem w rytm głosu (--moc z analizy sygnału). */
.mow-mik-obszar { position: relative; width: 116px; height: 116px; }
/* Płótno fali leży POD przyciskiem i nie łapie kliknięć. `color` po to, żeby JS wziął z niego barwę linii. */
.mow-fala {
  position: absolute; inset: -10px; width: calc(100% + 20px); height: calc(100% + 20px);
  pointer-events: none; color: var(--muted-light);
}
/* Pierścień odliczania: po sekundzie ciszy wypełnia się w MOW_ODLICZANIE_MS i wtedy wypowiedź idzie do
   sprawdzenia. Czas animacji MUSI równać się stałej w JS (pilnuje tego testy_mowienie). */
.mow-odliczanie {
  position: absolute; inset: 8px; width: calc(100% - 16px); height: calc(100% - 16px);
  pointer-events: none; transform: rotate(-90deg); opacity: 0; transition: opacity .2s var(--mow-ease);
}
.mow-odliczanie circle {
  fill: none; stroke: var(--primary); stroke-width: 3.5; stroke-linecap: round;
  stroke-dasharray: 100; stroke-dashoffset: 100;
}
.mow-mik-obszar.odlicza .mow-odliczanie { opacity: 1; }
.mow-mik-obszar.odlicza .mow-odliczanie circle { animation: mowOdlicz 2s linear forwards; }
@keyframes mowOdlicz { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
.mow-mik {
  position: absolute; inset: 14px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--bg-soft); color: var(--testo);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 calc(var(--moc, 0) * 12px) color-mix(in srgb, var(--testo) 8%, transparent);
  transition: background .25s var(--mow-ease), color .25s var(--mow-ease), transform .15s var(--mow-ease), opacity .25s var(--mow-ease);
}
.mow-mik .ico { font-size: 1.7rem; line-height: 1; margin: 0; }
.mow-mik:hover:not(:disabled) { background: var(--border-warm-soft); }
.mow-mik:active:not(:disabled) { transform: scale(.94); }
.mow-mik:disabled { color: var(--muted-light); cursor: default; }
/* W nasłuchu ZIELONY (Alek 2026-09-15: „mikrofon ma się świecić na zielony, gdy jest aktywny, a biały,
   gdy nieaktywny, żeby to było lepiej rozróżnione") - stan widać kątem oka, bez czytania. */
.mow-mik.slucha, .mow-mik.slucha:hover { background: var(--verde); color: var(--na-akcencie); }
.mow-mik.mysli .ico { animation: glosMysli 0.9s ease-in-out infinite; }
/* Łączenie z transkrypcją na żywo (tylko przy zimnym starcie) - ta sama pulsacja. */
.mow-mik.laczy .ico { animation: glosMysli 0.9s ease-in-out infinite; }
/* LEKTOR MÓWI = TRZY KROPKI ZAMIAST MIKROFONU (Alek 2026-09-22: „gdy mówi LEKTOR powinien chować się mój mikrofon
   i zamiast mojego mikrofonu powinny pojawiać się trzy kropki w kolorach loga czyli zielony czerwony i niebieski
   i w tych kolorach powinny drgać te klocki gdy mówi lektor. jak kończy mówić to pojawia się mój mikrofon").
   Stan niesie klasa `lektor` na #mowMikObszar, którą mowRysujGlosWl stawia z MOW.botMowi - z tego samego miejsca,
   które zapala głośniki `.mow-glos-bot`, więc kropki i głośnik nie mogą się rozjechać. Mikrofon odjeżdża (opacity 0,
   scale .6, bez kliknięć), kropki wjeżdżają w to samo koło. KROPKI SĄ PRZYCISKIEM: dotknięcie robi dokładnie to, co
   dotknięcie mikrofonu w tej chwili - przerywa lektora i włącza nasłuch (mowPrzelacz, „wejście w słowo") - bo mikrofon
   znika z oczu, a nie z rozmowy. Czasy z makiety Alka: 0,3 s cubic-bezier(.4,0,.2,1) ruch, 0,25 s krycie; powrót
   mikrofonu idzie przejściem bazowym .mow-mik (transform .15 s) - ma być pod ręką od razu. */
.mow-mik-obszar.lektor .mow-mik {
  opacity: 0; transform: scale(.6); pointer-events: none;
  /* visibility z opóźnieniem równym przejściu: niewidoczny przycisk (opacity 0) nadal brał fokus z Tab i był
     oznajmiany czytnikowi obok kropek (przegląd 2026-09-22) - tak samo, jak kropki poza stanem lektora. */
  visibility: hidden;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .25s var(--mow-ease), visibility 0s linear .3s;
}
/* Fala i pierścień w stanie lektora nie mają prawa być widoczne: nasłuch podczas głosu nie chodzi (mowGlosBota woła
   mowStop), ale płótno czyści się dopiero następną klatką, a klasa `odlicza` schodzi w mowZerujZegary - to zapora na
   wypadek, gdyby którakolwiek z tych dróg zawiodła po przerwaniu nasłuchu. */
.mow-mik-obszar.lektor .mow-fala, .mow-mik-obszar.lektor .mow-odliczanie { opacity: 0; visibility: hidden; }
.mow-lektor {
  position: absolute; inset: 14px; border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  /* Poza stanem lektora element nie istnieje dla wskaźnika ani klawiatury: bez `visibility` niewidoczne kropki
     brałyby fokus z Tab i kliknięcia przeznaczone dla mikrofonu. Znika z opóźnieniem 0,3 s, żeby zdążyło zgasnąć ruchem. */
  opacity: 0; transform: scale(.6); pointer-events: none; visibility: hidden;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .25s var(--mow-ease), visibility 0s linear .3s;
}
.mow-lektor:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.mow-mik-obszar.lektor .mow-lektor { opacity: 1; transform: none; pointer-events: auto; visibility: visible; transition-delay: 0s; }
/* Kropka to pastylka o stałym promieniu: skacze WYSOKOŚĆ (12 → 28 px), nie skala - koło wydłuża się w słupek, jak
   w makiecie. Barwy loga w kolejności z zamówienia: zielona, czerwona, niebieska. Opóźnienia stoją w regułach
   O WYŻSZEJ swoistości niż skrót `animation`, bo skrót zeruje animation-delay i kropki drgałyby równo. */
.mow-kropka { width: 12px; height: 12px; border-radius: 99px; background: var(--marka-zielony); flex: none; }
.mow-kropka:nth-child(2) { background: var(--marka-czerwony); }
.mow-kropka:nth-child(3) { background: var(--marka-niebieski); }
.mow-mik-obszar.lektor .mow-kropka { animation: mowLektorFala .8s ease-in-out infinite; }
.mow-mik-obszar.lektor .mow-kropka:nth-child(2) { animation-delay: .18s; }
.mow-mik-obszar.lektor .mow-kropka:nth-child(3) { animation-delay: .36s; }
@keyframes mowLektorFala { 0%, 100% { height: 12px; } 50% { height: 28px; } }
/* WPROWADZENIE CZEKA NA UCZNIA (Alek 2026-09-23: „gdy w kanwie pojawia się »Wprowadzenie«, po zakończeniu wypowiedzi
   na górze zamiast mikrofonu zrób przycisk »Dalej«, żeby można było na spokojnie odsłuchać wprowadzenie i przetłumaczyć,
   jeśli ktoś chce, i dopiero potem kliknąć dalej, co rozpoczyna dalszą część"). Ten sam mechanizm, co kropki lektora:
   klasę `dalej` na #mowMikObszar stawia mowRysujGlosWl, mikrofon odjeżdża, przycisk wjeżdża w to samo koło. Stany się
   nie biją, bo `dalej` wchodzi DOPIERO, gdy lektor skończył - w trakcie czytania są kropki. */
.mow-mik-obszar.dalej .mow-mik {
  opacity: 0; transform: scale(.6); pointer-events: none; visibility: hidden;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .25s var(--mow-ease), visibility 0s linear .3s;
}
.mow-mik-obszar.dalej .mow-fala, .mow-mik-obszar.dalej .mow-odliczanie { opacity: 0; visibility: hidden; }
.mow-dalej {
  position: absolute; inset: 14px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--oro); color: var(--na-akcencie); font: inherit; font-size: 0.82rem; font-weight: 800;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  /* Poza stanem „dalej" przycisk nie istnieje dla wskaźnika ani dla Taba (ta sama pułapka, co przy kropkach:
     niewidoczny przycisk nadal brał fokus i był oznajmiany czytnikowi). */
  opacity: 0; transform: scale(.6); pointer-events: none; visibility: hidden;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .25s var(--mow-ease), visibility 0s linear .3s;
}
.mow-dalej .ico { font-size: 1.5rem; line-height: 1; margin: 0; }
.mow-dalej:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.mow-mik-obszar.dalej .mow-dalej { opacity: 1; transform: none; pointer-events: auto; visibility: visible; transition-delay: 0s; }
.mow-mik-obszar.dalej .mow-dalej:hover { filter: brightness(1.06); }
.mow-mik-obszar.dalej .mow-dalej:active { transform: scale(.94); }
/* LINIJKA POD MIKROFONEM: status („Dobrze!", „Powtórz", zdanie sprzedawcy „nie zrozumiałem") i kwestia
   bota leżą w tej samej komórce siatki i wymieniają się ruchem - status odjeżdża w górę, kwestia wjeżdża
   od dołu. Stała minimalna wysokość, żeby zmiana treści nie szarpała kartą pod spodem. */
.mow-linia { display: grid; margin-top: 20px; min-height: 2.4rem; width: 100%; max-width: 680px; }
.mow-linia > * { grid-area: 1 / 1; transition: opacity .32s var(--mow-ease), transform .32s var(--mow-ease); }
.mow-linia .mow-status { margin-top: 0; align-self: center; }
.mow-linia:not(.z-statusem) .mow-status, .mow-linia.pusto .mow-status { opacity: 0; transform: translateY(-12px); pointer-events: none; }
.mow-linia.z-statusem .mow-pytanie, .mow-linia.pusto .mow-pytanie { opacity: 0; transform: translateY(12px); pointer-events: none; visibility: hidden; }
.mow-status {
  margin-top: 20px; min-height: 1.5em; font-size: 0.95rem; line-height: 1.4;
  color: var(--grigio); animation: mowWejscie .35s var(--mow-ease);
}
.mow-status.ok { color: var(--verde); font-weight: 600; }
.mow-status.powtorz { color: var(--testo); font-weight: 600; font-size: 1.05rem; }
.mow-status.cicho { color: var(--muted-light); font-style: italic; }
.mow-status-cichy { margin-top: 6px; font-size: 0.82rem; color: var(--muted-light); }
.mow-status-cichy:empty { display: none; }
.mow-status-cichy a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.mow-pytanie { display: flex; flex-direction: column; align-items: center; }
.mow-pytanie:empty { display: none; }
.mow-pytanie-wiersz { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2px 6px; }
/* Kwestia bota: tekst w języku nauki, obok narzędzia (głos, tempo, oko), tłumaczenie schowane pod okiem. */
.mow-bot { animation: mowWejscie .4s var(--mow-ease); }
.mow-bot-tekst { font-size: clamp(1.15rem, 2.6vw, 1.45rem); font-weight: 500; line-height: 1.45; color: var(--testo); }
.mow-bot-narzedzia { display: inline-flex; justify-content: center; gap: 0; }
.mow-bot-narzedzia .mow-glos { padding: 4px 6px; font-size: 1rem; }
.mow-glos { background: none; border: none; cursor: pointer; color: var(--muted-light); padding: 0 6px; font-size: .95em; vertical-align: middle; }
.mow-glos:hover { color: var(--testo); }
.mow-glos .ico { margin: 0; }
.mow-glos.wl { color: var(--primary); }
/* Przełącznik tempa: font uicons nie ma zająca ani żółwia (sprawdzone 2026-09-14) - prędkościomierz + liczba. */
.mow-tempo { display: inline-flex; align-items: center; gap: 3px; }
.mow-tempo-liczba { font-size: 0.72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.mow-bot-tlum { margin-top: 2px; font-size: 0.9rem; line-height: 1.45; color: var(--grigio); animation: mowWejscie .25s var(--mow-ease); }
/* WPROWADZENIE („Bot opis"): akapit narracji, nie kwestia rozmówcy - więc karta, tekst do lewej i mniejszy
   stopień pisma niż zdanie, na które się odpowiada. Fiolet ten sam, co klocek na kanwie, żeby dało się je
   ze sobą powiązać bez czytania. */
.mow-bot-opis { max-width: 640px; margin: 0 auto; padding: 14px 18px; border-radius: 16px; text-align: left;
  background: color-mix(in srgb, #8b5cf6 9%, var(--card-bg)); border: 1px solid color-mix(in srgb, #8b5cf6 30%, transparent); }
.mow-bot-opis .mow-bot-tekst { font-size: clamp(0.98rem, 1.9vw, 1.14rem); font-weight: 400; }
.mow-bot-opis .mow-pytanie-wiersz { align-items: flex-start; }
.mow-opis-etykieta { display: block; font-size: 0.64rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: #8b5cf6; margin-bottom: 7px; }
/* KARTA NA DOLE - zdanie sprzedawcy po polsku i uwaga modelu. Bez ramki i bez tła (Alek: „bez tych
   okienek"). Gaśnie delikatnie, gdy uczeń mówi dalej. */
.mow-karta { max-width: 620px; margin-top: 26px; }
.mow-karta:empty { display: none; }
.mow-karta.gasnie { animation: mowGasnie .35s var(--mow-ease) forwards; }
.mow-recenzja { font-size: 1rem; line-height: 1.55; color: var(--grigio); animation: mowWejscie .4s var(--mow-ease); }
.mow-rada { margin-top: 10px; display: inline-flex; gap: 8px; align-items: baseline; text-align: left; font-size: 0.92rem; line-height: 1.5; color: var(--testo); }
.mow-rada .ico { color: var(--oro); margin: 0; flex: none; }
/* XP lecące do konta - element na body, animowany Web Animations API (mowLecXp). */
.mow-xp-lot {
  position: fixed; z-index: 3000; pointer-events: none; transform: translate(-50%, -50%);
  font-weight: 900; font-size: 1.05rem; color: var(--zielen-gleboka); white-space: nowrap;
}
.mow-xp-trafienie { animation: mowXpTrafienie .55s var(--mow-ease); }
@keyframes mowXpTrafienie { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.18); } }
/* Ciche linki pod sceną (podpowiedź na poziomie 3); na końcu poziomu - przyciski. */
.mow-akcje { display: flex; gap: 14px 26px; justify-content: center; align-items: center; flex-wrap: wrap; margin-top: 18px; min-height: 1.6em; }
.mow-akcje button {
  background: none; border: none; padding: 4px 2px; cursor: pointer; font: inherit; font-size: 0.9rem;
  color: var(--grigio); transition: color .2s var(--mow-ease);
}
.mow-akcje button:hover { color: var(--testo); }
.mow-akcje button.cichy { font-size: 0.82rem; color: var(--muted-light); }
.mow-akcja-koszt { font-size: 0.72rem; }
/* TLO MUSI STAC TUTAJ, nie tylko w .btn-verde (Alek 2026-09-16: „Przejdz do poziomu 3 na 3 nie widac na
   bialym designie"). Regula .mow-akcje button ustawia `background: none` dla wszystkich przyciskow w tym
   pasku i ma WYZSZA specyficznosc (klasa + typ) niz .btn-verde (sama klasa), wiec zjadala zielone tlo -
   a .mow-btn-dalej dokladalo do tego bialy tekst. Na ciemnym motywie bialy napis bylo widac na ciemnym
   tle strony i usterka nie rzucala sie w oczy; na jasnym przycisk znikal calkowicie. Dwie klasy
   (.mow-akcje .mow-btn-dalej) bija regule z klasa i typem, wiec tlo wraca. */
.mow-akcje .mow-btn-dalej {
  width: auto; margin: 0; padding: 10px 18px; border-radius: 999px;
  background: var(--oro); color: var(--na-akcencie); font-weight: 800;
  animation: mowWejscie .4s var(--mow-ease);
}
.mow-akcje .mow-btn-dalej:hover { background: var(--oro); color: var(--na-akcencie); filter: brightness(1.08); }
.mow-wszystko { font-weight: 600; color: var(--verde); }
/* Kontener „Czy miałeś na myśli?" nad mikrofonem: pytanie, poprawione zdanie, „Powtórz poprawnie", krzyżyk. */
.mow-cwiczenie { animation: mowWejscie .4s var(--mow-ease); }
.mow-cwiczenie-etykieta { display: block; font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-light); margin-bottom: 8px; }
.mow-cwiczenie-uwaga { font-size: 0.86rem; line-height: 1.45; color: var(--grigio); }
.mow-cwiczenie-zdanie { font-size: clamp(1.2rem, 2.8vw, 1.6rem); font-weight: 500; line-height: 1.45; color: var(--testo); }
.mow-poprawka-karta {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  max-width: 620px; margin: 0 auto 8px; padding: 14px 40px 12px; border-radius: 18px;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft); box-shadow: 0 6px 22px rgba(0,0,0,.06);
}
.mow-poprawka-pytanie { font-size: 0.88rem; font-weight: 600; color: var(--grigio); }
.mow-poprawka-karta .mow-cwiczenie-etykieta { margin: 2px 0 0; }
.mow-poprawka-x {
  position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  background: none; border: none; color: var(--muted-light); font-size: 1.1rem; transition: background .2s var(--mow-ease), color .2s var(--mow-ease);
}
.mow-poprawka-x:hover { background: var(--bg-soft); color: var(--testo); }
.mow-poprawka-x .ico { margin: 0; }
/* FRAGMENT DO POWTÓRKI (Alek 2026-09-22): po drugiej nieudanej próbie w węźle karta pokazuje CAŁE zdanie, a słowa, które
   trzeba powiedzieć, WERSALIKAMI w kolorze akcentu - jak w przykładzie Alka „Quanto costa IL FORMAGGIO". Mały głośnik
   z podpisem czyta całe zdanie; duży (jak przy poprawce) czyta sam fragment. */
.mow-fragment-slowo { text-transform: uppercase; font-weight: 700; color: var(--oro); }
/* BŁĄD W POPRAWCE (Alek 2026-09-22: „podkreślaj w zdaniu błąd, na którym trzeba się głównie skupić"): wyrazy poprawki, których
   w wypowiedzi nie było albo padły inaczej (`bledy` z serwera, mowienie_roznica_slow), mają falistą czerwoną kreskę - znak
   „tu jest błąd" znany z każdego edytora tekstu. Kreska, nie tło: tło niesie już znajomość słowa (.znane-slowo), a oba
   znaczenia mają być widoczne naraz. */
.mow-poprawka-blad {
  font-weight: 700; text-decoration: underline wavy var(--rosso); text-decoration-thickness: 2px;
  text-underline-offset: .22em; text-decoration-skip-ink: none;
}
/* NAJPIERW CO ŹLE (poziom 2, 2026-09-25): karta z wypowiedzią UCZNIA - złe słowa z tą samą falistą kreską (.mow-poprawka-blad),
   brakujące miejsce jako przerywana pigułka w kolorze błędu, a na dole cicha zapowiedź, że poprawne zdanie przyjdzie przy
   następnej porażce. */
.mow-pomylka-luka {
  display: inline-block; min-width: 1.7em; padding: 0 6px; margin: 0 1px; border: 1.5px dashed var(--rosso); border-radius: 999px;
  color: var(--rosso); font-weight: 700; line-height: 1.25; text-align: center; vertical-align: baseline;
}
.mow-pomylka-dalej { font-size: 0.76rem; line-height: 1.4; color: var(--muted-light); text-align: center; }
/* KARTA NAPROWADZA (2026-09-29, Alek: „niech mnie naprowadzi jak coś powiedzieć pokazując mi to”): złe słowo przekreślone czerwoną
   kreską i przygaszone, poprawne słowo obok jako zielona pigułka (zieleń = „dobrze” w stylu kanwy; tekst --verde ma kontrast w obu
   motywach, tło to 16% zieleni logo na karcie). Pigułka łamie się w dymku razem ze słowami (box-decoration-break), więc dwa wstawione
   słowa na wąskim telefonie nie wychodzą poza kartę. */
.mow-zmiana-zle {
  color: var(--grigio); text-decoration: line-through; text-decoration-color: var(--rosso); text-decoration-thickness: 2px;
}
.mow-zmiana-wstaw {
  display: inline; padding: 1px 8px; border-radius: 999px; font-weight: 700; color: var(--verde);
  background: color-mix(in srgb, var(--marka-zielony, #35A64D) 16%, transparent);
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--marka-zielony, #35A64D) 45%, transparent);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.mow-pomylka-karta.naprowadza .mow-cwiczenie-zdanie { line-height: 1.6; }
/* ODPOWIEDŹ SWOBODNA (2026-10-02, sekcja ODPOWIEDŹ SWOBODNA w JS). Pod pytaniem „o czym powiedzieć”, w miejscu dymków przykład do podejrzenia
   (przerywana ramka: to podpowiedź, a nie zdanie do przeczytania), pod mikrofonem „Skończyłem” z zegarem, a po ocenie karta oceny w stylu kart
   poprawki: werdykt w pigułce w barwie wyniku (zieleń = zaliczone, żółty = zaliczone z poprawkami, czerwień = jeszcze raz), wypowiedź ucznia
   z poprawkami w miejscu (.mow-zmiana-*), „można też powiedzieć”, uwaga i „Powiedz jeszcze raz”. Wszystko na tokenach - oba motywy. */
.mow-swobodna-kryteria { display: flex; align-items: flex-start; justify-content: center; gap: 6px; margin-top: 6px;
  font-size: 0.9rem; line-height: 1.45; color: var(--grigio); }
.mow-swobodna-kryteria .ico { margin: 3px 0 0; font-size: 0.8rem; color: var(--muted-light); }
.mow-swobodna { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; max-width: 620px; }
.mow-swobodna-zacheta { font-size: 0.82rem; line-height: 1.4; color: var(--muted-light); text-align: center; }
.mow-swobodna-przyklad-btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 999px; cursor: pointer;
  background: none; border: 1.5px dashed var(--border-warm-soft); color: var(--grigio); font: inherit; font-size: 0.86rem; font-weight: 600;
  transition: border-color .2s var(--mow-ease), color .2s var(--mow-ease);
}
.mow-swobodna-przyklad-btn:hover, .mow-swobodna-przyklad-btn:focus-visible { border-color: var(--oro); color: var(--testo); }
.mow-swobodna-przyklad-btn .ico { margin: 0; }
.mow-swobodna-przyklad {
  display: flex; flex-direction: column; gap: 4px; width: 100%; max-width: 560px; padding: 10px 14px; border-radius: 16px; text-align: left;
  background: var(--bg-soft); border: 1.5px dashed color-mix(in srgb, var(--oro) 40%, transparent); animation: mowWejscie .3s var(--mow-ease);
}
.mow-swobodna-przyklad-glowa { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-light); }
.mow-swobodna-schowaj { width: 26px; height: 26px; padding: 0; border: none; border-radius: 50%; background: none; color: var(--muted-light); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; }
.mow-swobodna-schowaj:hover { background: var(--card-bg); color: var(--testo); }
.mow-swobodna-schowaj .ico { margin: 0; font-size: 0.85rem; }
.mow-swobodna-przyklad-tekst { font-size: 1rem; line-height: 1.5; color: var(--testo); }
.mow-swobodna-przyklad-tekst .mow-glos { margin-left: 4px; vertical-align: middle; }
.mow-swobodna-przyklad-pl { font-size: 0.86rem; line-height: 1.4; color: var(--grigio); }
.mow-swobodna-pasek { display: none; }
.mow-swobodna-pasek.wl { display: flex; justify-content: center; align-items: center; min-height: 42px; margin-top: 12px; }
.mow-skonczylem {
  display: inline-flex; align-items: center; gap: 8px; padding: 9px 18px; border: none; border-radius: 999px; cursor: pointer;
  background: var(--oro); color: var(--na-akcencie); font: inherit; font-size: 0.92rem; font-weight: 800; animation: mowWejscie .3s var(--mow-ease);
}
.mow-skonczylem:hover { filter: brightness(1.06); }
.mow-skonczylem:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.mow-skonczylem .ico { margin: 0; }
.mow-skonczylem-zegar { padding-left: 8px; border-left: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  font-weight: 600; font-variant-numeric: tabular-nums; opacity: .85; }
/* Dwie klasy, bo `.mow-cwiczenie-slot .mow-cwiczenie` zeruje pionowy margines wewnętrzny każdej karty w slocie (zmierzone na zrzucie:
   pigułka werdyktu leżała na samej krawędzi karty). */
.mow-cwiczenie-slot .mow-ocena-karta { max-width: 680px; align-items: stretch; text-align: left; padding: 14px 22px; }
.mow-ocena-karta .mow-cwiczenie-etykieta { margin: 6px 0 0; }
.mow-ocena-werdykt { display: inline-flex; align-items: center; gap: 7px; align-self: flex-start; padding: 4px 12px; border-radius: 999px;
  font-size: 0.92rem; font-weight: 800; }
.mow-ocena-werdykt .ico { margin: 0; }
.mow-ocena-karta.zaliczone .mow-ocena-werdykt { color: var(--verde); background: color-mix(in srgb, var(--marka-zielony, #35A64D) 16%, transparent); }
.mow-ocena-karta.do-poprawy .mow-ocena-werdykt { color: var(--testo); background: color-mix(in srgb, #FFC83D 32%, transparent); }
.mow-ocena-karta.odrzucone .mow-ocena-werdykt { color: var(--rosso); background: color-mix(in srgb, var(--rosso) 13%, transparent); }
.mow-ocena-karta.bez-oceny .mow-ocena-werdykt { color: var(--grigio); background: var(--bg-soft); }
/* Kilka zdań to nie jedna kwestia: mniejszy krój niż w karcie poprawki i własne przewijanie, żeby mikrofon i „Dalej” nie zjechały pod kartę. */
.mow-ocena-karta .mow-ocena-zdanie { font-size: clamp(1rem, 2.2vw, 1.18rem); line-height: 1.65; max-height: 32vh; overflow-y: auto; }
.mow-ocena-ladniej { font-size: 0.98rem; line-height: 1.5; font-style: italic; color: var(--testo); }
.mow-ocena-zdanie .mow-glos, .mow-ocena-ladniej .mow-glos { margin-left: 4px; vertical-align: middle; font-style: normal; }
.mow-ocena-uwaga { display: flex; align-items: flex-start; gap: 6px; margin-top: 4px; }
.mow-ocena-uwaga .ico { margin: 3px 0 0; color: var(--oro); }
.mow-ocena-uwaga-oko { align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; padding: 4px 10px; border-radius: 999px;
  background: none; border: 1px solid var(--border-warm-soft); color: var(--grigio); font: inherit; font-size: 0.8rem; cursor: pointer; }
.mow-ocena-uwaga-oko:hover { color: var(--testo); border-color: var(--oro); }
.mow-ocena-uwaga-oko .ico { margin: 0; }
.mow-ocena-akcje { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.mow-ocena-ponownie { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 999px; cursor: pointer;
  background: none; border: 1.5px solid var(--border-warm-soft); color: var(--testo); font: inherit; font-size: 0.86rem; font-weight: 700;
  transition: border-color .2s var(--mow-ease); }
.mow-ocena-ponownie:hover, .mow-ocena-ponownie:focus-visible { border-color: var(--oro); }
.mow-ocena-ponownie .ico { margin: 0; }
.mow-ocena-ponownie .mow-akcja-koszt { font-weight: 500; color: var(--muted-light); }
@media (max-width: 640px) {
  .mow-cwiczenie-slot .mow-ocena-karta { padding: 12px 14px; }
  .mow-ocena-karta .mow-ocena-zdanie { max-height: 28vh; }
  .mow-ocena-akcje { justify-content: center; }
}
/* CZYTANIE POPRAWIONYCH ZDAŃ (2026-10-03, Alek: „poprawione zdanie i je przeczytać na głos, a nie tylko przeczytać i dać »dalej«”): na dole karty
   oceny blok „Teraz powiedz to poprawnie:” z jednym zdaniem w kroju karty poprawki (poprawione słowa zielone jak wstawki karty „co źle”, po pudle
   falista kreska, od drugiej porażki fragment wersalikami). Wypowiedź ucznia nad nim ściska się, żeby mikrofon został na ekranie. Przerysowanie
   po pudle nie wjeżdża całą kartą od nowa (.cicho), wjeżdża tylko nowe zdanie (.nowe). */
.mow-czytanie { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; padding: 12px 14px; border-radius: 14px;
  background: var(--bg-soft); border: 1.5px solid color-mix(in srgb, var(--oro) 35%, transparent); }
.mow-czytanie.nowe { animation: mowWejscie .3s var(--mow-ease); }
.mow-czytanie-tytul { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: 0.92rem; font-weight: 800; color: var(--testo); }
.mow-czytanie-licznik { font-size: 0.74rem; font-weight: 600; color: var(--muted-light); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mow-czytanie-zdanie { font-size: clamp(1.1rem, 2.6vw, 1.42rem); line-height: 1.6; }
.mow-czytanie-zdanie .mow-glos { margin-left: 4px; vertical-align: middle; }
/* Tłumaczenie zdania pod okiem (2026-10-05, mowSwobodnaTlumacz): to samo ciche pismo, co tłumaczenie kwestii rozmówcy (.mow-bot-tlum). */
.mow-czytanie-tlum { font-size: 0.95rem; line-height: 1.45; color: var(--grigio); animation: mowWejscie .25s var(--mow-ease); }
.mow-czytanie-zdanie .mow-oko[disabled] { opacity: .5; cursor: progress; }
@media (prefers-reduced-motion: reduce) { .mow-czytanie-tlum { animation: none; } }
.mow-ocena-karta.czyta .mow-ocena-zdanie { max-height: 18vh; font-size: 0.95rem; }
.mow-cwiczenie.cicho { animation: none; }
.mow-czytanie-pomin { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: 999px; cursor: pointer;
  background: none; border: 1.5px solid var(--border-warm-soft); color: var(--testo); font: inherit; font-size: 0.9rem; font-weight: 700;
  animation: mowWejscie .3s var(--mow-ease); transition: border-color .2s var(--mow-ease); }
.mow-czytanie-pomin:hover, .mow-czytanie-pomin:focus-visible { border-color: var(--oro); }
.mow-czytanie-pomin .ico { margin: 0; }
@media (prefers-reduced-motion: reduce) { .mow-swobodna-przyklad, .mow-skonczylem, .mow-czytanie.nowe, .mow-czytanie-pomin { animation: none; } }
.mow-fragment-cale {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 2px 10px; border-radius: 999px;
  background: none; border: 1px solid var(--border-warm-soft); color: var(--muted-light); font-size: 0.74rem; cursor: pointer;
  vertical-align: middle; transition: background .2s var(--mow-ease), color .2s var(--mow-ease);
}
.mow-fragment-cale:hover { background: var(--bg-soft); color: var(--testo); }
.mow-fragment-cale .ico { margin: 0; font-size: 0.9rem; }
.mow-historia-pusto { font-size: 0.86rem; color: var(--muted-light); line-height: 1.5; }
/* Klikane słowo (styl Sylvi): bez podkreślenia w spoczynku, żeby zdanie czytało się jak zdanie. */
/* Slowo to juz TYLKO kolor znajomosci (znane-slowo p-*) - klikalny jest caly dymek, wiec wlasny kursor
   i podswietlenie pojedynczego slowa obiecywalyby akcje, ktorej nie ma. */
.mow-slowo { border-radius: 4px; }
.mow-dymek.slowa { cursor: pointer; }   /* cały dymek to przycisk (czyta + tłumaczenie), słowa mają własny kursor wyżej */
/* Okienko klikniętego słowa. */
/* „Zacznij od nowa" - stały w prawym górnym rogu sceny. */
.mow-od-nowa {
  position: absolute; top: 12px; right: 8px; z-index: 2; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border-warm-soft); cursor: pointer;
  background: var(--card-bg); color: var(--grigio); font: inherit; font-size: 0.8rem; font-weight: 600;
  transition: color .2s var(--mow-ease), border-color .2s var(--mow-ease);
}
.mow-od-nowa:hover { color: var(--testo); border-color: var(--primary); }
.mow-od-nowa .ico { margin: 0; }
/* TWÓRCA - przycisk pod mapą, ołówek na własnym kafelku i pełnoekranowe okno z listą, formularzem i kanwą
   (kanwa to ten sam komponent, co w konsoli admina - komponenty/scenariusze_edytor.php). */
.mow-mapa-stopka { margin-top: 22px; display: none; flex-direction: column; align-items: center; gap: 10px; }
.mow-mapa-stopka.wl { display: flex; }
.mow-mapa-tworca-podpis { font-size: 0.8rem; color: var(--muted-light); }
.mow-tworca-btn {
  display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px; border-radius: 999px; cursor: pointer;
  border: 1px dashed var(--primary); background: var(--card-bg); color: var(--primary); font: inherit; font-size: 0.88rem; font-weight: 600;
  transition: background .2s var(--mow-ease), color .2s var(--mow-ease), border-style .2s var(--mow-ease);
}
.mow-tworca-btn:hover { background: var(--primary); color: #fff; border-style: solid; }
.mow-tworca-btn .ico { margin: 0; }
.mow-kafelek-moj {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--primary); background: transparent; color: var(--primary); font: inherit; font-size: 0.68rem; font-weight: 700; letter-spacing: .04em;
}
.mow-kafelek-moj:hover { background: var(--primary); color: #fff; }
.mow-kafelek-moj .ico { margin: 0; font-size: 0.7rem; }
/* KARTA NA PRZYCIEMNIONYM TLE - dziś nosi ją już tylko potwierdzenie usunięcia rozmowy (#tworcaUsunOkno). Paletka fiszek,
   dla której te klasy powstały, przeszła 2026-09-29 do wspólnego komponentu .paletka-* (sekcja PALETKA FISZEK Z MATERIAŁU
   niżej w arkuszu i w JS). */
.mow-fiszki-okno { position: fixed; inset: 0; z-index: 2600; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(15, 23, 42, .55); text-align: left; animation: mowWejscie .2s var(--mow-ease); }
.mow-fiszki-okno.hidden { display: none; }
.mow-fiszki-karta { display: flex; flex-direction: column; width: min(720px, 100%); max-height: min(78vh, 720px);
  background: var(--card-bg); color: var(--testo); border-radius: 18px; overflow: hidden; box-shadow: var(--shadow-hover); }
.mow-fiszki-glowa { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--border-warm-soft); }
.mow-fiszki-tytul { font-size: 1.02rem; font-weight: 700; display: inline-flex; align-items: center; gap: 8px; }
.mow-fiszki-tytul .ico { color: var(--oro); margin: 0; }
.mow-mapa-czeka { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: -8px 0 16px; padding: 10px 14px;
  border-radius: 12px; background: var(--bg-soft); border: 1px solid var(--border-warm-soft); font-size: 0.9rem; line-height: 1.45;
  text-align: left; font-weight: 400; color: var(--testo); }
.mow-mapa-czeka .spinner { width: 18px; height: 18px; border-width: 2px; flex: none; }
.mow-mapa-czeka span { flex: 1; min-width: 180px; }
.mow-fiszki-stopka { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 18px; border-top: 1px solid var(--border-warm-soft); }
.tworca-usun-karta { width: min(520px, 100%); }
.tworca-usun-tytul .ico { color: var(--rosso); }
.tworca-usun-tresc { padding: 16px 18px; font-size: 0.9rem; line-height: 1.55; color: var(--grigio); }
.tworca-usun-tresc p { margin: 0 0 8px; }
.tworca-usun-nazwa { font-weight: 700; color: var(--testo); font-size: 1rem; }
.tworca-usun-karta .mow-fiszki-stopka { justify-content: flex-end; }
.mow-fiszki-stopka .btn { width: auto; margin: 0; padding: 9px 16px; }
@media (max-width: 560px) { .mow-fiszki-karta { max-height: 88vh; } }
/* ===== PALETKA FISZEK Z MATERIAŁU (2026-09-29) =====
   Alek po zrzucie starego okna „Zrób fiszki z rozmowy”: „Gdy w Mówieniu kliknę FISZKI lub w Słuchaniu i Czytaniu powinien
   pojawić się taki sam, stylistycznie dopasowany przez Ciebie nowy kontener … (efekt wow) (JAK TA APLIKACJA TO ROBI?? WOW)”.
   Stare okno było formularzem: przełącznik z trzech kafli, lista z checkboxami, „Wybrano: 27” drobnym drukiem i zielony
   przycisk. Nowe jest EKRANEM MARKI w miniaturze, tym samym językiem, co plansze kanwy:
   · GŁOWA W BARWIE TRYBU (Mówienie zielony, Czytanie niebieski, Słuchanie czerwony; stałe w obu motywach jak okładka),
     tytuł Outfit 800, okładka materiału w białej ramce przechylona jak zdjęcie przypięte do planszy i pierścień „znasz X%”.
     Tekst na zieleni granatowy (biały ma na #35A64D 3,1 : 1), na błękicie i czerwieni biały.
   · POZYCJE TO KAFLE, NIE WIERSZE: słowo duże (Outfit), tłumaczenie małe, pasek poziomu z lewej w barwach logo, kółko wyboru
     w prawym górnym rogu (wybór = żółty z granatem, jak w całej kanwie), pozycja z talii spokojnie „w talii” z ptaszkiem.
   · LEPKA STOPKA: duża liczba wybranych, która przelicza się na oczach, i główna pigułka ze strzałką „Dodaj N do fiszek”.
   · NA TELEFONIE ARKUSZ OD DOŁU (jak Arkusz w aplikacji), na komputerze karta na środku.
   z-index 1990, czyli POD .wordmap-overlay (2000): nad paletką staje okno planu (pokazOknoPlanu, #planOverlay) i ściana
   Premium. Stare okno miało 2600 i okno planu (2000) otwierało się POD nim - przy 16 i więcej zaznaczonych pozycjach
   „Dodaj do fiszek” nie robiło na oko nic (plan czekał schowany za kartą; PLAN_TEMPA[0].tempo = 15). */
.paletka-okno {
  position: fixed; inset: 0; z-index: 1990; display: flex; align-items: center; justify-content: center; padding: 12px;
  background: rgba(23, 24, 59, 0.62); text-align: left; animation: paletkaTlo .22s ease both;
}
.paletka-okno.hidden { display: none; }
.paletka-karta {
  --pk-tlo: #35A64D; --pk-tekst: #17183B; --pk-tekst2: #17183B; --pk-akcent: #17183B; --pk-tor: rgba(23, 24, 59, 0.18);
  /* min-width: 0 KONIECZNE: karta jest elementem flexa (nakładki), a min-width: auto rozpychało ją do szerokości rzędu
     zakładek i przycisku - zmierzone na zrzucie 390 px: krzyżyk i kółko przycisku „Dodaj” za prawą krawędzią ekranu. */
  position: relative; display: flex; flex-direction: column; width: min(1180px, 100%); min-width: 0; max-height: min(96vh, 1040px); max-height: min(96dvh, 1040px);
  background: var(--crema); color: var(--testo); border-radius: 32px; overflow: hidden; outline: none;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.6); animation: paletkaWejscie .34s cubic-bezier(.2, .9, .3, 1.15) both;
}
.paletka-karta.tryb-tekst { --pk-tlo: #2463E9; --pk-tekst: #FFFFFF; --pk-tekst2: #EEF3FF; --pk-akcent: #FFC83D; --pk-tor: rgba(255, 255, 255, 0.26); }
.paletka-karta.tryb-film  { --pk-tlo: #DB2727; --pk-tekst: #FFFFFF; --pk-tekst2: #FFFFFF; --pk-akcent: #FFC83D; --pk-tor: rgba(255, 255, 255, 0.28); }
/* Zdjęcie (2026-10-08, sekcja SŁÓWKA ZE ZDJĘCIA W PALETCE FISZEK w JS): żółć logo, barwa trybu Zdjęcie z kanwy (jak okno
   samouczka „Fiszki z Twoich materiałów”), tekst granatowy jak na żółtym oknie marki. */
.paletka-karta.tryb-zdjecie { --pk-tlo: #FFC83D; --pk-tekst: #17183B; --pk-tekst2: #2E3055; --pk-akcent: #17183B; --pk-tor: rgba(23, 24, 59, 0.18); }
@keyframes paletkaTlo { from { opacity: 0; } to { opacity: 1; } }
@keyframes paletkaWejscie { from { opacity: 0; transform: translateY(18px) scale(.96); } to { opacity: 1; transform: none; } }
/* GŁOWA - ekran marki w miniaturze. Poświata w rogu, żeby płaski kolor nie wyglądał jak pasek nagłówka tabeli. */
.paletka-bohater { position: relative; flex: none; padding: 14px 20px 16px; background: var(--pk-tlo); color: var(--pk-tekst); overflow: hidden; }
.paletka-bohater::before {
  content: ''; position: absolute; width: 340px; height: 340px; right: -110px; top: -170px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 68%); pointer-events: none;
}
.paletka-pasek { position: relative; z-index: 1; display: flex; align-items: center; gap: 12px; }
.paletka-pasek .om-pigulka { max-width: calc(100% - 60px); }
.paletka-pasek .om-zamknij { margin-left: auto; }
.paletka-karta:is(.tryb-tekst, .tryb-film) .paletka-pasek .om-zamknij { background: #FFFFFF; color: #17183B; }
.paletka-glowa { position: relative; z-index: 1; display: flex; align-items: center; gap: 20px; margin-top: 8px; }
.paletka-glowa-tekst { flex: 1; min-width: 0; }
.paletka-nadtytul { margin: 0 0 4px; font-size: 0.78rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--pk-tekst2); opacity: .9; }
.paletka-tytul {
  margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.8rem; line-height: 1.05; letter-spacing: -0.02em;
  color: var(--pk-tekst); text-wrap: balance; overflow-wrap: anywhere;
}
.paletka-podtytul { margin: 6px 0 0; font-size: 0.86rem; font-weight: 700; color: var(--pk-tekst2); }
.paletka-znasz { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.paletka-pierscien { position: relative; flex: none; width: 58px; height: 58px; }
.paletka-pierscien svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.paletka-pierscien circle { fill: none; stroke-width: 3.6; }
.paletka-pierscien .tor { stroke: var(--pk-tor); }
.paletka-pierscien .postep { stroke: var(--pk-akcent); stroke-linecap: round; transition: stroke-dasharray 1.1s cubic-bezier(.2, .8, .2, 1) .15s; }
.paletka-pierscien b {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-naglowek); font-weight: 800; font-size: 0.94rem; color: var(--pk-tekst); font-variant-numeric: tabular-nums;
}
.paletka-pierscien.laduje .tor { animation: paletkaMigot 1.2s ease-in-out infinite; }
.paletka-znasz-opis { display: flex; flex-direction: column; gap: 2px; font-size: 0.78rem; font-weight: 600; color: var(--pk-tekst2); }
.paletka-znasz-opis b { font-family: var(--font-naglowek); font-weight: 800; font-size: 0.94rem; color: var(--pk-tekst); }
/* Okładka jak zdjęcie przypięte do planszy: biała ramka, lekki przechył. Bez okładki plansza w barwie trybu z ikoną. */
.paletka-okladka {
  position: relative; flex: none; width: 178px; aspect-ratio: 16 / 10; border-radius: 16px; overflow: hidden;
  border: 5px solid #FFFFFF; transform: rotate(3deg); background: rgba(255, 255, 255, 0.18);
  box-shadow: 0 18px 34px -16px rgba(0, 0, 0, 0.55); animation: paletkaOkladka .5s cubic-bezier(.2, .9, .3, 1.2) .08s both;
}
.paletka-okladka img { width: 100%; height: 100%; object-fit: cover; display: block; }
.paletka-okladka.bez { display: flex; align-items: center; justify-content: center; font-size: 3rem; color: var(--pk-tekst); background: rgba(255, 255, 255, 0.2); }
.paletka-okladka.bez .ico { margin: 0; }
@keyframes paletkaOkladka { from { opacity: 0; transform: rotate(9deg) translateY(10px) scale(.9); } to { opacity: 1; transform: rotate(3deg); } }
/* NARZĘDZIA: zakładki sekcji z liczbami, szukajka (od PALETKA_SZUKAJ_OD pozycji), filtr poziomów (tylko obecne) i zaznaczanie. */
.paletka-narzedzia { flex: none; display: flex; flex-direction: column; gap: 8px; padding: 10px 20px 8px; background: var(--crema); }
.paletka-narzedzia:empty { display: none; }
.paletka-zakladki { display: flex; gap: 8px; flex-wrap: wrap; }
.paletka-zakladka {
  display: inline-flex; align-items: center; gap: 7px; min-height: 34px; padding: 0 6px 0 14px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--border-2); background: var(--card-bg); color: var(--testo); font: inherit; font-size: 0.82rem; font-weight: 800;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.paletka-zakladka:hover { border-color: var(--oro); transform: translateY(-1px); }
.paletka-zakladka b {
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--testo); font-size: 0.72rem; font-variant-numeric: tabular-nums;
}
.paletka-zakladka[aria-selected="true"] { background: var(--zolty); border-color: var(--zolty); color: #17183B; }
.paletka-zakladka[aria-selected="true"] b { background: #17183B; color: #FFFFFF; }
.paletka-rzad { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.paletka-szukaj { position: relative; flex: 1 1 220px; min-width: 0; max-width: 340px; }
.paletka-szukaj .ico { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); margin: 0; color: var(--grigio); pointer-events: none; }
.paletka-szukaj input {
  width: 100%; min-height: 34px; padding: 0 12px 0 34px; border-radius: 999px; border: 1.5px solid var(--border-2);
  background: var(--card-bg); color: var(--testo); font: inherit; font-size: 0.84rem;
}
.paletka-szukaj input:focus { outline: none; border-color: var(--oro); }
.paletka-filtr {
  display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 11px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--border-warm); background: transparent; color: var(--grigio); font: inherit; font-size: 0.74rem; font-weight: 700;
}
.paletka-filtr i { width: 9px; height: 9px; border-radius: 50%; background: var(--pk-zn, var(--szary-marki)); }
.paletka-filtr[aria-pressed="true"] { border-color: var(--oro); background: var(--bg-highlight); color: var(--testo); }
.paletka-rozpora { flex: 1; }
.paletka-mini {
  display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 10px; border-radius: 999px; cursor: pointer;
  border: none; background: transparent; color: var(--testo); font: inherit; font-size: 0.76rem; font-weight: 700; text-decoration: underline;
  text-underline-offset: 3px; text-decoration-thickness: 1.5px; text-decoration-color: var(--border-2);
}
.paletka-mini:hover { text-decoration-color: var(--oro); }
.paletka-mini .ico { margin: 0; }
/* LISTA: sekcje z nagłówkiem i kafle w siatce. Słówka i wyrażenia w kolumnach, zdania szerzej (są długie). */
.paletka-lista { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 2px 20px 18px; }
.paletka-sekcja + .paletka-sekcja { margin-top: 16px; }
.paletka-sekcja-glowa { display: flex; align-items: baseline; gap: 8px; margin: 6px 0 8px; flex-wrap: wrap; }
.paletka-sekcja-glowa h3 { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 0.98rem; }
.paletka-sekcja-ile { font-size: 0.74rem; font-weight: 700; color: var(--grigio); font-variant-numeric: tabular-nums; }
.paletka-sekcja-glowa .paletka-mini { margin-left: auto; min-height: 28px; }
.paletka-siatka { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.paletka-siatka.zdania { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.paletka-siatka.wyrazenia { grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); }
.paletka-kafel {
  --pk-zn: transparent;
  position: relative; display: flex; flex-direction: column; gap: 2px; min-height: 66px; padding: 10px 34px 8px 14px;
  border-radius: 16px; background: var(--card-bg); border: 1.5px solid var(--border-warm); cursor: pointer; user-select: none;
  transition: border-color .16s ease, background .16s ease, transform .16s ease, box-shadow .16s ease;
}
/* Wypełnienie „backwards”, NIE „both”: animacja z „forwards” trzyma po końcu ostatnią klatkę (transform: none) i ta wygrywa
   z :hover, więc uniesienie kafla pod kursorem nie działało nigdy po wejściu listy (przegląd D1). */
.paletka-lista.wchodzi .paletka-kafel { animation: paletkaKafel .38s cubic-bezier(.2, .9, .3, 1.2) backwards; animation-delay: var(--d, 0s); }
@keyframes paletkaKafel { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: none; } }
.paletka-kafel:hover { transform: translateY(-2px); box-shadow: var(--shadow-hover); }
.paletka-kafel:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
/* Pasek poziomu po lewej, jak ramka fiszki w talii - w barwach logo (latwe zielony, średnie niebieski, trudne czerwony). */
.paletka-kafel::before { content: ''; position: absolute; left: 0; top: 12px; bottom: 12px; width: 4px; border-radius: 0 4px 4px 0; background: var(--pk-zn); }
.paletka-kafel.zn-latwe, .paletka-filtr.zn-latwe { --pk-zn: var(--marka-zielony); }
.paletka-kafel.zn-srednie, .paletka-filtr.zn-srednie { --pk-zn: var(--marka-niebieski); }
.paletka-kafel.zn-trudne, .paletka-filtr.zn-trudne { --pk-zn: var(--marka-czerwony); }
.paletka-kafel.zn-nowe, .paletka-filtr.zn-nowe { --pk-zn: var(--szary-marki); }
.paletka-t { font-family: var(--font-naglowek); font-weight: 800; font-size: 0.98rem; line-height: 1.2; color: var(--testo); overflow-wrap: anywhere; }
.paletka-siatka.zdania .paletka-t { font-family: var(--font-tekst); font-weight: 700; font-size: 0.88rem; line-height: 1.38; }
.paletka-pl { font-size: 0.78rem; font-weight: 500; line-height: 1.32; color: var(--grigio); overflow-wrap: anywhere; }
.paletka-przyklad {
  margin-top: 3px; font-size: 0.72rem; font-style: italic; line-height: 1.38; color: var(--grigio);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.paletka-dol { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin-top: auto; padding-top: 4px; min-height: 0; }
.paletka-mam, .paletka-poziom, .paletka-sekunda {
  display: inline-flex; white-space: nowrap; align-items: center; gap: 5px; font-size: 0.68rem; font-weight: 800; color: var(--grigio);
}
.paletka-mam .ico { margin: 0; color: var(--verde); }
.paletka-poziom i { width: 8px; height: 8px; border-radius: 50%; background: var(--pk-zn); }
.paletka-sekunda { padding: 1px 8px; border-radius: 999px; background: var(--bg-soft); font-variant-numeric: tabular-nums; }
/* Głośnik w prawym dolnym rogu kafla, w kolumnie kółka wyboru (prawy padding 34 px), a nie w osobnym wierszu: wiersz
   z samym głośnikiem dokładał każdemu kaflowi ~30 px pustego pasa (zrzut Alka 2026-09-29, jedno piętro kafli na ekranie). */
.paletka-glos {
  position: absolute; right: 5px; bottom: 6px;
  flex: none; width: 26px; height: 26px; margin: 0; padding: 0; border: none; border-radius: 50%; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; background: var(--bg-soft); color: var(--testo); font-size: 0.78rem;
  transition: background .16s ease, color .16s ease, transform .16s ease;
}
.paletka-glos .ico { margin: 0; line-height: 1; }
.paletka-glos:hover { background: var(--oro); color: var(--na-akcencie); transform: scale(1.08); }
.paletka-glos.gra { background: var(--oro); color: var(--na-akcencie); }
/* Kółko wyboru: puste obramowanie, a po wyborze żółte z granatowym ptaszkiem (wybór w kanwie = żółty z granatem). */
.paletka-znacznik {
  position: absolute; top: 9px; right: 9px; width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; border: 2px solid var(--border-2); background: var(--card-bg); color: #17183B;
  transition: background .16s ease, border-color .16s ease;
}
.paletka-znacznik .ico { margin: 0; font-size: 0.64rem; line-height: 1; transform: scale(0); transition: transform .22s cubic-bezier(.2, .9, .3, 1.6); }
.paletka-kafel.wybrany { border-color: var(--oro); background: color-mix(in srgb, var(--zolty) 13%, var(--card-bg)); }
.paletka-kafel.wybrany .paletka-znacznik { background: var(--zolty); border-color: var(--zolty); }
.paletka-kafel.wybrany .paletka-znacznik .ico { transform: scale(1); }
/* Pozycja, którą uczeń już ma w talii: NIE znika (to informacja „to już umiesz”, a nie zgubiony materiał), stoi spokojnie
   na tle strony, dopóki ktoś jej świadomie nie zaznaczy. */
.paletka-kafel.mam:not(.wybrany) { background: transparent; border-style: dashed; }
.paletka-kafel.mam:not(.wybrany) .paletka-t { color: var(--grigio); }
.paletka-kafel.ukryty, .paletka-sekcja.ukryty, .paletka-brak.ukryty { display: none; }
.paletka-uwaga {
  display: flex; gap: 10px; align-items: flex-start; margin: 4px 0 14px; padding: 12px 14px; border-radius: 16px; font-size: 0.88rem;
  line-height: 1.5; background: var(--bg-highlight); border: 1.5px solid var(--zolty); color: var(--testo);
}
.paletka-uwaga .ico { margin: 2px 0 0; color: var(--testo); }
/* CZĘŚCI ADAPTERA PRZY KAFLACH (dodatkiNad / dodatkiPod, dziś tylko zdjęcie). Przewijają się z kaflami: na stałe nad stopką
   zabierałyby kaflom wysokość okna (1280 × 650: z dwóch rzędów kafli zostawał jeden, a o ten rząd był spór o gęstość paletki).
   NAD kaflami jeden rząd jak nagłówek sekcji: „Nazwa zbioru”, pole i „Zaproponuj nazwę (AI)”, pod nimi podpowiedź. POD kaflami
   karta z notkami i zgodą na galerię (długi tekst zgody nad kaflami zasłaniał przy 834 × 523 całą pierwszą linię kafli). */
.paletka-dodatki.nad { margin: 8px 0 16px; }
.paletka-dodatki.nad .zakres-nazwa { margin: 0; max-width: none; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; }
.paletka-dodatki.nad .zakres-nazwa-etykieta { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 0.98rem; color: var(--testo); }
.paletka-dodatki.nad .pole-z-przyciskiem { flex: 1 1 380px; min-width: 0; max-width: 680px; }
.paletka-dodatki.nad .zakres-nazwa-podpowiedz { flex: 1 1 100%; margin: 0; }
.paletka-dodatki.pod {
  display: flex; flex-direction: column; gap: 8px; margin: 18px 0 2px; padding: 12px 16px; border-radius: 16px;
  background: var(--card-bg); border: 1.5px solid var(--border-warm);
}
.paletka-dodatki.pod > * { margin: 0; }
.paletka-dodatki.pod .photo-review-skipped, .paletka-dodatki.pod .photo-review-silnik { line-height: 1.45; }
.paletka-dodatki.pod .photo-zgoda-blokada { margin-left: 25px; }
/* STANY: szkielet przy ładowaniu (wyciąganie słówek z tekstu potrafi trwać kilka sekund), czekanie na tłumaczenie,
   pusto i błąd z ponowieniem. */
.paletka-czeka { display: flex; align-items: center; gap: 10px; margin: 6px 0 14px; font-size: 0.9rem; line-height: 1.45; color: var(--testo); }
.paletka-czeka .spinner { width: 18px; height: 18px; border-width: 2px; flex: none; }
.paletka-szkielet { min-height: 72px; border-radius: 16px; background: var(--card-bg); border: 1.5px solid var(--border-warm); position: relative; overflow: hidden; }
.paletka-szkielet::before, .paletka-szkielet::after { content: ''; position: absolute; left: 16px; height: 12px; border-radius: 6px; background: var(--bg-soft); animation: paletkaMigot 1.2s ease-in-out infinite; }
.paletka-szkielet::before { top: 18px; width: 58%; height: 16px; }
.paletka-szkielet::after { top: 46px; width: 38%; animation-delay: .15s; }
@keyframes paletkaMigot { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.paletka-stan { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 34px 16px 18px; text-align: center; }
.paletka-stan-ikona {
  width: 64px; height: 64px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--testo); font-size: 1.6rem;
}
.paletka-stan-ikona .ico { margin: 0; }
.paletka-stan p { margin: 0; max-width: 440px; font-size: 0.96rem; line-height: 1.55; color: var(--grigio); }
.paletka-stan .btn { width: auto; margin: 4px 0 0; }
/* STOPKA: lepka, zawsze w zasięgu kciuka. Liczba wybranych przelicza się na oczach (paletkaLicznik). */
.paletka-stopka {
  flex: none; display: flex; align-items: center; gap: 16px; padding: 10px 20px; background: var(--card-bg);
  border-top: 1.5px solid var(--border-warm); box-shadow: 0 -14px 26px -22px rgba(23, 24, 59, 0.45);
}
.paletka-licznik { display: flex; flex-direction: column; min-width: 0; }
.paletka-licznik-opis { font-size: 0.66rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--grigio); }
.paletka-licznik-rzad { display: flex; align-items: baseline; gap: 6px; }
.paletka-licznik-liczba { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.65rem; line-height: 1; font-variant-numeric: tabular-nums; }
.paletka-licznik-liczba.skok { animation: paletkaSkok .32s cubic-bezier(.2, .9, .3, 1.6); }
@keyframes paletkaSkok { 40% { transform: scale(1.18); } }
.paletka-licznik-z { font-size: 0.8rem; font-weight: 700; color: var(--grigio); }
.paletka-stopka .btn.paletka-dodaj { width: auto; min-width: 250px; margin: 0 0 0 auto; }
.paletka-stopka .btn.paletka-dodaj[disabled] { opacity: .45; cursor: default; transform: none; box-shadow: none; }
/* PO DODANIU: zaznaczone kafle odlatują jako żetony do awatara konta (tam, gdzie leci XP w Mówieniu), a awatar podskakuje. */
.paletka-lot {
  position: fixed; z-index: 100001; pointer-events: none; transform: translate(-50%, -50%); max-width: 220px; padding: 7px 14px;
  border-radius: 999px; background: var(--zolty); color: #17183B; font-family: var(--font-naglowek); font-weight: 800; font-size: 0.95rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: 0 12px 26px -12px rgba(23, 24, 59, 0.6);
}
.paletka-trafienie { animation: paletkaTrafienie .5s cubic-bezier(.2, .9, .3, 1.6); }
@keyframes paletkaTrafienie { 35% { transform: scale(1.22); } 70% { transform: scale(.95); } }
/* NISKI EKRAN NA KOMPUTERZE (Alek 2026-09-29: „zwiększ wysokość kontenera i pomniejsz trochę zawartość o jakieś 15%, żeby
   trochę więcej było widać klocków. Na monitorze 16:9 widać tylko jedno piętro klocków, na moim 21:9 trochę więcej, ale
   niewygodnie nadal”). 1080p ze skalowaniem Windows 150% to ~720 px wysokości okna: głowa z okładką 214 px, narzędzia
   i stopka zabierały ~470 px i na kafle zostawał jeden rząd. Tu głowa jest niska: tytuł, liczby i pierścień w jednym pasie. */
@media (min-width: 641px) and (max-height: 820px) {
  .paletka-bohater { padding: 10px 18px 12px; }
  .paletka-glowa { margin-top: 4px; gap: 16px; }
  .paletka-tytul { font-size: 1.5rem; }
  .paletka-znasz { margin-top: 6px; }
  .paletka-pierscien { width: 46px; height: 46px; }
  .paletka-pierscien b { font-size: 0.8rem; }
  .paletka-okladka, .paletka-okladka.bez { width: 128px; border-width: 4px; }
  .paletka-okladka.bez { font-size: 2rem; }
}
/* TELEFON: arkusz od dołu (jak Arkusz w aplikacji), okładka schodzi, przycisk na całą szerokość pod licznikiem. */
@media (max-width: 640px) {
  .paletka-okno { align-items: flex-end; padding: 0; }
  .paletka-karta { width: 100%; max-height: 92vh; max-height: 92dvh; border-radius: 28px 28px 0 0; animation-name: paletkaArkusz; animation-duration: .38s; }
  @keyframes paletkaArkusz { from { transform: translateY(100%); } to { transform: none; } }
  .paletka-bohater { padding: 14px 16px 18px; }
  /* Także plansza BEZ okładki (czytanka, rozmowa bez obrazka): `.paletka-okladka.bez { display: flex }` ma wyższą swoistość
     niż sama klasa i na zrzucie 390 px czytanki (D2) stała obok tytułu, ściskając go do dwóch słów w wierszu. */
  .paletka-okladka, .paletka-okladka.bez { display: none; }
  .paletka-tytul { font-size: 1.7rem; }
  .paletka-pierscien { width: 58px; height: 58px; }
  .paletka-narzedzia { padding: 12px 16px 8px; }
  /* Zakładki w jednym przewijanym pasku: łamane w dwa rzędy zjadały ze szczytu arkusza ~50 px nad pierwszym kaflem. */
  .paletka-zakladki { flex: 1 1 100%; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 -16px; padding: 0 16px 2px; }
  .paletka-zakladki::-webkit-scrollbar { display: none; }
  .paletka-zakladka { flex: none; min-height: 36px; font-size: 0.86rem; }
  .paletka-mini { min-height: 30px; }
  .paletka-lista { padding: 2px 16px 18px; }
  .paletka-siatka, .paletka-siatka.wyrazenia { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .paletka-siatka.zdania { grid-template-columns: 1fr; }
  .paletka-kafel { min-height: 78px; padding: 10px 36px 8px 14px; }
  .paletka-t { font-size: 1.02rem; }
  .paletka-szukaj { max-width: none; flex-basis: 100%; }
  .paletka-stopka { padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); gap: 12px; }
  .paletka-stopka .btn.paletka-dodaj { min-width: 0; flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .paletka-okno, .paletka-karta, .paletka-okladka, .paletka-lista.wchodzi .paletka-kafel, .paletka-licznik-liczba.skok,
  .paletka-szkielet::before, .paletka-szkielet::after, .paletka-pierscien.laduje .tor { animation: none; }
  .paletka-kafel, .paletka-znacznik .ico, .paletka-pierscien .postep { transition: none; }
  .paletka-kafel:hover { transform: none; }
}
.tworca-okno {
  position: fixed; inset: 0; z-index: 2500; display: flex; flex-direction: column;
  background: var(--bg-soft); color: var(--testo); text-align: left; animation: mowWejscie .25s var(--mow-ease);
}
.tworca-glowa { display: flex; align-items: center; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--border-warm-soft); background: var(--card-bg); flex-wrap: wrap; }
.tworca-tytul { font-size: 1.05rem; font-weight: 700; }
.tworca-tytul .ico { color: var(--primary); margin: 0; }
.tworca-podpis { flex: 1; min-width: 200px; font-size: 0.82rem; color: var(--grigio); line-height: 1.4; }
/* Podpis, nie nawigacja - stad pointer-events: none (tak samo jak znak na planszy kanwy). Na waskim
   ekranie schodzi, bo tam kazdy piksel glowy jest potrzebny tytulowi i krzyzykowi. */
.tworca-logo { height: 24px; opacity: .55; flex-shrink: 0; pointer-events: none; user-select: none; }
@media (max-width: 760px) { .tworca-logo { display: none; } }
.tworca-zamknij { background: none; border: 1px solid var(--border-warm-soft); border-radius: 50%; width: 36px; height: 36px; cursor: pointer; color: var(--grigio); font-size: 1rem; }
.tworca-zamknij:hover { color: var(--testo); border-color: var(--primary); }
.tworca-zamknij .ico { margin: 0; }
.tworca-cialo { flex: 1; min-height: 0; display: flex; }
.tworca-bok { width: 260px; flex: none; border-right: 1px solid var(--border-warm-soft); padding: 14px; display: flex; flex-direction: column; gap: 10px; overflow: auto; background: var(--card-bg); }
.tworca-lista { display: flex; flex-direction: column; gap: 6px; }
.tworca-wiersz { position: relative; display: flex; flex-direction: column; gap: 3px; padding: 9px 34px 9px 11px; border-radius: 12px; border: 1px solid var(--border-warm-soft); background: var(--bg-soft); cursor: pointer; font: inherit; color: var(--testo); text-align: left; }
/* Kosz wychodzi dopiero po najechaniu na wiersz (i zawsze przy wierszu aktywnym): usuwanie ma być pod ręką,
   ale nie ma prawa kusić przy każdym przewinięciu listy. Na dotyku hovera nie ma, więc tam jest widoczny zawsze. */
.tworca-wiersz-kosz { position: absolute; right: 6px; top: 8px; width: 26px; height: 26px; border-radius: 8px; cursor: pointer;
  border: 1px solid transparent; background: none; color: var(--muted-light); opacity: 0; transition: opacity .15s, color .15s, border-color .15s; }
.tworca-wiersz:hover .tworca-wiersz-kosz, .tworca-wiersz.aktywny .tworca-wiersz-kosz, .tworca-wiersz-kosz:focus-visible { opacity: 1; }
.tworca-wiersz-kosz:hover { color: var(--rosso); border-color: var(--rosso); }
.tworca-wiersz-kosz .ico { margin: 0; font-size: 0.82rem; }
@media (hover: none) { .tworca-wiersz-kosz { opacity: 1; } }
.tworca-wiersz:hover, .tworca-wiersz.aktywny { border-color: var(--primary); }
.tworca-wiersz b { font-size: 0.92rem; }
.tworca-wiersz small { font-size: 0.74rem; color: var(--grigio); }
.tworca-wiersz .tworca-szkic { color: var(--muted-light); }
.tworca-publiczna { color: var(--verde); font-weight: 700; }
.tworca-pusto { font-size: 0.84rem; color: var(--muted-light); line-height: 1.45; }
/* Formularz metadanych mieszka teraz W RAMIE edytora (gniazdo #seMeta), więc ta kolumna nie przewija się
   już sama i nie zostawia pasa nad kanwą - cała wysokość idzie do edytora. */
.tworca-edytor { flex: 1; min-width: 0; padding: 10px 14px 12px; overflow: hidden; display: flex; flex-direction: column; gap: 8px; }
/* EKRAN STARTOWY OKNA TWÓRCY (Alek 2026-09-22: „zanim najpierw straszyć użytkownika tymi nodami, zrób duże okno
   do wpisania własnej historii do generowania lub okno (chcę sam zrobić szablon)"). Zajmuje miejsce edytora;
   oba przełącza atrybut hidden - a ten PRZEGRYWA z display:flex wpisanym w klasę (ta sama pułapka, co przy
   okładce i panelu JSON), stąd reguła z !important także dla .tworca-edytor, który do tej pory „chował się"
   tylko na papierze. */
.tworca-start[hidden], .tworca-start [hidden], .tworca-edytor[hidden] { display: none !important; }
.tworca-start { flex: 1; min-width: 0; overflow: auto; padding: 18px 16px 24px; display: flex; justify-content: center; align-items: flex-start; }
.tworca-start-karta { width: min(720px, 100%); display: flex; flex-direction: column; gap: 10px; padding: 22px 22px 20px; border-radius: 18px;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft); box-shadow: var(--shadow-hover); }
.tworca-start-tytul { font-size: 1.25rem; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.tworca-start-tytul .ico { color: var(--primary); margin: 0; }
.tworca-start-opis { margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--grigio); }
.tworca-start-etykieta { margin-top: 6px; font-size: 0.82rem; font-weight: 700; color: var(--testo); }
/* Pole na CAŁĄ historię, nie na hasło: osiem wierszy i większa czcionka niż w formularzu metadanych. Selektor z rodzicem,
   bo `.tworca-in` stoi w tym arkuszu NIŻEJ i sama klasa `.tworca-start-temat` (ta sama swoistość) przegrywała z nią
   rozmiar czcionki i odstępy - pole wracało do wyglądu małego pola formularza. To samo niżej przy przyciskach. */
.tworca-start .tworca-start-temat { width: 100%; box-sizing: border-box; resize: vertical; min-height: 180px; font-size: 0.95rem; line-height: 1.5; padding: 12px 14px; }
.tworca-start-licznik { align-self: flex-end; font-size: 0.74rem; color: var(--muted-light); margin-top: -4px; }
.tworca-start-zakresy { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; }
.tworca-start-zakres { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--grigio); }
.tworca-start-zakres input { width: 64px; }
.tworca-start-stan { display: flex; align-items: center; gap: 10px; font-size: 0.86rem; color: var(--grigio); }
.tworca-start-stan .spinner { width: 18px; height: 18px; border-width: 2px; flex: none; }
.tworca-start-akcje { margin-top: 6px; }
.tworca-start-akcje .btn[disabled] { opacity: .6; cursor: default; }
/* 375 px: pole na całą szerokość ma już z góry, przyciski jeden pod drugim. */
@media (max-width: 560px) {
  .tworca-start { padding: 12px 8px 20px; }
  .tworca-start-karta { padding: 16px 14px; }
  .tworca-start .tworca-start-akcje { flex-direction: column; align-items: stretch; }
  .tworca-start .tworca-start-akcje .btn { width: 100%; justify-content: center; }
}
/* KREATOR ROZMÓW: WYBÓR DROGI, LEJEK „UŁATWIONE TWORZENIE” I „UKŁADAM TWOJĄ ROZMOWĘ” (2026-10-06, kanwa „Kreator rozmów Mówienie”,
   https://claude.ai/artifact/WUxEvRcTzRMBP2ddwkfQPD, zatwierdzona przez Alka). Ekran w barwie Mówienia (zieleń marki), granatowe
   i białe karty, pigułki z kółkiem ze strzałką - barwy marki są tu STAŁE w obu motywach, jak na innych kolorowych ekranach marki.
   Klasa .kl-tlo na #tworcaStart zmienia dawny ekran startowy (wyśrodkowana karta na tle okna) w zielony ekran przewijany w pionie. */
.tworca-start.kl-tlo { display: block; background: var(--marka-zielony); color: var(--granat); padding: 20px clamp(16px, 3vw, 40px) 40px; }
.tworca-start.kl-tlo > .tworca-start-karta { margin: 0 auto; }
.tworca-start-wroc { align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; min-height: 36px; padding: 0 12px 0 6px; border-radius: 999px;
  border: 1px solid var(--border-warm-soft); background: none; color: var(--testo); font: inherit; font-size: 0.84rem; font-weight: 700; cursor: pointer; }
.tworca-start-wroc .ico { margin: 0; }
.kl-ekran { max-width: 1200px; margin: 0 auto; display: flex; flex-direction: column; gap: 24px; color: var(--granat); }
.kl-ekran[hidden] { display: none !important; }
.kl-gora { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.kl-pigulka { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px 0 14px; box-sizing: border-box; border-radius: 999px;
  background: #fff; color: var(--granat); font-size: 0.95rem; font-weight: 800; }
.kl-pigulka .ico { margin: 0; font-size: 1.05rem; }
.kl-pigulka-granat { background: var(--granat); color: #fff; }
.kl-pigulka-granat .ico { color: var(--zolty); }
.kl-plakietka { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 14px; border-radius: 999px;
  background: var(--zolty); color: var(--granat); font-size: 0.82rem; font-weight: 800; }
.kl-plakietka .ico { margin: 0; }
.kl-naglowek { display: flex; flex-direction: column; gap: 10px; }
.kl-nadtytul { font-size: 0.8rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.kl-h1 { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: clamp(2rem, 4.4vw, 3.4rem); line-height: 1.03; letter-spacing: -0.02em;
  text-wrap: balance; color: var(--granat); }
.kl-opis { margin: 0; max-width: 640px; font-size: 1.05rem; font-weight: 500; line-height: 1.5; color: var(--granat); }
.kl-tylko-telefon { display: none; }
.kl-karty { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
.kl-karta { position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: flex-start; gap: 14px; min-height: 420px;
  padding: 30px; box-sizing: border-box; border: 0; border-radius: 28px; text-align: left; font: inherit; }
.kl-karta > :not(.kl-karta-ilu) { position: relative; }
.kl-karta-ilu { position: absolute; right: -18px; bottom: -22px; width: 280px; height: 280px; pointer-events: none; }
/* WĄSKA KARTA (okno 1024 px z listą rozmów obok daje karty po ~265 px, telefon ~360 px): ilustracja w dolnym rogu wchodziła na opis
   i przycisk. Liczy się szerokość KARTY (container query), nie okna - ta sama karta bywa wąska na szerokim ekranie i szeroka na węższym. */
.kl-karta { container-type: inline-size; }
@container (max-width: 519px) {
  .kl-karta-ilu { position: relative; order: -1; align-self: flex-end; right: auto; bottom: auto; width: 120px; height: 120px; margin: -14px -12px -56px 0; }
  .kl-karta-tytul { font-size: 1.9rem; }
}
.kl-karta-latwa { background: var(--granat); color: #fff; cursor: pointer; transition: transform .18s ease; }
.kl-karta-latwa:hover { transform: translateY(-2px); }
.kl-karta-sama { background: #fff; color: var(--granat); }
.kl-znaczek { display: inline-flex; align-items: center; min-height: 30px; padding: 0 12px; box-sizing: border-box; border-radius: 999px;
  background: var(--zolty); color: var(--granat); font-size: 0.8rem; font-weight: 800; }
.kl-znaczek-obrys { background: none; border: 1.5px solid var(--granat); }
.kl-karta-tytul { margin: 0; font-family: var(--font-naglowek); font-size: 2.2rem; font-weight: 800; line-height: 1.05; letter-spacing: -0.01em; }
.kl-karta-opis { margin: 0; max-width: 330px; font-size: 1rem; font-weight: 500; line-height: 1.5; }
.kl-karta-latwa .kl-karta-opis { color: #D4D5F0; }
.kl-karta-sama .kl-karta-opis { color: #4A4B6B; }
.kl-cechy { display: flex; flex-wrap: wrap; gap: 8px; max-width: 330px; }
.kl-cechy span { display: inline-flex; align-items: center; min-height: 30px; padding: 0 12px; border-radius: 999px; background: #2A2C5E; font-size: 0.8rem; font-weight: 700; }
.kl-cta { margin-top: auto; display: inline-flex; align-items: center; gap: 14px; min-height: 58px; padding: 0 7px 0 24px; box-sizing: border-box; border: 0;
  border-radius: 999px; font: inherit; font-size: 1.05rem; font-weight: 800; cursor: pointer; }
.kl-cta[disabled] { opacity: .6; cursor: default; }
.kl-cta-kolko { width: 44px; height: 44px; flex: none; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }
.kl-cta-kolko .ico { margin: 0; font-size: 1.1rem; }
.kl-cta-zolta { background: var(--zolty); color: var(--granat); }
.kl-cta-zolta .kl-cta-kolko { background: var(--granat); color: var(--zolty); }
.kl-cta-granat { background: var(--granat); color: #fff; }
.kl-cta-granat .kl-cta-kolko { background: var(--zolty); color: var(--granat); }
.kl-karta-akcje { margin-top: auto; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.kl-karta-akcje .kl-cta { margin-top: 0; }
.kl-obrys { display: inline-flex; align-items: center; min-height: 48px; padding: 0 20px; box-sizing: border-box; border: 2px solid var(--granat); border-radius: 999px;
  background: #fff; color: var(--granat); font: inherit; font-size: 1rem; font-weight: 800; cursor: pointer; }
.kl-stopka, .kl-maly { margin: 0; font-size: 0.9rem; font-weight: 600; line-height: 1.5; color: var(--granat); }
.kl-tel-info, .kl-uwaga-tel { display: none; gap: 12px; align-items: flex-start; padding: 14px 16px; border-radius: 20px; background: #1F7A35; color: #fff;
  font-size: 0.88rem; font-weight: 500; line-height: 1.45; }
.kl-tel-info-ikona { width: 40px; height: 40px; flex: none; border-radius: 12px; background: #fff; color: var(--granat); display: inline-flex; align-items: center; justify-content: center; }
.kl-tel-info-ikona .ico { margin: 0; font-size: 1.15rem; }
.kl-tel-info-tresc { display: flex; flex-direction: column; gap: 3px; }
.kl-tel-info-tresc b { font-size: 0.95rem; font-weight: 800; }
.kl-ekran button:focus-visible, .kl-ekran textarea:focus-visible, .tworca-start-wroc:focus-visible { outline: 3px solid var(--granat); outline-offset: 3px; }
/* Lejek: pasek kroków, pytanie z kaflami odpowiedzi i boczna „Twoja lekcja” z rosnącym poleceniem dla AI. */
.kl-zamknij { width: 44px; height: 44px; flex: none; border: 0; border-radius: 999px; background: #fff; color: var(--granat); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; }
.kl-zamknij .ico { margin: 0; font-size: 1.2rem; }
.kl-postep { flex: 1 1 260px; min-width: 200px; display: flex; flex-direction: column; gap: 7px; }
.kl-postep-licznik { font-size: 0.8rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.kl-postep-pasek { display: flex; gap: 5px; }
.kl-postep-pasek span { flex: 1 1 0; height: 6px; border-radius: 3px; background: rgba(23, 24, 59, 0.2); }
.kl-postep-pasek span.zrobiony { background: var(--granat); }
.kl-postep-pasek span.teraz { background: #fff; }
.kl-uklad { display: flex; flex-wrap: wrap; gap: 32px; align-items: flex-start; }
.kl-glowna { flex: 999 1 520px; min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.kl-bok { flex: 1 1 320px; max-width: 440px; min-width: 0; display: flex; flex-direction: column; }
.kl-bok-ilu { height: 190px; display: flex; justify-content: center; align-items: flex-end; }
.kl-bok-ilu img { width: 220px; height: 220px; margin-bottom: -14px; }
.kl-lekcja { display: flex; flex-direction: column; gap: 14px; padding: 20px; border-radius: 24px; background: #fff; color: var(--granat); }
.kl-lekcja-glowa { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.kl-lekcja-tytul { font-family: var(--font-naglowek); font-size: 1.3rem; font-weight: 800; }
.kl-lekcja-licznik { display: inline-flex; align-items: center; min-height: 28px; padding: 0 11px; border-radius: 999px; background: var(--marka-zielony);
  color: var(--granat); font-size: 0.78rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.kl-lekcja-pusto { margin: 0; font-size: 0.88rem; font-weight: 500; line-height: 1.5; color: #4A4B6B; }
.kl-wiersze { display: flex; flex-wrap: wrap; gap: 8px; }
.kl-wiersz { display: inline-flex; align-items: center; gap: 7px; min-height: 36px; max-width: 100%; padding: 4px 12px 4px 10px; box-sizing: border-box; border: 0;
  border-radius: 999px; background: #F3F5FB; color: var(--granat); text-align: left; font: inherit; font-size: 0.8rem; font-weight: 600; line-height: 1.3; cursor: pointer; }
.kl-wiersz .ico { margin: 0; color: #4A4B6B; font-size: 0.8rem; }
.kl-wiersz b { font-weight: 800; }
.kl-polecenie-podglad { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 16px; border: 1.5px dashed #9FA1C4; }
.kl-polecenie-etykieta { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: #4A4B6B; }
.kl-polecenie-tekst { font-size: 0.84rem; font-weight: 500; line-height: 1.5; overflow-wrap: anywhere; }
.kl-znaki { align-self: flex-end; font-size: 0.75rem; font-weight: 700; color: #4A4B6B; font-variant-numeric: tabular-nums; }
.kl-opcje { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }
.kl-opcja { display: flex; align-items: center; gap: 14px; min-height: 84px; padding: 14px; box-sizing: border-box; border: 0; border-radius: 20px;
  background: #fff; color: var(--granat); text-align: left; font: inherit; cursor: pointer; transition: transform .15s ease; }
.kl-opcja:hover { transform: translateY(-1px); }
.kl-opcja.wybrana { background: var(--granat); color: #fff; }
.kl-opcja-ikona { width: 52px; height: 52px; flex: none; border-radius: 16px; display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-naglowek); font-size: 1.15rem; font-weight: 800; }
.kl-opcja-ikona .ico { margin: 0; font-size: 1.45rem; }
.kl-k-n { background: var(--granat); color: #fff; }
.kl-opcja.wybrana .kl-k-n { background: #2A2C5E; }
.kl-k-b { background: var(--marka-niebieski); color: #fff; }
.kl-k-y { background: var(--zolty); color: var(--granat); }
.kl-k-r { background: var(--marka-czerwony); color: #fff; }
.kl-k-g { background: var(--marka-zielony); color: var(--granat); }
.kl-k-j { background: #F3F5FB; color: var(--granat); }
.kl-opcja-teksty { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.kl-opcja-t { font-family: var(--font-naglowek); font-size: 1.1rem; font-weight: 800; line-height: 1.15; }
.kl-opcja-p { font-size: 0.84rem; font-weight: 500; line-height: 1.4; color: #4A4B6B; }
.kl-opcja.wybrana .kl-opcja-p { color: #D4D5F0; }
.kl-ptaszek { width: 26px; height: 26px; flex: none; border-radius: 999px; background: var(--zolty); color: var(--granat); display: inline-flex; align-items: center; justify-content: center; }
.kl-ptaszek .ico { margin: 0; font-size: 0.85rem; }
.kl-pole { width: 100%; box-sizing: border-box; padding: 14px 16px; border: 0; border-radius: 18px; background: #fff; color: var(--granat); font: inherit;
  font-size: 1rem; font-weight: 500; line-height: 1.5; resize: vertical; }
.kl-przyciski { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 4px; }
.kl-przyciski .kl-cta { margin-top: 0; }
.kl-wstecz { display: inline-flex; align-items: center; gap: 6px; min-height: 48px; padding: 0 18px 0 12px; box-sizing: border-box; border: 0; border-radius: 999px;
  background: #fff; color: var(--granat); font: inherit; font-size: 0.95rem; font-weight: 800; cursor: pointer; }
.kl-wstecz .ico, .kl-losuj .ico { margin: 0; }
.kl-losuj { display: inline-flex; align-items: center; gap: 8px; min-height: 48px; padding: 0 18px 0 14px; box-sizing: border-box; border: 2px solid var(--granat);
  border-radius: 999px; background: transparent; color: var(--granat); font: inherit; font-size: 0.95rem; font-weight: 800; cursor: pointer; }
.kl-polecenie-blok { display: flex; flex-direction: column; gap: 10px; padding: 18px 20px; border-radius: 22px; background: #fff; }
.kl-polecenie-blok .kl-pole { padding: 0; border-radius: 0; min-height: 9.5em; }
/* WŁASNY POMYSŁ obok kafli (2026-10-06 wieczór, Alek: „z możliwością dopisania obok klocka swojego pomysłu”): ostatni kafel tej samej
   siatki, z polem i kółkiem „Dalej”, czynnym od KL_WLASNY_MIN znaków. Przerywana ramka odróżnia go od propozycji AI. */
.kl-wlasna { display: flex; flex-direction: column; justify-content: center; gap: 10px; min-height: 84px; padding: 12px 14px; box-sizing: border-box;
  border: 2px dashed var(--granat); border-radius: 20px; background: rgba(255, 255, 255, 0.6); color: var(--granat); }
.kl-wlasna.wybrana { border-style: solid; background: var(--granat); color: #fff; }
.kl-wlasna-glowa { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-naglowek); font-size: 1.05rem; font-weight: 800; }
.kl-wlasna-glowa .ico { margin: 0; font-size: 0.95rem; }
.kl-wlasna-wiersz { display: flex; gap: 8px; }
.kl-wlasna-pole { flex: 1 1 auto; min-width: 0; min-height: 44px; padding: 0 16px; box-sizing: border-box; border: 0; border-radius: 999px;
  background: #fff; color: var(--granat); font: inherit; font-size: 0.95rem; font-weight: 600; }
.kl-wlasna-pole:focus-visible { outline: 3px solid var(--zolty); outline-offset: 1px; }
.kl-wlasna-ok { width: 44px; height: 44px; flex: none; border: 0; border-radius: 999px; background: var(--granat); color: var(--zolty);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.kl-wlasna.wybrana .kl-wlasna-ok { background: var(--zolty); color: var(--granat); }
.kl-wlasna-ok[disabled] { opacity: .4; cursor: default; }
.kl-wlasna-ok .ico { margin: 0; font-size: 1.05rem; }
/* Czekanie na pytanie od modelu: szkielety kafli w tym samym miejscu, żeby układ nie skakał, gdy pytanie przyjdzie. */
.kl-mysli { display: flex; align-items: center; gap: 12px; }
.kl-mysli-znak { width: 24px; height: 24px; flex: none; box-sizing: border-box; border-radius: 999px; border: 3px solid var(--granat);
  border-right-color: var(--zolty); animation: klKrec .9s linear infinite; }
.kl-opcja.kl-szkielet { cursor: default; }
.kl-opcja.kl-szkielet:hover { transform: none; }
.kl-szkielet-pas { display: block; height: 12px; border-radius: 999px; background: #E3E6F2; animation: klPuls 1.4s ease-in-out infinite; }
.kl-szkielet-pas.dlugi { width: 72%; }
.kl-szkielet-pas.krotki { width: 46%; margin-top: 6px; }
@keyframes klPuls { 50% { opacity: .45; } }
.kl-losuj[disabled] { opacity: .5; cursor: default; }
.kl-blad { display: flex; flex-direction: column; gap: 12px; padding: 16px 18px; border-radius: 20px; background: #fff; color: var(--granat); }
.kl-blad-tekst { font-size: 0.95rem; font-weight: 700; line-height: 1.45; }
.kl-blad .kl-przyciski { margin-top: 0; }
/* USTAWIENIA W PODSUMOWANIU: poziom (domyślnie konta), długość i wyjaśnienie w języku ucznia. Wybór = żółty z granatem, jak w całym
   stylu kanwy; przełącznik granatowy z żółtą gałką. */
.kl-ust { display: flex; flex-direction: column; gap: 14px; padding: 18px 20px; border-radius: 22px; background: #fff; color: var(--granat); }
.kl-ust-tytul { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: #4A4B6B; }
.kl-ust-wiersz { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.kl-ust-etykieta { min-width: 88px; font-size: 0.92rem; font-weight: 800; }
.kl-ust-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 42px; padding: 0 16px; box-sizing: border-box; border: 0;
  border-radius: 999px; background: #F3F5FB; color: var(--granat); font: inherit; font-size: 0.9rem; font-weight: 700; cursor: pointer; }
.kl-ust-chip small { font-size: 0.75rem; font-weight: 600; color: #4A4B6B; }
.kl-ust-chip.wybrany { background: var(--zolty); font-weight: 800; }
.kl-ust-chip.wybrany small { color: var(--granat); }
.kl-ust-chip:focus-visible, .kl-ust-przelacznik:focus-visible { outline: 3px solid var(--granat); outline-offset: 2px; }
.kl-ust-przelacznik { display: flex; align-items: flex-start; gap: 14px; padding: 4px 0; border: 0; background: none; color: var(--granat);
  text-align: left; font: inherit; cursor: pointer; }
.kl-ust-tor { position: relative; width: 46px; height: 28px; flex: none; margin-top: 2px; border-radius: 999px; background: #D5D8E6; transition: background .15s ease; }
.kl-ust-tor::after { content: ''; position: absolute; top: 4px; left: 4px; width: 20px; height: 20px; border-radius: 999px; background: #fff; transition: transform .15s ease; }
.kl-ust-przelacznik[aria-checked="true"] .kl-ust-tor { background: var(--granat); }
.kl-ust-przelacznik[aria-checked="true"] .kl-ust-tor::after { transform: translateX(18px); background: var(--zolty); }
.kl-ust-przelacznik-teksty { display: flex; flex-direction: column; gap: 3px; }
.kl-ust-przelacznik-teksty b { font-size: 0.95rem; font-weight: 800; }
.kl-ust-przelacznik-teksty span { font-size: 0.84rem; font-weight: 500; line-height: 1.45; color: #4A4B6B; }
.kl-ust-uwaga { display: flex; align-items: flex-start; gap: 10px; font-size: 0.84rem; font-weight: 500; line-height: 1.45; color: #4A4B6B; }
.kl-ust-uwaga .ico { margin: 2px 0 0; color: var(--granat); }
.kl-link { min-height: 48px; padding: 0 6px; border: 0; background: none; color: var(--granat); font: inherit; font-size: 0.95rem; font-weight: 800;
  text-decoration: underline; cursor: pointer; }
/* „Układam Twoją rozmowę” (plansza „AI układa rozmowę”): kroki odhaczają się, gdy naprawdę minie dana część pracy (patrz klUkladaj). */
/* Dwie kolumny, a w wąskim miejscu (okno 1024 px z listą rozmów obok, telefon) mała ilustracja nad treścią - duża wypychała listę
   etapów pod krawędź ekranu. Liczy się szerokość ekranu kreatora (container query), nie okna. */
.kl-uklada { container-type: inline-size; }
.kl-uk-uklad { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); align-items: center; gap: 40px; }
.kl-uk-ilu { display: flex; justify-content: center; }
.kl-uk-ilu img { width: 100%; max-width: 340px; height: auto; aspect-ratio: 1 / 1; animation: klUnos 3.2s ease-in-out infinite; }
.kl-uk-tresc { min-width: 0; display: flex; flex-direction: column; gap: 18px; }
@container (max-width: 680px) {
  .kl-uk-uklad { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .kl-uk-ilu img { width: 160px; }
}
.kl-uk-pasek { height: 12px; border-radius: 999px; background: rgba(23, 24, 59, 0.2); overflow: hidden; }
.kl-uk-pasek > div { height: 100%; border-radius: 999px; background: var(--granat); transition: width .6s ease; }
.kl-uk-kroki { margin: 0; padding: 18px 20px; list-style: none; display: flex; flex-direction: column; gap: 12px; border-radius: 22px; background: #fff; color: var(--granat); }
.kl-uk-kroki li { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; font-weight: 600; }
.kl-uk-kroki li.czeka { color: #4A4B6B; }
.kl-uk-kroki li.teraz { font-weight: 800; }
.kl-uk-znak { width: 28px; height: 28px; flex: none; box-sizing: border-box; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }
.kl-uk-znak .ico { margin: 0; font-size: 0.85rem; }
.kl-uk-kroki li.zrobiony .kl-uk-znak { background: var(--marka-zielony); color: var(--granat); }
.kl-uk-kroki li.teraz .kl-uk-znak { border: 3px solid var(--granat); border-right-color: var(--zolty); animation: klKrec .9s linear infinite; }
.kl-uk-kroki li.czeka .kl-uk-znak { border: 2px dashed #9FA1C4; }
@keyframes klKrec { to { transform: rotate(360deg); } }
@keyframes klUnos { 50% { transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) {
  .kl-uk-ilu img, .kl-uk-kroki li.teraz .kl-uk-znak { animation: none; }
  .kl-karta-latwa, .kl-opcja, .kl-ust-tor, .kl-ust-tor::after { transition: none; }
  .kl-mysli-znak, .kl-szkielet-pas { animation: none; }
  .kl-karta-latwa:hover, .kl-opcja:hover { transform: none; }
}
/* TELEFON (do 760 px, Alek: „na telefonie powinien działać tylko ten kreator ułatwiony, z informacją, że na desktopie jest pełna
   edytowalność”): bez listy rozmów i bez drogi „Samodzielnie”, za to z zieloną informacją o komputerze. */
@media (max-width: 760px) {
  .tworca-okno .tworca-bok, .tworca-okno .tworca-podpis { display: none; }
  .kl-tylko-komputer, .kl-karta-sama, .kl-stopka { display: none; }
  .kl-tylko-telefon { display: block; }
  .kl-tel-info, .kl-uwaga-tel { display: flex; }
  .tworca-start.kl-tlo { padding: 14px 16px 28px; }
  .kl-karta { min-height: 0; padding: 22px; padding-bottom: 26px; }
  .kl-karta-latwa .kl-cta { margin-top: 8px; }
  .kl-bok-ilu { display: none; }
}
.tworca-meta { display: flex; flex-direction: column; gap: 8px; }
/* Kanwa bierze CALA reszte okna twórcy zamiast stalej wysokosci liczonej z vh: nad nia stoi pasek okladki
   i formularz, ktore zmieniaja wysokosc razem z trescia (dlugi opis lamie sie na dwie linie), a kazda stala
   zostawiala albo pusty pas pod kanwa, albo kanwe wychodzaca poza ekran. */
/* Rama edytora musi byc OGRANICZONA wysokoscia okna: formularz siedzi teraz w srodku, wiec bez min-height:0
   rosnie razem z nim i wypycha kanwe pod dolna krawedz ekranu (zmierzone: gorny brzeg kanwy na 659 px
   przy oknie 900 px). flex-basis 0 + min-height 0 = rama bierze dokladnie to, co zostalo. */
/* OGNIWO, KTOREGO BRAKOWALO: .se nie jest bezposrednim dzieckiem kolumny - siedzi w #tworcaEdytorMiejsce,
   a ten div nie mial zadnych regul flex, wiec rosl do TRESCI i caly lancuch wysokosci sie urywal (kanwa
   trzymala 556 px niezaleznie od okna i wychodzila pod dolna krawedz). Oba ogniwa musza umiec sie kurczyc. */
#tworcaEdytorMiejsce { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.tworca-edytor .se { flex: 1 1 0; height: auto; min-height: 0; margin-top: 0; }
.tworca-pola { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tworca-in { font: inherit; font-size: 0.86rem; padding: 7px 10px; border-radius: 10px; border: 1px solid var(--border-warm-soft); background: var(--card-bg); color: var(--testo); min-width: 0; }
.tworca-in:focus { outline: none; border-color: var(--primary); }
.tworca-in-tytul { flex: 1 1 260px; font-weight: 600; }
.tworca-in-szeroki { flex: 1 1 100%; }
.tworca-pole-szeroki { flex: 1 1 100%; display: flex; gap: 6px; align-items: center; }
.tworca-rola { display: flex; gap: 6px; align-items: center; flex: 1 1 220px; }
.tworca-rola .tworca-in { flex: 1; min-width: 90px; }
.tworca-jezyki { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Flagi zamiast nazw: dwadzieścia pięć nazw nie zmieściłoby się w wierszu, a flaga jest czytelna od razu
   i nie wymaga tłumaczenia. Nazwa siedzi w tytule (langName - Intl.DisplayNames w języku oglądającego). */
.tworca-jezyki-chipy { display: flex; flex-wrap: wrap; gap: 4px; max-height: 76px; overflow: auto; }
.tworca-jezyk {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: 999px; cursor: pointer;
  border: 1px dashed var(--border-2); background: transparent; color: var(--muted-light); font: inherit; font-size: 0.72rem;
}
.tworca-jezyk svg { border-radius: 2px; display: block; }
.tworca-jezyk.wl { border-style: solid; border-color: var(--primary); background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--testo); font-weight: 700; }
.tworca-jezyk:hover { border-color: var(--primary); }
.tworca-jezyki-stan { font-size: 0.76rem; color: var(--muted-light); }
.tworca-etykieta { font-size: 0.78rem; color: var(--grigio); }
/* Rozmowa nie moja, otwarta olowkiem z mapy (admin) - zeby nie dalo sie jej pomylic z wlasna. */
.tworca-obca { color: var(--primary); font-weight: 600; }
.tworca-pole-szeroki .tworca-in { flex: 1; }
/* Różówka przy tytule: to ten sam rodzaj akcji, co „Zacznij od pomysłu" w palecie, więc ten sam akcent. */
.tworca-mini-ai { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 45%, transparent); }
.tworca-mini-ai:hover { background: var(--primary); color: #fff; }
.tworca-mini[disabled] { opacity: .5; cursor: default; }
.tworca-mini { background: none; border: 1px solid var(--border-warm-soft); border-radius: 10px; width: 34px; height: 34px; cursor: pointer; color: var(--grigio); }
.tworca-mini:hover { color: var(--primary); border-color: var(--primary); }
.tworca-mini .ico { margin: 0; }
.tworca-bledy { white-space: pre-line; }
.tworca-akcje { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tworca-akcje .btn { width: auto; margin: 0; padding: 8px 14px; }
/* PRZYCISKI 3D (Alek 2026-09-16: „te zielone przyciski zrób 3d"). Wypukłość robi twarda krawędź pod spodem
   (box-shadow bez rozmycia) plus delikatny połysk od góry - a nie gradient w tle, bo ten w ciemnym motywie
   robi się brudny. Wciśnięcie ZJEŻDŻA przycisk o tę samą krawędź, więc ruch jest dokładnie taki, jak na
   prawdziwym klawiszu. Przy `prefers-reduced-motion` zostaje sam kolor, bez skakania. */
.tworca-akcje .btn, .mow-tworca-btn {
  position: relative; border-bottom-width: 0;
  box-shadow: 0 4px 0 color-mix(in srgb, currentColor 22%, #0b1220), 0 6px 14px rgba(15, 23, 42, .28);
  background-image: linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,0) 58%);
  transition: transform .08s ease, box-shadow .08s ease, filter .15s ease;
}
.tworca-akcje .btn.btn-verde, .tworca-akcje .btn.btn-rosso, .tworca-akcje .btn.btn-grigio {
  box-shadow: 0 4px 0 rgba(8, 15, 30, .45), 0 6px 14px rgba(15, 23, 42, .28);
}
.tworca-akcje .btn:hover, .mow-tworca-btn:hover { filter: brightness(1.06); }
.tworca-akcje .btn:active, .mow-tworca-btn:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 rgba(8, 15, 30, .45), 0 2px 6px rgba(15, 23, 42, .22);
}
.tworca-akcje .btn:focus-visible, .mow-tworca-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .tworca-akcje .btn, .mow-tworca-btn { transition: none; }
  .tworca-akcje .btn:active, .mow-tworca-btn:active { transform: none; }
}
.tworca-rozpora { flex: 1; }
.tworca-stan { font-size: 0.8rem; color: var(--grigio); }
/* OKŁADKA W OKNIE TWÓRCY: podgląd po lewej, trzy drogi po prawej (narysuj, wgraj, zdejmij).
   PUŁAPKA ZMIERZONA 2026-09-16 (Alek: „bug: bez obrazka, mimo że jest obrazek"): atrybut `hidden` przegrywa
   z `display:flex` wpisanym w klasę, więc napis „Bez obrazka" leżał NA wgranym zdjęciu. Ta sama rzecz ugryzła
   już panel JSON w edytorze - stąd ten sam ratunek: w obrębie okładki `hidden` ma znaczyć „nie ma tego", kropka. */
.tworca-okladka [hidden] { display: none !important; }
.tworca-okladka { display: flex; gap: 14px; align-items: flex-start; padding: 10px 12px; border-radius: 14px;
  background: var(--bg-soft); border: 1px solid var(--border-warm-soft); }
/* Proporcje 16:9, bo taki kształt ma generator (1536×1024) i taki jest pas okładki na kafelku - podgląd ma
   pokazywać to, co zobaczą inni, a nie własny wycinek. */
.tworca-okladka-plyta { position: relative; width: 232px; aspect-ratio: 16 / 9; flex: none; border-radius: 12px; overflow: hidden;
  border: 1px dashed var(--border-warm-dash); background: var(--card-bg); display: flex; align-items: center; justify-content: center; }
.tworca-okladka-plyta.jest { border-style: solid; border-color: var(--border-warm-soft); }
.tworca-okladka-plyta img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tworca-okladka-pusto { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 0.74rem; color: var(--muted-light); text-align: center; padding: 0 10px; }
.tworca-okladka-pusto .ico { margin: 0; font-size: 1.5rem; }
/* Zasłona na czas rysowania: obraz powstaje do minuty i bez tego wyglądało to jak zawieszony przycisk. */
.tworca-okladka-pracuje { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  background: color-mix(in srgb, var(--card-bg) 82%, transparent); font-size: 0.74rem; color: var(--grigio); text-align: center; padding: 0 10px; }
.tworca-okladka-akcje { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.tworca-okladka-rzad { display: flex; gap: 6px; flex-wrap: wrap; }
.tworca-mini2 { display: inline-flex; align-items: center; gap: 6px; font: inherit; font-size: 0.82rem; padding: 6px 12px; border-radius: 10px;
  border: 1px solid var(--border-warm-soft); background: var(--card-bg); color: var(--testo); cursor: pointer; }
.tworca-mini2:hover { border-color: var(--primary); color: var(--primary); }
.tworca-mini2[disabled] { opacity: .5; cursor: default; }
.tworca-mini2 .ico { margin: 0; }
.tworca-okladka-info { font-size: 0.76rem; color: var(--muted-light); line-height: 1.4; max-width: 420px; }
@media (max-width: 720px) { .tworca-okladka { flex-direction: column; } .tworca-okladka-plyta { width: 100%; } }
@media (max-width: 760px) { .tworca-cialo { flex-direction: column; } .tworca-bok { width: auto; border-right: none; border-bottom: 1px solid var(--border-warm-soft); max-height: 32vh; } .tworca-edytor .se { height: 70vh; } }
@media (prefers-reduced-motion: reduce) {
  .mow-mapa, .mow-bot, .mow-bot-tlum, .mow-zaczep, .mow-zaczep-tlum, .mow-dymek, .mow-status, .mow-recenzja, .mow-cwiczenie { animation: none; }
  .mow-gora-cisza i { animation: none; }
  .mow-linia > * { transition: none; }
  .mow-xp-trafienie { animation: none; }
}
.ustawienia-select {
  padding: 8px 32px 8px 12px; border-radius: 10px; border: 1px solid var(--border-2);
  background: var(--card-bg); color: var(--testo); font: inherit; font-size: 0.9rem; cursor: pointer;
}
#kartaHistoriaMowienia .tekst-poziom { min-width: 30px; padding: 5px 0; }
#kartaHistoriaMowienia .tekst-poziom .ico { margin: 0; font-size: 0.8rem; }
#kartaHistoriaMowienia .tekst-wiersz.aktywny .tekst-wiersz-tytul { color: var(--primary); }
@media (max-width: 640px) {
  .mow-scena { min-height: 460px; padding-top: 96px; }
  .mow-naglowek { right: 8px; }
  .mow-dymki { min-height: 52px; gap: 8px 10px; }
  .mow-dymek { font-size: 0.88rem; max-width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .mow-mik { box-shadow: none; }
  /* Kropki lektora STOJĄ - zamiast skoków wysokości co najwyżej łagodna pulsacja krycia; stan „lektor mówi" ma być
     widoczny także bez ruchu (ta sama reguła swoistości, co drganie, tylko później w źródle). */
  .mow-mik-obszar.lektor .mow-kropka { animation: mowLektorPuls 1.6s ease-in-out infinite; }
}
@keyframes mowLektorPuls { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

/* ===== TRYB TEKSTY - RUCH =====
   Kartka ma się zachowywać jak papier, a nie jak tabela: zdania wchodzą kaskadą, ocena
   „rozlewa się" po zdaniu, panel próby rozwija się na wysokość zamiast wskakiwać.
   Wszystko poniżej wyłącza się przy prefers-reduced-motion (na końcu sekcji). */

/* Wejście przy otwarciu kartki - AKAPITAMI, nie zdaniami: transform nie działa na elemencie
   inline, a i tak lepiej wygląda kilka spokojnych ruchów niż trzydzieści drobnych.
   Opóźnienie ustawia JS przez --i, żeby nie pisać reguł nth-child. */
.kartka-akapit { animation: segmentWjazd 0.42s cubic-bezier(.22,1,.36,1) backwards;
  animation-delay: calc(var(--i, 0) * 70ms); }
@keyframes segmentWjazd { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Moment oceny: zdanie na chwilę zapala się kolorem wyniku i gaśnie, jak ślad zakreślacza.
   Wcześniej był to błysk rysowany nakładką ::after - ta wymaga elementu pozycjonowanego,
   a zdanie jest teraz elementem inline w akapicie. Animowane tło robi to samo i przełamuje
   się razem ze zdaniem na kolejny wiersz. */
.kartka-segment.blysk { animation: blyskOceny 0.85s cubic-bezier(.4,0,.2,1); }
@keyframes blyskOceny {
  from { background-color: var(--blysk-kolor, transparent); }
  to   { background-color: transparent; }
}
/* Trafienie dodatkowo "oddycha" - jedno delikatne pchnięcie skali, bez przesuwania sąsiadów. */
/* Zdanie, na którym poprzednio się skończyło. Miga ramką przez chwilę po otwarciu tekstu -
   bez tego przewinięcie w środek tekstu wygląda jak zgubione miejsce, a nie jak zakładka. */
.kartka-segment.wznowione { animation: segmentWznowienie 2.2s ease; }
@keyframes segmentWznowienie {
  0%, 100% { background-color: transparent; }
  15%, 62% { background-color: color-mix(in srgb, var(--primary) 22%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .kartka-segment.wznowione { animation: none; } }

/* Puls i potrząśnięcie ruszają CAŁYM zdaniem, więc mają sens tylko wtedy, gdy zdanie jest
   blokiem - czyli w trakcie próby. Zamknięte zdanie wraca do akapitu i dostaje sam błysk. */
.kartka-segment.aktywny.puls { animation: segmentPuls 0.5s cubic-bezier(.22,1,.36,1); }
@keyframes segmentPuls { 0%,100% { transform: scale(1); } 45% { transform: scale(1.012); } }
/* Pudło - krótkie potrząśnięcie zamiast czerwonego komunikatu na pół ekranu. */
.kartka-segment.aktywny.potrzasnij { animation: segmentPotrzas 0.4s ease; }
@keyframes segmentPotrzas {
  0%,100% { transform: translateX(0); } 20% { transform: translateX(-5px); }
  50% { transform: translateX(4px); } 80% { transform: translateX(-2px); }
}

/* Panel próby rozwija się na WYSOKOŚĆ (grid-template-rows 0fr->1fr), a nie przez display -
   to jedyny sposób, żeby animować pojawienie się elementu o nieznanej wysokości bez
   mierzenia go JS-em. */
.kartka-proba { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.32s cubic-bezier(.22,1,.36,1); }
.kartka-proba > * { overflow: hidden; }
.kartka-proba.otwarty { grid-template-rows: 1fr; }
.kartka-proba-wnetrze { display: flex; flex-direction: column; gap: 4px; padding-top: 2px; }

/* Liczba XP odlatująca w górę od zdania - natychmiastowa informacja zwrotna dokładnie tam,
   gdzie patrzy oko, zamiast tosta w rogu ekranu. */
.xp-lecacy {
  position: fixed; z-index: 3000; pointer-events: none;
  font-weight: 900; font-size: 1.1rem;
  animation: xpLeci 1.1s cubic-bezier(.22,1,.36,1) forwards;
}
.xp-lecacy.plus  { color: var(--zielen-gleboka); }
.xp-lecacy.minus { color: var(--muted-dark); }
@keyframes xpLeci {
  0%   { opacity: 0; transform: translateY(6px) scale(0.85); }
  25%  { opacity: 1; transform: translateY(-6px) scale(1.1); }
  100% { opacity: 0; transform: translateY(-46px) scale(1); }
}

/* Dymek nad zaznaczeniem */
.kartka-dymek { position: fixed; z-index: 2500; transform: translate(-50%, -100%); }
.kartka-dymek button {
  display: flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 999px;
  border: none; cursor: pointer; font-family: inherit; font-size: 0.8rem; font-weight: 700;
  background: var(--testo); color: var(--crema); box-shadow: 0 8px 24px rgba(0,0,0,0.28);
  animation: dymekWjazd 0.22s cubic-bezier(.22,1,.36,1);
}
.kartka-dymek button:hover { filter: brightness(1.15); }
.kartka-dymek .ico { margin-right: 0; }
@keyframes dymekWjazd { from { opacity: 0; transform: translateY(6px) scale(0.9); } to { opacity: 1; transform: none; } }
/* ===== ODSŁUCH TEKSTU ===== */
.odsluch {
  position: sticky; bottom: 12px; z-index: 60; margin-top: 14px;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft); border-radius: 18px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.14); padding: 10px 12px;
  animation: odsluchWjazd 0.35s cubic-bezier(.22,1,.36,1);
}
@keyframes odsluchWjazd { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.odsluch-wiersz { display: flex; align-items: center; gap: 8px; }
/* Lektor jest jedynym głosem w tym trybie, więc jego brak to komunikat, a nie szept w tle:
   mówimy wprost, co jest nie tak i co z tym zrobić. */
.odsluch-blad {
  display: flex; align-items: flex-start; gap: 8px; margin-bottom: 10px;
  padding: 10px 12px; border-radius: 12px; font-size: 0.82rem; font-weight: 600; line-height: 1.5;
  background: var(--bg-info-soft);
  border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent); color: var(--testo);
}
.odsluch-blad .ico { margin: 2px 0 0; color: var(--primary); flex-shrink: 0; }
.odsluch-sprawdz {
  flex-shrink: 0; margin-left: auto; padding: 6px 12px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--primary); background: transparent; color: var(--primary);
  font-family: inherit; font-size: 0.75rem; font-weight: 800; transition: var(--transition);
}
.odsluch-sprawdz:hover { background: var(--primary); color: #fff; }
.odsluch-sprawdz:disabled { opacity: 0.5; cursor: default; }
/* Który głos gra. Kolor niesie tu ocenę jakości, nie ozdobę: zielony = lektor, niebieski =
   zapas Google, czerwony = ostateczność, czyli syntezator przeglądarki. */
.odsluch-glos {
  flex-shrink: 0; padding: 4px 9px; border-radius: 999px;
  font-size: 0.7rem; font-weight: 800; white-space: nowrap;
}
.odsluch-glos.glos-top    { background: color-mix(in srgb, var(--verde) 16%, transparent); color: var(--zielen-gleboka); }
.odsluch-glos.glos-sredni { background: var(--bg-info-soft); color: var(--primary); }
.odsluch-glos.glos-slaby  { background: color-mix(in srgb, var(--rosso) 14%, transparent); color: var(--rosso); }
.odsluch-play {
  width: 46px; height: 46px; flex-shrink: 0; border-radius: 50%; cursor: pointer; border: none;
  background: var(--oro); color: var(--na-akcencie); font-size: 1rem;
  display: inline-flex; align-items: center; justify-content: center; transition: var(--transition);
}
.odsluch-play:hover { transform: scale(1.06); }
.odsluch-play .ico { margin: 0; }
.odsluch-ikona {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  display: inline-flex; align-items: center; justify-content: center; transition: var(--transition);
}
.odsluch-ikona:hover { border-color: var(--oro); color: var(--oro); }
.odsluch-ikona .ico { margin: 0; }
.odsluch-ikona.wl { background: var(--rosso); border-color: var(--rosso); color: #fff; }
.odsluch-tempo { width: auto; padding: 0 10px; font-size: 0.78rem; font-weight: 800; }
.odsluch-tempo-wrap { position: relative; flex-shrink: 0; }
.odsluch-tempo-panel {
  position: absolute; bottom: calc(100% + 10px); right: 0; z-index: 300; width: 210px;
  padding: 12px 14px; border-radius: 14px; background: var(--card-bg);
  border: 1px solid var(--border-warm-soft); box-shadow: var(--shadow-hover);
  font-size: 0.75rem; font-weight: 700; color: var(--grigio);
  animation: dymekWjazd 0.18s cubic-bezier(.22,1,.36,1);
}
.odsluch-tempo-panel input[type=range] { width: 100%; margin: 8px 0 4px; accent-color: var(--oro); }
.odsluch-tempo-skala { display: flex; justify-content: space-between; align-items: center; }
.odsluch-tempo-skala b { color: var(--testo); font-size: 0.85rem; }
.odsluch-srodek { flex: 1; min-width: 0; }
.odsluch-status {
  font-size: 0.82rem; font-weight: 700; margin-bottom: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.odsluch-tor { height: 5px; border-radius: 999px; background: var(--border-2); overflow: hidden; }
.odsluch-fill { height: 100%; width: 0; border-radius: 999px; background: var(--oro); transition: width 0.3s ease; }
.odsluch-check { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; flex-shrink: 0; }
.odsluch-check.zablokowany { opacity: 0.4; cursor: not-allowed; }
.odsluch-check.zablokowany .toggle { pointer-events: none; }
.odsluch-check .ico { margin: 0; color: var(--grigio); }
.odsluch-spacer {
  display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0; cursor: pointer;
  padding: 9px 14px; border-radius: 999px; border: none; font-family: inherit;
  font-size: 0.8rem; font-weight: 800; background: var(--primary); color: #fff;
  transition: var(--transition);
}
.odsluch-spacer:hover { transform: translateY(-1px); }
.odsluch-spacer .ico { margin: 0; }

/* Czytane w tej chwili zdanie - to ono jest "kursorem" podczas słuchania. Samo tło, bez paska
   z boku: zdanie płynie w akapicie i zaczyna się w połowie wiersza, więc nie ma tam krawędzi,
   przy której pasek mógłby stanąć. */
.kartka-segment.czytane {
  background: color-mix(in srgb, var(--primary) 16%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 16%, transparent);
}

/* Pytanie kontrolne. Warianty są duże i wysokie także w wersji na biurko - te same
   przyciski obsługuje się na spacerze kciukiem, więc nie ma dwóch osobnych layoutów. */
.odsluch-pytanie, .spacer-pytanie { animation: odsluchWjazd 0.3s cubic-bezier(.22,1,.36,1); }
.odsluch-pytanie { padding: 4px 4px 12px; border-bottom: 1px solid var(--border-warm-soft); margin-bottom: 10px; }
.ods-pytanie-tresc { font-weight: 800; font-size: 0.95rem; margin-bottom: 10px; }
.ods-pytanie-tresc b { color: var(--primary); }
.ods-opcje { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.ods-opcja {
  display: flex; align-items: center; gap: 10px; text-align: left; cursor: pointer;
  padding: 12px 14px; border-radius: 14px; font-family: inherit; font-size: 0.9rem; font-weight: 700;
  background: var(--card-bg); border: 1px solid var(--border-2); color: var(--testo);
  transition: var(--transition);
}
.ods-opcja:hover { border-color: var(--primary); transform: translateY(-1px); }
.ods-opcja b {
  width: 26px; height: 26px; flex-shrink: 0; border-radius: 50%; font-size: 0.78rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-info-soft); color: var(--primary);
}
.ods-opcja.dobra { border-color: var(--verde); background: color-mix(in srgb, var(--verde) 14%, transparent); }
.ods-opcja.zla   { border-color: var(--rosso); background: color-mix(in srgb, var(--rosso) 12%, transparent); }
.ods-opcja[disabled] { cursor: default; }

/* ===== TRYB SPACEROWY ===== */
.spacer-overlay {
  position: fixed; inset: 0; z-index: 3000; background: var(--crema); color: var(--testo);
  display: flex; flex-direction: column; padding: 16px;
  /* dvh, nie vh - pasek adresu na telefonie inaczej przycina dolne sterowanie. */
  height: 100dvh;
  animation: spacerWjazd 0.3s cubic-bezier(.22,1,.36,1);
}
@keyframes spacerWjazd { from { opacity: 0; transform: scale(0.98); } to { opacity: 1; transform: none; } }
.spacer-gora { display: flex; align-items: center; gap: 12px; }
.spacer-tytul { flex: 1; min-width: 0; font-weight: 800; font-size: 0.9rem;
                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spacer-srodek {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; text-align: center; padding: 20px 6px; min-height: 0; overflow-y: auto;
}
/* Litery w spacerze są DUŻE, bo ekran ogląda się z wyciągniętej ręki, w ruchu i często
   w słońcu - a zwykle tylko przez sekundę, żeby zerknąć, co leci. */
.spacer-zdanie { font-size: 2.3rem; font-weight: 800; line-height: 1.3; }
.spacer-tlum { font-size: 1.5rem; }
.spacer-overlay.slowko .spacer-zdanie { font-size: 3.2rem; color: var(--primary); line-height: 1.15; }
.spacer-overlay.slowko .spacer-tlum { font-size: 2rem; font-weight: 700; }
@media (max-width: 560px) {
  .spacer-zdanie { font-size: 1.9rem; }
  .spacer-tlum { font-size: 1.25rem; }
  .spacer-overlay.slowko .spacer-zdanie { font-size: 2.5rem; }
  .spacer-overlay.slowko .spacer-tlum { font-size: 1.6rem; }
}
.spacer-tlum { font-size: 1rem; color: var(--grigio); line-height: 1.5; }
/* Gdy leci pytanie, znika treść zdania: na spacerze liczy się jedna rzecz naraz, a cztery
   warianty mają być największym elementem na ekranie, żeby trafić w nie bez patrzenia. */
.spacer-overlay.pytanie .spacer-srodek { display: none; }
.spacer-pytanie { padding: 10px 0 16px; }
/* Cztery warianty na krzyż, każdy ćwiartką ekranu. Na spacerze celuje się kciukiem, nie
   patrząc - a wtedy liczy się wielkość pola, nie elegancja listy. */
.spacer-overlay.pytanie .spacer-pytanie { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.spacer-pytanie .ods-pytanie-tresc {
  font-size: 1.6rem; text-align: center; margin-bottom: 14px; line-height: 1.3;
}
.spacer-overlay.pytanie .ods-opcje {
  flex: 1; min-height: 0;
  grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 10px;
}
.spacer-pytanie .ods-opcja {
  height: 100%; padding: 14px 12px; font-size: 1.3rem; line-height: 1.3; font-weight: 800;
  flex-direction: column; justify-content: center; text-align: center; gap: 10px;
}
.spacer-pytanie .ods-opcja b { width: 42px; height: 42px; font-size: 1.15rem; }
@media (max-width: 560px) {
  .spacer-pytanie .ods-pytanie-tresc { font-size: 1.3rem; }
  .spacer-pytanie .ods-opcja { font-size: 1.1rem; padding: 10px 8px; }
}
.spacer-dol { display: flex; flex-direction: column; gap: 14px; }
.spacer-sterowanie { display: flex; align-items: center; justify-content: center; gap: 24px; }
.spacer-btn {
  width: 64px; height: 64px; border-radius: 50%; cursor: pointer; font-size: 1.2rem;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  display: inline-flex; align-items: center; justify-content: center; transition: var(--transition);
}
.spacer-btn .ico { margin: 0; }
.spacer-btn-duzy { width: 88px; height: 88px; border: none; background: var(--oro); color: var(--na-akcencie); font-size: 1.6rem; }
.spacer-btn:active { transform: scale(0.94); }
.spacer-podpis { text-align: center; font-size: 0.95rem; font-weight: 700; color: var(--grigio); }
.spacer-overlay.slucha .spacer-podpis { color: var(--rosso); font-weight: 800; }

/* Telefon: osiem kontrolek w jednym rzędzie nie mieści się na 375 px - pasek łamie się
   na dwa. Górny wiersz to odtwarzanie i postęp (to, na co się patrzy), dolny to reszta.
   Kolejność ustawiamy przez order, bo w HTML przewijanie stoi przed opisem. */
@media (max-width: 560px) {
  .odsluch-wiersz { flex-wrap: wrap; row-gap: 10px; justify-content: center; }
  .odsluch-play { order: 0; }
  .odsluch-srodek { order: 1; flex: 1 1 180px; }
  .odsluch-wiersz > :not(.odsluch-play):not(.odsluch-srodek) { order: 2; }
  .odsluch-spacer span { display: none; }
  .odsluch-spacer { padding: 9px 12px; }
  .ods-opcje { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .odsluch, .odsluch-pytanie, .spacer-pytanie, .spacer-overlay { animation: none; }
}

/* --- Znane słówka: tło wg poziomu z talii ---
   Ta sama konwencja co ramka fiszki i kropki w statystykach: łatwe zielone, średnie
   niebieskie, trudne czerwone. Tło jest CELOWO bardzo rozrzedzone - ma podpowiadać
   w tle czytania, a nie przykrywać tekst. "Nowe" i słowa spoza talii zostają bez koloru:
   kolorowanie wszystkiego zamieniłoby zdanie w tęczę i nic by z niej nie wynikało. */
.znane-slowo { border-radius: 4px; padding: 1px 2px; }
.znane-slowo.p-latwe   { background: color-mix(in srgb, var(--chart-latwe) 22%, transparent); }
.znane-slowo.p-srednie { background: color-mix(in srgb, var(--primary) 20%, transparent); }
.znane-slowo.p-trudne  { background: color-mix(in srgb, var(--rosso) 20%, transparent); }

/* --- Auto-podpowiedzi: fraza pod kursorem --- */
.kartka-fraza { border-radius: 4px; padding: 0 1px; transition: background 0.15s ease; }
.kartka-segment.auto .kartka-fraza { cursor: help; }
.kartka-segment.auto .kartka-fraza:hover { background: color-mix(in srgb, var(--primary) 20%, transparent); }
/* Dymek jedzie za kursorem, więc musi być position:fixed i poza przepływem zdania -
   wstawiony do środka zawijałby wiersz i tekst skakałby przy każdym najechaniu. */
.fraza-dymek {
  position: fixed; z-index: 2600; transform: translate(-50%, -100%); pointer-events: none;
  padding: 6px 12px; border-radius: 10px; white-space: nowrap;
  background: var(--testo); color: var(--crema); font-size: 0.82rem; font-weight: 700;
  box-shadow: 0 6px 20px rgba(0,0,0,0.26);
  animation: dymekWjazd 0.14s ease;
}
.kartka-przelacznik.zablokowany { opacity: 0.45; cursor: not-allowed; }
.kartka-przelacznik.zablokowany .toggle { pointer-events: none; }

/* ===== AUTO-PODPOWIEDZI: przełącznik z rozwijanym wyborem trybu ===== */
.kartka-auto { position: relative; }
.kartka-auto-etykieta { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
/* Zablokowany jest sam PRZEŁĄCZNIK, a nie cała kontrolka: gdy w tekście nic jeszcze nie jest
   zrobione, to właśnie w strzałce stoi jedyny tryb, który cokolwiek pokaże - zgaszenie jej
   razem z resztą chowałoby wyjście przed osobą, która go akurat szuka. Opacity rodzica
   przygasza całe poddrzewo, więc gasimy wybiórczo dzieci. */
.kartka-auto.zablokowany { opacity: 1; }
.kartka-auto.zablokowany .kartka-auto-etykieta,
.kartka-auto.zablokowany .toggle { opacity: 0.45; }
.kartka-auto-strzalka {
  border: none; background: transparent; cursor: pointer; padding: 0 2px;
  font: inherit; font-size: 0.8rem; line-height: 1; color: var(--grigio);
  border-radius: 6px; transition: var(--transition);
}
.kartka-auto-strzalka:hover { color: var(--oro); background: var(--bg-highlight); }
.kartka-auto-menu { top: calc(100% + 6px); left: auto; right: 0; min-width: 268px; }
.kartka-auto-menu .mode-tab-item small { line-height: 1.45; white-space: normal; }
/* Tekst już prześwietlony - mówimy to przy samym przełączniku, a nie tylko w okienku, które
   zamknęło się dawno temu. Kolor ostrzegawczy, bo to informacja o utraconych punktach. */
/* Odznaka rangi w ustawieniach - ten sam element co w profilu, tylko z podpisem obok,
   bo w ustawieniach nie ma wokół niej całego widgetu twórcy, który by ją tłumaczył. */
.settings-ranga { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.settings-ranga-opis { font-size: 0.8rem; color: var(--grigio); font-weight: 600; }

/* Nota o zgodzie przy akcjach o skutku prawnym - publikacja materiału i zgłoszenie
   naruszenia. Drobna, ale NIE ukryta: to jedyne miejsce, w którym ktoś niezalogowany do tej
   pory tylko przeglądający dowiaduje się, że właśnie coś oświadcza. */
.naruszenie-zgoda, .pochodzenie-zgoda {
  display: block; font-size: 0.72rem; line-height: 1.5; color: var(--muted-light);
  margin: 0 0 12px; text-align: center;
}
.pochodzenie-zgoda { margin: 0; text-align: left; flex-basis: 100%; }
.naruszenie-zgoda a, .pochodzenie-zgoda a { color: var(--grigio); font-weight: 600; }

/* ===== STOPKA PRAWNA ===== */
.app-stopka {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 16px;
  padding: 22px 20px 26px; margin-top: 28px;
  border-top: 1px solid var(--border);
  font-size: 0.74rem; color: var(--muted-light); text-align: center;
}
.app-stopka a { color: var(--grigio); text-decoration: none; font-weight: 600; }
.app-stopka a:hover { color: var(--oro); text-decoration: underline; }
/* Znak własności w osobnym wierszu (flex-basis:100%), pod odnośnikami. Wciśnięty między nie
   ginąłby jako czwarty link, a to jedyne zdanie w stopce, które ma być zauważone od razu -
   stąd też mocniejszy kolor niż reszta. Rok liczy PHP: wpisany na sztywno zestarzeje się
   dokładnie 1 stycznia i nikt tego nie zauważy. */
.app-stopka-marka {
  flex-basis: 100%; margin-top: 2px;
  color: var(--grigio); font-weight: 700;
}
/* Wewnątrz tablicy Społeczności stopka jedzie razem z jej przewijaniem, więc nie potrzebuje
   własnego marginesu od góry - nakładka ma już swój padding na dole. */
.community-full .app-stopka { margin-top: 8px; padding-bottom: 8px; }

/* ===== ZGŁOSZENIE NARUSZENIA ===== */
/* Napis, nie przycisk: ma być do znalezienia, gdy ktoś go szuka, i cichy przez resztę czasu. */
.cmty-zglos {
  display: inline-flex; align-items: center; gap: 6px; margin: 10px auto 0;
  border: none; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 0.7rem; font-weight: 600; color: var(--muted-light);
  padding: 4px 8px; border-radius: 8px; transition: var(--transition);
}
.cmty-zglos:hover { color: var(--rosso); background: var(--bg-error-soft); }
a.cmty-zglos { text-decoration: none; }   /* gość: link do formularza bez konta (zglosLinkHtml) */
.cmty-zglos .ico { margin-right: 0; font-size: 0.78rem; }
.community-detail-panel .cmty-zglos { display: flex; }
/* Na kafelku napis stoi w nakładce, pod rzędem akcji - w jednym wierszu z nimi robiłby się
   czwartym przyciskiem obok „Zapisz", a nie jest akcją tej samej wagi. */
.community-tile .cmty-zglos { margin: 4px 0 0; font-size: 0.64rem; padding: 2px 6px; }

.naruszenie-lista { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.naruszenie-poz {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; text-align: left;
  border: 1px solid var(--border); border-radius: 11px; background: var(--card-bg);
  font-family: inherit; font-size: 0.85rem; font-weight: 600; color: var(--testo);
  cursor: pointer; transition: var(--transition);
}
.naruszenie-poz:hover { border-color: var(--oro); background: var(--bg-highlight); }
.naruszenie-poz.wybrany { border-color: var(--rosso); background: var(--bg-error-soft); color: var(--rosso); }
.naruszenie-poz .ico { margin-right: 0; }
.naruszenie-opis { margin-bottom: 14px; }
.naruszenie-opis input {
  width: 100%; padding: 11px 13px; border-radius: 11px;
  border: 1px solid var(--border-2); background: var(--crema);
  color: var(--testo); font-family: inherit; font-size: 0.88rem;
}

/* Licznik przy „Do weryfikacji" (kolejka moderatora). Puls jest CELOWO ledwie widoczny:
   ma przyciągnąć wzrok przy przewijaniu listy, a nie migać w kącie ekranu przez cały dzień. */
.cmty-licznik {
  display: inline-flex; align-items: center; justify-content: center; min-width: 21px;
  height: 21px; padding: 0 6px; margin-left: auto; border-radius: 999px;
  background: var(--verde); color: #fff; font-size: 0.68rem; font-weight: 800;
  animation: licznikPuls 2.6s ease-in-out infinite;
}
@keyframes licznikPuls {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--verde) 55%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--verde) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .cmty-licznik { animation: none; } }
.cmty-kategoria { position: relative; }

/* Kafelek zgłoszonego materiału w kolejce moderatora - czerwona ramka odróżnia go od
   zgłoszeń czekających na wpuszczenie: tu materiał JEST na tablicy i właśnie z niej zniknął. */
.community-tile.naruszenie { border: 2px solid var(--rosso); }
.naruszenie-plakietka {
  position: absolute; top: 8px; left: 8px; z-index: 3;
  background: var(--rosso); color: #fff; border-radius: 999px;
  padding: 3px 9px; font-size: 0.68rem; font-weight: 800;
}
.naruszenie-powody { display: block; font-size: 0.7rem; opacity: 0.9; margin-top: 2px; }
/* Zgłoszenia z formularza bez konta: rozwijane pod tytułem, bo wyjaśnienie bywa długie, a dane
   zgłaszającego (nazwa, e-mail) są potrzebne dopiero przy decyzji. Plakietka „ukryty” mówi, że materiał już zniknął. */
.naruszenie-formularz { display: block; margin-top: 4px; font-size: 0.7rem; text-align: start; }
.naruszenie-formularz summary { cursor: pointer; font-weight: 700; }
.naruszenie-formularz p { margin: 3px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 9em; overflow: auto; }
.naruszenie-ukryty { display: inline-block; margin-top: 3px; padding: 1px 8px; border-radius: 999px; font-size: 0.66rem; font-weight: 800;
  background: var(--oro); color: var(--na-akcencie); }

/* ===== STOPIEŃ PISMA NA KARTCE ===== */
.kartka-pismo-btn {
  border: none; background: transparent; cursor: pointer; padding: 2px 5px;
  font-family: inherit; font-weight: 800; font-size: 0.8rem; line-height: 1;
  color: var(--grigio); border-radius: 7px; transition: var(--transition);
}
.kartka-pismo-btn:hover:not([disabled]) { color: var(--oro); background: var(--bg-highlight); }
.kartka-pismo-btn[disabled] { opacity: 0.35; cursor: default; }
.kartka-pismo-ile { min-width: 16px; text-align: center; font-variant-numeric: tabular-nums; }

.kartka-auto-znacznik {
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px; line-height: 1.6;
  background: var(--bg-warn-soft); color: var(--muted-dark);
}
/* Rozpoznanie słów i wyrównanie fraz to przebieg AI - kilka sekund, w których nic się nie
   dzieje. Bez widocznego kręcioła wygląda to jak martwy przełącznik i klika się go drugi raz. */
.kartka-przelacznik.pracuje { opacity: 0.75; }
.kartka-przelacznik .spinner-maly {
  width: 13px; height: 13px; flex-shrink: 0; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--oro) 30%, transparent); border-top-color: var(--oro);
  animation: obrot 0.7s linear infinite;
}
@keyframes obrot { to { transform: rotate(360deg); } }

/* Przetłumaczony fragment podświetlony w zdaniu - zostaje widoczny po zamknięciu dymka.
   Idzie w wierszu, zaraz za zdaniem, jak dopisek na marginesie. */
.frag-tlumaczenie {
  font-size: 0.8rem; font-weight: 600; color: var(--primary); margin-left: 6px;
  animation: segmentWjazd 0.3s cubic-bezier(.22,1,.36,1);
}

/* --- Przełączniki nad kartką --- */
/* Każdy przełącznik jest osobnym KAFELKIEM z ramką, a suwak stoi na jego końcu.
   Wcześniej był to rząd luźnych par "suwak + podpis": przy zawijaniu suwak jednego
   przełącznika lądował tuż obok podpisu poprzedniego i nie dało się odczytać, co jest czym.
   Ramka zamyka parę w całość, a włączony stan widać po całym kafelku, nie po samym suwaku. */
.kartka-przelaczniki { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.kartka-przelacznik {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 7px 8px 7px 13px; border-radius: 999px;
  /* Tło przezroczyste i cieńsza ramka: siedem kafelków w pełnym kontraście stało nad kartką
     jak pasek narzędzi i przykrywało to, po co się tu przychodzi. Włączony przełącznik dalej
     świeci złotem, więc stan widać tak samo dobrze, tylko ciszej. */
  border: 1px solid var(--border); background: transparent;
  font-size: 0.78rem; font-weight: 700; color: var(--grigio);
  transition: var(--transition);
}
.kartka-przelacznik:hover { color: var(--testo); border-color: var(--oro); background: var(--card-bg); }
.kartka-przelacznik .ico { margin-right: 0; font-size: 0.95rem; }
/* Suwak w wersji mini - własne wymiary zamiast transform:scale, bo skalowanie zostawia
   po sobie pustą przestrzeń starego rozmiaru i kafelek robi się dziurawy. */
.kartka-przelacznik .toggle { width: 34px; height: 19px; }
.kartka-przelacznik .toggle-slider::before { width: 13px; height: 13px; }
.kartka-przelacznik .toggle input:checked + .toggle-slider::before { transform: translateX(15px); }
.kartka-przelacznik:has(input:checked) {
  color: var(--testo); border-color: var(--oro);
  background: color-mix(in srgb, var(--oro) 10%, transparent);
}

/* --- Okrągłe przyciski w pasku kartki --- */
.kartka-ikona {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  font-size: 0.95rem; line-height: 1; transition: var(--transition);
}
.kartka-ikona:hover { border-color: var(--oro); color: var(--oro); }
/* Nie ma czego dodać - przycisk ma to POKAZAĆ, zanim ktoś go naciśnie. Wcześniej wyglądał
   tak samo zawsze i jedyną odpowiedzią na kliknięcie był komunikat po długim czekaniu. */
.kartka-ikona.zablokowany { opacity: 0.4; cursor: not-allowed; }
.kartka-ikona.zablokowany:hover { border-color: var(--border-warm); color: inherit; }
/* --- Kartka jako pole do pisania --- */
.kartka-edycja { position: relative; padding: 0; }
.kartka-textarea {
  /* Wysokość ustawia JS (dopasujWysokoscTekstu) - stąd resize:none i overflow:hidden:
     kartka ma sama urosnąć do wklejonego tekstu, a nie chować go w pasku przewijania.
     Przejście na height działa tylko między dwiema wartościami w px, więc JS nigdy nie
     zostawia tu "auto". */
  width: 100%; min-height: 300px; height: 300px; resize: none; overflow: hidden;
  transition: height 0.5s cubic-bezier(.22,1,.36,1);
  border: none; outline: none;
  background: transparent; color: var(--testo);
  font-family: inherit; font-size: 1.02rem; font-weight: 600;
  /* line-height równy krokowi kratki (26 px) - tekst siada NA liniach zamiast pływać
     losowo między nimi, i o to w kartce chodzi. */
  line-height: 26px; padding: 34px 30px 34px 66px;
}
.kartka-textarea::placeholder { color: var(--muted-light); font-weight: 500; }
@media (max-width: 768px) {
  /* Kartka na telefonie ma węższy margines (linia na 30 px), więc pole musi zejść razem z nią
     - inaczej pisze się 36 px za linią, a po przetworzeniu tekst wraca pod nią i wygląda,
     jakby przeskoczył. */
  .kartka-textarea { padding: 22px 16px 22px 44px; font-size: 0.98rem; }
}
/* "Wossh" przy wklejeniu: kartka na moment jaśnieje i odbija się w skali, żeby było widać,
   że tekst wpadł na papier - samo urośnięcie pola bywa niezauważalne przy krótkim tekście. */
.kartka-edycja.wossh { animation: kartkaWossh 0.6s cubic-bezier(.22,1,.36,1); }
@keyframes kartkaWossh {
  0%   { transform: scale(0.985); box-shadow: 0 0 0 0 color-mix(in srgb, var(--oro) 45%, transparent); }
  55%  { transform: scale(1.006); box-shadow: 0 0 0 10px color-mix(in srgb, var(--oro) 0%, transparent); }
  100% { transform: none; box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .kartka-textarea { transition: none; }
  .kartka-edycja.wossh { animation: none; }
}
.kartka-drop-nakladka {
  position: absolute; inset: 0; border-radius: 16px; display: none;
  align-items: center; justify-content: center; gap: 10px; flex-direction: column;
  background: color-mix(in srgb, var(--oro) 12%, var(--card-bg));
  border: 2px dashed var(--oro); color: var(--oro); font-weight: 800; font-size: 0.9rem;
}
.kartka-drop-nakladka .ico { font-size: 1.8rem; margin-right: 0; }
.kartka-edycja.przeciaganie .kartka-drop-nakladka { display: flex; animation: dymekWjazd 0.18s ease; }

.tekst-narzedzia { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 14px; }
.tekst-narzedzie {
  display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  font-family: inherit; font-size: 0.78rem; font-weight: 700; cursor: pointer;
  transition: var(--transition);
}
.tekst-narzedzie:hover { border-color: var(--oro); color: var(--oro); transform: translateY(-1px); }
.tekst-narzedzie .ico { margin-right: 0; }
.tekst-narzedzie[disabled] { opacity: 0.6; cursor: default; transform: none; }
.tekst-narzedzia .tekst-licznik { margin: 0 0 0 auto; }

/* Znacznik funkcji w budowie. Stoi PRZY przycisku, a nie w osobnym komunikacie nad
   formularzem: ostrzeżenie ma być tam, gdzie zapada decyzja o kliknięciu. Kolor ostrzegawczy,
   nie akcentowy - to nie jest nowość do wypróbowania, tylko zastrzeżenie, że bywa nierówne. */
.znacznik-beta {
  font-size: 0.58rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 999px; line-height: 1.5;
  background: var(--bg-warn-soft); color: var(--muted-dark);
}

/* Pełny ekran w trybie Tekstów korzysta z gotowego body.focus-mode (chowa boczny panel
   i nagłówek), ale kartce dokładamy szerokości - to jedyna treść na ekranie. */
body.focus-mode #widokTekstow .kartka,
body.focus-mode #widokTekstow .kartka-pasek,
body.focus-mode #widokTekstow .kartka-przelaczniki,
body.focus-mode #widokTekstow .kartka-postep,
body.focus-mode #widokTekstow .kartka-stopka,
body.focus-mode #widokTekstow .odsluch { max-width: 900px; margin-left: auto; margin-right: auto; }
body.focus-mode #widokTekstow .kartka { padding: 44px 44px 44px 60px; }
/* Kartka ma tu większy padding, więc akapit dokłada tylko resztę do 66 px od jej krawędzi. */
body.focus-mode #widokTekstow .kartka-akapit { padding-left: 6px; }
/* Na telefonie pełny ekran nie zmienia proporcji kartki - czerwony margines stoi tam na 30 px
   i szeroki padding z biurka odsunąłby od niego tekst o pół ekranu. */
@media (max-width: 768px) {
  body.focus-mode #widokTekstow .kartka { padding: 22px 16px; }
  body.focus-mode #widokTekstow .kartka-akapit { padding-left: 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .kartka-akapit, .kartka-segment.blysk, .kartka-segment.aktywny.puls,
  .kartka-segment.aktywny.potrzasnij,
  .kartka-dymek button, .frag-tlumaczenie { animation: none; }
  .kartka-proba { transition: none; }
  .xp-lecacy { animation: xpLeci 0.6s linear forwards; }
  .tekst-narzedzie:hover { transform: none; }
}

/* ===== PANEL ADMINISTRACYJNY ===== */
.admin-log-box { max-height: 220px; overflow-y: auto; background: var(--crema); border-radius: 8px; padding: 10px 14px; }
.admin-log-line { font-size: 0.8rem; padding: 6px 0; border-bottom: 1px dashed var(--border); }
.admin-log-line:last-child { border-bottom: none; }
.admin-user-stats { font-size: 0.8rem; color: var(--muted-dark); font-weight: 700; }
.admin-user-stats .live-dot { color: #16A34A; }

/* ===== PRZEGLĄD SŁÓWEK ZE ZDJĘCIA =====
   Od 2026-10-08 lista to paletka fiszek (.paletka-*, sekcja SŁÓWKA ZE ZDJĘCIA W PALETCE FISZEK); dawne wiersze z krzyżykiem
   (.photo-review-row i reszta) zeszły razem z oknem. Zostały notki, które stoją w części pod kaflami (.paletka-dodatki.pod). */
.photo-review-skipped { font-size: 0.8rem; color: var(--grigio); margin-bottom: 10px; }
.photo-review-silnik { font-size: 0.8rem; color: var(--grigio); margin: -4px 0 10px; line-height: 1.45; }
/* WERSJE JĘZYKOWE KAMPANII.
   Lista, a nie siatka kafelków: przy dwudziestu czterech językach kafelki dają ścianę,
   z której nie da się wyłowić tego jednego, który wygląda podejrzanie. Wiersz z nazwą,
   liczbą odbiorców i stanem czyta się z góry na dół. */
.kamp-tlum { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-warm); }
.kamp-tlum-gora { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.kamp-tlum-gora strong { font-size: 0.82rem; margin-right: auto; }
.kamp-tlum-wszystkie { display: inline-flex; align-items: center; gap: 5px; font-size: 0.72rem; color: var(--grigio); cursor: pointer; }
.kamp-tlum-wiersz {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 8px;
  font-size: 0.76rem; border-bottom: 1px solid var(--border-warm);
}
.kamp-tlum-wiersz:hover { background: var(--bg-soft); }
.kamp-tlum-nazwa { font-weight: 700; min-width: 96px; }
.kamp-tlum-ilu { color: var(--grigio); font-size: 0.7rem; min-width: 58px; }
.kamp-tlum-temat {
  flex: 1; min-width: 0; color: var(--grigio);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kamp-tlum-stan { font-size: 0.68rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.kamp-tlum-stan.jest { background: var(--bg-success-soft); color: var(--verde); }
.kamp-tlum-stan.brak { background: var(--border-warm-soft); color: var(--grigio); }
.kamp-tlum-stan.zle  { background: var(--bg-error-soft); color: var(--rosso); }
.kamp-tlum-edytor { padding: 10px 8px 14px; background: var(--bg-soft); border-radius: 10px; margin: 6px 0 10px; }
.kamp-tlum-edytor input, .kamp-tlum-edytor textarea { width: 100%; box-sizing: border-box; margin-bottom: 6px; }
.kamp-tlum-edytor textarea { min-height: 110px; resize: vertical; }
.admin-campaign-vars { font-size: 0.72rem; color: var(--muted-light); margin: 0 0 10px; line-height: 1.5; }
.admin-campaign-item {
  padding: 10px 12px; border-radius: 8px; background: var(--crema); border: 1px solid var(--border);
  margin-bottom: 8px; font-size: 0.82rem; cursor: pointer; transition: var(--transition);
}
.admin-campaign-item:hover { background: var(--bg-soft); }
.admin-campaign-item .name { font-weight: 800; }
.admin-campaign-item .meta { color: var(--grigio); font-size: 0.72rem; margin-top: 2px; }
.admin-campaign-actions { display: flex; gap: 6px; margin-top: 8px; }
.admin-campaign-actions button { width: auto; margin: 0; padding: 5px 10px; font-size: 0.72rem; }

/* ===== REGUŁY POWIADOMIEŃ AUTOMATYCZNYCH =====
   Każda reguła to jedno pudełko: włącznik, warunek, temat, treść, podgląd. Wszystko obok
   siebie, bo to jedna decyzja - „co i kiedy dostanie użytkownik" - a nie pięć osobnych
   ustawień rozrzuconych po formularzu. */
.regula-mail {
  border: 1px solid var(--border); border-radius: 10px; background: var(--crema);
  padding: 12px 14px; margin-bottom: 12px;
}
.regula-gora { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.regula-nazwa { font-weight: 800; font-size: 0.9rem; }
/* Włącznik stoi PIERWSZY, przed nazwą: przy trzech regułach najczęstszą operacją jest
   sprawdzenie, która z nich w ogóle działa - a tego szuka się wzrokiem w jednej kolumnie. */
.regula-wlacznik {
  display: flex; align-items: center; gap: 6px; font-size: 0.72rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; white-space: nowrap;
}
.regula-warunek {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.76rem; color: var(--grigio); margin-bottom: 10px;
}
.regula-zmienne { display: flex; flex-wrap: wrap; gap: 5px; margin: 8px 0 10px; }
.regula-zmienna {
  border: 1px solid var(--border); background: var(--bg-soft); color: var(--muted-dark);
  border-radius: 999px; padding: 3px 9px; font-size: 0.7rem; font-weight: 700;
  cursor: pointer; width: auto; margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.regula-zmienna:hover { background: var(--crema); color: var(--testo); }
.regula-podglad { margin-top: 10px; }
.regula-podglad-temat { font-size: 0.76rem; color: var(--grigio); margin-bottom: 6px; }
/* Ramka ma stałą wysokość i własne przewijanie: mail bywa dłuższy niż ekran, a rosnący
   podgląd spychałby przy każdej literze wszystko, co jest pod nim. */
.regula-podglad-ramka {
  width: 100%; height: 360px; border: 1px solid var(--border); border-radius: 8px;
  background: #F4F6FA; display: block;
}

/* ===== KATALOG MAILI (zakładka Maile → „Wszystkie maile") =====
   Jedna karta na każdy mail, jaki aplikacja wysyła. Karta odpowiada na trzy pytania, ZANIM
   ktokolwiek cokolwiek kliknie: KIEDY wychodzi, DO KOGO i CZY w ogóle chodzi (liczby z logu).
   Dopiero pod spodem stoją przyciski. Wcześniej edytor treści siedział na dole karty „Historia
   wysyłek", a próbka w osobnej ramce z listą rozwijaną - trzeba było wiedzieć, że tam są. */
.mk-pasek { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.mk-kpi { background: var(--bianco); border: 1px solid var(--border); border-left: 4px solid #0EA5E9;
  border-radius: 8px; padding: 8px 12px; font-size: 0.72rem; color: var(--grigio); min-width: 140px; flex: 1; }
.mk-kpi b { display: block; font-size: 1.05rem; color: var(--testo); font-variant-numeric: tabular-nums; margin: 2px 0; }
.mk-kpi-o { display: block; color: var(--muted-light); font-size: 0.66rem; }
.mk-filtry { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 12px; }
.mk-filtry > span { display: contents; }
.mk-chip { border: 1px solid var(--border); background: var(--bg-soft); color: var(--muted-dark);
  border-radius: 999px; padding: 4px 11px; font-size: 0.72rem; font-weight: 700; cursor: pointer; width: auto; margin: 0; }
.mk-chip:hover { color: var(--testo); }
.mk-chip.akt { background: var(--testo); color: var(--bianco); border-color: var(--testo); }
.mk-szukaj { margin-left: auto; min-width: 220px; }
.mk-grupa-tytul { font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--grigio); margin: 18px 0 4px; }
.mk-grupa-opis { font-size: 0.74rem; color: var(--grigio); margin: 0 0 8px; line-height: 1.5; }
.mk-karta { border: 1px solid var(--border); border-radius: 10px; background: var(--bianco); padding: 12px 14px; margin-bottom: 10px; }
/* Wyłączony mail zostaje na liście (treść i statystyki są dalej potrzebne), ale ma wyglądać
   na wyłączony z drugiego końca pokoju - stąd przerywana ramka i przygaszenie. */
.mk-karta.wylaczony { border-style: dashed; opacity: 0.75; }
.mk-karta.mk-inne { background: var(--crema); }
.mk-gora { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.mk-ikona { font-size: 1.05rem; line-height: 1; }
.mk-nazwa { font-weight: 800; font-size: 0.92rem; }
.mk-rodzaj { font-size: 0.68rem; color: var(--muted-light); background: var(--bg-soft); padding: 1px 6px; border-radius: 5px; }
.mk-znacznik { font-size: 0.66rem; font-weight: 800; border-radius: 999px; padding: 2px 8px;
  background: var(--bg-soft); color: var(--muted-dark); white-space: nowrap; }
.mk-znacznik.zielony  { background: var(--bg-success-soft); color: var(--verde); }
.mk-znacznik.czerwony { background: var(--bg-error-soft2); color: var(--rosso); }
.mk-znacznik.zloty    { background: var(--bg-info-soft); color: var(--oro); }
.mk-znacznik.szary    { background: var(--border); color: var(--muted-dark); }
.mk-wlacznik { display: flex; align-items: center; gap: 5px; font-size: 0.7rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; white-space: nowrap; margin-left: auto; }
.mk-opis { font-size: 0.78rem; line-height: 1.55; color: var(--testo); margin: 2px 0; }
.mk-opis b { color: var(--grigio); font-weight: 800; margin-right: 3px; }
.mk-zrodlo code { font-size: 0.7rem; color: var(--muted-dark); }
.mk-meta { font-size: 0.7rem; color: var(--grigio); margin: 6px 0 8px; display: flex; flex-wrap: wrap; gap: 3px 14px; }
.mk-meta b { color: var(--testo); font-variant-numeric: tabular-nums; }
.mk-blad, .mk-blad b { color: var(--rosso); }
.mk-akcje { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.mk-akcje .admin-in { padding: 5px 8px; font-size: 0.74rem; }
.mk-akcje [data-mk="adres"] { flex: 1; min-width: 200px; }
.mk-rozwin { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px;
  margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border); }
.mk-rozwin.jedna { grid-template-columns: 1fr; }
@media (max-width: 960px) { .mk-rozwin { grid-template-columns: 1fr; } }

/* ===== PANEL ADMINA: SUROWE DUŻE OKNO =====
   Świadomie wychodzi z „gierkowej" stylistyki reszty aplikacji: chłodna paleta, gęste
   tabele, liczby tabularne. To narzędzie robocze, w którym liczy się gęstość informacji,
   a nie zaokrąglone kafelki. */
.admin-shell {
  /* Cała strona, bez marginesów i bez ograniczenia szerokości. Konsola to nie okno dialogowe,
     tylko narzędzie pracy: tabele płatności i tokenów mają kilkanaście kolumn, a pusty pas
     po bokach kosztował dokładnie tyle miejsca, ile brakowało im na ekranie. */
  width: 100vw; height: 100vh;
  background: var(--crema); color: var(--testo);
  border-radius: 0; overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: 0 30px 90px rgba(0,0,0,0.45);
  font-family: 'Nunito', system-ui, sans-serif;
}
.admin-topbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  /* Celowo NIE var(--testo)/var(--crema): ten pasek ma zawsze wyglądać jak ciemny "titlebar"
     konsoli administracyjnej, niezależnie od jasny/ciemny appki - --testo w trybie ciemnym
     robi się jasny (bo to zwykle kolor TEKSTU), więc jako tło zamieniał ten pasek w białą,
     rażącą belkę. Literalne kolory = zawsze to samo, w obu motywach. */
  padding: 12px 18px; background: #0F172A; color: #F8FAFC;
}
.admin-topbar h2 { font-size: 1rem; font-weight: 800; margin: 0; letter-spacing: 0.02em; }
.admin-topbar .admin-env {
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  background: rgba(248,250,252,0.14); padding: 3px 8px; border-radius: 5px;
}
.admin-topbar .spacer { flex: 1; }
.admin-topbar .wordmap-close { color: #F8FAFC; background: rgba(248,250,252,0.12); }

/* Pasek filtru dat - wspólny dla pulpitu i płatności, żeby „okres" znaczył wszędzie to samo */
.admin-daterange { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 0.76rem; }
.admin-daterange input[type="date"] {
  padding: 5px 8px; border-radius: 6px; border: 1px solid #334155;
  background: #1E293B; color: #F8FAFC; font-family: inherit; font-size: 0.76rem;
  color-scheme: dark; /* natywna ikonka kalendarza w przeglądarce też ma być jasna na tym ciemnym polu */
}
.admin-quick {
  border: 1px solid #334155; background: #1E293B; color: #CBD5E1;
  border-radius: 6px; padding: 5px 10px; font-family: inherit;
  font-size: 0.72rem; font-weight: 700; cursor: pointer; transition: var(--transition);
}
.admin-quick:hover { background: #334155; color: var(--bianco); }
.admin-quick.active { background: #38BDF8; border-color: #38BDF8; color: var(--testo); }

/* ===== REGULACJA WAG (konsola admina) ===== */
.wagi-uklad { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .wagi-uklad { grid-template-columns: 1fr; } }
.wagi-naglowek {
  margin: 16px 0 8px; font-size: 0.74rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--grigio);
}
.wagi-naglowek:first-child { margin-top: 0; }
.wagi-suwak { margin-bottom: 11px; }
.wagi-suwak label { display: flex; justify-content: space-between; gap: 10px; font-size: 0.78rem; margin-bottom: 3px; }
.wagi-suwak label b { font-variant-numeric: tabular-nums; }
.wagi-suwak input[type=range] { width: 100%; accent-color: var(--verde); }
.wagi-suwak .wagi-opis { font-size: 0.68rem; color: var(--grigio); line-height: 1.4; margin-top: 2px; }

/* Tabela symulacji: kolumna "w talii" stoi obok "w pytaniach" nie dla ozdoby - różnica
   między nimi JEST odpowiedzią na pytanie, po które się tu przychodzi. */
.wagi-tab { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.wagi-tab th {
  text-align: right; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--grigio); padding: 0 0 7px; font-weight: 700;
}
.wagi-tab th:first-child, .wagi-tab td:first-child { text-align: left; }
.wagi-tab td { padding: 7px 0; border-top: 1px solid var(--border-warm-2); text-align: right;
  font-variant-numeric: tabular-nums; }
.wagi-tab .wagi-pasek-kom { width: 34%; }
.wagi-pasek-tlo { height: 7px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.wagi-pasek { height: 100%; border-radius: 999px; transition: width 0.45s cubic-bezier(.22,1,.36,1); }
.wagi-pasek.nowe { background: var(--grigio); }
.wagi-pasek.latwe { background: var(--verde); }
.wagi-pasek.srednie { background: var(--primary); }
.wagi-pasek.trudne { background: var(--rosso); }
.wagi-przewaga { font-weight: 700; }
.wagi-suma {
  font-size: 0.82rem; padding: 11px 13px; border-radius: 12px; margin-bottom: 12px;
  background: var(--bg-info-soft); line-height: 1.5;
}

/* --- Okno potwierdzenia i okno szczegółów ikony - nad konsolą admina (zakładka Ikony). Do 2026-09-27 nazywały się
   .post-modal*, bo powstały dla kreatora postaci; postaci odeszły z konsoli, a tablica ikon została przy tym oknie. --- */
.iko-okno-tlo {
  position: fixed; inset: 0; z-index: 100000; background: rgba(15, 23, 42, 0.55);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.iko-okno {
  background: var(--bianco); border-radius: 22px; padding: 22px 24px; max-width: 420px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.35); text-align: center;
}
.iko-okno p { margin: 0 0 16px; font-size: 0.9rem; line-height: 1.55; }
.iko-okno .przyciski { display: flex; gap: 10px; justify-content: center; }
.iko-okno button {
  border: none; border-radius: 13px; padding: 10px 20px; font: inherit; font-weight: 800;
  font-size: 0.85rem; cursor: pointer; transition: var(--transition);
}
.iko-okno button.potwierdz { background: #EF4444; color: #fff; box-shadow: 0 4px 0 #B91C1C; }
.iko-okno button.potwierdz:active { transform: translateY(3px); box-shadow: 0 1px 0 #B91C1C; }
.iko-okno button.anuluj { background: var(--bg-soft); color: var(--testo); }

/* --- Tablica ikon słów (zakładka Ikony w konsoli admina) --- */
.iko-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.iko-karta {
  position: relative; background: var(--card-bg); border: 1px solid var(--border-2);
  border-radius: 14px; padding: 12px 8px 9px; text-align: center; cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.iko-karta:hover { transform: translateY(-2px); box-shadow: 0 8px 18px rgba(15, 23, 42, 0.10); }
.iko-karta.pusta { opacity: 0.55; }
.iko-karta.czeka-gen .iko-rys { opacity: 0.35; }
.iko-karta.czeka-gen { animation: ikoPuls 1.1s ease-in-out infinite; }
@keyframes ikoPuls { 50% { border-color: #38BDF8; } }
.iko-rys { display: block; margin: 0 auto; --rys-h: 92px; height: 92px; }
.iko-rys-brak {
  display: flex; align-items: center; justify-content: center; width: 92px; height: 92px;
  margin: 0 auto; border: 2px dashed var(--border-2); border-radius: 16px;
  font-size: 1.5rem; color: var(--grigio);
}
.iko-karta b { display: block; font-size: 11px; margin-top: 7px; word-break: break-word; }
.iko-slowa { display: block; font-size: 10px; color: var(--grigio); word-break: break-word; }
.iko-pl { display: block; font-size: 10.5px; font-weight: 800; color: #0369A1; margin-top: 2px; word-break: break-word; }

/* Tryb PRZEGLĄD: wielkie karty (ok. 3 w rzędzie na dużym ekranie), polskie znaczenie
   i miniatury poprzednich wersji od razu pod ikoną - do przeglądania talii okiem. */
.iko-grid.przeglad { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.iko-grid.przeglad .iko-rys { --rys-h: 170px; height: 170px; }
.iko-grid.przeglad .iko-rys-brak { width: 170px; height: 170px; font-size: 2.4rem; }
.iko-grid.przeglad .iko-karta b { font-size: 14px; }
.iko-grid.przeglad .iko-slowa { font-size: 12px; }
.iko-grid.przeglad .iko-pl { font-size: 13px; }
.iko-grid.przeglad .iko-akcje button { display: block; }
.iko-mini-hist {
  display: flex; gap: 6px; justify-content: center; align-items: center;
  flex-wrap: wrap; margin-top: 8px; min-height: 20px; font-size: 10px; color: var(--grigio);
}
.iko-mini {
  --rys-h: 42px; height: 42px; display: block; padding: 2px;
  border: 1px dashed var(--border-2); border-radius: 9px; opacity: 0.85;
}
.iko-plakietka {
  position: absolute; top: 6px; left: 6px; font-size: 9px; font-weight: 900;
  padding: 2px 7px; border-radius: 999px; background: #E0F2FE; color: #0369A1;
}
.iko-plakietka.f5 { background: #DCFCE7; color: #15803D; }   /* Fable 5 - ręczne */
.iko-plakietka.df { background: #E0F2FE; color: #0369A1; }   /* DeepSeek flash */
.iko-plakietka.go  { background: #FEF3C7; color: #B45309; }   /* Gemini (Google) */
.iko-plakietka.cg  { background: #CCFBF1; color: #0F766E; }   /* ChatGPT (OpenAI) */
.iko-plakietka.ad  { background: #EDE9FE; color: #6D28D9; }   /* wklejona przez admina */
.iko-klodka { position: absolute; top: 24px; left: 6px; font-size: 12px; color: #B91C1C; }
.iko-akcje { position: absolute; top: 6px; right: 6px; display: flex; gap: 4px; }
.iko-akcje button {
  width: 23px; height: 23px; border: none; border-radius: 8px; font: inherit; font-size: 12px;
  font-weight: 900; line-height: 1; cursor: pointer; display: none; padding: 0;
}
.iko-karta:hover .iko-akcje button { display: block; }
.iko-akcje .iko-x    { background: #FEE2E2; color: #B91C1C; }
.iko-akcje .iko-baza { background: #E0E7FF; color: #4338CA; }
.iko-akcje .iko-gen  { background: #DBEAFE; color: #1D4ED8; }
/* Kłódka = stan: otwarta zielona (ikona wolna), zamknięta czerwona (zatwierdzona). */
.iko-akcje .iko-klodka-btn { font-size: 11px; }
.iko-akcje .iko-klodka-btn.otwarta   { background: #DCFCE7; color: #15803D; }
.iko-akcje .iko-klodka-btn.zamknieta { background: #FEE2E2; color: #B91C1C; }
.iko-modal { max-width: 660px; width: 100%; text-align: left; max-height: 86vh; overflow-y: auto; }
.iko-modal h4 { margin: 0 0 4px; font-size: 1rem; }
.iko-modal .meta { font-size: 0.78rem; color: var(--grigio); line-height: 1.6; }
.iko-modal .glowa { display: flex; gap: 16px; align-items: flex-start; }
.iko-modal .glowa .iko-rys { --rys-h: 128px; height: 128px; margin: 0; flex-shrink: 0; }
.iko-modal .przyciski { justify-content: flex-start; flex-wrap: wrap; margin-top: 14px; }
.iko-modal button.zwykly { background: var(--bg-soft); color: var(--testo); }
.iko-modal button.zwykly:hover { background: var(--border-2); }
.iko-hist { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 8px; margin-top: 10px; }
.iko-hist .poz {
  border: 1px dashed var(--border-2); border-radius: 12px; padding: 8px; text-align: center;
  font-size: 10px; color: var(--grigio);
}
.iko-hist .poz .iko-rys { --rys-h: 72px; height: 72px; }
.iko-hist .poz button {
  margin-top: 6px; border: none; border-radius: 8px; background: #E0E7FF; color: #4338CA;
  font: inherit; font-size: 10px; font-weight: 800; padding: 4px 8px; cursor: pointer;
}

/* Zgłoszenie w konsoli: treść jest tu najważniejsza, więc dostaje pełną szerokość i normalny
   rozmiar pisma - metryczka (kto, kiedy, w jakim języku) idzie drobnym drukiem NAD nią. */
.fb-poz {
  border: 1px solid var(--border-warm); border-radius: 14px;
  padding: 12px 14px; margin-bottom: 9px; background: var(--card-bg);
}
.fb-poz.nowe { border-color: var(--verde); background: var(--bg-success-soft); }
.fb-meta {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  font-size: 0.72rem; color: var(--grigio); margin-bottom: 7px;
}
.fb-meta b { color: var(--testo); font-size: 0.78rem; }
.fb-meta .fb-akcje { margin-left: auto; display: flex; gap: 6px; }
.fb-meta button {
  border: 1px solid var(--border-warm); background: transparent; color: var(--grigio);
  border-radius: 9px; padding: 3px 9px; font: inherit; font-size: 0.7rem; cursor: pointer;
  transition: var(--transition);
}
.fb-meta button:hover { border-color: var(--testo); color: var(--testo); }
.fb-meta button.usun:hover { border-color: var(--rosso); color: var(--rosso); }
.fb-tresc { font-size: 0.88rem; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }

/* Pasek zakładek (.admin-tabs) zszedł 2026-09-29 razem z przebudową konsoli: nawigacja stoi dziś w panelu bocznym,
   style w sekcji „KONSOLA ADMINA: UKŁAD Z PANELEM BOCZNYM” na końcu arkusza. */
.admin-body { flex: 1; overflow-y: auto; padding: 18px; }
.admin-pane { display: none; }
.admin-pane.active { display: block; }
.admin-card {
  background: var(--bianco); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; margin-bottom: 14px;
}
.admin-card h3 {
  font-size: 0.78rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--grigio); margin: 0 0 12px;
}

/* KPI */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; margin-bottom: 14px; }
.kpi {
  background: var(--bianco); border: 1px solid var(--border); border-left: 4px solid #0EA5E9;
  border-radius: 8px; padding: 12px 14px;
}
.kpi .kpi-label {
  font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: var(--grigio);
}
.kpi .kpi-value {
  font-size: 1.5rem; font-weight: 800; margin-top: 3px;
  font-variant-numeric: tabular-nums; line-height: 1.15;
}
.kpi .kpi-sub { font-size: 0.7rem; color: var(--muted-light); font-weight: 600; margin-top: 2px; }
.kpi.zysk { border-left-color: #16A34A; }
.kpi.zysk .kpi-value { color: #15803D; }
.kpi.uwaga { border-left-color: var(--primary); }
.kpi.zle { border-left-color: var(--rosso); }

/* Gęsta tabela robocza */
.dt { width: 100%; border-collapse: collapse; font-size: 0.79rem; }
.dt th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-soft); text-align: left; padding: 8px 10px;
  font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--muted-dark); border-bottom: 1px solid var(--border-2); white-space: nowrap;
}
.dt td { padding: 8px 10px; border-bottom: 1px solid var(--bg-soft); vertical-align: middle; }
.dt tbody tr:hover { background: var(--crema); }
.dt .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dt .mono { font-family: 'Consolas', 'Courier New', monospace; font-size: 0.74rem; color: var(--grigio); }
.dt-scroll { max-height: 420px; overflow: auto; border: 1px solid var(--border); border-radius: 8px; background: var(--bianco); }
.dt-empty { padding: 26px; text-align: center; color: var(--muted-light); font-size: 0.82rem; font-weight: 600; }

.pill {
  display: inline-block; padding: 2px 8px; border-radius: 20px;
  font-size: 0.68rem; font-weight: 800; white-space: nowrap;
}
.pill.ok   { background: #DCFCE7; color: #15803D; }
.pill.wait { background: var(--bg-amber-soft); color: var(--muted-dark); }
.pill.bad  { background: var(--bg-error-soft2); color: #B91C1C; }
.pill.info { background: var(--bg-info-soft); color: #0369A1; }
.pill.off  { background: var(--bg-soft); color: var(--grigio); }

/* Skrzynka zgłoszeń (2026-09-27): wiersz = karta, bo zgłoszenie ma za dużo pól na tabelę (karta, nagrania z odtwarzaczem,
   to, co uczeń widział, propozycja, stan i akcje). Nagranie przy „złej wymowie” stoi na górze wiersza, bo po nie się tu
   przychodzi. */
.zgl-admin-pasek { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.zgl-admin-zakladki { display: flex; flex-wrap: wrap; gap: 6px; }
.zgl-admin-zakladki button {
  border: 1px solid var(--border-2); background: var(--bianco); color: var(--testo); border-radius: 999px;
  padding: 5px 12px; font: inherit; font-size: 0.78rem; font-weight: 700; cursor: pointer;
}
.zgl-admin-zakladki button.aktywna { background: var(--testo); color: var(--bianco); border-color: var(--testo); }
.zgl-admin-zbierz { margin: 0; width: auto; flex: 0 0 auto; padding: 8px 16px; font-size: 0.82rem; min-height: 0; }
.zgl-admin-lista { display: flex; flex-direction: column; gap: 10px; max-height: 720px; overflow: auto; }
.zgl-admin-wiersz { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; background: var(--bianco); font-size: 0.82rem; }
.zgl-admin-wiersz.rozwiazane { opacity: 0.72; }
.zgl-admin-glowa { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin-bottom: 8px; color: var(--grigio); font-size: 0.76rem; }
.zgl-admin-glowa strong { color: var(--testo); }
.zgl-admin-karta { font-size: 0.95rem; margin: 0 0 6px; overflow-wrap: anywhere; }
.zgl-admin-karta b { font-weight: 800; }
.zgl-admin-pola { display: grid; grid-template-columns: max-content 1fr; gap: 3px 10px; margin: 6px 0; }
.zgl-admin-pola dt { color: var(--grigio); font-weight: 700; }
.zgl-admin-pola dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.zgl-admin-pola dd.propozycja { font-weight: 800; }
.zgl-admin-audio { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 6px 0; }
.zgl-admin-audio audio { height: 34px; max-width: 100%; }
.zgl-admin-akcje { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.zgl-admin-akcje .btn { margin: 0; padding: 6px 14px; font-size: 0.78rem; min-height: 0; width: auto; flex: 0 0 auto; }

/* Poziome słupki rozbić (waluty / metody / plany) */
.bars { display: flex; flex-direction: column; gap: 7px; }
.bar-row { display: grid; grid-template-columns: 92px 1fr 46px; align-items: center; gap: 9px; font-size: 0.76rem; }
.bar-track { height: 9px; background: var(--bg-soft); border-radius: 5px; overflow: hidden; }
.bar-fill { height: 100%; background: #0EA5E9; border-radius: 5px; }
.bar-row .num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 800; }

.admin-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
@media (max-width: 900px) {
  .admin-grid-2 { grid-template-columns: 1fr; }
}

/* Formularze wewnątrz panelu - kompaktowe, bez „grubych" inputów z reszty aplikacji */
.admin-form-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.admin-in {
  padding: 7px 10px; border: 1px solid var(--border-2); border-radius: 7px;
  font-family: inherit; font-size: 0.8rem; background: var(--bianco); color: var(--testo); outline: none;
}
.admin-in:focus { border-color: #0EA5E9; }
.admin-btn {
  padding: 7px 14px; border: none; border-radius: 7px; background: var(--testo); color: var(--bianco);
  font-family: inherit; font-size: 0.78rem; font-weight: 800; cursor: pointer; transition: var(--transition);
}
.admin-btn:hover { background: #1E293B; }
.admin-btn.sec { background: var(--border); color: var(--testo); }
.admin-btn.sec:hover { background: var(--border-2); }

/* ===== EDYTOR PORADNIKA (zakładka „Poradnik" w panelu admina) ===== */
.por-siatka { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin-bottom: 14px; }
.por-pole { display: flex; flex-direction: column; gap: 5px; }
.por-pole > span { font-size: 0.75rem; font-weight: 800; color: var(--testo); }
/* Objaśnienie przy etykiecie - po to, żeby nie trzeba było zgadywać, do czego służy pole.
   Lżejsze i nie kursywą przez przypadek: to podpowiedź, nie druga etykieta. */
.por-pole > span em { font-weight: 600; font-style: normal; color: var(--grigio); }
.por-pole .admin-in { width: 100%; box-sizing: border-box; }
.por-szeroko { grid-column: 1 / -1; }

/* Okno „sesja wygasła". Na wierzchu wszystkiego (także okien aplikacji), bo od tej chwili
   żaden przycisk pod spodem i tak nic nie zrobi - a przeklikiwanie się przez martwy interfejs
   jest gorsze niż jedno zdanie wprost. */
.sesja-koniec {
  position: fixed; inset: 0; z-index: 12000;
  background: rgba(15, 23, 42, 0.55); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.sesja-koniec-karta {
  background: var(--card-bg); border: 1px solid var(--border-2); border-radius: 22px;
  padding: 30px 28px; max-width: 380px; width: 100%; text-align: center;
  box-shadow: 0 20px 50px rgba(15, 23, 42, 0.35);
}
.sesja-koniec-ikona { font-size: 2.2rem; line-height: 1; margin-bottom: 12px; }
.sesja-koniec-karta h3 { margin: 0 0 8px; font-size: 1.15rem; color: var(--testo); }
.sesja-koniec-karta p { margin: 0 0 18px; font-size: 0.92rem; color: var(--grigio); line-height: 1.6; }
.sesja-koniec-karta .btn { width: 100%; margin: 0; }

/* Zdjęcie główne artykułu: podgląd obok przycisków, a nie pod nimi - przy podmianie obrazka
   trzeba widzieć NARAZ to, co jest, i to, czym się je zastępuje. */
.por-zdjecie { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.por-zdjecie-podglad {
  width: 190px; aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden;
  border: 1px dashed var(--border-2); background: var(--crema);
  display: flex; align-items: center; justify-content: center; flex: none;
}
.por-zdjecie-podglad img { width: 100%; height: 100%; object-fit: cover; display: block; }
.por-zdjecie-akcje { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }

.por-pasek { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 6px; }
.por-btn {
  padding: 5px 11px; border: 1px solid var(--border-2); border-radius: 20px; background: var(--bianco);
  color: var(--testo); font-family: inherit; font-size: 0.72rem; font-weight: 700; cursor: pointer;
}
.por-btn:hover { border-color: #0EA5E9; color: #0EA5E9; }
/* Wzór i kreator stoją SKLEJONE, bo to jeden blok w dwóch trybach. Osobno, w jednym
   rzędzie z resztą, wyglądałyby jak dziesięć niezależnych przycisków. */
.por-para { display: inline-flex; }
.por-para .por-btn { border-radius: 20px 0 0 20px; }
.por-para .por-btn-ai { border-radius: 0 20px 20px 0; margin-left: -1px; padding: 5px 9px; }
.por-btn-ai[disabled] { opacity: .5; cursor: progress; }

/* Treść pisze się w foncie o stałej szerokości: bloki :frazy są tabelami rozdzielanymi
   kreską i w foncie proporcjonalnym kolumny rozjeżdżają się tak, że nie widać, co z czym. */
/* SPLIT-SCREEN EDYTORA. Domyślnie jedna kolumna (samo pisanie) - podgląd wchodzi dopiero
   z przełącznika, bo przy wąskim panelu dwie kolumny po ~400 px to dwa nieczytelne paski.
   Obie kolumny mają TĘ SAMĄ wysokość i własne przewijanie, więc długi artykuł nie rozpycha
   całego panelu admina w dół. */
.por-split { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: stretch; }
.por-split.z-podgladem { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .por-split.z-podgladem { grid-template-columns: minmax(0, 1fr); } }

.por-podglad {
  border: 1px solid var(--border-warm); border-radius: 16px;
  background: var(--card-bg); overflow: hidden;
  display: flex; flex-direction: column; min-height: 420px; max-height: 70vh;
}
.por-podglad-stan {
  padding: 8px 14px; font-size: 0.74rem; color: var(--grigio);
  border-bottom: 1px solid var(--border-warm); background: var(--bg-soft); flex-shrink: 0;
}
/* Treść podglądu przewija się SAMA, niezależnie od panelu - inaczej przy dłuższym tekście
   trzeba by przewijać całą konsolę admina, żeby zobaczyć koniec artykułu. */
.por-podglad-tresc { padding: 18px 20px; overflow-y: auto; font-size: 0.92rem; line-height: 1.75; }
.por-podglad-uwagi {
  flex-shrink: 0; padding: 9px 14px; margin: 0; list-style: none;
  font-size: 0.74rem; line-height: 1.55; color: #92400E;
  background: rgba(245, 158, 11, 0.14); border-bottom: 1px solid var(--border-warm);
}
.por-podglad-uwagi div { padding: 2px 0; }
.por-podglad-tresc h2 { font-size: 1.15rem; margin: 18px 0 8px; }
.por-podglad-tresc h3 { font-size: 1rem; margin: 14px 0 6px; }
.por-podglad-tresc p { margin: 0 0 10px; }
.por-podglad-tresc img { max-width: 100%; height: auto; border-radius: 12px; }

/* BLOKI INTERAKTYWNE W PODGLĄDZIE. Wygląd bierzemy z poradnik_bloki_css() - z tego samego
   pliku, z którego bierze go strona artykułu. Skopiowany tutaj rozjechałby się przy pierwszej
   poprawce i podgląd zacząłby pokazywać coś, czego czytelnik nie zobaczy.

   Panel admina nazywa kolory inaczej niż strona publiczna, więc brakujące nazwy mapujemy
   RAZ, tutaj, zamiast rozsypywać warunki po CSS bloków. Bez tego blok w ciemnym panelu
   dostawałby jasne wartości zapasowe i byłby nieczytelny. */
.por-podglad-tresc {
  --karta: var(--card-bg);
  --tlo: var(--bg-soft);
  --tekst: var(--testo);
  --zielen: #16A34A;
  --czerwien: #DC2626;
  --primary-jasny: var(--bg-soft);
  --primary-ciemny: var(--primary);
}
.por-blok {
  margin: 26px 0; padding: 18px 20px 16px;
  background: var(--karta, #fff);
  border: 1px solid var(--border, #E2E8F0);
  border-left: 4px solid var(--primary, #2563EB);
  border-radius: 16px;
}
.por-blok-quiz      { border-left-color: var(--primary, #2563EB); }
.por-blok-fiszki    { border-left-color: #A855F7; }
.por-blok-sluchanie { border-left-color: #F59E0B; }
.por-blok-smart-czytanie { border-left-color: var(--zielen, #16A34A); }
.por-blok-tytul {
  margin: 0 0 14px; font-size: 1.02rem; font-weight: 700;
  color: var(--testo, #0F172A); display: flex; align-items: center; gap: 8px;
}
.por-blok-ikona { font-size: 1.15rem; line-height: 1; }
.por-blok-podp { margin: 12px 0 0; font-size: .82rem; color: var(--grigio, #64748B); }
.por-blok-glos {
  flex: none; width: 30px; height: 30px; padding: 0; cursor: pointer;
  border: 1px solid var(--border, #E2E8F0); border-radius: 9px; font-size: .9rem;
  background: var(--crema, #F8FAFC); color: inherit; line-height: 1;
}
.por-blok-glos:hover { border-color: var(--primary, #2563EB); }
.por-blok-akcja {
  padding: 8px 16px; cursor: pointer; font: inherit; font-size: .85rem; font-weight: 600;
  border: 1px solid var(--border-2, #CBD5E1); border-radius: 999px;
  background: var(--crema, #F8FAFC); color: var(--testo, #0F172A);
}
.por-blok-akcja:hover { border-color: var(--primary, #2563EB); color: var(--primary, #2563EB); }

/* --- FISZKI --------------------------------------------------------------- */
.por-fiszki { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.por-fiszka { display: flex; align-items: stretch; gap: 8px; }
.por-fiszka-karta {
  flex: 1; display: flex; flex-direction: column; gap: 4px; cursor: pointer;
  padding: 12px 14px; text-align: left; font: inherit;
  background: var(--crema, #F8FAFC); color: var(--testo, #0F172A);
  border: 1px solid var(--border, #E2E8F0); border-radius: 12px;
}
.por-fiszka-karta:hover { border-color: #A855F7; }
/* Przód karty układa się w kolumnę tak samo jak tył - bez tego zwrot i jego wymowa
   sklejają się w jedną linijkę i wygląda to jak literówka, a nie jak dwie informacje. */
.por-fiszka-przod { display: flex; flex-direction: column; gap: 3px; }
.por-fiszka-obcy { font-weight: 700; }
.por-fiszka-wym { font-size: .82rem; color: var(--grigio, #64748B); font-style: italic; }
.por-fiszka-tyl { display: flex; flex-direction: column; gap: 2px; }
.por-fiszka-pol { color: var(--primary, #2563EB); font-weight: 600; }
.por-fiszka-notka { font-size: .82rem; color: var(--grigio, #64748B); }
/* Tył karty chowa się DOPIERO, gdy skrypt zgłosi, że działa (data-js). Bez JavaScriptu
   fiszka jest zwykłą tabelką zwrotów - czytelną i widoczną dla wyszukiwarki. */
.por-blok[data-js] .por-fiszka-tyl { display: none; }
.por-blok[data-js] .por-fiszka-karta[aria-expanded="true"] .por-fiszka-tyl { display: flex; }

/* --- QUIZ ----------------------------------------------------------------- */
.por-quiz { margin: 0; padding: 0 0 0 4px; list-style: none; counter-reset: pyt; display: grid; gap: 18px; }
.por-quiz-pyt { counter-increment: pyt; }
.por-quiz-tresc { margin: 0 0 10px; font-weight: 600; color: var(--testo, #0F172A); }
.por-quiz-tresc::before { content: counter(pyt) ". "; color: var(--primary, #2563EB); }
.por-quiz-odp { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.por-quiz-btn {
  width: 100%; text-align: left; cursor: pointer; font: inherit; font-size: .95rem;
  padding: 10px 14px; border-radius: 11px;
  background: var(--crema, #F8FAFC); color: var(--testo, #0F172A);
  border: 1px solid var(--border, #E2E8F0);
}
.por-quiz-btn:hover { border-color: var(--primary, #2563EB); }
.por-quiz-btn.dobra  { border-color: var(--zielen, #16A34A); background: rgba(22,163,74,.12); font-weight: 600; }
.por-quiz-btn.zla    { border-color: var(--czerwien, #DC2626); background: rgba(220,38,38,.10); }
.por-quiz-btn[disabled] { cursor: default; }
.por-quiz-wyj {
  margin: 10px 0 0; padding: 10px 13px; font-size: .88rem; border-radius: 10px;
  background: var(--primary-jasny, #EFF6FF); color: var(--tekst, #334155);
}
.por-blok[data-js] .por-quiz-wyj { display: none; }
.por-blok[data-js] .por-quiz-pyt.odpowiedziane .por-quiz-wyj { display: block; }

/* --- SŁUCHANIE ------------------------------------------------------------ */
.por-sluch-audio { width: 100%; margin: 0 0 12px; }
.por-dialog { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.por-dialog-w { display: flex; align-items: flex-start; gap: 9px; }
.por-dialog-tekst { display: flex; flex-direction: column; gap: 2px; padding-top: 3px; }
.por-dialog-obcy { font-weight: 600; }
.por-dialog-tlum { font-size: .85rem; color: var(--grigio, #64748B); }
.por-sluch-akcje { margin-top: 12px; display: none; }
.por-blok[data-js] .por-sluch-akcje { display: block; }
/* Zakryty tekst zostaje w dokumencie i zajmuje swoje miejsce - inaczej blok skakałby
   o kilkadziesiąt pikseli w chwili odsłonięcia. */
.por-blok[data-js] .por-dialog.zakryty .por-dialog-tekst { filter: blur(5px); opacity: .55; user-select: none; }

/* --- SMART CZYTANIE ------------------------------------------------------- */
.por-smart-tekst { margin: 0 0 8px; font-size: 1.02rem; line-height: 2; }
.por-smart-slowo {
  /* Własna wysokość linii, a nie odziedziczona z akapitu: przy line-height 2 kropkowane
     podkreślenie odjeżdża od słowa na tyle, że wygląda na osobny element strony. */
  padding: 0; font: inherit; line-height: 1.3; cursor: pointer; background: none;
  color: inherit; vertical-align: baseline;
  border: none; border-bottom: 2px dotted var(--zielen, #16A34A);
}
.por-smart-slowo:hover, .por-smart-slowo.wybrane { background: rgba(22,163,74,.14); border-radius: 4px; }
.por-smart-cien { color: var(--grigio, #64748B); font-size: .88em; }
.por-blok[data-js] .por-smart-cien { display: none; }
.por-smart-panel {
  margin: 10px 0 0; padding: 10px 13px; min-height: 42px; font-size: .9rem; border-radius: 10px;
  background: var(--crema, #F8FAFC); color: var(--tekst, #334155);
}
.por-smart-panel b { color: var(--testo, #0F172A); }
.por-smart-panel i { color: var(--grigio, #64748B); }

/* --- FILM (miniatura zamiast odtwarzacza) --------------------------------- */
.por-film { position: relative; aspect-ratio: 16 / 9; border-radius: 14px; overflow: hidden; background: #000; }
.por-film-plakat {
  display: block; width: 100%; height: 100%; padding: 0; border: none; cursor: pointer;
  background: #000;
}
.por-film-plakat img { width: 100%; height: 100%; object-fit: cover; display: block; }
.por-film-play {
  position: absolute; inset: 0; margin: auto; width: 68px; height: 68px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.7rem; color: #fff; padding-left: 5px;
  background: rgba(15,23,42,.72); border-radius: 50%; pointer-events: none;
}
.por-film-plakat:hover .por-film-play { background: #DC2626; }
.por-film iframe { width: 100%; height: 100%; border: 0; display: block; }

/* --- PRZYCISK OTWIERAJĄCY PEŁNY EKRAN ------------------------------------- */
.por-trigger-linia { margin: 22px 0; text-align: center; }
.por-trigger {
  padding: 13px 26px; cursor: pointer; font: inherit; font-size: 1rem; font-weight: 700;
  color: #fff; background: var(--primary, #2563EB); border: none; border-radius: 999px;
  box-shadow: 0 6px 18px rgba(37,99,235,.28);
}
.por-trigger:hover { background: var(--primary-ciemny, #1D4ED8); }

/* --- NAKŁADKA PEŁNOEKRANOWA ----------------------------------------------- */
.por-blok-modal {
  position: fixed; inset: 0; z-index: 9000; display: none;
  align-items: center; justify-content: center; padding: 20px;
  background: rgba(8,12,20,.72);
}
.por-blok-modal.otwarty { display: flex; }
.por-blok-modal-okno {
  position: relative; width: min(680px, 100%); max-height: 88vh; overflow-y: auto;
  padding: 26px 22px 22px; border-radius: 20px;
  background: var(--tlo, #F0F4F8);
}
.por-blok-modal-x {
  position: absolute; top: 12px; right: 14px; width: 34px; height: 34px; cursor: pointer;
  font-size: 1.3rem; line-height: 1; border-radius: 50%;
  border: 1px solid var(--border, #E2E8F0); background: var(--karta, #fff); color: inherit;
}
.por-blok-modal .por-blok { margin: 0; }

@media (max-width: 560px) {
  .por-blok { padding: 15px 14px 13px; border-radius: 13px; }
  .por-smart-tekst { font-size: .97rem; line-height: 1.95; }
}
@media (prefers-reduced-motion: reduce) {
  .por-blok, .por-blok * { transition: none !important; animation: none !important; }
}
.por-przelacznik {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font-size: 0.78rem; color: var(--muted-dark);
}

.por-tresc {
  width: 100%; box-sizing: border-box; resize: vertical; line-height: 1.55;
  font-family: ui-monospace, Consolas, 'Courier New', monospace; font-size: 0.78rem;
}
.por-stan { font-size: 0.75rem; font-weight: 700; color: var(--grigio); margin: 6px 0 10px; }
.por-stan b { color: var(--testo); }
.por-stan.ok b { color: var(--verde); }
.por-stan.malo b { color: #B45309; }

.por-sciaga { background: var(--crema); border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; margin-bottom: 10px; }
.por-sciaga summary { cursor: pointer; font-size: 0.78rem; font-weight: 800; }
.por-sciaga table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 0.76rem; }
.por-sciaga td { padding: 4px 8px 4px 0; vertical-align: top; color: var(--grigio); }
.por-sciaga td:first-child { white-space: nowrap; width: 1%; color: var(--testo); }
.por-sciaga code { background: var(--bianco); border: 1px solid var(--border-2); border-radius: 4px; padding: 1px 5px; font-size: 0.95em; }

/* Wiersz spisu artykułów. Kolor lewej krawędzi niesie status - szkic ma być widoczny
   jednym spojrzeniem, bo to on NIE jest w wyszukiwarce. */
.por-wiersz {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px; margin-bottom: 7px;
  background: var(--bianco); border: 1px solid var(--border); border-left: 4px solid var(--border-2);
  border-radius: 9px; cursor: pointer;
}
.por-wiersz:hover { border-color: #0EA5E9; }
.por-wiersz.jest { border-left-color: var(--verde); }
.por-wiersz.szkic { border-left-color: #D97706; }
.por-wiersz-tytul { font-size: 0.85rem; font-weight: 800; }
.por-wiersz-meta { font-size: 0.72rem; color: var(--grigio); font-weight: 600; margin-top: 2px; }
.por-wiersz-stan { margin-left: auto; font-size: 0.7rem; font-weight: 800; white-space: nowrap; }
.por-wiersz.jest .por-wiersz-stan { color: var(--verde); }
.por-wiersz.szkic .por-wiersz-stan { color: #B45309; }

.por-uwaga {
  background: #FEF3C7; border-left: 4px solid #D97706; border-radius: 0 8px 8px 0;
  padding: 9px 13px; margin-bottom: 8px; font-size: 0.78rem; font-weight: 600; color: #78350F;
}
.admin-btn.del { background: var(--bg-error-soft2); color: #B91C1C; }
.admin-btn.del:hover { background: var(--rosso); color: var(--bianco); }
.admin-btn.mini { padding: 4px 9px; font-size: 0.7rem; }

.chart-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 0.72rem; font-weight: 700; color: var(--muted-dark); margin-top: 8px; }
.chart-legend span i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; }

/* ===== FILTRY ===== */

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  font-size: 0.85rem;
  color: var(--grigio);
}
.toggle {
  position: relative;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
}
.toggle input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--border-2);
  border-radius: 24px;
  cursor: pointer;
  transition: var(--transition);
}
.toggle-slider::before {
  content: '';
  position: absolute;
  width: 18px; height: 18px;
  left: 3px; top: 3px;
  background: white;
  border-radius: 50%;
  transition: var(--transition);
}
.toggle input:checked + .toggle-slider { background: var(--oro); }
.toggle input:checked + .toggle-slider::before { transform: translateX(20px); }

/* ===== PROGRESS BAR ===== */
.progress-wrap { margin: 10px 0; }
.progress-label { display: flex; justify-content: space-between; font-size: 0.75rem; color: var(--grigio); margin-bottom: 4px; }
.progress-bar {
  height: 8px;
  background: var(--border-warm);
  border-radius: 8px;
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--zielen-gleboka), var(--zielen-pastel));
  border-radius: 8px;
  transition: width 0.6s ease;
}

/* ===== UPLOAD LOG ===== */
/* =========================================================
   WGRYWANIE EXCELA - ekran postępu
   Zastępuje czarną konsolę z logami. Konsola pokazywała PRAWDĘ (dokładnie to, co się dzieje),
   ale prawdę w formie, której nikt poza programistą nie umie przeczytać - a treść w rodzaju
   "SQLSTATE[HY000]: General error: 5 database is locked" jest dla użytkownika wyłącznie
   sygnałem, że coś się zepsuło. Zostaje ten sam przebieg, powiedziany po ludzku.
   ========================================================= */
.wgr-panel {
  background: var(--card-bg); border: 1px solid var(--border-warm); border-radius: 18px;
  padding: 20px 18px; margin-top: 12px; text-align: center;
}
/* Pierścień: obraca się bez końca, dopóki trwa praca, a wypełnienie idzie za postępem.
   Dwa okręgi na sobie - szary tor i zielony łuk sterowany stroke-dashoffset. */
.wgr-pierscien { position: relative; width: 96px; height: 96px; margin: 0 auto 14px; }
.wgr-pierscien svg { transform: rotate(-90deg); }
.wgr-pierscien circle { fill: none; stroke-width: 8; stroke-linecap: round; }
.wgr-tor { stroke: var(--bg-soft); }
.wgr-luk { stroke: var(--verde); transition: stroke-dashoffset 0.5s cubic-bezier(.22,1,.36,1); }
.wgr-procent {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
.wgr-etap { font-size: 0.95rem; font-weight: 700; margin-bottom: 4px; }
.wgr-detal { font-size: 0.82rem; color: var(--grigio); line-height: 1.5; min-height: 2.4em; }

/* Kroki: widać, co już za nami, co trwa, a co przed nami. To jedyna rzecz, której czarna
   konsola nie pokazywała wcale - leciała lista zdarzeń bez poczucia, ile jeszcze zostało. */
.wgr-kroki { display: flex; justify-content: center; gap: 18px; margin-top: 16px; flex-wrap: wrap; }
.wgr-krok { font-size: 0.74rem; color: var(--grigio); display: flex; align-items: center; gap: 6px; }
.wgr-krok .kropka {
  width: 8px; height: 8px; border-radius: 50%; background: var(--border-warm); flex-shrink: 0;
}
.wgr-krok.trwa { color: var(--testo); font-weight: 700; }
.wgr-krok.trwa .kropka { background: var(--verde); animation: wgrPuls 1.2s ease-in-out infinite; }
.wgr-krok.zrobiony .kropka { background: var(--verde); }
@keyframes wgrPuls { 50% { transform: scale(1.5); opacity: 0.5; } }

/* Odrzucone tłumaczenia - lista, nie toast: to jest praca do poprawienia w arkuszu,
   więc musi dać się przeczytać na spokojnie i porównać wiersz po wierszu. */
.wgr-odrzucone {
  margin-top: 14px; text-align: left; background: var(--bg-warn-soft);
  border-radius: 14px; padding: 13px 15px;
}
.wgr-odrzucone h4 { margin: 0 0 4px; font-size: 0.88rem; font-weight: 800; }
.wgr-odrzucone > p { margin: 0 0 10px; font-size: 0.78rem; color: var(--grigio); line-height: 1.5; }
.wgr-zla {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 8px; align-items: baseline;
  padding: 7px 0; border-top: 1px solid var(--border-warm-soft); font-size: 0.8rem;
}
.wgr-zla b { font-weight: 700; }
.wgr-zla .podane { color: var(--rosso); text-decoration: line-through; }
.wgr-zla .strzalka { color: var(--grigio); font-size: 0.72rem; }
.wgr-zla .powod { grid-column: 1 / -1; font-size: 0.72rem; color: var(--grigio); }
.wgr-odrzucone-wiecej { font-size: 0.76rem; color: var(--grigio); margin-top: 8px; }

.upload-log {
  background: #1A1A1A;
  color: #00FF88;
  border-radius: 10px;
  padding: 12px;
  font-family: monospace;
  font-size: 0.75rem;
  max-height: 160px;
  overflow-y: auto;
  margin-top: 10px;
  display: none;
  line-height: 1.6;
}
.upload-log.active { display: block; }
.log-line { margin: 0; }
.log-line.err { color: #FF6B6B; }
.log-line.ok  { color: #00FF88; }
.log-line.info { color: #FFD700; }

/* ===== MAIN CONTENT ===== */
.main-content { min-width: 0; }

/* ===== FISZKA ===== */
.fiszka-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
  font-size: 0.85rem;
  color: var(--grigio);
}
.fiszka-nav-select {
  padding: 6px 12px; border-radius: 50px; border: 1px solid var(--border-warm);
  background: var(--crema); font-family: inherit; font-size: 0.78rem; font-weight: 600;
  color: var(--testo); cursor: pointer; outline: none; max-width: 150px; transition: var(--transition);
}
.fiszka-nav-select:focus { border-color: var(--oro); }
/* Custom-zbudowany odpowiednik <select> (filtr poziomu/kategorii) - natywny popup <select>
   nie da się zaokrąglić w większości przeglądarek (ograniczenie platformy), więc to własny,
   w pełni stylowalny dropdown. Przycisk (zamknięty stan) używa tej samej klasy .fiszka-nav-select
   co poprzednio, więc wygląda identycznie jak wcześniej - zmienia się tylko rozwinięta lista. */
.custom-select { position: relative; display: inline-block; }
.custom-select-btn { display: inline-flex; align-items: center; gap: 6px; }
.custom-select-caret { font-size: 0.7em; opacity: 0.7; }
.custom-select-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 200;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft);
  border-radius: 12px; box-shadow: var(--shadow-hover);
  min-width: 180px; max-height: 320px; overflow-y: auto;
  padding: 6px; font-size: 0.85rem; font-weight: 600;
}
.custom-select-item {
  padding: 8px 12px; border-radius: 8px; cursor: pointer; color: var(--testo);
  white-space: nowrap;
}
.custom-select-item:hover { background: var(--crema); }
.custom-select-item.active { background: var(--bg-gold-soft); color: var(--testo); }

/* ===== TABLICA SPOŁECZNOŚCI ===== */
/* Etapowe wydawanie paczki z linku (patrz paczki_subskrypcje w db.php) */

/* ===== SPOŁECZNOŚĆ - pełnoekranowa tablica w stylu Pinteresta ===== */
/* Zasłania całą stronę, zostawiając widoczny wyłącznie nagłówek. --cmty-top ustawia
   dopasujGoreSpolecznosci() z realnej wysokości nagłówka - ta zmienia się przy zawijaniu
   na wąskich ekranach, więc sztywna wartość rozjeżdżałaby się na telefonie. */
.community-full {
  position: fixed; left: 0; right: 0; bottom: 0; top: var(--cmty-top, 64px);
  z-index: 90; overflow-y: auto; overscroll-behavior: contain;
  /* --crema to tło strony (patrz body) - musi być NIEPRZEZROCZYSTE, inaczej spod nakładki
     prześwituje panel konta i statystyki, które ta zakładka ma w całości zasłonić. */
  background: var(--crema); padding: 18px 20px 60px;
}
.community-topbar {
  /* Ta sama szerokość co siatka pod spodem - wyśrodkowany pasek nad pełnoekranową tablicą
     wyglądałby jak element innej strony. */
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0 0 20px;
}

/* Kafelek reklamowy w siatce - wygląda jak karta tablicy, ale z jawną etykietą. Bez niej
   reklama udająca treść to zarówno naruszenie zasad AdSense, jak i zwykłe oszukiwanie usera. */
.community-tile.reklama {
  background: var(--bg-soft); border: 1px dashed var(--border-2); cursor: default;
  padding: 10px; min-height: 220px; display: flex; flex-direction: column; gap: 8px;
}
.community-tile.reklama:hover { transform: none; }
.reklama-etykieta {
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted-light);
}

/* --- TRYB GOŚCIA: chowamy wszystko, czego backend i tak by nie wpuścił ---
   Ukrywanie klasą na <body>, a nie warunkami przy każdym przycisku z osobna: tych miejsc jest
   kilkanaście i rozsypanie po nich `if (TRYB_GOSCIA)` gwarantowałoby, że przy następnej nowej
   akcji ktoś o jednym zapomni. Tu wystarczy, że nowy przycisk trafi w istniejący selektor. */
body.tryb-goscia .mode-tabs,
/* Cały panel konta, nie tylko jego przyciski: gość nie ma nicku, awatara ani planu, więc
   pokazywanie mu pustego "?" i licznika "0/160 słówek" tylko myli. */
body.tryb-goscia .header-konto,
body.tryb-goscia #headerLangSwitcher,
body.tryb-goscia #communityAparatBtn,
body.tryb-goscia #communitySortBtn,
body.tryb-goscia .community-tile-akcje,
body.tryb-goscia #communityDetailLike,
/* Rząd akcji karty („Dodaj do <tryb>”, „Weź słówka do fiszek”) i ikona w rogu (#communityDetailExtract) gość WIDZI od 2026-10-12
   (Alek: „w Społeczności dla niezalogowanych użytkowników też zrób tak jak na zalogowanej tablicy […], ale po kliknięciu
   użytkownik trafia do lejka zakładania konta”). Do tego dnia stały na tej liście, bo serwer i tak by odmówił (require_user),
   więc gość nie wiedział, że z karty da się cokolwiek wziąć. Klik gościa nie woła serwera, tylko prowadzi do lejka
   z tym materiałem (cmtyGoscDoLejka, sekcja TRYB GOŚCIA w JS). */
body.tryb-goscia #communityDetailSave,
body.tryb-goscia #communityDetailDelete,
body.tryb-goscia .community-komentarz-form,
body.tryb-goscia .community-btn-zapisz,
body.tryb-goscia .community-btn-przejdz { display: none !important; }
/* Osobna regula, a NIE kolejna pozycja listy wyzej: tamta lista konczy sie na
   `display: none`, wiec dopisanie do niej selektora z innym zachowaniem urywalo ja w polowie
   i wszystko przed spinaczem przestawalo sie chowac.
   Gosc widzi autorstwo materialu (to informacja o nim), ale profil wymaga konta - wiec sam
   link przestaje byc klikalny, zamiast znikac razem z nazwiskiem autora. */
body.tryb-goscia .cmty-autor-link { pointer-events: none; }
body.tryb-goscia .cmty-autor-link:hover .cmty-autor-nick { text-decoration: none; }
/* Nick zastępujemy zaproszeniem do rejestracji - miejsce w pasku jest to samo. */
body.tryb-goscia .header-konto { cursor: pointer; }
.gosc-cta { display: none; }
body.tryb-goscia .gosc-cta {
  display: inline-flex; align-items: center; gap: 6px; border: none; border-radius: 999px;
  padding: 9px 16px; background: var(--oro); color: var(--na-akcencie); font-family: inherit;
  font-size: 0.82rem; font-weight: 800; cursor: pointer; white-space: nowrap;
}
body.tryb-goscia .gosc-cta:hover { filter: brightness(1.08); }

/* --- Tryb Społeczności: nagłówek znika, nawigacja wchodzi do paska narzędzi tablicy ---
   Tablica jest tu jedyną treścią i ma dostać całą wysokość ekranu; poziomy nagłówek zjadał
   ~64 px na coś, co w tym widoku sprowadza się do czterech przycisków. Zakładki i panel konta
   są PRZENOSZONE (nie kopiowane) obok wyszukiwarki - patrz przeniesDoPaska(). */
body.cmty-mode .app-header { display: none; }

/* Pasek narzędzi zostaje przyklejony do góry: mieszkają w nim teraz jedyne wyjście z zakładki
   i jedyny dostęp do ustawień, a te nie mogą odjechać w górę razem z przewijaniem tablicy. */
body.cmty-mode .community-topbar {
  position: sticky; top: 0; z-index: 40;
  background: var(--crema); padding: 10px 0; margin-bottom: 12px;
  transition: transform 0.26s cubic-bezier(.22,1,.36,1), opacity 0.2s ease;
  will-change: transform;
}
/* Zjazd w dół znaczy „chcę oglądać treść" - pasek ustępuje. Ruch w górę znaczy „wracam do
   sterowania" i przywraca go natychmiast, bo mieszka w nim jedyne wyjście z zakładki.
   Chowamy TRANSFORMEM, nie zmianą wysokości: element sticky, który zmienia wysokość, przesuwa
   całą tablicę pod sobą i przewijanie zaczyna skakać pod palcem. */
body.cmty-mode.cmty-pasek-schowany .community-topbar {
  transform: translateY(calc(-100% - 12px));
  opacity: 0;
  pointer-events: none;
}
/* Kto woli bez ruchu, dostaje pasek na stałe - znikanie i pojawianie się elementu bez
   przejścia jest gorsze niż brak efektu. */
@media (prefers-reduced-motion: reduce) {
  body.cmty-mode .community-topbar { transition: none; }
  body.cmty-mode.cmty-pasek-schowany .community-topbar { transform: none; opacity: 1; pointer-events: auto; }
}
/* Konto i zakładki na prawy skraj paska, oddzielone od guzika filtrów. */
.cmty-nawigacja { display: flex; align-items: center; gap: 10px; margin-left: auto; }
/* Logo dosuwa siebie I nawigację do prawej krawędzi: margin-left:auto na nim zjada całą wolną
   przestrzeń po wyszukiwarce, a nawigacja idzie za nim. Wcześniej ten margines siedział na
   .cmty-nawigacja - po dołożeniu logo trzeba go było przenieść, żeby oba nie walczyły o odstęp. */
.cmty-logo { height: 31px; margin-left: 14px; flex-shrink: 0; }
@media (max-width: 900px) {
  /* Na wąskim pasku logo ustępuje miejsca temu, co klikalne. */
  .cmty-logo { display: none; }
}
/* Kolory przeniesionych komponentów NIE są tu już nadpisywane - nagłówek aplikacji ma teraz
   to samo jasne tło co ten pasek, więc reguły bazowe pasują do obu miejsc. Zostają wyłącznie
   różnice naprawdę specyficzne dla paska Społeczności. */
.cmty-nawigacja .mode-tab { font-size: 0.8rem; padding: 6px 14px; }
/* display: block MUSI tu być: reguła z @media (max-width:1000px) chowa nick w wąskim NAGŁÓWKU,
   gdzie o miejsce biją się jeszcze logo, flaga i passa. W pasku Społeczności tych rzeczy nie ma,
   więc nick mieści się spokojnie i chowamy go dopiero poniżej 760 px. */
.cmty-nawigacja .header-konto-opis { display: block; }
/* Menu otwiera się przy prawej krawędzi paska, więc zakotwiczamy je od prawej - przy lewej
   wychodziłoby poza ekran. */
.cmty-nawigacja .header-lang-menu { left: auto; right: 0; }

@media (max-width: 760px) {
  /* Na wąskim ekranie nick zjada całą szerokość paska - zostaje sam awatar z akcjami. */
  .cmty-nawigacja { margin-left: 0; }
  .cmty-nawigacja .header-konto-opis { display: none; }
}
@media (max-width: 560px) {
  /* Nawet bez nicku sama nawigacja (motyw + flaga + zakładki + konto) jest szersza niż telefon,
     a że nic w niej nie zawijało, panel konta z wylogowaniem po prostu wychodził poza ekran
     i nie dało się go kliknąć. Tu pozwalamy jej złamać się na dwa wiersze. */
  .cmty-nawigacja { flex-wrap: wrap; justify-content: flex-end; row-gap: 8px; }
}
/* Pasek narzędzi jest CELOWO stonowany - to tło dla zdjęć, a nie osobna atrakcja.
   Cieńsze obramowania, mniejsza czcionka i brak wypełnień: uwagę ma przyciągać tablica. */
.community-search-wrap { position: relative; flex: 1; min-width: 200px; max-width: 420px; }
.community-search-ico {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  font-size: 0.8rem; pointer-events: none; opacity: 0.5;
}
#communitySearch {
  width: 100%; box-sizing: border-box; padding: 9px 32px 9px 34px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--bg-soft);
  color: var(--testo); font-family: inherit; font-size: 0.85rem; transition: var(--transition);
}
#communitySearch::placeholder { color: var(--muted-light); }

/* Aparat: ten sam rozmiar i promień co pigułki filtrów obok, żeby pasek został równy. */
.community-aparat {
  flex-shrink: 0; width: 40px; height: 40px; border-radius: 12px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-warm); background: var(--card-bg); color: var(--testo);
  font-size: 1rem; transition: var(--transition);
}
.community-aparat:hover { border-color: var(--oro); color: var(--oro); }
.community-aparat .ico { margin: 0; }

/* Pasek „wgrywasz na Społeczność X" - stoi nad strefą wrzucania i nad listą słówek, bo
   z obu tych ekranów trzeba wiedzieć, DOKĄD to idzie. Zdjęcie wgrane na złą tablicę jest
   bezużyteczne dla wszystkich, a poprawić się tego nie da. */
.cmty-wgraj-info {
  display: flex; align-items: center; gap: 9px; margin-bottom: 14px;
  padding: 10px 13px; border-radius: 12px; line-height: 1.45;
  background: var(--bg-success-soft); border: 1px solid var(--zielen-pastel);
  font-size: 0.82rem; color: var(--muted-dark);
}
.cmty-wgraj-info b { color: var(--testo); }
.cmty-wgraj-info .flaga { display: inline-flex; line-height: 0; vertical-align: -2px; margin: 0 2px; }
.cmty-wgraj-opis { font-size: 0.78rem; color: var(--grigio); line-height: 1.55; margin: 12px 0 0; }
#communitySearch:focus { outline: none; border-color: var(--oro); background: var(--card-bg); }
.community-search-clear {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  background: none; border: none; color: var(--grigio); cursor: pointer; font-size: 0.8rem;
}
.community-filters {
  display: flex; align-items: center; gap: 6px;
  /* nowrap, a NIE wrap: przy zawijaniu ten blok zgłaszał znikomą szerokość minimalną, więc
     wyszukiwarka obok trzymała pełne 420 px, a filtr, nawigacja i logo rozjeżdżały się na
     trzy wiersze jeden pod drugim. Bez zawijania to wyszukiwarka ustępuje miejsca (ma
     min-width 200 px), a gdy i to nie starcza - cały pasek łamie się raz, w czytelnym
     miejscu: wyszukiwarka w pierwszym wierszu, reszta w drugim. */
  flex-wrap: nowrap;
  /* flex:1 jest KONIECZNE, żeby margin-left:auto na logo miało co zjeść: bez tego ten blok
     zwęża się do swojej treści i "dosunięcie do prawej" odbywa się w kilkupikselowym pudełku
     tuż za wyszukiwarką, a nie przy krawędzi paska.
     min-width: min-content (a nie 0!) sprawia, że przy ciasnocie ustępuje WYSZUKIWARKA, a nie
     ten blok: z zerem kurczył się on sam, a jego zawartość wychodziła poza pasek. */
  flex: 1; min-width: min-content;
}
.community-chip {
  border: 1px solid var(--border); background: transparent; color: var(--grigio);
  border-radius: 999px; padding: 7px 13px; font-family: inherit; font-size: 0.8rem;
  font-weight: 600; cursor: pointer; transition: var(--transition); white-space: nowrap;
}
.community-chip:hover { border-color: var(--border-2); color: var(--testo); background: var(--bg-soft); }
/* Aktywny filtr wyróżniamy samym kolorem tekstu i obramowania, bez ciężkiego wypełnienia */
.community-chip.active { border-color: var(--oro); color: var(--oro); background: transparent; font-weight: 700; }
/* Okrągły brat cyklu filtrów: ten sam wzrok, inna funkcja - cykl przewija po jednej pozycji,
   ten pokazuje wszystkie naraz. Osobne kółko, żeby nie dało się go pomylić z filtrem. */
.community-kafelki {
  width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%;
  border: 1px solid var(--border); background: transparent; color: var(--grigio);
  font-size: 0.85rem; line-height: 1; cursor: pointer; transition: var(--transition);
  display: inline-flex; align-items: center; justify-content: center;
}
.community-kafelki .ico { margin-right: 0; }
.community-kafelki:hover { border-color: var(--border-2); color: var(--testo); background: var(--bg-soft); }
.community-kafelki.otwarty { border-color: var(--oro); color: var(--oro); background: var(--bg-highlight); }

/* Panel kategorii - wysuwa się z LEWEJ krawędzi ekranu. position: fixed, bo tablica jest
   sama w sobie przewijaną, pełnoekranową warstwą: panel przyklejony do niej odjeżdżałby
   w górę razem ze zdjęciami. */
.cmty-kategorie {
  position: fixed; left: 0; top: var(--cmty-top, 0px); bottom: 0; z-index: 60;
  width: 260px; max-width: 82vw; padding: 14px 12px;
  background: var(--card-bg); border-right: 1px solid var(--border-warm-soft);
  box-shadow: 18px 0 50px rgba(0,0,0,0.20);
  display: flex; flex-direction: column; gap: 4px;
  transform: translateX(-100%);
  transition: transform 0.32s cubic-bezier(.22,1,.36,1);
  overflow-y: auto;
}
.cmty-kategorie.otwarty { transform: translateX(0); }
/* Tło przygasza tablicę i łapie kliknięcie „obok" - bez niego panel dałoby się zamknąć
   wyłącznie krzyżykiem albo ponownym kliknięciem w ten sam przycisk. */
.cmty-kategorie-tlo {
  position: fixed; inset: 0; z-index: 55; background: rgba(15,23,42,0.32);
  opacity: 0; pointer-events: none; transition: opacity 0.28s ease;
}
.cmty-kategorie-tlo.otwarty { opacity: 1; pointer-events: auto; }
.cmty-kategorie-head {
  display: flex; align-items: center; justify-content: space-between;
  font-weight: 800; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--grigio); padding: 4px 8px 10px; border-bottom: 1px solid var(--border-warm-soft);
  margin-bottom: 6px;
}
.cmty-kategorie-zamknij {
  width: 28px; height: 28px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--bg-soft); color: var(--grigio); font-size: 0.85rem; line-height: 1;
  transition: var(--transition);
}
.cmty-kategorie-zamknij:hover { background: var(--bg-error-soft); color: var(--rosso); }
.cmty-kategorie-lista { display: flex; flex-direction: column; gap: 2px; }
.cmty-kategoria {
  display: flex; align-items: flex-start; gap: 11px; width: 100%; text-align: left;
  padding: 10px 11px; border: none; border-radius: 12px; background: transparent;
  font-family: inherit; color: var(--testo); cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}
.cmty-kategoria:hover { background: var(--bg-soft); transform: translateX(2px); }
.cmty-kategoria.active { background: var(--bg-highlight); color: var(--oro); }
.cmty-kategoria .ico { font-size: 1rem; margin-right: 0; margin-top: 3px; }
.cmty-kategoria b { display: block; font-size: 0.85rem; font-weight: 700; }
.cmty-kategoria small { display: block; font-size: 0.71rem; color: var(--grigio); line-height: 1.45; margin-top: 2px; }
/* Wjazd pozycji kaskadą - panel ma się „rozwinąć", a nie zamigotać całą listą naraz. */
.cmty-kategorie.otwarty .cmty-kategoria { animation: kategoriaWjazd 0.34s cubic-bezier(.22,1,.36,1) backwards; }
@keyframes kategoriaWjazd { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .cmty-kategorie { transition: none; }
  .cmty-kategorie.otwarty .cmty-kategoria { animation: none; }
  .cmty-kategoria:hover { transform: none; }
}

.community-empty { text-align: center; padding: 60px 20px; color: var(--grigio); font-size: 0.95rem; }
/* Ekran pośredni pozycji-akcji w cyklu filtrów: grid-column 1/-1, bo siatka tablicy jest
   masonry i bez tego karta wcisnęłaby się w jedną wąską kolumnę. */
.cmty-zaproszenie {
  grid-column: 1 / -1; text-align: center; padding: 48px 24px; max-width: 460px;
  margin: 20px auto; background: var(--card-bg); border-radius: var(--radius);
  border: 2px dashed var(--border-2);
}
.cmty-zaproszenie-ikona { font-size: 2.4rem; line-height: 1; margin-bottom: 10px; }
.cmty-zaproszenie-tytul { font-size: 1.15rem; font-weight: 800; color: var(--testo); margin-bottom: 8px; }
.cmty-zaproszenie p { color: var(--grigio); font-size: 0.86rem; line-height: 1.6; margin: 0 0 18px; }

/* Kafelek, na który da się UPUŚCIĆ zdjęcie. Przerywana ramka była tu od początku i wyglądała
   jak strefa wrzucania, tylko nią nie była - trzeba było kliknąć „Otwórz", w oknie kliknąć
   pole pliku i dopiero w oknie systemowym wskazać zdjęcie. Trzy okna po to, żeby wgrać jeden
   plik. Teraz przerywana ramka znaczy dokładnie to, co obiecuje wyglądem. */
.cmty-zaproszenie.upuszczalny { cursor: pointer; transition: var(--transition); }
.cmty-zaproszenie.upuszczalny:hover { border-color: var(--oro); }
.cmty-zaproszenie.dragover {
  border-color: var(--oro); border-style: solid;
  background: var(--bg-success-soft);
  transform: scale(1.01);
}
@media (prefers-reduced-motion: reduce) { .cmty-zaproszenie.dragover { transform: none; } }
/* Podpowiedź o upuszczaniu jest DRUGORZĘDNA wobec przycisku: myszą klika się przycisk,
   a przeciąga ten, kto i tak trzyma już plik w ręku. */
.cmty-zaproszenie-upusc {
  display: block; margin-top: 12px; font-size: 0.76rem; color: var(--muted-light);
}
.cmty-zaproszenie input[type="file"] { display: none; }

/* Masonry: siatka o bardzo drobnym wierszu (8px), a każdy kafelek dostaje z JS-a
   grid-row-end: span N wyliczone z PROPORCJI zdjęcia - dzięki temu kafelki mają realnie
   różne wysokości i układają się jak na Pintereście, zamiast równych kwadratów. */
/* Pas polecenia nad tablicą. Wygląda jak wiadomość od aplikacji, nie jak kolejny kafelek -
   ma się różnić od treści, którą poleca, żeby nie brać go za zwykłą pozycję listy. */
.cmty-polecany {
  display: flex; align-items: center; gap: 14px; margin: 0 0 16px;
  padding: 14px 18px; border-radius: 18px;
  background: linear-gradient(120deg, color-mix(in srgb, var(--primary) 12%, var(--card-bg)), var(--card-bg));
  border: 1px solid color-mix(in srgb, var(--primary) 28%, transparent);
  animation: odsluchWjazd 0.4s cubic-bezier(.22,1,.36,1);
}
.polecany-ikona {
  width: 42px; height: 42px; flex-shrink: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff; font-size: 1.05rem;
}
.polecany-ikona .ico { margin: 0; }
.polecany-tresc { flex: 1; min-width: 0; }
.polecany-powod { font-size: 0.78rem; font-weight: 700; color: var(--primary); }
.polecany-tytul { font-size: 1rem; font-weight: 800; margin-top: 2px; }
.polecany-meta { font-size: 0.76rem; color: var(--grigio); margin-top: 2px; }
.polecany-btn { width: auto; margin: 0; flex-shrink: 0; padding: 10px 18px; font-size: 0.85rem; }
@media (max-width: 560px) {
  .cmty-polecany { flex-wrap: wrap; }
  .polecany-btn { width: 100%; }
}


.community-board {
  /* Bez max-width: tablica ma wypełniać ekran jak u Pinteresta. Sztywne 1500 px zostawiało
     na monitorze 2560 px dwa szerokie na kilkaset pikseli marginesy, w których nie było nic -
     a to siatka zdjęć, więc każda dodatkowa kolumna to realnie więcej treści na ekranie. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  grid-auto-rows: 8px; gap: 18px; align-items: start;
}
/* Z otwartym powiększeniem karta zajmuje prostokąt w lewym górnym rogu siatki, a "dense"
   każe przeglądarce wciskać kolejne kafelki w KAŻDĄ wolną szczelinę - także w wąski pas
   obok karty i pod nią. Bez tego auto-placement idzie tylko w przód i zostawiłby obok karty
   pustkę. Włączamy je wyłącznie na czas powiększenia, żeby nie zmieniać kolejności kafelków
   na zwykłej tablicy. */
.community-board.z-closeup { grid-auto-flow: row dense; }
/* Kafelek, który właśnie jest otwarty - cienki pierścień zamiast chowania go, żeby było
   widać, w którym miejscu tablicy się jest. */
.community-tile.otwarty { outline: 3px solid var(--oro); outline-offset: 2px; }
.community-tile.otwarty:hover { transform: none; }
.community-tile {
  position: relative; border-radius: 18px; overflow: hidden; cursor: pointer;
  background: var(--bg-soft); box-shadow: var(--shadow);
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.28s ease;
  will-change: transform;
}
/* Kafelek wychodzi nad sąsiadów - stąd z-index, inaczej powiększony róg chowałby się pod
   następnym elementem siatki. */
.community-tile:hover { transform: translateY(-8px) scale(1.035); box-shadow: 0 18px 40px rgba(0,0,0,0.32); z-index: 5; }
.community-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.community-tile-badge {
  position: absolute; top: 10px; right: 10px; background: rgba(15,23,42,0.78); color: #fff;
  font-size: 0.72rem; font-weight: 800; padding: 4px 9px; border-radius: 999px;
}

/* Serce = polubienie. Domyślnie sam kontur na przezroczystym tle (widoczne na każdym zdjęciu
   dzięki cieniowi), po kliknięciu wypełnia się kolorem nagłówka strony. */
/* Przyciemniona podkładka jest konieczna: samo serce ma przezroczyste wypełnienie i biały
   kontur, więc na jasnym zdjęciu (skan menu, biała kartka) byłoby niewidoczne. Ten sam
   wzorzec i ten sam kolor co licznik pobrań w drugim rogu kafelka. */

.community-serce {
  background: rgba(15,23,42,0.55); border: none; border-radius: 999px;
  padding: 5px 9px 5px 7px; cursor: pointer; line-height: 0; flex-shrink: 0;
  display: flex; align-items: center; gap: 4px;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), background 0.2s ease;
}
.community-serce:hover { background: rgba(15,23,42,0.75); }
.community-serce svg { width: 22px; height: 22px; display: block; }
.community-serce path {
  fill: transparent; stroke: #fff; stroke-width: 2;
  transition: fill 0.22s ease, stroke 0.22s ease;
}
.community-serce.lubie path { fill: var(--primary); stroke: var(--primary); }
.community-serce:hover { transform: scale(1.18); }
/* Krótkie "pyknięcie" w momencie polubienia - bez tego klik jest wizualnie płaski */
.community-serce.pyk { animation: sercePyk 0.42s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes sercePyk {
  0% { transform: scale(1); } 40% { transform: scale(1.42); } 100% { transform: scale(1); }
}
.community-serce-ile {
  font-size: 0.72rem; font-weight: 800; color: #fff; font-family: inherit;
}
/* Gradient musi być mocny i sięgać wysoko - zdjęcia bywają jasne (skan menu, biała kartka),
   a na białym tle biały tytuł byłby niewidoczny. */
.community-tile-overlay {
  position: absolute; inset: 0; padding: 12px;
  background: linear-gradient(0deg, rgba(15,23,42,0.95) 0%, rgba(15,23,42,0.82) 40%, rgba(15,23,42,0.25) 78%, rgba(15,23,42,0) 100%);
  display: flex; flex-direction: column; justify-content: flex-end; gap: 3px;
  opacity: 0; transition: opacity 0.25s ease;
}
.community-tile:hover .community-tile-overlay { opacity: 1; }
.community-tile-tytul { color: #fff; font-weight: 800; font-size: 0.9rem; line-height: 1.25; }

/* Kafelek zgłoszenia - obwódka odróżnia go od tego, co już jest na tablicy */
.community-tile.kandydat { outline: 2px dashed var(--oro); outline-offset: -2px; }

.wer-powod {
  border: 1.5px solid var(--border-warm); background: var(--bg-soft); color: var(--testo);
  border-radius: 999px; padding: 8px 14px; font: inherit; font-size: 0.86rem; cursor: pointer;
}
.wer-powod.wybrany { border-color: var(--rosso); background: var(--bg-error, #fdecec); font-weight: 600; }
/* Podgląd słówek na miniaturze celowo USUNIĘTY - zaśmiecał kafelek i zasłaniał samo zdjęcie,
   które jest tu główną treścią. Pełna lista jest po wejściu w grafikę. */
.community-tile-meta { color: #CBD5E1; font-size: 0.7rem; }
/* align-items:center jest KONIECZNE - domyślne "stretch" rozciąga przyciski na całą wysokość
   kontenera, a przy border-radius:999px robią się z nich wielkie koła zamiast pigułek. */
.community-tile-akcje { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.community-btn-zapisz, .community-btn-przejdz {
  border: none; border-radius: 999px; padding: 7px 13px; font-family: inherit;
  font-size: 0.75rem; font-weight: 800; cursor: pointer; transition: var(--transition);
  white-space: nowrap; line-height: 1.2;
}
/* Czerwien z palety (--rosso), nie osobny rozowy odcien: paleta ma miec dokladnie trzy
   barwy. Przycisk lezy na zdjeciu, wiec tekst zostaje bialy niezaleznie od motywu. */
.community-btn-zapisz { background: var(--rosso); color: #fff; }
.community-btn-zapisz.zapisane { background: #0F172A; color: #fff; }
.community-btn-przejdz { background: rgba(255,255,255,0.92); color: #0F172A; }
.community-btn-zapisz:hover, .community-btn-przejdz:hover { filter: brightness(1.1); }

/* Nakładka z przyciemnieniem - używa jej już tylko modal wgrywania zdjęcia. Powiększenie
   zdjęcia nakładką nie jest, patrz .community-detail-karta.w-siatce niżej. */
.community-detail {
  position: fixed; inset: 0; z-index: 200; background: rgba(2, 6, 23, 0.82);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.community-detail-karta {
  position: relative; background: var(--card-bg); border-radius: 22px; overflow: hidden;
  display: flex; align-items: stretch;
}
/* align-items/justify-content: center są KONIECZNE - domyślne "stretch" rozciągałoby <img>
   na całą wysokość kolumny, a wtedy object-fit:contain robiłby letterbox wewnątrz
   rozdmuchanego pudełka. Wyśrodkowanie zostawia obrazkowi jego naturalne proporcje. */
.community-detail-obraz {
  position: relative; display: flex;
  align-items: center; justify-content: center; background: var(--card-bg);
}
/* PIGUŁKI NA OKŁADCE ROZMOWY (poziom, „obraz z AI”): lewy dolny róg obrazka, bez poświaty. Do 2026-10-05 ta warstwa niosła
   nalepki ze zdaniami i słówkami na granatowej poświacie; treść rozmowy pokazuje dziś zwiastun pod okładką (sekcja 20). */
.cmty-nalepki {
  position: absolute; left: 0; bottom: 0; z-index: 2;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 14px;
  pointer-events: none;
}
.cmty-nalepki.hidden { display: none; }
/* ODTWARZACZ UTWORU: rama w tych samych proporcjach i z tym samym zaokrągleniem, co okładka, żeby przy
   kliknięciu nic nie podskoczyło. Przycisk leży NA klatce i jest przezroczysty - klikalna ma być cała
   miniatura, a widoczny jest z niego tylko trójkąt pośrodku. */
.cmty-film { width: 100%; max-width: 760px; aspect-ratio: 16 / 9; border-radius: 18px; overflow: hidden;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.28); background: #000; }
.cmty-film.hidden { display: none; }
.cmty-film iframe { width: 100%; height: 100%; border: 0; display: block; }
.cmty-film-graj {
  position: absolute; inset: 0; z-index: 3; border: 0; background: transparent; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.cmty-film-graj.hidden { display: none; }
.cmty-film-graj::before {
  content: ""; width: 68px; height: 48px; border-radius: 12px; background: rgba(15, 23, 42, 0.72);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35); transition: background .15s ease, transform .15s ease;
}
.cmty-film-graj::after {
  content: ""; position: absolute; width: 0; height: 0;
  border-left: 18px solid #fff; border-top: 11px solid transparent; border-bottom: 11px solid transparent;
  margin-left: 5px;
}
.cmty-film-graj:hover::before, .cmty-film-graj:focus-visible::before { background: var(--marka-czerwony); transform: scale(1.06); }
@media (prefers-reduced-motion: reduce) { .cmty-film-graj:hover::before { transform: none; } }
.community-detail-obraz img {
  display: block; width: auto; height: auto; max-width: 100%;
  /* max-height jest KONIECZNE: bez niego wysoka infografika (typowe zdjęcie ze słówkami ma
     proporcje ~4:5) rozpycha kartę na kilka ekranów wzwyż i użytkownik nie widzi ani listy
     słówek obok, ani przycisków pod spodem. */
  max-height: 82vh;
  object-fit: contain;
}

/* ---- Powiększenie w stylu Pinteresta ----
   Karta NIE jest nakładką: po otwarciu wskakuje jako pierwszy element siatki i zajmuje
   prostokąt --closeup-kolumny x --closeup-wiersze (oba liczone w JS, patrz przeliczCloseup).
   Dzięki temu mniejsze kafelki opływają ją z prawej i od dołu, są w pełni klikalne i nic
   ich nie przymgla. Wcześniej to była nakładka z max-width w jednostkach EKRANU (52vw),
   więc na szerokim monitorze kolumna zdjęcia rosła ponad szerokość karty i wypychała panel
   z komentarzami poza jej krawędź. */
.community-detail-karta.w-siatce {
  grid-column: 1 / span var(--closeup-kolumny, 3);
  grid-row: 1 / span var(--closeup-wiersze, 40);
  align-self: start;
  width: auto; max-width: none; max-height: none;
  /* Bez przyciemnienia tła karta musi sama odciąć się od kolorowych kafelków wokół */
  box-shadow: 0 20px 60px rgba(2, 6, 23, 0.42);
  border: 1px solid var(--border);
  animation: closeupWjazd 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes closeupWjazd {
  from { opacity: 0; transform: scale(0.965); }
  to   { opacity: 1; transform: none; }
}
/* To kolumna zdjęcia ustępuje miejsca, nigdy panel. flex-basis 0 zamiast auto - przy "auto"
   punktem wyjścia jest naturalna szerokość obrazka, więc wielka grafika znów dyktowałaby
   podział karty. */
/* align-items: flex-start - inaczej przy panelu wyższym niż zdjęcie obrazek wisiał na
   ŚRODKU kolumny i nad nim pojawiał się biały pas (widoczny zwłaszcza po rozwinięciu listy
   słówek). Teraz zdjęcie trzyma się góry, a ewentualny zapas idzie pod spód. */
.community-detail-karta.w-siatce .community-detail-obraz { flex: 1 1 0%; min-width: 0; align-items: flex-start; }
.community-detail-karta.w-siatce .community-detail-obraz img {
  max-height: 74vh; max-width: 100%;
}
.community-detail-karta.w-siatce .community-detail-panel {
  flex: 0 0 340px; min-width: 0; max-height: 74vh;
}
/* Wąska karta (mało kolumn albo mały ekran): zdjęcie nad panelem, bo przy podziale w poziomie
   na obrazek zostawałoby kilkadziesiąt pikseli. Próg liczy JS z realnej szerokości karty. */
.community-detail-karta.w-siatce.pion { flex-direction: column; }
.community-detail-karta.w-siatce.pion .community-detail-obraz { flex: 0 0 auto; }
.community-detail-karta.w-siatce.pion .community-detail-obraz img { max-height: 46vh; }
.community-detail-karta.w-siatce.pion .community-detail-panel {
  flex: 1 1 auto; max-height: none; min-height: 0;
}

/* Strzałka powrotu - lewy górny róg zdjęcia. Zawsze widoczna, bo to główne wyjście z tego
   widoku; chowanie jej za najechaniem zostawiałoby użytkownika bez oczywistej drogi powrotu. */
.community-detail-wroc {
  position: absolute; top: 12px; left: 12px; z-index: 3;
  width: 38px; height: 38px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(255,255,255,0.94); color: #0F172A; font-size: 1.15rem; line-height: 1;
  box-shadow: 0 3px 12px rgba(0,0,0,0.32);
  transition: transform 0.18s cubic-bezier(0.22,1,0.36,1), background 0.18s ease;
}
.community-detail-wroc:hover { transform: translateX(-3px); background: #fff; }

/* ===== AKCJE NA ZDJĘCIU (powiększenie) =====
   Rząd leży NA treści, w prawym górnym rogu lewej kolumny, i jest niewidoczny dopóki kursor
   nie wejdzie na kartę. Powód: to zdjęcie jest tu treścią, a cztery kółka nad tytułem zjadały
   pierwszy wiersz panelu i przyciągały wzrok zanim ktokolwiek zdążył spojrzeć na słówka.
   pointer-events wyłączamy w stanie ukrytym, żeby przezroczyste przyciski nie łapały kliknięć. */
.community-detail-akcje-gora {
  position: absolute; top: 12px; right: 12px; z-index: 4;
  display: flex; gap: 8px;
  opacity: 0; pointer-events: none;
}
.community-detail-karta:hover .community-detail-akcje-gora,
.community-detail-akcje-gora:focus-within { opacity: 1; pointer-events: auto; }

.community-akcja {
  width: 40px; height: 40px; border-radius: 50%; cursor: pointer; flex-shrink: 0;
  border: 1px solid rgba(255,255,255,0.34); background: rgba(15,23,42,0.62); color: #fff;
  font-size: 1rem; line-height: 1;
  /* Każdy przycisk wjeżdża osobno (opóźnienia niżej) - dlatego własne transition zamiast
     wspólnego var(--transition) na rodzicu. */
  opacity: 0; transform: translateY(-10px) scale(0.8);
  transition: opacity 0.26s cubic-bezier(.22,1,.36,1), transform 0.26s cubic-bezier(.22,1,.36,1),
              background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.community-detail-karta:hover .community-akcja,
.community-detail-akcje-gora:focus-within .community-akcja { opacity: 1; transform: none; }
/* Kaskada: przyciski wysypują się kolejno od lewej, zamiast pojawiać się jednym blokiem.
   Przy chowaniu opóźnień NIE ma - znikają razem, bo powolne gaszenie po zjechaniu kursorem
   wygląda jak zacięcie. */
.community-detail-karta:hover .community-akcja:nth-child(1) { transition-delay: 0.02s; }
.community-detail-karta:hover .community-akcja:nth-child(2) { transition-delay: 0.06s; }
.community-detail-karta:hover .community-akcja:nth-child(3) { transition-delay: 0.10s; }
.community-detail-karta:hover .community-akcja:nth-child(4) { transition-delay: 0.14s; }

.community-akcja:hover { background: rgba(15,23,42,0.86); border-color: #fff; transform: translateY(-2px); }
.community-akcja.aktywna { border-color: var(--primary); background: var(--primary); }
/* Polubione/zapisane muszą być widoczne NA PIERWSZY RZUT OKA - przy 16 px różnica między
   konturem a wypełnieniem glifu jest zbyt subtelna, żeby potwierdzić kliknięcie. */
.community-akcja.polubione { border-color: var(--rosso); background: var(--rosso); color: #fff; }
.community-akcja.zapisane-akcja { border-color: var(--zielen-pastel); background: var(--zielen-gleboka); color: #fff; }
/* Akcja główna (dodanie słówek) - po to się tu wchodzi, więc jako jedyna jest wypełniona. */
.community-akcja.glowna { border-color: var(--zielen-pastel); background: var(--zielen-gleboka); color: #fff; }
.community-akcja.glowna:hover { background: var(--zielen-pastel); color: var(--testo); border-color: #fff; }

/* Dotyk nie ma hovera - tam przyciski są po prostu widoczne od razu, inaczej byłyby
   nieosiągalne. To samo przy prefers-reduced-motion: pokazujemy je bez wjazdu. */
@media (hover: none) {
  .community-detail-akcje-gora { opacity: 1; pointer-events: auto; }
  .community-akcja { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .community-detail-akcje-gora { opacity: 1; pointer-events: auto; }
  .community-akcja { opacity: 1; transform: none; transition-delay: 0s !important; }
}
/* Dla paczki miejsce na przyciski rezerwuje reguła .community-detail-karta.paczka
   .community-detail-obraz niżej (ta sama specyficzność, ale późniejsza - musi więc
   ustawiać padding sama, inaczej wygrywała nadpisaniem). */

/* Panel bierze resztę szerokości. min-height pilnuje, żeby przy bardzo szerokim, niskim
   zdjęciu komentarze nie skurczyły się do paska nie do użycia. */
/* Panel NIE przewija się jako całość (overflow:hidden, nie auto). Przewijają się dwie strefy
   w jego środku: lista słówek i lista komentarzy. Dzięki temu formularz komentarza siedzi na
   dole bez żadnego sticky - a to sticky wcześniej nachodziło na tekst listy, bo przewijana
   treść przejeżdżała pod przyklejonym elementem. */
.community-detail-panel {
  flex: 1 1 340px; padding: 22px; overflow: hidden;
  min-width: 300px; min-height: 420px; display: flex; flex-direction: column;
}
/* Nagłówek karty (tytuł, meta, opis, pasek postępu) nigdy się nie kurczy - to on niesie
   informację, czym w ogóle jest ta pozycja. Miejsce oddaje najpierw lista słówek. */
.community-detail-panel > h2,
.community-detail-panel > .community-detail-meta,
.community-detail-panel > .community-ai-nota,
.community-detail-panel > .community-paczka-opis,
.community-detail-panel > .community-postep,
.community-detail-panel > .community-detail-akcje-gora { flex: 0 0 auto; }
/* Sekcja komentarzy schodzi na SPÓD panelu. Panel jest kolumną flex o stałej wysokości karty,
   więc przy krótkiej treści (kilka słówek, brak opisu) formularz "Napisz komentarz" zawisał
   w połowie wysokości z pustką pod spodem. margin-top:auto zjada tę pustkę nad nim. */
.community-komentarze-sekcja { margin-top: auto; padding-top: 14px; }
.community-detail-panel h2 { margin: 0 0 6px; font-size: 1.15rem; }
.community-detail-meta { color: var(--grigio); font-size: 0.78rem; margin-bottom: 14px; }
/* Adnotacja o grafice z generatora - celowo drobna, to informacja, nie ostrzezenie */
.community-ai-nota {
  font-size: 0.66rem; color: var(--muted-light); letter-spacing: 0.02em;
  margin: -8px 0 12px;
}
/* Ok. 5 rzędów chipów, potem własny suwak. Wcześniej ta lista rosła do 34vh i spychała
   komentarze poza dolną krawędź karty - a komentarze są tu treścią, nie dodatkiem.
   flex: 0 1 auto => przy ciasnej karcie to ona oddaje miejsce jako pierwsza. */
.community-detail-slowa {
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px;
  flex: 0 1 auto; min-height: 0; max-height: 210px; overflow-y: auto; padding-right: 4px;
}

/* Komentarze zajmują miejsce po dawnych wielkich przyciskach i rosną do dołu panelu */
.community-komentarze-sekcja {
  display: flex; flex-direction: column;
  /* min-height, nie samo flex:1 - komentarze mają ZAWSZE dostać kawałek karty, nawet gdy
     nad nimi jest długi opis paczki i pełna lista słówek. */
  flex: 1 1 auto; min-height: 190px;
  border-top: 1px solid var(--border); padding-top: 14px;
}
.community-komentarze-naglowek { font-size: 0.82rem; font-weight: 800; margin-bottom: 10px; }
.community-komentarze-naglowek span { color: var(--grigio); font-weight: 600; }
.community-komentarze-lista { flex: 1 1 auto; overflow-y: auto; min-height: 0; margin-bottom: 10px; padding-right: 4px; }
.community-komentarz {
  display: flex; gap: 9px; padding: 8px 0; border-bottom: 1px solid var(--border-warm-soft);
}
.community-komentarz:last-child { border-bottom: none; }
.community-komentarz-tresc { flex: 1; min-width: 0; }
.community-komentarz-autor { font-size: 0.78rem; font-weight: 800; }
.community-komentarz-kiedy { font-size: 0.68rem; color: var(--muted-light); font-weight: 500; }
.community-komentarz-tekst { font-size: 0.83rem; line-height: 1.5; word-wrap: break-word; margin-top: 2px; }
/* Akcje siedzą w jednej linii z autorem i datą - pod tekstem robiły niepotrzebny drugi wiersz */
.community-komentarz-akcje { margin-left: 6px; }
.community-komentarz-akcje button {
  background: none; border: none; padding: 0; cursor: pointer; font-family: inherit;
  font-size: 0.7rem; color: var(--muted-light); transition: var(--transition);
}
.community-komentarz-akcje button:hover { color: var(--rosso); }
.community-komentarz-akcje button.zgloszony { color: var(--oro); cursor: default; }
.community-komentarz-flaga { font-size: 0.68rem; color: var(--rosso); font-weight: 700; }
.community-komentarze-pusto { color: var(--muted-light); font-size: 0.8rem; padding: 10px 0; }
/* Formularz PRZYKLEJONY do dołu panelu, nie tylko zepchnięty flexem: panel ma własne
   przewijanie, więc przy dłuższej treści (opis paczki + kilkanaście słówek) zwykłe "na końcu
   listy" oznaczało, że do pola komentarza trzeba się doscrollować. sticky trzyma je w kadrze
   zawsze. Tło jest KONIECZNE - bez niego komentarze przewijałyby się widoczne pod polem. */
/* Bez sticky: formularz jest po prostu ostatnim, niekurczliwym elementem kolumny, a lista
   nad nim ma własny suwak. Sticky było obejściem problemu, którego już nie ma. */
.community-komentarz-form { display: flex; gap: 8px; flex: 0 0 auto; }

.community-komentarz-form input {
  flex: 1; box-sizing: border-box; padding: 9px 14px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg-soft); color: var(--testo);
  font-family: inherit; font-size: 0.83rem;
}
.community-komentarz-form input:focus { outline: none; border-color: var(--oro); }
.community-komentarz-form button {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 50%; border: none;
  background: var(--oro); color: var(--na-akcencie); cursor: pointer; font-size: 0.85rem;
  transition: var(--transition);
}
.community-komentarz-form button:hover { filter: brightness(1.1); }
.community-komentarz-licznik {
  text-align: right; font-size: 0.68rem; color: var(--muted-light); margin-top: 4px;
  flex: 0 0 auto;
}
.community-komentarz-licznik.blisko { color: var(--oro); font-weight: 700; }
.community-slowo-chip {
  background: var(--bg-soft); border: 1px solid var(--border-2); border-radius: 999px;
  padding: 5px 11px; font-size: 0.78rem; font-weight: 600; color: var(--testo);
}
.community-slowo-chip small { color: var(--grigio); font-weight: 500; }
/* Zielona ramka = słówko, które użytkownik JUŻ zna (ma je w swoich fiszkach). Reszta, czyli
   bez ramki, to dla niego nowość - od razu widać, ile realnie zyska z tego zdjęcia. */
.community-slowo-chip.juz-mam { border-color: var(--verde); border-width: 2px; background: var(--bg-success-soft); }
/* Rozwiń/zwiń - ten sam kształt co pigułka słówka, ale czytelnie klikalny */
.community-chip-akcja {
  cursor: pointer; font-family: inherit; border-color: var(--oro); color: var(--oro);
  background: transparent; transition: var(--transition);
}
.community-chip-akcja:hover { background: var(--oro); color: var(--na-akcencie); }
/* (Wysokość listy słówek ustala reguła .community-detail-slowa wyżej - 210 px i własny
   scroll. Stało tu drugie, późniejsze max-height: 34vh, które ją po cichu nadpisywało:
   na wysokim ekranie to ~370 px, więc rozwinięcie listy realnie rozciągało kartę.) */
/* Usuwanie - celowo stonowane i na samym dole, żeby nie kusiło przy codziennym klikaniu */
.community-detail-usun {
  margin-top: 14px; width: 100%; padding: 9px 14px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--rosso); background: transparent; color: var(--rosso);
  font-family: inherit; font-size: 0.8rem; font-weight: 700; transition: var(--transition);
}
.community-detail-usun:hover { background: var(--rosso); color: #fff; }
.community-detail-close {
  position: absolute; top: 12px; right: 12px; z-index: 3; width: 34px; height: 34px;
  border-radius: 50%; border: none; background: rgba(15,23,42,0.7); color: #fff;
  cursor: pointer; font-size: 0.9rem;
}
.community-upload-karta {
  position: relative; background: var(--card-bg); border-radius: 22px; padding: 28px 26px;
  max-width: 460px; width: 100%; max-height: 88vh; overflow-y: auto; box-shadow: var(--shadow-hover);
}
.community-upload-karta h2 { margin: 0 0 6px; font-size: 1.15rem; }
.community-upload-hint { color: var(--grigio); font-size: 0.85rem; line-height: 1.55; margin: 0 0 18px; }
.community-upload-pole { display: block; margin-bottom: 14px; }
.community-upload-pole span { display: block; font-size: 0.8rem; font-weight: 700; margin-bottom: 6px; }
/* Warunki wgrywania zdjęć - widoczne od razu po wejściu w zakładkę "Zdjęcie" */
.photo-warunki {
  background: var(--bg-warn-soft); border-radius: 14px; padding: 12px 15px; margin-bottom: 14px;
  font-size: 0.78rem; line-height: 1.6; color: var(--muted-dark);
}
.photo-warunki a { color: var(--oro); font-weight: 700; }
.photo-warunki-limit { display: block; margin-top: 6px; }
.photo-duplikat-nota {
  margin-top: 14px; background: var(--bg-warn-soft); border-radius: 12px; padding: 10px 13px;
  font-size: 0.78rem; line-height: 1.5; color: var(--muted-dark);
}
.photo-zgoda.zablokowana { opacity: 0.5; cursor: default; }
.photo-zgoda {
  display: flex; gap: 9px; align-items: flex-start; margin: 12px 0 4px;
  font-size: 0.78rem; line-height: 1.55; color: var(--muted-dark); cursor: pointer;
}
.photo-zgoda input { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; accent-color: var(--oro); }

.community-upload-jezyk {
  display: flex; align-items: center; gap: 8px; margin: 4px 0 16px;
  padding: 10px 13px; border-radius: 12px; background: var(--bg-info-soft);
  font-size: 0.82rem; color: var(--muted-dark);
}
/* Pole tekstowe z przyciskiem akcji w jednej linii (nazwa zbioru + "✨ Auto") */
.pole-z-przyciskiem { display: flex; gap: 8px; align-items: stretch; }
.pole-z-przyciskiem input { flex: 1; min-width: 0; }
.btn-auto-nazwa {
  flex-shrink: 0; border: 2px solid var(--oro); background: transparent; color: var(--oro);
  border-radius: 12px; padding: 0 14px; font-family: inherit; font-size: 0.82rem;
  font-weight: 700; cursor: pointer; transition: var(--transition); white-space: nowrap;
  display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 84px;
}
.btn-auto-nazwa:hover:not(:disabled) { background: var(--oro); color: var(--na-akcencie); }
.btn-auto-nazwa:disabled { opacity: 0.6; cursor: default; }
/* Spinner w tym przycisku ma kontur w kolorze akcentu, bo tło jest przezroczyste */
.btn-auto-nazwa .spinner-w-przycisku { border-color: color-mix(in srgb, var(--oro) 35%, transparent); border-top-color: var(--oro); }

.community-upload-pole input, .community-upload-pole select {
  width: 100%; box-sizing: border-box; padding: 11px 14px; border-radius: 12px;
  border: 2px solid var(--border-2); background: var(--bg-soft); color: var(--testo);
  font-family: inherit; font-size: 0.9rem;
}
/* Rozwijana lista <select> to widget SYSTEMU, nie element strony - nadanie selectowi własnego
   tła sprawia, że Chrome rysuje popup na domyślnym, białym tle, a <option> dziedziczą jasny
   kolor tekstu z motywu ciemnego. Efekt: biała plama z nieczytelnymi napisami. Dlatego opcje
   muszą dostać własne, jawne tło i kolor. */
.community-upload-pole select option {
  background: var(--card-bg);
  color: var(--testo);
}
#cmtyBtn { width: 100%; margin-top: 6px; }

/* Karta uploadu rośnie dopiero z wynikiem OCR - w kroku 1 jest wąskim okienkiem wyboru pliku,
   w kroku 2 musi pomieścić podgląd zdjęcia obok listy słówek. Przejście na max-width daje
   wrażenie rozwijania się tej samej karty zamiast podmiany na inne okno. */
.community-upload-karta { transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1); }
.community-upload-karta.cmty-szeroka { max-width: 780px; }
.cmty-ladowanie {
  display: flex; align-items: center; gap: 13px; padding: 14px 16px; border-radius: 14px;
  background: var(--bg-info-soft); font-size: 0.82rem; color: var(--muted-dark);
}
.cmty-ladowanie strong { display: block; font-size: 0.88rem; }
.cmty-ladowanie span:not(.spinner) { color: var(--grigio); }
.cmty-szkic-uklad { display: grid; grid-template-columns: 250px 1fr; gap: 18px; margin-bottom: 18px; }
.cmty-szkic-podglad { position: relative; }
.cmty-szkic-podglad img {
  display: block; width: 100%; height: auto; max-height: 320px; object-fit: contain;
  border-radius: 14px; background: var(--bg-soft); border: 2px solid var(--border-2);
}
.cmty-zmien-plik {
  width: 100%; margin-top: 8px; border: 2px solid var(--border-2); background: transparent;
  color: var(--grigio); border-radius: 12px; padding: 7px 10px; font-family: inherit;
  font-size: 0.76rem; font-weight: 700; cursor: pointer; transition: var(--transition);
}
.cmty-zmien-plik:hover { border-color: var(--oro); color: var(--oro); }
.cmty-szkic-slowa { display: flex; flex-direction: column; min-width: 0; }
.cmty-szkic-naglowek { font-size: 0.8rem; font-weight: 700; margin-bottom: 8px; }
.cmty-szkic-naglowek span { color: var(--grigio); font-weight: 400; }
.cmty-slowa-lista {
  flex: 1; max-height: 260px; min-height: 90px; overflow-y: auto; display: flex;
  flex-direction: column; gap: 6px; padding-right: 4px;
}
.cmty-slowo-wiersz {
  display: flex; align-items: center; gap: 10px; padding: 7px 11px; border-radius: 11px;
  background: var(--bg-soft); font-size: 0.82rem;
}
.cmty-slowo-tresc { flex: 1; min-width: 0; }
.cmty-slowo-pytanie { font-weight: 700; }
.cmty-slowo-odpowiedz { font-size: 0.75rem; color: var(--grigio); }
/* Ręcznie dopisane wyróżniamy, żeby po dłuższej sesji poprawek było widać, co dołożył
   moderator, a co faktycznie odczytał OCR. */
.cmty-slowo-wiersz.reczne { border-left: 3px solid var(--oro); }
.cmty-slowo-usun {
  flex-shrink: 0; width: 24px; height: 24px; border: none; border-radius: 50%;
  background: transparent; color: var(--grigio); cursor: pointer; font-size: 0.72rem;
  transition: var(--transition);
}
.cmty-slowo-usun:hover { background: var(--rosso); color: #fff; }
.cmty-slowa-pusto { font-size: 0.8rem; color: var(--grigio); padding: 10px 2px; }
.cmty-dodaj-slowo { display: flex; gap: 6px; margin-top: 10px; }
.cmty-dodaj-slowo input {
  flex: 1; min-width: 0; box-sizing: border-box; padding: 8px 11px; border-radius: 11px;
  border: 2px solid var(--border-2); background: var(--bg-soft); color: var(--testo);
  font-family: inherit; font-size: 0.8rem;
}
.cmty-dodaj-slowo button {
  flex-shrink: 0; width: 38px; border: 2px solid var(--oro); background: transparent;
  color: var(--oro); border-radius: 11px; font-size: 1rem; font-weight: 700; cursor: pointer;
  transition: var(--transition);
}
.cmty-dodaj-slowo button:hover { background: var(--oro); color: var(--na-akcencie); }
.cmty-dodaj-hint { font-size: 0.72rem; color: var(--grigio); line-height: 1.5; margin: 8px 0 0; }

@media (max-width: 720px) {
  .cmty-szkic-uklad { grid-template-columns: 1fr; }
  .cmty-szkic-podglad img { max-height: 200px; }
  .cmty-slowa-lista { max-height: 200px; }
}

/* Słówko pochodzące z paczki zdań - delikatny znacznik i lewa krawędź w kolorze akcentu.
   Bez tego nie da się odróżnić własnego słownictwa od tego, co przyszło z cudzą paczką. */
.word-chip.z-paczki { border-left: 3px solid var(--oro); }
.chip-paczka { font-size: 0.72rem; opacity: 0.75; margin-left: 4px; cursor: help; }
.chip-artykul { font-size: 0.72rem; opacity: 0.8; margin-left: 4px; text-decoration: none; }
.chip-artykul:hover { opacity: 1; }
/* Odsyłacz „skąd mam to słówko" na tyle fiszki. Dyskretny: to jest przypis, a nie treść
   karty - ma dać się doczytać, gdy ktoś się zastanowi, i nie rozpraszać, gdy się uczy. */
.card-zrodlo {
  display: inline-block; max-width: 90%; margin-top: 6px; padding: 3px 10px;
  font-size: 0.7rem; line-height: 1.35; text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--grigio); background: var(--bg-soft); border-radius: 999px;
}
.card-zrodlo:hover { color: var(--primary); }

/* Pasek "skąd pochodzą te słówka" nad kategoriami w mapie słówek. Osobno od kategorii, bo
   pochodzenie jest niezależne od tematu - jedna paczka rozsypuje się po kilku kategoriach. */
.wordmap-paczki {
  background: var(--bg-info-soft); border-radius: 14px; padding: 13px 16px; margin-bottom: 16px;
}
.wordmap-paczki-tytul { font-size: 0.8rem; font-weight: 700; margin-bottom: 9px; }
.wordmap-paczka-wiersz {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 6px 0; font-size: 0.82rem;
}
.wordmap-paczka-nazwa { font-weight: 700; }
.wordmap-paczka-ile { color: var(--grigio); font-size: 0.76rem; margin-right: auto; }
.wordmap-paczka-usun {
  border: 2px solid var(--border-2); background: transparent; color: var(--grigio);
  border-radius: 10px; padding: 5px 11px; font-family: inherit; font-size: 0.75rem;
  font-weight: 700; cursor: pointer; transition: var(--transition); white-space: nowrap;
}
.wordmap-paczka-usun:hover { border-color: var(--rosso); color: var(--rosso); }
.wordmap-paczka-przejdz {
  border: 2px solid var(--border-2); background: transparent; color: var(--grigio);
  border-radius: 10px; padding: 5px 11px; font-family: inherit; font-size: 0.75rem;
  font-weight: 700; cursor: pointer; transition: var(--transition); white-space: nowrap;
}
.wordmap-paczka-przejdz:hover { border-color: var(--oro); color: var(--oro); }

/* Postęp w zbiorze: pasek proporcji + podpisy. flex-basis:100% wypycha go do własnego wiersza
   pod nazwą i przyciskami, bo rodzic jest flex-wrap. */
.paczka-postep { flex-basis: 100%; margin-top: 2px; }
.paczka-pasek {
  display: flex; height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--border); margin-bottom: 6px;
}
.paczka-pasek i { display: block; height: 100%; }
.paczka-lvl-lista { display: flex; flex-wrap: wrap; gap: 12px; font-size: 0.72rem; color: var(--grigio); }
.paczka-lvl { display: inline-flex; align-items: center; gap: 5px; }
.paczka-lvl i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
/* Te same trzy kolory co ramka fiszki i suwaki w Ustawieniach - jedna konwencja w całej
   aplikacji: łatwe zielone, średnie niebieskie, trudne czerwone, nowe neutralne. */
.p-latwe   { background: var(--chart-latwe); } .paczka-lvl.p-latwe   { background: none; }
.p-srednie { background: var(--primary); }     .paczka-lvl.p-srednie { background: none; }
.p-trudne  { background: var(--rosso); }       .paczka-lvl.p-trudne  { background: none; }
.p-nowe    { background: var(--border-2); }    .paczka-lvl.p-nowe    { background: none; }
.paczka-lvl.p-latwe i   { background: var(--chart-latwe); }
.paczka-lvl.p-srednie i { background: var(--primary); }
.paczka-lvl.p-trudne i  { background: var(--rosso); }
.paczka-lvl.p-nowe i    { background: var(--border-2); }

/* Pasek trybu paczki bywa KLIKALNY - prowadzi na ścieżkę poziomów tej paczki (patrz pasekPaczkiMaMape). Kursor
   dostaje więc klasa, a nie sam element: pasek nad paczką, której ścieżki nie ma, nie ma udawać przycisku. Reguły
   stały do 2026-09-26 w bloku starej mapy poziomów z zamkami, usuniętej tego dnia razem z nią. */
.paczka-pasek-trybu.ppt-klikalny { cursor: pointer; }
.paczka-pasek-trybu.ppt-klikalny:hover { border-color: var(--oro); }

/* ===== DARMOWA GODZINA PREMIUM: LICZNIK W ROGU =====
   POZYCJA: position: fixed w <body>, a NIE element nagłówka. Nagłówek na telefonie chowa się
   przy przewijaniu (body.naglowek-schowany), w pełnym ekranie fiszek znika całkiem
   (body.focus-mode), a w Społeczności jego zawartość wędruje do pionowego paska
   (przeniesDoPaska) - licznik, który ma odliczać minuty, nie może znikać razem z paskiem,
   po którym nikt nie płacze.
   LEWY DÓŁ: prawy dół należy do toastów (.toast-container), dolny środek do baneru cookies
   i dymka wyniku quizu, a mikrofon Mówienia stoi na środku sceny. W Czytaniu podjeżdża wyżej,
   bo tam do dołu przykleja się pasek odsłuchu i test ze zrozumienia (position: sticky, 12 px). */
.probne-licznik {
  position: fixed; z-index: 1500; left: 20px; bottom: 20px;
  display: inline-flex; align-items: center; gap: 8px;
  max-width: min(280px, calc(100vw - 32px));
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  font-family: inherit; font-size: 0.78rem; font-weight: 700; line-height: 1.35; text-align: left;
  color: var(--testo); background: var(--card-bg);
  border: 1px solid var(--oro); box-shadow: 0 8px 24px rgba(15, 23, 42, 0.16);
}
.probne-licznik .ico { color: var(--oro); font-size: 0.95rem; margin: 0; flex-shrink: 0; }
.probne-licznik:hover { border-color: var(--oro); filter: brightness(1.03); }
/* Ostatnie minuty: mocniejszy akcent, ale nadal pigułka w rogu, a nie alarm na pół ekranu -
   to ma przypomnieć o decyzji, a nie wyrwać z nauki, w której człowiek właśnie jest. */
.probne-licznik.konczy { border-color: var(--rosso); color: var(--rosso); }
.probne-licznik.konczy .ico { color: var(--rosso); animation: probnePuls 2.6s ease-in-out infinite; }
.probne-licznik.laska { border-style: dashed; }
@keyframes probnePuls { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.16); } }
@media (prefers-reduced-motion: reduce) { .probne-licznik.konczy .ico { animation: none; } }
/* Czytanka: pasek odsłuchu i panel testu siedzą na dole (sticky, 12 px), więc licznik
   ustępuje im miejsca zamiast zasłaniać przycisk odtwarzania. */
body.tryb-teksty .probne-licznik { bottom: 92px; }
@media (max-width: 767px) {
  .probne-licznik {
    left: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    font-size: 0.72rem; padding: 6px 12px; max-width: 62vw;
  }
  body.tryb-teksty .probne-licznik { bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
}

/* ===== KONIEC DARMOWEJ GODZINY: BANER Z LEJKIEM =====
   Ten sam szkielet co okno limitu słówek (.wordmap-overlay + .wordmap-modal): to jest ta sama
   chwila - coś się właśnie skończyło i trzeba pokazać, co dalej - więc nie ma powodu uczyć
   oka drugiego układu. Lista strat jest KRÓTKA i bez liczb: progi konta darmowego zmieniają
   się w swoich miejscach (limit słówek, przydział materiałów, limit Mówienia), a liczba
   wpisana tutaj rozjechałaby się z nimi przy pierwszej zmianie. */
.probne-koniec-opis { margin: 0; font-size: 0.92rem; line-height: 1.6; }
.probne-koniec-strata-tytul { margin-top: 16px; font-weight: 800; font-size: 0.85rem; }
.probne-koniec-lista { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; }
.probne-koniec-lista li { display: flex; gap: 8px; align-items: flex-start; font-size: 0.88rem; line-height: 1.45; }
.probne-koniec-lista .ico { color: var(--grigio); flex-shrink: 0; margin: 2px 0 0; }
.probne-koniec-plany { margin: 18px 0 6px; font-weight: 800; font-size: 0.85rem; }

/* =========================================================
   WSPÓLNY CEL SPOŁECZNOŚCI
   Baner wydarzenia: tytuł, odliczanie, pasek postępu i jedno miejsce na aktywność innych.
   Świadomie nie krzyczy - to jest zaproszenie stojące obok treści, a nie reklama
   zasłaniająca ją do czasu kliknięcia.

   KARTA, A NIE CIEMNY GRADIENT. Wcześniej baner był płatem ciemnej zieleni przechodzącej
   w granat - jedynym takim elementem w całej aplikacji, więc czytał się jak wklejka
   z innego produktu albo jak reklama, którą wzrok uczy się omijać. Teraz to zwykła karta
   z tej samej rodziny co reszta interfejsu, wyróżniona JEDNĄ rzeczą: zielonym paskiem
   akcentu przy krawędzi. Kolory idą przez zmienne, więc ciemny motyw obsługuje się sam -
   wcześniej cały baner był na sztywno biały-na-ciemnym i w ciemnym motywie świecił.
   ========================================================= */
.wyz-baner {
  position: relative; overflow: hidden;
  background: var(--card-bg); color: var(--testo);
  border: 1px solid var(--border-warm); border-radius: 20px;
  padding: 16px 18px 16px 22px; margin-bottom: 16px;
  box-shadow: 0 6px 20px -8px rgba(15, 23, 42, 0.18);
}
/* Pasek akcentu przy lewej krawędzi (przy prawej w językach pisanych od prawej - stąd
   inset-inline, a nie left). To on niesie „to jest wspólny cel", zamiast całego tła. */
.wyz-baner::before {
  content: ''; position: absolute; inset-block: 0; inset-inline-start: 0; width: 5px;
  background: linear-gradient(180deg, #16A34A, #15803D);
}
.wyz-gora { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.wyz-tytul { font-size: 0.98rem; font-weight: 800; line-height: 1.3; flex: 1; min-width: 200px; }
.wyz-zegar {
  font-size: 0.76rem; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--bg-success-soft); color: var(--verde);
  padding: 4px 10px; border-radius: 999px; white-space: nowrap;
}
/* Krzyżyk chowa baner NA STAŁE, ale tylko to jedno wydarzenie - zapamiętany jest podpis
   wyzwania, więc następne pokaże się normalnie (patrz zamknijWyzwanie w JS). */
.wyz-zamknij {
  border: none; background: var(--bg-soft); color: var(--grigio);
  width: 26px; height: 26px; border-radius: 50%; cursor: pointer; flex-shrink: 0;
  font-size: 0.95rem; line-height: 1; display: flex; align-items: center; justify-content: center;
  transition: var(--transition);
}
.wyz-zamknij:hover { background: var(--border); color: var(--testo); }
.wyz-zamknij:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }

/* Licznik i procent to główna informacja tego banera, więc dostają pełny kontrast tekstu
   i cyfry o stałej szerokości - inaczej „1 234" skacze w bok przy każdym doliczeniu. */
.wyz-liczby {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 0.82rem; margin-bottom: 8px; color: var(--muted-dark);
  font-variant-numeric: tabular-nums;
}
.wyz-liczby b { font-size: 1.22rem; font-weight: 800; color: var(--testo); }
.wyz-liczby .wyz-pct b { color: var(--verde); }
.wyz-pasek-tlo {
  height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--bg-soft); border: 1px solid var(--border-warm);
}
.wyz-pasek {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, #16A34A, #15803D);
  /* Długie przejście, bo pasek rusza o ułamki procenta - skok byłby niewidoczny,
     a powolne dojechanie widać kątem oka i to ono niesie „coś się właśnie stało". */
  transition: width 1.2s cubic-bezier(.22, 1, .36, 1);
  position: relative;
}
/* Połysk sunący po pasku - jedyny ruch w banerze, gdy nikt nic akurat nie robi. */
.wyz-pasek::after {
  content: ''; position: absolute; inset: 0; border-radius: 999px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.45), transparent);
  animation: wyzPolysk 2.6s ease-in-out infinite;
}

@keyframes wyzPolysk { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }

/* JEDNO MIEJSCE NA AKTYWNOŚĆ INNYCH - patrz wyzRuszStrumien w JS.
   Slot ma STAŁĄ wysokość (min-height), bo inaczej baner podskakiwałby przy każdej zmianie
   wpisu: „La fossa" i „przyimek nieregularny" mają różną długość, a przy zawinięciu do
   drugiego wiersza rósłby cały element. */
/* Aktywność i licznik uczestników stoją W JEDNYM WIERSZU: pigułka z nickiem po lewej,
   „bierze udział / aktywnych teraz" tuż za nią. Wcześniej były to dwa osobne wiersze jeden
   pod drugim - a że pigułka i tak zajmuje ledwie kawałek szerokości, obok niej zostawało
   puste pole, a baner rósł o cały wiersz bez powodu. Złączenie ich odbiera banerowi te
   ~28 px wysokości i nic nie zabiera z treści.
   flex-wrap, bo na wąskim ekranie długi nick plus dwie liczby nie zmieszczą się obok
   siebie - wtedy licznik schodzi pod pigułkę, czyli tam, gdzie był do tej pory. */
.wyz-dol {
  display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap;
  margin-top: 12px; min-height: 30px;
}
.wyz-strumien { min-height: 30px; display: flex; align-items: center; min-width: 0; }
.wyz-wpis {
  display: inline-flex; align-items: center; gap: 7px; max-width: 100%;
  background: var(--bg-soft); border: 1px solid var(--border-warm); border-radius: 999px;
  padding: 5px 12px; font-size: 0.76rem; color: var(--muted-dark);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transition: opacity 0.4s ease;
}
.wyz-wpis.widoczny { opacity: 1; }
.wyz-wpis-kto { font-weight: 700; color: var(--testo); }
.wyz-wpis b { font-weight: 800; color: var(--verde); }
.wyz-wpis-plus {
  font-weight: 800; color: var(--verde);
  background: var(--bg-success-soft); border-radius: 999px; padding: 1px 7px;
}

/* Ilu ludzi bierze udział. Kropka pulsuje TYLKO wtedy, gdy ktoś faktycznie był aktywny
   w ostatnim kwadransie - inaczej byłaby ozdobą udającą ruch, którego nie ma. */
/* Bez margin-top i bez kurczenia: to jest teraz sąsiad pigułki w tym samym wierszu,
   a nie osobne piętro banera. */
.wyz-ludzie {
  display: flex; align-items: center; gap: 7px; font-size: 0.76rem;
  color: var(--grigio); flex-shrink: 0; white-space: nowrap;
}
.wyz-ludzie .zywa-kropka {
  width: 7px; height: 7px; border-radius: 50%; background: var(--verde); flex-shrink: 0;
  animation: wyzTetno 1.8s ease-in-out infinite;
}
@keyframes wyzTetno { 50% { opacity: 0.25; transform: scale(0.75); } }

/* Osiągnięty cel: pasek zamiera na 100%, połysk gaśnie - bo już się nie dzieje. */
.wyz-baner.zdobyte .wyz-pasek::after { animation: none; opacity: 0; }
.wyz-zdobyte {
  margin-top: 10px; font-size: 0.86rem; font-weight: 700;
  background: var(--bg-success-soft); color: var(--verde);
  border-radius: 12px; padding: 9px 13px;
}

@media (prefers-reduced-motion: reduce) {
  .wyz-pasek::after, .wyz-konfetti i, .wyz-ludzie .zywa-kropka { animation: none; }
  /* Wpisy nadal się zmieniają (to informacja, nie ozdoba), ale bez przenikania -
     pojawiają się od razu, w pełnej widoczności. */
  .wyz-wpis { transition: none; opacity: 1; }
  .wyz-pasek { transition: none; }
}

/* Konfetti. Bez biblioteki: kilkadziesiąt divów, każdy z własnym opóźnieniem i obrotem.
   pointer-events:none, bo świętowanie nie ma prawa przeszkodzić w klikaniu. */
.wyz-konfetti { position: fixed; inset: 0; z-index: 2500; pointer-events: none; overflow: hidden; }
.wyz-konfetti i {
  position: absolute; top: -12px; width: 9px; height: 14px; border-radius: 2px;
  animation: wyzSpada linear forwards;
}
@keyframes wyzSpada {
  to { transform: translateY(104vh) rotate(var(--obrot, 540deg)); opacity: 0.15; }
}

@media (prefers-reduced-motion: reduce) {
  .wyz-pasek::after, .wyz-konfetti i, .wyz-ludzie .zywa-kropka { animation: none; }
  /* Taśma zatrzymana, ale NIE ukryta: pigułki zostają czytelne, po prostu nie jadą. */
  .wyz-tasma { animation: none; }
  .wyz-pasek { transition: none; }
}

/* =========================================================
   ONBOARDING STEROWANY AKCJĄ
   Zastępuje oprowadzanie z przyciskiem "Dalej". Różnica nie jest kosmetyczna: tamto
   ZATRZYMYWAŁO aplikację i kazało czytać, to tylko pokazuje palcem i czeka, aż człowiek
   sam coś zrobi. Dlatego nie ma tu żadnej nakładki przyciemniającej ekran ani przechwytywania
   kliknięć - wskazówka jest warstwą NAD interfejsem, a nie zamiast niego.
   ========================================================= */

/* Poświata na aktywnym elemencie. box-shadow, nie outline: nie wchodzi w układ, więc
   nie przesuwa niczego pod sobą i działa na elemencie dowolnego kształtu. */
.akcja-cel {
  position: relative; z-index: 60;
  border-radius: 12px;
  animation: akcjaPuls 1.6s ease-in-out infinite;
}
@keyframes akcjaPuls {
  0%, 100% { box-shadow: 0 0 0 0 rgba(27, 126, 65, 0.55); }
  50%      { box-shadow: 0 0 0 9px rgba(27, 126, 65, 0); }
}

/* Kropka przy celu - dla elementów, których nie wypada obrysowywać (pojedyncze słowo
   w zdaniu). Sama się pozycjonuje przy lewej krawędzi celu. */
.akcja-kropka {
  position: fixed; z-index: 61; width: 10px; height: 10px; border-radius: 50%;
  background: var(--verde); pointer-events: none;
  animation: akcjaPuls 1.6s ease-in-out infinite;
}

.akcja-dymek {
  position: fixed; z-index: 62; max-width: 260px;
  background: var(--testo); color: var(--bianco);
  padding: 9px 13px; border-radius: 12px;
  font-size: 0.82rem; line-height: 1.45; font-weight: 600;
  box-shadow: 0 8px 26px rgba(15, 23, 42, 0.28);
  /* Kliknięcia MUSZĄ przechodzić przez dymek: gdyby je łapał, wskazówka zasłaniałaby
     dokładnie to, do czego zachęca. */
  pointer-events: none;
  animation: akcjaDymekWejscie 0.28s cubic-bezier(.22, 1, .36, 1) both;
}
@keyframes akcjaDymekWejscie {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.akcja-dymek::after {
  content: ''; position: absolute; width: 10px; height: 10px;
  background: var(--testo); transform: rotate(45deg);
  left: var(--ogon-x, 24px); bottom: -5px;
}
.akcja-dymek.pod::after { bottom: auto; top: -5px; }

/* Toast w prawym górnym rogu - jedyny element tego onboardingu, o który nikt nie prosił
   kliknięciem, więc znika sam i nie ma przycisku zamknięcia do przeoczenia. */
.akcja-toast {
  position: fixed; top: 84px; right: 20px; z-index: 62; width: 280px;
  background: var(--card-bg); border: 1px solid var(--border-warm); border-radius: 16px;
  box-shadow: var(--shadow-hover); padding: 12px; display: flex; gap: 11px;
  animation: akcjaToastWejscie 0.35s cubic-bezier(.22, 1, .36, 1) both;
}
.akcja-toast.znika { animation: akcjaToastWyjscie 0.3s ease forwards; }
@keyframes akcjaToastWejscie {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: none; }
}
@keyframes akcjaToastWyjscie {
  to { opacity: 0; transform: translateX(24px); }
}
.akcja-toast img {
  width: 62px; height: 62px; object-fit: cover; border-radius: 11px; flex-shrink: 0;
}
.akcja-toast-tresc { font-size: 0.79rem; line-height: 1.45; }
.akcja-toast-tresc b { display: block; margin-bottom: 3px; }

@media (max-width: 640px) {
  .akcja-toast { top: auto; bottom: 16px; right: 12px; left: 12px; width: auto; }
}

/* Cząsteczki przy zdobyciu XP w onboardingu. Nie ma tu licznika ani paska - cały sens
   jest w tym, że coś się dzieje DOKŁADNIE tam, gdzie człowiek właśnie kliknął. */
.akcja-iskra {
  position: fixed; z-index: 63; pointer-events: none;
  font-weight: 800; font-size: 0.9rem; color: var(--verde);
  animation: akcjaIskra 0.9s ease-out forwards;
}
@keyframes akcjaIskra {
  from { opacity: 1; transform: translate(-50%, 0) scale(0.8); }
  to   { opacity: 0; transform: translate(-50%, -46px) scale(1.1); }
}

@media (prefers-reduced-motion: reduce) {
  .akcja-cel, .akcja-kropka { animation: none; box-shadow: 0 0 0 3px rgba(27,126,65,0.5); }
  .akcja-dymek, .akcja-toast, .akcja-iskra { animation: none; }
}


/* Kafle poziomu w starym wyglądzie (.start-cel.start-poziom z podpisem <small>) zeszły 2026-09-27: ekran poziomu
   rysuje dziś sekcja „LEJEK W STYLU KANWY" (.lk-kafel-poziom, podpis .lk-poziom-opis). */

/* ===== PANEL KONTA =====
   Otwierany kliknięciem w awatar. Zbiera to, co człowiek chce o sobie wiedzieć, w jednym
   miejscu: ile umie, ile z tego oddał innym i jak bardzo mu się to przydało. Świadomie NIE
   pokazuje limitu liczbowo - od tego jest pierścień, który mówi to samo, nie strasząc. */
.konto-panel { max-width: 460px; }
.konto-panel .wordmap-body { padding: 0 22px 22px; }

.konto-glowa { text-align: center; padding: 26px 22px 18px; }
.konto-glowa .awatar-pierscien { display: inline-block; padding: 5px; }
.konto-glowa .account-avatar { width: 104px; height: 104px; font-size: 2.4rem; }
.konto-nick { font-size: 1.25rem; font-weight: 800; margin-top: 12px; }
.konto-podpis { font-size: 0.8rem; color: var(--grigio); margin-top: 3px; }

.konto-kafle { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
.konto-kafel {
  background: var(--card-bg); border: 1px solid var(--border-warm);
  border-radius: 16px; padding: 13px 12px; text-align: center;
}
.konto-kafel-liczba { font-size: 1.45rem; font-weight: 800; line-height: 1.15; }
.konto-kafel-podpis { font-size: 0.72rem; color: var(--grigio); margin-top: 3px; }

/* ===== ODZNAKA TWÓRCY =====
   Format jest ŚCIŚLE ustalony: [ikona] [tytuł rangi] [poziom] · [wskaźnik]%. Stoi przy
   autorze materiału w Społeczności, więc musi mieścić się w jednej linijce metadanych
   i czytać się przy 12 px - stąd pigułka, a nie karta.

   Barwa i ramka idą za KRUSZCEM (szary → brąz → srebro → złoto → diament → korona), nie za
   samym poziomem: sześć rodzin kolorów da się rozróżnić rzutem oka, trzydzieści odcieni nie.
   Każdy kruszec ma osobne wartości dla trybu ciemnego - jasne wypełnienia (srebro, złoto)
   na grafitowym tle świeciłyby jak lampka.

   Kolory są tu wpisane wprost, a nie przez tokeny palety, bo to JEDYNE miejsce w aplikacji,
   które ich używa, i mają oznaczać kruszec, a nie stan (sukces/błąd/informacja). Wciągnięcie
   ich do palety sugerowałoby, że wolno ich użyć gdzie indziej. */
.tw-odznaka {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border-radius: 999px;
  font-size: 0.68rem; font-weight: 800; line-height: 1.5;
  white-space: nowrap; vertical-align: middle; flex-shrink: 0;
  border: 1px solid var(--tw-ramka); background: var(--tw-tlo); color: var(--tw-tekst);
}
.tw-odznaka-ikona { font-size: 0.78rem; line-height: 1; }
/* Wskaźnik jest cichszy od nazwy rangi: rangę czyta się z dumą, procent to przypis. */
.tw-odznaka-pct { opacity: 0.72; font-weight: 700; }

/* Szary „Obserwator” idzie dziś na tokenach w sekcji 16 stylu kanwy (sam odwraca się z motywem). */
.tw-odznaka.braz    { --tw-tlo: #FBEDE3; --tw-ramka: #D8A278; --tw-tekst: #8A5124; }
.tw-odznaka.srebro  { --tw-tlo: #F2F4F7; --tw-ramka: #B4BDC9; --tw-tekst: #4A5567; }
.tw-odznaka.zloto   { --tw-tlo: #FCF3D9; --tw-ramka: #DCB540; --tw-tekst: #7D5F08; }
.tw-odznaka.diament { --tw-tlo: #E4F4FA; --tw-ramka: #7CC4DD; --tw-tekst: #14607B; }
.tw-odznaka.korona  { --tw-tlo: #F0E9FB; --tw-ramka: #A98CDD; --tw-tekst: #5B3A9E; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tw-odznaka.braz    { --tw-tlo: #33231A; --tw-ramka: #8A5A34; --tw-tekst: #E0AC7E; }
  :root:not([data-theme="light"]) .tw-odznaka.srebro  { --tw-tlo: #262C36; --tw-ramka: #5C6879; --tw-tekst: #CBD5E1; }
  :root:not([data-theme="light"]) .tw-odznaka.zloto   { --tw-tlo: #332C16; --tw-ramka: #8F7420; --tw-tekst: #EBC85E; }
  :root:not([data-theme="light"]) .tw-odznaka.diament { --tw-tlo: #16303A; --tw-ramka: #3C7E96; --tw-tekst: #8FD5EA; }
  :root:not([data-theme="light"]) .tw-odznaka.korona  { --tw-tlo: #281E3D; --tw-ramka: #6F55A8; --tw-tekst: #C4ABF0; }
}
:root[data-theme="dark"] .tw-odznaka.braz    { --tw-tlo: #33231A; --tw-ramka: #8A5A34; --tw-tekst: #E0AC7E; }
:root[data-theme="dark"] .tw-odznaka.srebro  { --tw-tlo: #262C36; --tw-ramka: #5C6879; --tw-tekst: #CBD5E1; }
:root[data-theme="dark"] .tw-odznaka.zloto   { --tw-tlo: #332C16; --tw-ramka: #8F7420; --tw-tekst: #EBC85E; }
:root[data-theme="dark"] .tw-odznaka.diament { --tw-tlo: #16303A; --tw-ramka: #3C7E96; --tw-tekst: #8FD5EA; }
:root[data-theme="dark"] .tw-odznaka.korona  { --tw-tlo: #281E3D; --tw-ramka: #6F55A8; --tw-tekst: #C4ABF0; }

/* Podpis autora na kafelku tekstu i paczki. Kafelek zdjęcia ma własny wiersz metadanych
   (.community-tile-meta) leżący na grafice; te dwa obrazka nie mają, więc autor dostaje
   osobną linijkę pod tytułem - tam, gdzie i tak szuka go oko. */
.cmty-autor {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 0.72rem; color: var(--grigio); margin-top: 5px; min-width: 0;
}
.cmty-autor-nick { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Awatar autora + nick jako JEDEN cel kliknięcia. Rozdzielenie ich na dwa linki dawałoby
   dwa sąsiadujące, prawie stykające się cele - a prowadzą w to samo miejsce. */
.cmty-autor-link {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0;
  border: none; padding: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.cmty-autor-foto {
  width: 22px; height: 22px; flex-shrink: 0; border-radius: 50%; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.62rem; font-weight: 800; color: #fff; line-height: 1;
  /* Pierścień oddziela kółko od tła, na którym akurat leży - na kafelku zdjęcia jest nim
     sama grafika, a tam wszystko jest możliwe. */
  box-shadow: 0 0 0 1.5px var(--card-bg), 0 1px 3px rgba(0,0,0,0.28);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.cmty-autor-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Powiększenie o 1% - tyle prosił projekt. Na kółku 22 px to ćwierć piksela, więc samo z
   siebie byłoby niewidoczne; rozjaśniony pierścień niesie tę samą informację („to się da
   kliknąć") w sposób, który da się zobaczyć. */
.cmty-autor-link:hover .cmty-autor-foto {
  transform: scale(1.01);
  box-shadow: 0 0 0 2px var(--zolty), 0 2px 6px rgba(0,0,0,0.32);
}
.cmty-autor-link:hover .cmty-autor-nick { text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { .cmty-autor-foto { transition: none; } }

/* Kółko leżące na METADANYCH kafelka zdjęcia - tam tłem jest gradient na grafice, więc
   pierścień musi być jasny, a nie w kolorze karty. */
.community-tile-meta .cmty-autor-foto { width: 20px; height: 20px; box-shadow: 0 0 0 1.5px rgba(255,255,255,0.85); }
/* W powiększeniu jest więcej miejsca, więc kółko może być czytelne. */
#communityDetailMeta .cmty-autor-foto { width: 26px; height: 26px; font-size: 0.7rem; }
#communityDetailMeta .cmty-autor-link { vertical-align: middle; margin-right: 2px; }

/* Odznaka leżąca na ZDJĘCIU (kafelek tablicy) - tło kafelka jest dowolne, więc pigułka
   musi się bronić sama: mocniejsza ramka i cień pod tekstem. */
.community-tile-meta .tw-odznaka { box-shadow: 0 1px 3px rgba(0,0,0,0.35); }

/* Komunikat o blokadzie publikacji. Mocniejszy niż zwykły status, bo mówi o karze - ale
   NIE czerwony na całej powierzchni: druga połowa tego zdania to dobra wiadomość
   („zdjęcia na własny użytek dodajesz dalej") i ma być przeczytana do końca. */
.tw-blokada {
  display: flex; gap: 9px; align-items: flex-start;
  background: var(--bg-error-soft); border: 1px solid var(--rosso);
  border-radius: 13px; padding: 10px 12px; margin-top: 12px;
  font-size: 0.75rem; line-height: 1.5; color: var(--testo);
}

/* Karta podpisu pod własnymi zgłoszeniami. Pojawia się TYLKO wtedy, gdy jest o czym mówić:
   albo ktoś ma zdjęcia z czasów obietnicy anonimowości, albo ma już podpisane i chce to
   cofnąć. Konto bez ani jednego zgłoszenia nie widzi tu nic. */
.tw-podpis {
  background: var(--card-bg); border: 1px solid var(--border-warm);
  border-radius: 16px; padding: 13px 15px; margin-bottom: 14px;
}
.tw-podpis-naglowek { font-weight: 800; font-size: 0.86rem; margin-bottom: 5px; }
.tw-podpis-opis { font-size: 0.75rem; color: var(--grigio); line-height: 1.5; }
.tw-podpis-akcje { display: flex; gap: 8px; margin-top: 11px; flex-wrap: wrap; }
.tw-podpis-akcje .btn { flex: 1; min-width: 150px; padding: 9px 14px; font-size: 0.8rem; }

/* Wyszarzona zgoda w oknie dodawania zdjęcia - ten sam wygląd, którego używa blokada
   duplikatu (.photo-zgoda.zablokowana), plus zdanie wyjaśniające pod spodem. */
.photo-zgoda-blokada {
  font-size: 0.74rem; line-height: 1.5; color: var(--rosso);
  margin: 6px 0 0 28px; font-weight: 600;
}
/* Nowe konto (odswiezZgodeSpolecznosci): to samo miejsce, ale to nie kara, tylko „od kiedy”, więc bez czerwieni. */
.photo-zgoda-blokada.informacja { color: var(--grigio); }

.konto-wklad { display: flex; gap: 8px; margin-bottom: 16px; }
.konto-wklad-poz {
  flex: 1; background: var(--bg-soft); border-radius: 13px; padding: 9px 8px; text-align: center;
  font-size: 0.72rem; color: var(--grigio);
}
.konto-wklad-poz b { display: block; font-size: 0.98rem; color: var(--testo); }

/* ===== ZGŁOSZENIE ===== */
.konto-zglos-otworz {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px; border-radius: 14px; cursor: pointer; font: inherit; font-size: 0.85rem;
  font-weight: 700; color: var(--testo);
  border: 2px dashed var(--border-warm-dash); background: transparent;
  transition: var(--transition);
}
.konto-zglos-otworz:hover { border-color: var(--oro); color: var(--oro); }

.konto-zglos textarea {
  width: 100%; min-height: 104px; padding: 12px 14px; border-radius: 14px;
  border: 2px solid var(--border-warm); background: var(--card-bg); color: var(--testo);
  font: inherit; font-size: 0.86rem; line-height: 1.55; outline: none; resize: vertical;
}
.konto-zglos textarea:focus { border-color: var(--oro); }
.konto-zglos-stopka {
  display: flex; align-items: center; gap: 10px; margin-top: 9px;
  font-size: 0.73rem; color: var(--grigio);
}
.konto-zglos-stopka .btn { width: auto; margin: 0; margin-left: auto; flex-shrink: 0; }
.konto-zglos-licznik.pusto { color: var(--rosso); font-weight: 700; }

/* Kafle czytanki, utworu i rozmowy na tablicy: sekcja 19 (kafle jak Pinterest, 2026-10-05); karta rozmowy: sekcja 20. */
/* „PACZKA ZDAŃ” to etykieta RODZAJU treści, a nie wyróżnienie - neutralna pigułka
   zamiast koloru akcentu (patrz --pigulka-tlo). */
.paczka-znacznik {
  align-self: flex-start; font-size: 0.66rem; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; padding: 3px 9px; border-radius: 999px;
  background: var(--pigulka-tlo); color: var(--pigulka-tekst);
}
.paczka-nazwa { font-size: 0.98rem; font-weight: 800; line-height: 1.3; }
.paczka-opis { font-size: 0.76rem; color: var(--grigio); line-height: 1.5; }
.community-postep-xp {
  margin-top: 8px; font-size: 0.76rem; color: var(--muted-dark); line-height: 1.5;
}
.community-postep-xp span { color: var(--grigio); }

/* Lewa kolumna karty powiększenia, gdy pokazuje paczkę zamiast zdjęcia */
.community-detail-karta.paczka .community-detail-obraz img { display: none; }
/* padding-top większy niż reszta: paczka nie ma zdjęcia, więc przyciski akcji (prawy górny
   róg kolumny) leżałyby wprost na pierwszym zdaniu z listy. Miejsce rezerwujemy na stałe,
   a nie dopiero przy najechaniu - inaczej cała lista skakałaby przy każdym ruchu kursora. */
.community-detail-karta.paczka .community-detail-obraz {
  align-items: stretch; justify-content: flex-start; padding: 60px 20px 22px; overflow-y: auto;
}
/* ===== UTWÓR ZE „SŁUCHANIA" W KARCIE TABLICY =====
   Przywrócona miniatura w karcie, którą reguła .paczka wyżej chowa dla wszystkiego, co nie jest zdjęciem.
   Kafel utworu na tablicy: sekcja 19 (kafle jak Pinterest). */
/* OKŁADKA UTWORU wypełnia lewą kolumnę, w proporcjach filmu. Reguła `.paczka` wyżej ustawia
   dla tekstów przewijaną kolumnę z transkrypcją - przy utworze transkrypcji nie ma
   (patrz renderTekstWKarcie), więc miejsce należy się okładce.
   aspect-ratio + object-fit: cover, bo miniatury z YouTube bywają w różnych proporcjach,
   a rama ma być zawsze taka sama; bez tego karta zmieniała wysokość zależnie od utworu. */
.community-detail-karta.paczka.utwor .community-detail-obraz {
  align-items: center; justify-content: center; padding: 60px 20px 22px; overflow: hidden;
}
.community-detail-karta.paczka.utwor .community-detail-obraz img {
  display: block; width: 100%; max-width: 760px; aspect-ratio: 16 / 9;
  object-fit: cover; border-radius: 18px; margin: 0 auto;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.28);
}
.cmty-lekcja-link { font-size: 0.85rem; font-weight: 700; color: inherit; }

/* Lista zdań dostaje własne przewijanie zamiast rozciągać kartę w nieskończoność: paczka
   z 30 zdaniami robiła z powiększenia pasek na kilka ekranów wzwyż, przez co ani panelu obok,
   ani reszty tablicy nie było widać bez przewijania całej strony.
   Wysokości nie da się związać z LICZBĄ pozycji w czystym CSS (wiersz ma zmienną wysokość -
   opis potrafi się zawinąć), więc cap jest wyrażony w pikselach dobranych na ~10 wierszy,
   dodatkowo ograniczony do wysokości okna, żeby na laptopie nie wyszedł poza ekran. */
.community-zdania {
  display: flex; flex-direction: column; gap: 10px; width: 100%;
  max-height: min(680px, 64vh); overflow-y: auto; padding-right: 4px;
}
.community-zdanie {
  border-radius: 14px; padding: 12px 15px; background: var(--bg-soft);
  border-left: 3px solid var(--verde);
}
/* Hierarchia jest tu ODWRÓCONA względem intuicji "obcy język najważniejszy": ktoś, kto
   dopiero zaczyna, przegląda paczkę żeby zobaczyć CZEGO SIĘ NAUCZY, a tego nie wyczyta ze
   zdania, którego jeszcze nie rozumie. Na pierwszym planie stoi więc opis po polsku, a samo
   zdanie w języku nauki jest podpisem pod nim. */
.community-zdanie-kontekst {
  font-size: 0.95rem; font-weight: 700; line-height: 1.4; color: var(--testo); margin-bottom: 4px;
}
.community-zdanie-tresc { font-size: 0.8rem; line-height: 1.5; color: var(--grigio); font-style: italic; }
/* Zdanie bez opisu nie ma czego wysuwać na pierwszy plan - wtedy ono samo nim zostaje,
   inaczej cały wiersz byłby wyszarzony i wyglądałby na zablokowany. */
.community-zdanie.bez-kontekstu .community-zdanie-tresc {
  font-size: 0.95rem; font-weight: 700; color: var(--testo); font-style: normal;
}
/* Zablokowane zdanie NIE pokazuje treści - pokazuje, czego brakuje, żeby ją odsłonić.
   Podglądanie zdań, których nie da się jeszcze zagrać, zabrałoby blokadzie sens. */
.community-zdanie.zamkniete { border-left-color: var(--border-2); opacity: 0.85; }
.community-zdanie-brak { font-size: 0.8rem; color: var(--grigio); line-height: 1.5; }
.community-zdanie-brak b { color: var(--muted-dark); }

.community-paczka-opis { font-size: 0.83rem; line-height: 1.6; color: var(--muted-dark); margin: 0 0 12px; }
/* Pasek postępu odblokowania - jedna liczba, którą user realnie śledzi */
.community-postep { margin-bottom: 14px; }
.community-postep-tekst { font-size: 0.78rem; font-weight: 700; margin-bottom: 6px; }
.community-postep-tor { height: 8px; border-radius: 999px; background: var(--border-2); overflow: hidden; }
.community-postep-wypelnienie { height: 100%; background: var(--marka-zielony); border-radius: 999px; transition: width 0.4s ease; }

/* ===== KREATOR PACZEK ZDAŃ =====
   Ta sama karta co przy wgrywaniu zdjęcia (klasy .community-upload-*), tylko szersza w kroku 2:
   zdania czyta się liniami, a 20 kart pod rząd w wąskim okienku byłoby nie do przejrzenia. */
.pz-karta.pz-szeroka { max-width: 900px; }
.pz-sekcja-tytul {
  font-size: 0.8rem; font-weight: 700; margin: 20px 0 8px;
  display: flex; align-items: center; gap: 8px;
}
.pz-sekcja-tytul span { color: var(--grigio); font-weight: 400; }
.pz-wyjasnienie {
  font-size: 0.76rem; line-height: 1.6; color: var(--muted-dark); margin: 0 0 12px;
  padding: 10px 13px; border-radius: 12px; background: var(--bg-info-soft);
}
/* Słownik paczki - to on, a nie treść zdania, decyduje później o odblokowaniu, więc autor
   musi go widzieć w całości, a nie tylko domyślać się z przykładów. */
.pz-slowa { display: flex; flex-wrap: wrap; gap: 6px; max-height: 132px; overflow-y: auto; }
.pz-slowo {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; border-radius: 999px;
  background: var(--bg-soft); font-size: 0.76rem; white-space: nowrap;
}
.pz-slowo b { font-weight: 700; }
.pz-slowo i { font-style: normal; color: var(--grigio); }

.pz-zdania { display: flex; flex-direction: column; gap: 12px; }
.pz-zdanie {
  border: 2px solid var(--border-2); border-radius: 16px; padding: 14px 16px; background: var(--bg-soft);
  transition: var(--transition);
}
/* Zielona ramka = przeczytane i zatwierdzone. To jedyny stan, w którym zdanie przejdzie
   publikację, więc musi być rozpoznawalny jednym spojrzeniem po całej liście. */
.pz-zdanie.ok { border-color: var(--verde); background: var(--bg-success-soft); }
.pz-zdanie.zly { border-color: var(--rosso); }
.pz-zdanie-gora { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; }
.pz-numer {
  flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%; background: var(--border-2);
  color: var(--muted-dark); font-size: 0.7rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.pz-cel {
  font-size: 0.74rem; font-weight: 700; padding: 3px 9px; border-radius: 999px;
  background: var(--bg-info-soft); color: var(--muted-dark); white-space: nowrap;
}
.pz-zdanie-akcje { margin-left: auto; display: flex; gap: 6px; }
.pz-akcja {
  border: 2px solid var(--border-2); background: transparent; color: var(--grigio);
  border-radius: 10px; padding: 5px 11px; font-family: inherit; font-size: 0.76rem;
  font-weight: 700; cursor: pointer; transition: var(--transition); white-space: nowrap;
}
.pz-akcja:hover { border-color: var(--oro); color: var(--oro); }
.pz-akcja.zatwierdz:hover { border-color: var(--verde); color: var(--verde); }
.pz-akcja.zatwierdz.aktywna { border-color: var(--verde); background: var(--verde); color: var(--na-akcencie); }
.pz-akcja.usun:hover { border-color: var(--rosso); color: var(--rosso); }
.pz-pole { display: block; margin-bottom: 8px; }
.pz-pole > span { display: block; font-size: 0.7rem; font-weight: 700; color: var(--grigio); margin-bottom: 4px; }
.pz-pole input, .pz-pole textarea {
  width: 100%; box-sizing: border-box; padding: 9px 12px; border-radius: 11px;
  border: 2px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  font-family: inherit; font-size: 0.85rem; resize: vertical;
}
.pz-dystraktory { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.pz-dystraktory input { font-size: 0.78rem; padding: 7px 10px; }
.pz-problem {
  margin-top: 8px; padding: 8px 11px; border-radius: 10px; background: var(--bg-warn-soft);
  font-size: 0.75rem; line-height: 1.5; color: var(--muted-dark);
}
.pz-lista-paczek { margin-top: 22px; }
.pz-paczka-wiersz {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 12px;
  background: var(--bg-soft); font-size: 0.82rem; margin-bottom: 6px; cursor: pointer;
  transition: var(--transition);
}
.pz-paczka-wiersz:hover { background: var(--bg-info-soft); }
.pz-paczka-tresc { flex: 1; min-width: 0; }
.pz-paczka-nazwa { font-weight: 700; }
.pz-paczka-meta { font-size: 0.72rem; color: var(--grigio); }
.pz-stopka {
  display: flex; align-items: center; gap: 12px; margin-top: 20px;
  padding-top: 16px; border-top: 2px solid var(--border-2);
}
.pz-stopka .btn { margin: 0; width: auto; }
.pz-podsumowanie { flex: 1; font-size: 0.8rem; color: var(--grigio); line-height: 1.5; }

@media (max-width: 720px) {
  .pz-dystraktory { grid-template-columns: repeat(2, 1fr); }
  .pz-stopka { flex-wrap: wrap; }
}

@media (max-width: 720px) {
  /* Na wąskim ekranie kolumny układają się jedna pod drugą, więc zdjęcie może wziąć całą
     szerokość - max-width:52vw z desktopu zostawiałby tu absurdalnie mały obrazek. */
  .community-detail-obraz { justify-content: center; }
  .community-detail-panel { min-height: 0; }
  .community-full { padding: 14px 12px 50px; }
  .community-board { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
}
.fiszka-toggles {
  display: flex; align-items: center; flex-wrap: wrap; gap: 16px;
  margin: 0 0 18px; font-size: 0.78rem; font-weight: 600; color: var(--grigio);
}
.fiszka-toggle-chip { display: flex; align-items: center; gap: 7px; }
.card-delete-btn {
  border: none;
  background: none;
  font-size: 1rem;
  cursor: pointer;
  opacity: 0.6;
  transition: var(--transition);
  padding: 2px 4px;
  border-radius: 8px;
}
.card-delete-btn:hover { opacity: 1; background: var(--bg-error-soft); transform: scale(1.1); }
.fiszka-counter {
  background: var(--crema);
  padding: 6px 14px;
  border-radius: 50px;
  font-weight: 600;
  font-size: 0.85rem;
  border: 1px solid var(--border-warm);
}
.level-badge {
  padding: 4px 12px;
  border-radius: 50px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
/* Rozbicie szybkiego testu na typy pytań (panel admina) - siatka, żeby paski i procenty
   stały równo w kolumnach niezależnie od długości nazwy quizu. */
.admin-quiz-rozklad { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.admin-quiz-wiersz,
.admin-quiz-legenda {
  display: grid; grid-template-columns: 34px 1fr 64px 78px 52px 62px 34px;
  align-items: center; gap: 10px; font-size: 0.8rem;
}
/* "pusty" = w tej talii nie ma słówka, na którym ten quiz dałoby się zbudować. Zgaszony
   wiersz, ale przełącznik i waga zostają klikalne - konfiguracja dotyczy wszystkich kont,
   nie tylko talii admina. */
.admin-quiz-wiersz.pusty .admin-quiz-nazwa,
.admin-quiz-wiersz.pusty .admin-quiz-pasek,
.admin-quiz-wiersz.pusty .admin-quiz-pct { opacity: 0.45; }
/* Wyłączony globalnie - przekreślona nazwa, żeby odróżnić "nie ma na czym" od "wyłączone". */
.admin-quiz-wiersz.wylaczony .admin-quiz-nazwa { text-decoration: line-through; color: var(--grigio); }
.admin-quiz-waga {
  width: 100%; padding: 3px 6px; border-radius: 8px; border: 1px solid var(--border-2);
  background: var(--card-bg); color: var(--testo); font-family: inherit; font-size: 0.75rem;
  text-align: right; font-variant-numeric: tabular-nums;
}
.admin-quiz-wiersz .toggle { transform: scale(0.72); transform-origin: left center; }
.admin-quiz-nazwa { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.admin-quiz-nazwa b { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Reguła wystąpienia - musi się zawijać, bo to zdanie, a nie etykieta. */
.admin-quiz-nazwa small { font-size: 0.68rem; color: var(--muted-light); line-height: 1.35; }
.admin-quiz-wiersz { align-items: start; padding: 4px 0; }
.admin-quiz-wiersz .toggle, .admin-quiz-wiersz .admin-quiz-waga,
.admin-quiz-wiersz .admin-quiz-pasek, .admin-quiz-wiersz .admin-quiz-pct,
.admin-quiz-wiersz .admin-btn { margin-top: 2px; }
.admin-quiz-pasek { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; }
.admin-quiz-pasek i { display: block; height: 100%; background: var(--primary); }
.admin-quiz-pct { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.admin-quiz-pct.slaby { color: var(--grigio); font-weight: 500; }
.admin-quiz-wiersz .admin-btn { padding: 3px 0; min-width: 0; }
.admin-quiz-legenda { color: var(--grigio); font-size: 0.68rem; margin-top: 2px; }
.admin-quiz-legenda span:nth-child(3), .admin-quiz-legenda span:nth-child(4) { text-align: right; }

.badge-nowe    { background: var(--border-warm-soft); color: var(--muted-dark); }
.badge-latwe   { background: var(--bg-success-soft); color: var(--verde); }
.badge-srednie { background: var(--bg-warn-soft); color: var(--srednie); }
.badge-trudne  { background: var(--bg-error-soft); color: var(--rosso); }

/* ===== 3D FLIP CARD =====
   Wyglad karty siedzi w komponenty/fiszka.php - TYM SAMYM pliku, z ktorego bierze go strona
   artykulu. Wczesniej stal tutaj na stale, a artykul mial wlasna imitacje: inne zaokraglenie,
   inna ramka, inne przyciski ocen. Jedno zrodlo znaczy, ze nie da sie poprawic jednego
   miejsca, zapominajac o drugim. */
/* Kropka poziomu - uzywana i w przyciskach oceny, i w legendach. Czesc tego komponentu,
   bo bez niej .ocena-btn .lvl-dot nie ma czego zmieniac. */
.lvl-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; vertical-align: middle; }
.lvl-dot-latwe   { background: var(--marka-zielony, #35A64D); }
.lvl-dot-srednie { background: var(--marka-niebieski, #2463E9); }
.lvl-dot-trudne  { background: var(--marka-czerwony, #DB2727); }

/* ===== 3D FLIP CARD ===== */
.flip-container {
  perspective: 1200px;
  width: 100%;
  min-height: 320px;
  cursor: pointer;
  margin-bottom: 20px;
}
.flip-inner {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 320px;
  transform-style: preserve-3d;
  transition: transform 0.6s cubic-bezier(.4,0,.2,1);
}
.flip-inner.flipped { transform: rotateY(180deg); }

.flip-front, .flip-back {
  position: absolute;
  width: 100%;
  min-height: 320px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 52px 32px 40px;
  box-shadow: 0 18px 36px -22px rgba(23, 24, 59, 0.45);
}
/* Kolor poziomu trudności BIEŻĄCEJ fiszki - jedna zmienna, z której czytają obie strony karty
   i tekst odpowiedzi. Ta sama konwencja co przy zdaniu przykładowym i suwakach w Ustawieniach:
   łatwe zielone, średnie niebieskie, trudne czerwone. Klasę poziomu ustawia renderCard().
   "Nowe" zostaje neutralne - słówko, którego user jeszcze nie ocenił, nie ma czego sygnalizować,
   a pomalowanie go którymkolwiek z trzech kolorów byłoby kłamstwem o jego stanie. */
.flip-container {
  --poziom-ramka: #9A9CB8;
  --poziom-tekst: var(--testo);
}
/* Odpowiedz na tyle: barwa poziomu zmieszana z kolorem tekstu strony - w jasnym motywie ciemnieje (zielen logo
   #35A64D na bieli ma 3,1 : 1, po zmieszaniu z granatem ~5 : 1), w ciemnym jasnieje. Jedna regula na oba motywy. */
.flip-container.poziom-latwe   { --poziom-ramka: var(--marka-zielony, #35A64D);   --poziom-tekst: color-mix(in srgb, var(--poziom-ramka) 70%, var(--testo)); }
.flip-container.poziom-srednie { --poziom-ramka: var(--marka-niebieski, #2463E9); --poziom-tekst: color-mix(in srgb, var(--poziom-ramka) 80%, var(--testo)); }
.flip-container.poziom-trudne  { --poziom-ramka: var(--marka-czerwony, #DB2727);  --poziom-tekst: color-mix(in srgb, var(--poziom-ramka) 80%, var(--testo)); }

.flip-front {
  background: var(--card-bg);
  border: 3px solid var(--poziom-ramka);
}
.flip-back {
  /* Fallback najpierw: color-mix wspiera każda aktualna przeglądarka, ale gdyby nie zadziałał,
     karta zostaje z czytelnym tłem zamiast przezroczystej. Plansza „Fiszki - odpowiedź”: od jasnej
     barwy poziomu u góry do tła karty w 78% wysokości. */
  background: var(--card-bg);
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--poziom-ramka) 13%, var(--card-bg)) 0%,
    var(--card-bg) 78%);
  border: 3px solid var(--poziom-ramka);
  transform: rotateY(180deg);
}

.card-word {
  font-family: 'Outfit', 'Fredoka', system-ui, sans-serif;
  font-size: 2.8rem;
  font-weight: 800;
  text-align: center;
  letter-spacing: -0.02em;
  line-height: 1.08;
  margin-bottom: 16px;
  word-wrap: break-word;
  overflow-wrap: break-word;
  hyphens: auto;
  max-width: 100%;
}
.card-word-back {
  font-family: 'Outfit', 'Fredoka', system-ui, sans-serif;
  font-size: 2.4rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.08;
  color: var(--poziom-tekst);
  text-align: center;
  margin-bottom: 8px;
  word-wrap: break-word;
  overflow-wrap: break-word;
  hyphens: auto;
  max-width: 100%;
}
/* Dłuższe frazy/zdania (do 25 słów) - mniejsza czcionka, żeby zmieściły się czytelnie na karcie */
.card-word.len-medium, .card-word-back.len-medium { font-size: 1.7rem; letter-spacing: normal; line-height: 1.3; }
.card-word.len-long,   .card-word-back.len-long   { font-size: 1.2rem; letter-spacing: normal; line-height: 1.35; }
.card-emotka { font-size: 4rem; margin-bottom: 16px; }
/* Ikona z sieci ikon (patrz ikony_lib.php) - zastepuje emotke, gdy slowo ma juz rysunek.
   Rozmiar zadaje --rys-h, bo rysunek montuje zamontujRysunek w index.php (Shadow DOM; do 2026-09-27
   zamontujKodPostaci i --postac-h, wspolne z postaciami z konsoli, ktore odeszly). Flaga zgloszenia
   pokazuje sie po najechaniu - stale widoczna bilaby sie o uwage z trescia fiszki. */
.card-ikona { position: relative; display: inline-block; margin-bottom: 10px; }
.card-ikona-rys { --rys-h: 96px; display: block; } /* 96 px od 2026-09-26, jak w aplikacji (plansza „Fiszki - odpowiedź”) */
.card-ikona-flaga {
  position: absolute; top: -8px; right: -20px; width: 24px; height: 24px;
  border: none; border-radius: 50%; background: var(--bg-soft); color: var(--grigio);
  font-size: 0.72rem; line-height: 1; cursor: pointer; opacity: 0; transition: var(--transition);
}
.card-ikona:hover .card-ikona-flaga, .card-ikona-flaga:disabled { opacity: 1; }
.card-ikona-flaga:hover { color: var(--rosso); background: color-mix(in srgb, var(--rosso) 14%, transparent); }
/* Admin/moderator: pod flaga klodka (zatwierdz ikone) i olowek (wlasne synonimy do
   rysowania) - te same 24 px, ten sam slupek po prawej. Zamknieta klodka jest widoczna
   BEZ najechania i na zielono: stan ikony ma byc widac od razu, nie po odkryciu. */
.card-ikona-klodka { top: 20px; }
.card-ikona-syn    { top: 48px; }
.card-ikona-syn:hover { color: var(--verde); background: color-mix(in srgb, var(--verde) 14%, transparent); }
/* Kłódka pokazuje STAN, nie akcję: otwarta zielona = ikona wolna (widać po najechaniu jak
   reszta narzędzi), zamknięta czerwona = zatwierdzona (widać zawsze). Klasy nadaje
   odswiezNarzedziaIkony w index.php. */
.card-ikona-klodka.otwarta { color: var(--verde); }
.card-ikona-klodka.otwarta:hover { color: var(--verde); background: color-mix(in srgb, var(--verde) 14%, transparent); }
.card-ikona-klodka.zamknieta, .card-ikona.zablokowana .card-ikona-klodka { opacity: 1; color: var(--rosso); }
.card-ikona-klodka.zamknieta:hover { color: var(--rosso); background: color-mix(in srgb, var(--rosso) 14%, transparent); }
/* Panel olowka: POJECIE (co narysowac) + synonimy + Zapisz, jedno pod drugim - wysuwa sie
   pod ikona nad reszta karty. Pojecie stoi PIERWSZE, bo to ono prowadzi rysunek: same
   synonimy nie ruszaly go z miejsca (patrz api/ikony.php action=synonimy). */
.card-ikona-syn-panel {
  position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%); z-index: 5;
  display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: 12px;
  background: var(--card-bg); border: 1px solid var(--border-warm); box-shadow: 0 8px 20px rgba(0,0,0,0.18);
}
.card-ikona-syn-panel input {
  width: 250px; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--border-warm);
  background: var(--bg-soft); color: var(--testo); font: inherit; font-size: 0.82rem;
}
.card-ikona-syn-panel button {
  padding: 7px 12px; border-radius: 8px; border: none; background: var(--verde); color: var(--na-akcencie);
  font: inherit; font-size: 0.8rem; font-weight: 700; cursor: pointer;
}
/* Trwa generacja nastepnego szczebla drabinki - rysunek przygasa, flaga pulsuje. */
.card-ikona.czeka .card-ikona-rys { opacity: 0.35; }
.card-ikona.czeka .card-ikona-flaga { animation: ikonaCzeka 1s ease-in-out infinite; }
@keyframes ikonaCzeka { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.25); } }
.card-hint { font-size: 0.9rem; font-weight: 500; color: var(--grigio); margin-top: 14px; }
.card-example {
  font-style: italic;
  font-weight: 500;
  color: var(--testo);
  font-size: 1rem;
  line-height: 1.45;
  text-align: left;
  align-self: stretch;
  margin-top: 16px;
  padding: 12px 16px;
  /* Tło i wcięcie biorą kolor poziomu bieżącej fiszki (patrz .flip-container). Wcześniej tło
     było zielone na sztywno, więc czerwona ramka trudnego słówka siedziała na zielonym pasku. */
  background: rgba(0,146,70,0.06);
  background: color-mix(in srgb, var(--poziom-ramka) 13%, var(--card-bg));
  border-radius: 14px;
  border-left: 4px solid var(--poziom-ramka);
}
/* Na tyle karty tło już jest w barwie poziomu - zdanie stoi na tle karty, żeby się od niego odcinało. */
.flip-back .card-example { background: var(--card-bg); font-style: normal; color: var(--grigio); }
/* Kolor "wcięcia" zdania przykładowego zależny od poziomu trudności aktualnej fiszki -
   ta sama konwencja co suwaki w Ustawieniach: łatwe zielone, średnie niebieskie, trudne czerwone */
.card-example.lvl-latwe   { border-left-color: var(--marka-zielony, #35A64D); }
.card-example.lvl-srednie { border-left-color: var(--marka-niebieski, #2463E9); }
.card-example.lvl-trudne  { border-left-color: var(--marka-czerwony, #DB2727); }
/* Kategoria jako pigułka w lewym górnym rogu karty (plansza „Fiszki”), a nie przygaszony podpis pod treścią. */
.card-kategoria {
  position: absolute;
  top: 16px;
  left: 16px;
  max-width: calc(100% - 100px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--grigio);
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--crema, #F3F5FB);
}
.flip-back .card-kategoria { background: var(--card-bg); }
/* Głośnik: DYSKRETNA ikona, nie zielone koło z emoji. Wymowa jest podręczną czynnością
   na karcie, a nie jej treścią - poprzednia wersja (pełny zielony krąg z 🔊) konkurowała
   wzrokiem ze słowem, o które w tej karcie chodzi. Tło pojawia się dopiero pod kursorem.

   TARCZA MA 44 px ZAWSZE, ikona jest mała: przy przezroczystym tle rozmiar przycisku to
   wyłącznie obszar kliknięcia, więc norma dotykowa (44 px Apple / 48 Google) nie kosztuje
   tu ani piksela wyglądu - osobna reguła @media (pointer: coarse) przestała być potrzebna.

   backface-visibility NA SAMYM PRZYCISKU, nie tylko na stronie karty: z-index daje mu
   własny kontekst rysowania, a ukrycie tylnej ściany rodzica NIE dziedziczy się na dzieci
   z własnym kontekstem - dlatego głośnik przodu prześwitywał w lustrze na tył karty
   i po obrocie widać było dwa. */
/* 2026-09-26 (plansze „Fiszki”): głośnik wraca jako KÓŁKO - granatowe z żółtą ikoną, jak w aplikacji. Nie konkuruje
   już ze słowem tak jak dawny zielony krąg z emoji, bo granat i żółć to barwy przycisków całej aplikacji, a nie
   treści karty. Na desktopie zostaje w prawym górnym rogu (plansza mobilna ma go na dole): obok stoi przycisk odmiany
   (.odmiana-btn w index.php), a oba razem to „narzędzia karty”. W ciemnym motywie odwrotnie - granat na granatowej
   karcie by zniknął. */
.speak-btn {
  position: absolute;
  top: 12px;
  right: 12px;
  background: #17183B;
  color: #FFC83D;
  border: none;
  border-radius: 999px;
  width: 42px;
  height: 42px;
  font-size: 1.05rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: var(--transition);
  z-index: 10;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.speak-btn:hover { transform: scale(1.06); }
:root[data-theme="dark"] .speak-btn { background: #FFC83D; color: #17183B; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .speak-btn { background: #FFC83D; color: #17183B; }
}
/* Strony artykulow nie maja globalnego pomocnika .ico z index.php - minimum potrzebne
   ikonie w tym przycisku jedzie wiec razem z komponentem. */
.speak-btn .ico, .speak-btn i { font-style: normal; line-height: 0; margin: 0; }

/* NIEWIDOCZNA strona karty nie moze lapac klikniec. backface-visibility ukrywa ja z oczu,
   ale hit-test dalej ja widzi - po obrocie glosnik PRZODU siedzial niewidzialny w lustrze
   po lewej stronie tylu i klikniecie tam czytalo slowo z przodu (zmierzone elementFromPoint).
   pointer-events: none na calej schowanej stronie; klik przechodzi wtedy do kontenera,
   czyli robi dokladnie to, co klik w kazde inne miejsce karty - obraca ja. */
.flip-inner.flipped .flip-front { pointer-events: none; }
.flip-inner:not(.flipped) .flip-back { pointer-events: none; }

/* ===== NAVIGACJA STRZAŁKI ===== */
.nav-arrows {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-bottom: 20px;
}
.nav-arrow {
  background: var(--card-bg);
  border: 2px solid var(--border-warm);
  border-radius: 50%;
  width: 48px;
  height: 48px;
  font-size: 1.4rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: var(--transition);
  box-shadow: var(--shadow);
}
.nav-arrow:hover:not(:disabled) { border-color: var(--testo); color: var(--testo); transform: scale(1.1); }
.nav-arrow:disabled { opacity: 0.3; cursor: not-allowed; }
.nav-pos { font-size: 0.9rem; color: var(--grigio); font-weight: 600; min-width: 80px; text-align: center; }

/* ===== PRZYCISKI OCENY - lekko 3D =====
   Trojwymiar robia DWA ciene naraz: twarda "polka" pod spodem (0 4px 0, bez rozmycia -
   to ona wyglada jak bok klawisza) i miekka poswiata koloru oceny. Wcisniecie zjezdza
   przyciskiem o wysokosc polki i ja chowa - palec czuje klik, zanim cokolwiek sie zapisze.
   Odcienie liczy color-mix z tokenow motywu, wiec klawisze trzymaja sie palety takze
   w ciemnym trybie - zadnych kolorow wpisanych na sztywno. */
.ocena-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
  margin-top: 4px;
  /* Polka wystaje 4px pod przycisk - bez tego zapasu przycina ja krawedz siatki. */
  padding-bottom: 4px;
}
/* 2026-09-26 (plansza „Fiszki - odpowiedź”): klawisz w PEŁNYM kolorze poziomu z logo - zielony z granatowym napisem
   (biały miałby na tej zieleni 3,1 : 1), niebieski i czerwony z białym. Półka pod spodem została (to ona robi „klik”
   myszą), tylko liczy się teraz z tej samej barwy, przyciemnionej. Kropka poziomu znika: kolor mówi to sam. */
.ocena-btn {
  --ocena-kolor: var(--grigio);
  --ocena-napis: #FFFFFF;
  min-height: 58px;
  padding: 14px 8px;
  border-radius: 18px;
  border: none;
  font-size: 1rem;
  font-weight: 800;
  cursor: pointer;
  transition: filter 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--ocena-kolor);
  color: var(--ocena-napis);
  box-shadow: 0 4px 0 color-mix(in srgb, var(--ocena-kolor) 72%, #000),
              0 8px 14px color-mix(in srgb, var(--ocena-kolor) 22%, transparent);
}
.ocena-btn:hover { filter: brightness(1.06); }
.ocena-btn:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--ocena-kolor) 72%, #000),
              0 2px 4px color-mix(in srgb, var(--ocena-kolor) 22%, transparent);
}
.ocena-btn .lvl-dot { display: none; }
/* Plakietka skrótu klawiszowego [1] [2] [3] w rogu przycisku (obsługa: KLAWISZE_OCENY w
   index.php, film.php). Na ekranach dotykowych bez myszy nie ma klawiatury - i nie ma plakietki. */
.ocena-btn { position: relative; }
.ocena-btn .ocena-skrot {
  position: absolute; top: 6px; right: 8px; padding: 2px 6px; border-radius: 6px;
  font-family: inherit; font-size: 0.68rem; font-weight: 800; line-height: 1;
  color: var(--ocena-napis); background: color-mix(in srgb, var(--ocena-napis) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--ocena-napis) 45%, transparent); opacity: 0.9;
}
@media (hover: none) { .ocena-btn .ocena-skrot { display: none; } }
.ocena-latwe   { --ocena-kolor: var(--marka-zielony, #35A64D);   --ocena-napis: #17183B; }
.ocena-srednie { --ocena-kolor: var(--marka-niebieski, #2463E9); --ocena-napis: #FFFFFF; }
.ocena-trudne  { --ocena-kolor: var(--marka-czerwony, #DB2727);  --ocena-napis: #FFFFFF; }
@media (prefers-reduced-motion: reduce) {
  .ocena-btn, .ocena-btn:active { transition: none; transform: none; }
}

/* Na telefonie karta jest nizsza, a strzalki ida na krawiedzie ekranu - kciukiem siega sie
   do rogow, nie na srodek. Ta sama regula obowiazuje w artykule, wiec jedzie razem
   z komponentem, a nie zostaje w arkuszu aplikacji. */
@media (max-width: 768px) {
  .flip-container, .flip-inner, .flip-front, .flip-back { min-height: 260px; }
  .flip-front, .flip-back { padding: 26px 18px; }
  .card-word { font-size: 2rem; }
  .card-word-back { font-size: 1.7rem; }
  .nav-arrows { justify-content: space-between; gap: 8px; }
  .nav-arrow { width: 54px; height: 54px; }
}

/* ===== PUSTA LISTA ===== */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--grigio);
}
.empty-state .empty-icon { font-size: 4rem; margin-bottom: 16px; }
.empty-state h3 { font-size: 1.2rem; margin-bottom: 8px; color: var(--testo); }
.empty-state-methods {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px;
  margin-top: 24px;
}
.empty-state-method {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  border: 2px dashed var(--border-warm-dash); border-radius: 14px;
  padding: 16px 20px; min-width: 130px;
  background: var(--crema);
}
.empty-state-method-icon { font-size: 1.8rem; margin-bottom: 2px; line-height: 1; }
.empty-state-method-icon .ico { margin-right: 0; color: var(--oro); }
/* Kafelki są <button>, więc trzeba zdjąć domyślny wygląd przycisku i oddać im kursor. */
.empty-state-method {
  font-family: inherit; cursor: pointer;
  transition: transform 0.18s cubic-bezier(.22,1,.36,1), border-color 0.18s ease, box-shadow 0.18s ease;
}
.empty-state-method:hover { transform: translateY(-3px); border-color: var(--oro); box-shadow: var(--shadow); }
@media (prefers-reduced-motion: reduce) { .empty-state-method:hover { transform: none; } }
.empty-state-method strong { font-size: 0.85rem; color: var(--testo); }
.empty-state-method small { font-size: 0.72rem; color: var(--grigio); }
.empty-state.dragover { border-radius: 16px; background: var(--bg-success-grad-b); }
.empty-state.dragover .empty-state-method { border-color: var(--oro); background: var(--crema); }

/* ===== QUIZ - powłoka wspólna dla mini egzaminu i szybkiego testu (styl inspirowany
   Duolingo: pasek postępu + X na górze, plakietka, pogrubiony nagłówek ćwiczenia, treść
   na całą szerokość, duży przycisk "Sprawdź" na dole zamiast bocznego przycisku w karcie). */
.quiz-topbar { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; }
.quiz-close {
  background: none; border: none; font-size: 1.3rem; color: var(--grigio);
  cursor: pointer; line-height: 1; padding: 4px; flex-shrink: 0;
}
.quiz-close:hover { color: var(--testo); }
.quiz-progress-track {
  flex: 1; height: 12px; border-radius: 999px; background: var(--border-warm-soft); overflow: hidden;
}
.quiz-progress-fill {
  height: 100%; width: 0%; border-radius: 999px; background: var(--marka-zielony);
  transition: width 0.4s cubic-bezier(.4,0,.2,1);
}
.quiz-report-btn {
  background: none; border: none; font-size: 1.1rem; cursor: pointer; line-height: 1;
  padding: 4px; flex-shrink: 0; opacity: 0.55; filter: grayscale(1);
  transition: opacity 0.15s ease, filter 0.15s ease;
}
.quiz-report-btn:hover { opacity: 1; filter: grayscale(0); }
/* Ta sama cicha flaga w Czytaniu, Słuchaniu i Mówieniu (2026-10-08, Alek: „malutka tyci tyci flaga »Zgłoś problem«”). W pasku
   kartki stoi w rzędzie ikon kartki, w Słuchaniu tuż za „Moje filmy”, w Mówieniu pod „Zacznij od nowa”, w miejscu, które
   nagłówek sceny zostawia wolne (margin-inline-end 170px). */
.kartka-zglos { opacity: 0.6; }
.kartka-zglos:hover { opacity: 1; }
.mow-zglos { position: absolute; top: 62px; inset-inline-end: 26px; z-index: 2; }

/* =========================================================================================
   EKRAN STARTU „KOLOROWY WYBUCH” NA STRONIE (2026-10-08, JS: sekcja EKRAN STARTU STRONY). Wszystkie elementy stoją w środku
   ekranu (left/top 50%) i ruszają się WYŁĄCZNIE transformacją i kryciem z jednego zegara requestAnimationFrame, więc całość
   idzie warstwą kompozytora. Rozmiary w px wprost z aplikacji (pt = px). Nakładka jest nad wszystkim (z-index nad oknami)
   i przyjmuje kliknięcie, które ją pomija.
   ========================================================================================= */
.es-start { position: fixed; inset: 0; z-index: 2147483000; overflow: hidden; cursor: pointer; background: var(--es-tlo, #17183B); contain: strict; }
.es-start > * { position: absolute; left: 50%; top: 50%; will-change: transform, opacity; }
.es-kolo, .es-kolo-celu { border-radius: 50%; transform: translate(-50%, -50%) scale(0); }
.es-pierscien { width: 195px; height: 195px; border-radius: 50%; border: 3px solid #FFC83D; box-sizing: border-box; opacity: 0; transform: translate(-50%, -50%); }
.es-ksztalt { box-sizing: border-box; opacity: 0; transform: translate(-50%, -50%); }
.es-kafel { width: 132px; height: 132px; transform: translate(-50%, -50%); }
.es-kafel-tlo { position: absolute; inset: 0; border-radius: 42px; background: #FFFFFF; opacity: 0; }
.es-kafel img { position: absolute; left: 6px; top: 6px; width: 120px; height: 120px; display: block; }
.es-napis { display: flex; transform: translate(-50%, -30px); font-family: var(--font-naglowek, 'Outfit', sans-serif); font-weight: 800;
  font-size: 60px; line-height: 1; letter-spacing: 0.02em; white-space: nowrap; }
.es-napis span { display: inline-block; opacity: 0; }
.es-podpis { transform: translate(-50%, 46px); font-family: var(--font-naglowek, 'Outfit', sans-serif); font-weight: 800; font-size: 14px;
  line-height: 1; letter-spacing: 0.42em; padding-left: 0.42em; white-space: nowrap; opacity: 0; }
@media (max-width: 420px) { .es-napis { font-size: 48px; } }

/* =========================================================================================
   ERGONOMIA DOTYKU - powiększone CELE, nie powiększony wygląd.
   =========================================================================================
   Zmierzone na 375×812 przed poprawką: krzyżyk quizu 29×30, „zgłoś pytanie" 26×26,
   „Wyjdź z paczki" i akcje paska 28 px wysokości, przycisk ▶ przy zakresie czasu 22×22,
   „nie wiem" 22 px. Minimum celu dotykowego to 44 px (Apple) / 48 px (Google) - wszystko
   powyżej trafia się kciukiem bez celowania.

   ZASADY tego bloku:
   - czcionki i wygląd zostają - rośnie TARCZA (min-width/height, padding), nie napis;
   - `pointer: coarse`, nie szerokość ekranu: o rozmiar palca chodzi tak samo na tablecie
     i laptopie z dotykiem; wąski ekran z myszą (okno przy krawędzi) tego nie potrzebuje;
   - elementy już w normie (strzałki 54 px, oceny 61 px, karta, SPRAWDŹ 51 px) - nietykane.
   ========================================================================================= */
@media (pointer: coarse) {
  /* Wyjścia z pełnoekranowych widoków - muszą być nie do spudłowania. */
  .quiz-close, .quiz-report-btn, .wordmap-close {
    min-width: 44px; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
  }

  /* Pasek „Ćwiczysz tylko…": wyjście i akcje z 28 px na pełnowymiarowe pigułki.
     Padding + min-height razem: sam padding kończył na 38 px (zmierzone), a min-height
     na inline-flexie dociąga do normy bez rozpychania napisu. */
  .ppt-wyjscie, .ppt-akcja { padding: 10px 16px; min-height: 44px; }

  /* Wiersze mapy słówek: „ćwicz tylko to" i „otwórz" to główne czynności tych wierszy. */
  .wordmap-paczka-graj, .wordmap-paczka-przejdz { padding: 10px 16px; min-height: 44px; }

  /* „nie wiem" / „nie mogę teraz słuchać": napis zostaje drobny (to celowo NIE jest drugi
     przycisk), ale obszar dotyku rośnie do normy. */
  .bez-audio-btn { padding: 12px 16px; min-height: 44px; }

  /* Przełączniki (tłumaczenia, ustawienia): sam suwak ma 24 px wysokości - etykieta obok
     należy do <label>, więc wystarczy podnieść wspólny wiersz. */
  .toggle-row { min-height: 40px; }
}
.quiz-badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: 0.78rem; font-weight: 800;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--oro); margin-bottom: 8px;
}
.quiz-heading { font-size: 1.5rem; font-weight: 800; color: var(--testo); margin-bottom: 28px; line-height: 1.3; }

.mini-exam-card { text-align: center; }
.mini-exam-input-row { display: flex; flex-direction: column; gap: 14px; max-width: 480px; margin: 0 auto; position: relative; }
/* Flaga „w linii” obok tekstu: tłumaczenie zdania w quizie głosowym (glosTlumHtml). Od 2026-10-03 flagę języka odpowiedzi
   niesie polecenie (quizPolecenie), więc flagi w rogu słowa i pola zeszły razem z kafelkiem fali. */
.lang-flag-inline { display: inline-flex; vertical-align: middle; margin-left: 6px; position: relative; top: -1px; }
.mini-exam-input-row input {
  padding: 16px 18px; border-radius: 14px; border: 2px solid var(--border-warm);
  background: var(--crema); color: var(--testo); font-size: 1.1rem; text-align: center;
}
.mini-exam-input-row input.correct { border-color: var(--verde); background: var(--bg-success-soft); }
.mini-exam-input-row input.wrong { border-color: var(--rosso); background: var(--bg-error-soft); }
.mini-exam-input-row .btn { width: 100%; padding: 16px; font-size: 1rem; }
.mini-exam-feedback { margin-top: 16px; font-weight: 700; min-height: 1.4em; transition: color 0.2s ease; }
.mini-exam-feedback.correct { color: var(--verde); }
.mini-exam-feedback.wrong { color: var(--rosso); }
/* STAN „SPRAWDZAM” (2026-09-27; patrz ODPOWIEDŹ SPRAWDZANA PRZEZ SERWER w JS). Dawne samo kółko czekania na AI
   (.quiz-czekam) zastąpiła poprawna odpowiedź widoczna od 0 ms. Ta linijka NIE ZMIENIA treści przy werdykcie,
   tylko barwę - stąd transition na kolorze karty i pola. Pod nią linijka STANU o stałej wysokości:
   · „Sprawdzam Twoją odpowiedź…” wchodzi dopiero po 200 ms - werdykt z pamięci albo reguły formy (0,1–0,2 s)
     zdąży przed nim, więc nic nie mignie (.quiz-stan-czeka; tę samą liczbę ma aplikacja: STAN_OPOZNIENIE_MS),
   · „Dobrze! Twoja odpowiedź też się liczy.” wchodzi w jej miejsce (.quiz-stan-dobrze),
   · przy „źle” pusta linijka zwija się w 0,2 s (.quiz-stan-znika), zamiast szarpnąć „Dalej” w górę.
   Akcent czekania to --oro (granat, w ciemnym żółty): zieleń znaczy tylko „dobrze”, czerwień tylko „źle”. */
.mini-exam-input-row input { transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease; }
.mini-exam-input-row input.sprawdza:not(.glos-pole) { border-color: color-mix(in srgb, var(--oro) 45%, var(--border)); }
/* „Dalej" czekające na werdykt: na zrzucie przy wspólnym 0,75 (.btn-dalej:disabled niżej) wyglądało na czynne,
   więc tu wyraźniej przygaszone, a kursor mówi, że coś się dzieje. Swoistość 0,3,0 - reguła stoi wyżej w arkuszu. */
.mini-exam-card .btn-dalej:disabled, .mini-exam-card .quiz-dalej:disabled { opacity: 0.5; cursor: progress; }
.mini-exam-input-row .glos-pole.sprawdza { color: var(--grigio); }
.quiz-stan {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: 1.6em; margin-top: 4px; overflow: hidden;
  font-size: 0.82rem; font-weight: 600; color: var(--grigio);
}
.quiz-stan-czeka { opacity: 0; animation: quizStanWejscie 0.25s ease-out 0.2s forwards; }
.quiz-stan-dobrze { font-size: 0.95rem; font-weight: 800; color: var(--verde); animation: quizStanDobrze 0.22s ease-out; }
.quiz-stan-znika { animation: quizStanZnika 0.2s ease-in forwards; }
.quiz-kropki { display: inline-flex; gap: 4px; }
.quiz-kropki i { width: 6px; height: 6px; border-radius: 50%; background: var(--oro); opacity: 0.3; animation: quizKropka 1.2s ease-in-out infinite; }
.quiz-kropki i:nth-child(2) { animation-delay: 0.2s; }
.quiz-kropki i:nth-child(3) { animation-delay: 0.4s; }
@keyframes quizStanWejscie { to { opacity: 1; } }
@keyframes quizStanDobrze { from { opacity: 0; transform: scale(0.94); } to { opacity: 1; transform: none; } }
@keyframes quizStanZnika { to { height: 0; margin-top: 0; } }
@keyframes quizKropka { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }
/* Bez ruchu: te same 200 ms opóźnienia (to one chronią przed mignięciem), ale bez wygaszania i pulsu. */
@media (prefers-reduced-motion: reduce) {
  .quiz-stan-czeka { animation: quizStanWejscie 0.01s linear 0.2s forwards; }
  .quiz-stan-dobrze { animation: none; }
  .quiz-stan-znika { animation: none; height: 0; margin-top: 0; }
  .quiz-kropki i { animation: none; opacity: 0.7; }
}
/* Tłumaczenie zdania na drugiej stronie - ten sam rozmiar co oryginał, ale bez kursywy
   i w kolorze tekstu pomocniczego: to podpowiedź do sprawdzenia się, nie druga główna treść. */
.card-example-tlum { font-style: normal; }

.mini-exam-ai-warning { margin-top: 8px; font-size: 0.82rem; font-weight: 600; color: var(--grigio); }

/* ===== JEDEN PRZYCISK NA KROK QUIZU =====
   Przycisk „SPRAWDŹ" po sprawdzeniu NIE gaśnie i nie znika - zmienia się w miejscu
   w niebieskie „Dalej →". Powód jest prosty: po odpowiedzi ręka i oko są już na tym
   przycisku. Wyszarzenie go i pokazanie drugiego, identycznego przycisku niżej kazało
   przenieść wzrok i kliknąć gdzie indziej dokładnie to samo.

   Pasek „słowo → tłumaczenie" pod werdyktem został usunięty razem z tamtym przyciskiem:
   powtarzał to, co i tak stoi w komunikacie („❌ Poprawna odpowiedź: …"), a przy pytaniu
   o formę czasownika potrafił pokazać zupełnie inne słowo niż to, o które pytano.

   Błękit to token --primary (#2463EA w jasnym motywie, czyli dokładnie blue-600), więc
   stan „dalej" odcina się od zieleni „sprawdź" i sam z siebie mówi, że coś się zmieniło. */
/* Wielkie litery dotyczą wyłącznie stanu „SPRAWDŹ". .btn-dalej stoi NIŻEJ w kaskadzie
   i przy tej samej specyficzności je zdejmuje - dlatego kolejność tych dwóch reguł
   jest tu znacząca, a nie przypadkowa. */
.quiz-sprawdz { text-transform: uppercase; letter-spacing: 0.03em; }
.btn-dalej { background: var(--primary); color: #FFFFFF; text-transform: none; letter-spacing: 0; }
.btn-dalej:hover { background: var(--primary-dark); }
/* Zapasowy przycisk dla quizów BEZ „Sprawdź" (klik w opcję = odpowiedź). Tam nie ma czego
   przekształcać, więc przycisk przejścia rodzi się od razu jako niebieskie „Dalej →". */
.quiz-dalej { width: 100%; margin: 14px 0 0; }

/* POLKA 3D - ta sama co przy ocenach na fiszce (.ocena-btn w komponenty/fiszka.php): cien
   0 4px 0 w ciemniejszym odcieniu tla udaje bok przycisku, a :active wciska go o 3 px w te
   polke. Kolor boku liczymy z tla przycisku, wiec zielony „Sprawdz" i granatowy „Dalej"
   (ten sam element po odpowiedzi, patrz przyciskNaDalej) dostaja kazdy swoj.
   Reguly stoja PO .btn:hover/.btn:active i maja te sama specyficznosc, wiec wygrywaja -
   bez tego .btn:hover zamienialby polke na zwykly rozmyty cien. Zapas 4 px pod spodem, zeby
   polki nie przycinala krawedz kontenera. */
.quiz-sprawdz, .btn-dalej, .quiz-dalej {
  --polka-kolor: var(--verde);
  margin-bottom: 4px;
  transition: background 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 8px 12px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
.btn-dalej, .quiz-dalej { --polka-kolor: var(--primary); }
.quiz-sprawdz:hover, .btn-dalej:hover, .quiz-dalej:hover {
  transform: none;
  box-shadow: 0 4px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 8px 12px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
.quiz-sprawdz:active:not(:disabled), .btn-dalej:active:not(:disabled), .quiz-dalej:active:not(:disabled) {
  transform: translateY(3px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--polka-kolor) 62%, black),
              0 2px 4px color-mix(in srgb, var(--polka-kolor) 18%, transparent);
}
/* Wylaczony (czeka na werdykt AI) - wcisniety i bez polki, zeby bylo widac, ze nie da sie
   go nacisnac drugi raz. */
.quiz-sprawdz:disabled, .btn-dalej:disabled, .quiz-dalej:disabled {
  transform: translateY(3px);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--polka-kolor) 62%, black);
  opacity: 0.75;
}
.quiz-dodatkowo { margin-top: 8px; font-size: 0.82rem; font-weight: 600; color: var(--grigio); }
/* --- Odpowiedź głosem (patrz „ODPOWIEDŹ GŁOSEM" w JS) ---
   Mikrofon jest prawdziwym <button>, żeby dało się na nim stanąć strzałką i klawiaturą jak na
   pozostałych wyjściach z pytania. Rant dookoła domyka się przez cały dozwolony czas nasłuchu
   (GLOS_MAKS_MS, wstawiany do --glos-maks), więc widać, ile go zostało. */
.glos-scena { display: flex; flex-direction: column; align-items: center; }
.quiz-mik {
  position: relative; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
/* margin: 0 jest tu obowiazkowy: globalne .ico:not(:only-child) dostawia 0.45em z prawej
   (ikona ma za sasiada SVG rantu), co w kolku przesuwalo glif o 7 px w lewo. */
.quiz-mik .ico { line-height: 1; margin: 0; }
.quiz-mik:disabled { opacity: 0.45; cursor: default; }
/* Rant czasu: domyka się przez cały dozwolony nasłuch (GLOS_MAKS_MS w --glos-maks), więc widać, ile go zostało. Zieleń
   tekstu (--verde), bo leży na zielonym pierścieniu mikrofonu z kanwy: ciemna w jasnym motywie, jasna w ciemnym. */
.quiz-mik-rant { position: absolute; inset: -6px; transform: rotate(-90deg); pointer-events: none; }
.quiz-mik-rant .plyn {
  fill: none; stroke: var(--verde); stroke-width: 4; stroke-linecap: round;
  stroke-dasharray: 352; stroke-dashoffset: 352; opacity: 0;
}
.quiz-mik.slucha .quiz-mik-rant .plyn { opacity: 1; animation: quizMikRant var(--glos-maks, 8s) linear forwards; }
@keyframes quizMikRant { to { stroke-dashoffset: 0; } }
/* Tłumaczenie przeczytanego zdania pod werdyktem - wyraźniejsze niż szara notatka nad nim. */
.glos-tlum { margin-top: 6px; font-size: 0.95rem; font-weight: 600; color: var(--testo); }
.glos-tlum .lang-flag-inline { margin: 0 4px 0 0; }
/* To samo tłumaczenie, ale NAD zdaniem i przed odpowiedzią („Przeczytaj to zdanie na głos" -
   patrz tlumNadZdaniem). Szare i mniejsze od zdania, żeby było jasne, co się czyta na głos.
   Wysokość zarezerwowana z góry: tłumaczenie bywa dociągane z serwera i bez tego zdanie
   podskakiwałoby w chwili, gdy odpowiedź dojeżdża. */
.glos-tlum-nad {
  max-width: 560px; margin: 0 auto 10px; min-height: 1.35em;
  font-size: 0.9rem; font-weight: 600; line-height: 1.35; color: var(--grigio);
}
.glos-tlum-nad .lang-flag-inline { margin: 0 4px 0 0; }
/* To samo tłumaczenie nad odczytem („Posłuchaj i powtórz zdanie", po odpowiedzi). Odstęp daje
   już odstęp kolumny w .mini-exam-input-row, więc własny margines byłby podwójny. */
.mini-exam-input-row .glos-tlum-odczyt { margin-top: 0; }
/* Silnik serwerowy: nagranie poszło, czekamy na tekst - ikona mruga, rant już zgasł. */
.quiz-mik.mysli .ico { animation: glosMysli 0.9s ease-in-out infinite; }
@keyframes glosMysli { 50% { opacity: 0.3; } }
/* Druga szansa: przycisk pod komunikatem, w tym samym miejscu, w którym potem staje „Dalej". */
.quiz-jeszcze-raz { width: 100%; margin: 12px 0 0; }
@media (prefers-reduced-motion: reduce) {
  .quiz-mik.slucha .quiz-mik-rant .plyn { animation: none; stroke-dashoffset: 0; }
  .quiz-mik.mysli .ico { animation: none; }
}
.mini-exam-done { text-align: center; font-size: 1.6rem; font-weight: 800; color: var(--testo); padding: 40px 0; }

/* ===== KARTKOWKA PISEMNA =====
   Od 2026-10-03 bez kartki w kratkę (kanwa „Kartkówka”: lista wierszy, słowo | pole 50 px); .kartkowka-kartka układa się
   w sekcji 16 „MINI QUIZY”. Poniżej zostaje to, co wspólne z dawną kartką: wiersz, numer, pole i stany werdyktu. */
.kartkowka-wiersz {
  display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.2fr);
  align-items: baseline; gap: 10px;
  min-height: 52px; /* dwie kratki na wiersz - pismo nie wchodzi na linie */
}
.kartkowka-nr { font-size: 0.82rem; font-weight: 700; color: var(--muted-light); }
.kartkowka-obce { font-weight: 800; color: var(--testo); overflow-wrap: anywhere; }
.kartkowka-pole { display: flex; flex-direction: column; min-width: 0; }
.kartkowka-input {
  width: 100%; border: none; border-bottom: 2px dashed var(--border-2);
  background: transparent; color: var(--testo); font: inherit; padding: 4px 2px;
  outline: none;
}
.kartkowka-input:focus { border-bottom-color: var(--oro); border-bottom-style: solid; }
.kartkowka-wiersz.dobrze .kartkowka-input { border-bottom-color: var(--verde); color: var(--verde); font-weight: 700; }
.kartkowka-wiersz.zle .kartkowka-input { border-bottom-color: var(--rosso); color: var(--rosso); text-decoration: line-through; }
/* Poprawna odpowiedz pod skreslona wlasna - jak nauczycielska poprawka na marginesie. */
.kartkowka-poprawna { font-size: 0.82rem; font-weight: 700; color: var(--verde); min-height: 0; transition: color 0.2s ease; }
/* Wiersz, który czeka na serwer (2026-09-27, stan „sprawdzam” jak w pytaniu pojedynczym): poprawna odpowiedź stoi pod
   polem od 0 ms, w kolorze tekstu, a obok niej ta sama linijka stanu, tyle że w wierszu, nie pod nim. */
.kartkowka-input { transition: color 0.2s ease, border-color 0.2s ease; }
.kartkowka-wiersz.sprawdza .kartkowka-input { border-bottom-style: solid; border-bottom-color: color-mix(in srgb, var(--oro) 45%, var(--border-2)); }
.kartkowka-wiersz.sprawdza .kartkowka-poprawna { color: var(--testo); }
.kartkowka-poprawna .quiz-stan { display: inline-flex; height: auto; margin: 0 0 0 8px; vertical-align: middle; font-size: 0.78rem; white-space: nowrap; }
.kartkowka .quiz-sprawdz { width: 100%; max-width: 560px; display: block; margin: 0 auto; padding: 16px; font-size: 1rem; }
@media (max-width: 560px) {
  .kartkowka-wiersz { grid-template-columns: auto minmax(0, 1fr); }
  /* Na waskim ekranie pole schodzi POD slowo (pelna szerokosc na pisanie), numer trzyma rzad. */
  .kartkowka-pole { grid-column: 2; }
}

/* ===== KONIUGACJA - „Odmiana przez osoby” (sekcja KONIUGACJA w JS) =====
   Układ z kanwy „Mini quizy Lingaria” (2026-10-03): postać i znacznik w wierszu polecenia, pod znacznikiem duży lemat
   z czasem, tabela BEZ obwódki - wiersze jak kafle: zrobiony na zielonym tle z ptaszkiem, aktywny z niebieską ramką
   i pierścieniem (wyjątek P8: wybór i „tu jesteś” w mini quizie są niebieskie, nie --oro), czekający z przerywaną ramką,
   zły na czerwonym tle z X i poprawną formą. Tylko tokeny, więc oba motywy działają same; zieleń WYŁĄCZNIE dla
   „dobrze”, czerwień dla „źle”, jak w kartkówce. Podpowiedź („(idziemy)”) pod zaimkiem. */
.mini-exam-card.koniug { text-align: left; max-width: none; margin: 0; gap: 18px; }
.koniug-glowa { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.koniug-naglowek { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; }
.koniug-czas { font-family: var(--font-tekst); font-size: 17px; font-weight: 600; color: var(--grigio); background: none; padding: 0; }
/* Czas w osobnej linii pod lematem, bez kropki (jak w aplikacji); kropka tylko w wierszu z lematem, gdy kolumna quizu ma
   ≥ 600 px. Recenzja 2026-10-03: przy 390 px czas spadał do drugiej linii i zaczynał się od „· ”. */
.koniug-czas { flex-basis: 100%; }
@container quiz (min-width: 600px) {
  .koniug-czas { flex-basis: auto; }
  .koniug-czas::before { content: '· '; }
}
.koniug-licznik { font-family: var(--font-tekst); font-size: 13px; font-weight: 700; color: var(--grigio); }
.koniug-licznik:empty { display: none; }
.koniug-lemat {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 28px; line-height: 1.1;
  letter-spacing: -0.01em; color: var(--testo); overflow-wrap: anywhere;
}
.koniug-tyl { margin: 0; font-family: var(--font-tekst); font-size: 15px; font-weight: 600; color: var(--grigio); overflow-wrap: anywhere; }
.koniug-tabela { list-style: none; margin: 0; padding: 0; border: none; background: none; display: flex; flex-direction: column; gap: 8px; }
.koniug-wiersz {
  display: grid; grid-template-columns: 76px minmax(0, 1fr) 28px; align-items: center; gap: 10px;
  min-height: 56px; padding: 0 14px; border-radius: 16px; border: 2px solid transparent;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.koniug-wiersz + .koniug-wiersz { margin-top: 0; }
.koniug-zaimek-kol { display: flex; flex-direction: column; min-width: 0; }
.koniug-zaimek { font-family: var(--font-tekst); font-weight: 700; font-size: 16px; color: var(--grigio); overflow-wrap: anywhere; }
.koniug-pole { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.koniug-forma { font-family: var(--font-naglowek); font-weight: 700; font-size: 21px; color: var(--testo); overflow-wrap: anywhere; }
.koniug-pusta { color: var(--grigio); font-weight: 600; }
.koniug-wpis { color: var(--grigio); text-decoration: line-through; font-weight: 600; overflow-wrap: anywhere; }
.koniug-pod, .koniug-uwaga { font-family: var(--font-tekst); font-size: 13px; font-weight: 600; color: var(--grigio); }
.koniug-znak { display: inline-flex; align-items: center; justify-content: center; font-size: 20px; }
.koniug-input {
  width: 100%; box-sizing: border-box; padding: 4px 0; border: none; background: transparent; color: var(--testo);
  font-family: var(--font-naglowek); font-size: max(16px, 21px); font-weight: 700;
}
.koniug-input:focus { outline: none; box-shadow: none; }
.koniug-wiersz.aktywny {
  min-height: 64px; background: var(--card-bg); border-color: var(--primary); box-shadow: 0 0 0 4px var(--fokus-pierscien);
}
.koniug-wiersz.aktywny .koniug-zaimek { color: var(--testo); }
.koniug-wiersz.czeka { border: 2px dashed var(--krawedz-kafla); }
.koniug-wiersz.dobrze, .koniug-wiersz.poprawiony { background: var(--bg-success-soft); }
.koniug-wiersz.dobrze .koniug-znak, .koniug-wiersz.poprawiony .koniug-znak { color: var(--verde); }
.koniug-wiersz.zle { background: var(--bg-error-soft); }
.koniug-wiersz.zle .koniug-znak { color: var(--rosso); }
.koniug-wiersz.zle.koniec .koniug-forma { color: var(--testo); }
.koniug-wiersz.koniec { opacity: 1; }
.koniug-kropka { width: 8px; height: 8px; border-radius: 50%; background: var(--primary); }
/* Krótki błysk dobrze trafionego wiersza (250 ms); przy ograniczonym ruchu bez animacji. */
.koniug-wiersz.blysk { animation: koniugBlysk 0.25s ease-out; }
@keyframes koniugBlysk { from { background: color-mix(in srgb, var(--verde) 30%, var(--bg-success-soft)); } to { background: var(--bg-success-soft); } }
.koniug-input.drga { animation: koniugDrga 0.3s ease-in-out; }
@keyframes koniugDrga { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
.koniug-rodzaj { font-size: 13px; font-weight: 600; color: var(--grigio); margin: 0 2px; }
.koniug-zrodlo { margin: 0; text-align: center; font-size: 12px; color: var(--grigio); }
/* „nie wiem” przy czekającym „Dalej” (błąd albo uwaga o pisowni) nie ma już czego pominąć. visibility, nie display,
   żeby przycisk nie podskakiwał. */
.mini-exam-card.koniug.czeka-dalej .quiz-nie-wiem { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  .koniug-wiersz.blysk, .koniug-input.drga { animation: none; }
  .koniug-wiersz { transition: none; }
}
@media (max-width: 560px) {
  .koniug-wiersz { grid-template-columns: minmax(0, 76px) minmax(0, 1fr) 24px; gap: 8px; padding: 0 12px; }
}

/* ===== PODSUMOWANIE PO MINI TEŚCIE =====
   Dotąd runda kończyła się napisem "Gotowe! 🎉" - jedynym w całej aplikacji, którego nawet
   nie tłumaczyliśmy. Wynik komentuje zdanie pod ilustracją (.quiz-koniec-zdanie, POPUPY_ADMIN 'quiz_koniec'):
   kwestia zależy od tego, jak poszło, a trzy warianty na pasmo sprawiają, że to samo zdanie nie wraca przy każdej
   rundzie. Do 2026-09-27 mówiła je postać z konsoli admina w dymku, a bez przypisanej postaci zdanie nie
   pokazywało się wcale - zostawały same liczby. Wygląd planszy w sekcji STYL KANWY (10). */
.quiz-koniec { padding: 6px 0 4px; }

.quiz-koniec-kafle { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.quiz-koniec-kafel {
  background: var(--card-bg); border: 1px solid var(--border-warm);
  border-radius: 16px; padding: 14px 10px; text-align: center;
}
.quiz-koniec-kafel .liczba { font-size: 1.6rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.quiz-koniec-kafel .podpis { font-size: 0.72rem; color: var(--grigio); margin-top: 3px; }
.quiz-koniec-kafel.dobre .liczba { color: var(--verde); }
.quiz-koniec-kafel.zle   .liczba { color: var(--rosso); }
.quiz-koniec-kafel.xp    .liczba { color: var(--oro); }
/* Szybki test: które słówka wypadły (patrz pokazPodsumowanieQuizu) - czerwone pigułki,
   ta sama czerwień co kafelek „źle" nad nimi, żeby było widać, że to jego rozwinięcie. */

/* Pasek dojeżdża dopiero PO wstawieniu w drzewo (patrz requestAnimationFrame niżej) -
   bez tego przeglądarka nie ma od czego animować i szerokość skacze od razu na docelową. */
.quiz-koniec-pasek-tlo {
  height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; margin-top: 14px;
}
.quiz-koniec-pasek {
  height: 100%; border-radius: 999px; background: var(--marka-zielony);
  width: 0; transition: width 0.9s cubic-bezier(.22, 1, .36, 1);
}
.quiz-koniec-akcje { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.quiz-koniec-akcje .btn { flex: 1; min-width: 150px; }
@media (prefers-reduced-motion: reduce) { .quiz-koniec-pasek { transition: none; } }

/* Lista słówek do wyboru: „Nie mogę teraz pisać” i audio_wybor (patrz htmlWyboruZamiastPisania).
   Do 2026-10-03 rysował ją też quiz obrazkowy „Co to jest?” (ikona u góry, słówka pod spodem);
   ten zszedł razem z „Wskaż obrazek” i klasami .quiz-ikona*, lista została, bo jest wspólna. */
.quiz-slowa-lista { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.quiz-slowo-opcja {
  background: var(--bg-soft); border: 2px solid var(--border-2); border-radius: 14px;
  padding: 14px 18px; font-family: inherit; font-size: 1.05rem; font-weight: 700;
  color: var(--testo); cursor: pointer; transition: var(--transition);
}
.quiz-slowo-opcja:hover { border-color: var(--oro); transform: translateY(-2px); }
.quiz-slowa-lista.zablokowane .quiz-slowo-opcja { cursor: default; }
.quiz-slowa-lista.zablokowane .quiz-slowo-opcja:hover { transform: none; border-color: var(--border-2); }
.quiz-slowo-opcja.poprawna { border-color: var(--verde); color: var(--verde); }
.quiz-slowa-lista.zablokowane .quiz-slowo-opcja.poprawna:hover { border-color: var(--verde); }
.quiz-slowo-opcja.bledna { border-color: var(--rosso); opacity: 0.55; }
/* Szesc odpowiedzi zamiast pisania (patrz opcjeZamiastPisania) - dwie kolumny, zeby lista nie
   spychala „nie wiem" i „Dalej" pod ekran; na waskim ekranie wraca jedna kolumna. */
.quiz-slowa-lista.szesc { display: grid; grid-template-columns: 1fr 1fr; }
@media (max-width: 520px) { .quiz-slowa-lista.szesc { grid-template-columns: 1fr; } }
.bez-audio-btn svg { width: 15px; height: 15px; vertical-align: -3px; margin-right: 3px; }

/* Krótka blokada klikania tuż po pojawieniu się quizu - patrz zablokujKlikniecia().
   Blokuje WYŁĄCZNIE wskaźnik; focus i klawiatura działają, więc wpisywanie nie czeka. */
.quiz-blokada-klikniec { pointer-events: none; }

.stats-grid.mini-exam-locked { position: relative; pointer-events: none; opacity: 0.45; filter: grayscale(0.6); }

.mini-exam-fly {
  position: fixed; z-index: 5000; padding: 6px 14px; border-radius: 999px;
  background: var(--card-bg); border: 2px solid var(--border-warm); font-weight: 700;
  font-size: 0.85rem; color: var(--testo); pointer-events: none;
  transition: top 0.7s cubic-bezier(.4,0,.2,1), left 0.7s cubic-bezier(.4,0,.2,1), opacity 0.7s ease;
}
.mini-exam-fly.correct { border-color: var(--verde); color: var(--verde); }
.mini-exam-fly.wrong { border-color: var(--rosso); color: var(--rosso); }

/* ===== PUZZLE "UŁÓŻ ZDANIE" - kafelki w stylu word-banku, jak w screenie referencyjnym ===== */
/* Generowanie zdania/puzzli przez AI trwa realnie kilka sekund - sam statyczny tekst wyglądał
   jak zawieszka, więc leci przy nim ten sam kręcący się .spinner co przy reszcie ładowania. */
.sentence-puzzle-loading {
  padding: 30px 10px; color: var(--grigio); font-size: 0.9rem;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.sentence-puzzle-prompt { font-size: 1.15rem; font-weight: 700; color: var(--testo); margin-bottom: 22px; text-align: center; }
.sentence-puzzle-answer {
  min-height: 52px; display: flex; flex-wrap: wrap; gap: 5px; align-items: center; justify-content: center;
  padding: 10px; margin-bottom: 20px;
  border-bottom: 2px solid var(--border-warm-dash);
  touch-action: none;
}
.sentence-puzzle-pool { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; touch-action: none; }
.sentence-tile {
  display: inline-block; padding: 9px 12px; border-radius: 8px;
  background: var(--card-bg); border: 2px solid var(--border-warm);
  font-weight: 700; color: var(--testo); cursor: grab; user-select: none;
  touch-action: none;
}
.sentence-tile:hover { border-color: var(--oro); }
.sentence-tile.placed { background: var(--bg-gold-soft); border-color: var(--oro); }
.sentence-tile-ghost {
  position: fixed; top: 0; left: 0; z-index: 9999; pointer-events: none;
  transform: translate(-50%, -50%); box-shadow: 0 6px 18px rgba(0,0,0,0.25); opacity: 0.95;
}

/* Klikane słowo w zdaniu quizu: dotknięcie odsłania tłumaczenie w dymku. Nazwa klas została
   po trybie „Uzupełnij zdanie" (odszedł 2026-09-23), ale sam mechanizm jest WSPÓLNY -
   używają go rozsypanka i odmiana przez zdanieZGlosami(). */
.context-word {
  cursor: pointer; border-bottom: 2px dashed var(--border-warm-dash);
  position: relative; padding-bottom: 1px;
}
.context-word.show-gloss::after {
  content: attr(data-gloss);
  position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
  background: var(--testo); color: var(--card-bg); font-size: 0.7rem; font-weight: 700;
  padding: 4px 9px; border-radius: 8px; white-space: nowrap; margin-bottom: 6px; z-index: 5;
}

/* ===== HISTORIA AI ===== */
.parole-usate {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0;
}
.parola-tag {
  background: var(--bg-success-soft);
  color: var(--verde);
  border-radius: 50px;
  padding: 4px 14px;
  font-size: 0.8rem;
  font-weight: 600;
}

/* ===== TOAST / NOTIFICATIONS ===== */
.toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.toast {
  background: var(--card-bg);
  border-radius: 14px;
  padding: 14px 18px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.2);
  font-size: 0.9rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 10px;
  animation: slideIn 0.3s ease;
  max-width: 320px;
  border-left: 4px solid var(--verde);
}
.toast.error { border-color: var(--rosso); }
.toast.warning { border-color: var(--oro); }
@keyframes slideIn {
  from { transform: translateX(100%); opacity: 0; }
  to   { transform: translateX(0);    opacity: 1; }
}

/* ===== LOADER ===== */
/* Ładowanie talii w miejscu fiszek wchodzi po 0,35 s: zwykłe wczytanie (~1/3 s) nie miga niczym, wolne pokazuje spinner.
   Samo krycie, bez ruchu, więc także przy ograniczonym ruchu. (2026-09-28, razem z taliaWczytana.) */
#cardAreaLoader:not(.hidden) { animation: ladowanieTalii 0.2s ease 0.35s both; }
@keyframes ladowanieTalii { from { opacity: 0; } to { opacity: 1; } }
.loader {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
  color: var(--grigio);
  font-size: 0.9rem;
}
.spinner {
  width: 20px; height: 20px;
  border: 3px solid var(--border-warm);
  border-top-color: var(--oro);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* Spinner wewnątrz kolorowego przycisku - mniejszy i w barwach tekstu przycisku, bo domyślny
   (zielony na jasnym) ginąłby na wypełnieniu. display:inline-block trzyma go w jednej linii
   z napisem, zamiast spychać tekst do następnego wiersza. */
.spinner-w-przycisku {
  width: 14px; height: 14px; border-width: 2px;
  /* currentColor, nie biel: w ciemnym motywie napis na akcencie jest grafitowy i biały
     spinner ginąłby na pastelowej zieleni. */
  border-color: color-mix(in srgb, currentColor 40%, transparent); border-top-color: currentColor;
  flex-shrink: 0; /* .btn to inline-flex - bez tego spinner spłaszczyłby się przy długim napisie */
}

/* ===== PROGRESS UPLOAD ===== */
.upload-progress {
  display: none;
  margin-top: 12px;
}
.upload-progress.active { display: block; }

/* ===== SEPARATOR ===== */
.sep {
  border: none;
  border-top: 1px solid var(--border-warm-soft);
  margin: 16px 0;
}

/* ===== SCROLLBAR ===== */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #D4C5B0; border-radius: 6px; }

/* ===== HIDDEN ===== */
.hidden { display: none !important; }

/* ===== ZAPIS FONETYCZNY NAD SŁOWAMI (fonetyka_lib.php, sekcja ZAPIS FONETYCZNY w JS, 2026-09-29) =====
   Zapis stoi w ATRYBUCIE data-fon i rysuje go ::before - w DOM-ie nie ma ani jednego znaku łacinki, więc textContent
   i innerText każdego słowa, zdania i dymka są co do znaku te same, co bez zapisu (klucze zdań Mówienia, lektor, klikane
   słowa, kopiowanie). <ruby><rt> dopisałoby tekst do textContent i trzeba by pilnować każdego miejsca, które go czyta.
   Słowo z zapisem to inline-block: szerokość = szerszy z dwóch (pinyin „zhuàng” nad jednym znakiem nie wjeżdża na sąsiada,
   jak w ruby), a linia bazowa zostaje linią tekstu. BEZ pointer-events: none - zaznaczenie myszą fragmentu kartki Czytania
   („przetłumacz ten fragment”) musi zaczynać się także w słowie z zapisem, a obsługa kliknięć szuka rodzica przez closest(),
   więc dodatkowy span w środku jej nie myli (przejrzane 2026-09-29). Zapis sam nie daje się zaznaczyć (user-select na ::before).
   Konto z wyłączonym zapisem ma na <html> klasę fon-wyl: zapis znika bez przerysowania widoku.
   Rozmiar: 0,58 em słowa pod nim, ale nie mniej niż 11 px - przy zdaniu przykładowym (16 px) samo 0,58 em dawało 9 px,
   na zrzucie telefonu nieczytelne. */
html:not(.fon-wyl) .fon[data-fon] {
  display: inline-block; text-align: center; text-indent: 0; vertical-align: baseline; line-height: 1.2;
}
html:not(.fon-wyl) .fon[data-fon]::before {
  /* Druga deklaracja z tekstem zastępczym "" (przegląd frontu 2026-10-02): treść ::before wchodziła do nazwy dostępności,
     więc czytnik ekranu czytał „Khleb Хлеб” - zapis i słowo, oba głosem języka nauki. Przeglądarka bez tej składni bierze
     pierwszą deklarację. */
  content: attr(data-fon); content: attr(data-fon) / ""; display: block;
  /* KRÓJ SYSTEMOWY, nie Figtree: Figtree nie ma ǐ ǒ ǔ ǖ ǘ ǚ ǜ ani ʿ ʾ (odczyt cmap z TTF, przegląd językowy 2026-10-02), więc
     przeglądarka brała te litery z innego kroju i prawie każde chińskie zdanie miało sylaby z dwóch krojów naraz („nǐ”
     cieńsze obok „hǎo”). Segoe UI, SF, Roboto i Noto mają całe Latin Extended-B (Segoe UI i Arial sprawdzone tym samym
     odczytem) - cały zapis stoi jednym krojem na każdej platformie. */
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Noto Sans', 'Helvetica Neue', Arial, sans-serif;
  font-size: max(0.58em, 11px); line-height: 1.2;
  font-weight: 500; font-style: normal; letter-spacing: 0; text-transform: none; text-decoration: none;
  color: var(--grigio); white-space: nowrap;
  /* Odstęp między sylabami: pinyin nad jednym znakiem bywa szerszy od znaku, a bez niego sąsiednie sylaby zlewały się
     w jedno słowo („wǒxiǎnghē” na zrzucie dymka Mówienia i „xuésheng” nad kartą na telefonie). */
  padding: 0 0.25em;
  /* Arabski i hindi: łacinka czyta się od lewej także nad słowem pisanym od prawej. */
  direction: ltr; unicode-bidi: isolate;
  -webkit-user-select: none; user-select: none;
}
/* PODKREŚLENIA SŁÓW (przegląd frontu 2026-10-02): słowo z zapisem jest inline-block, a według CSS Text Decoration kreska
   przodka NIE przechodzi do potomka inline-block - pod słowami znikała szara kreska zdania przerobionego, czerwona trudnej
   frazy i falista błędu (Czytanie, karta „Czy miałeś na myśli?”, krok 1 „Zdania na pamięć” po pudle); zostawały kreseczki pod
   spacjami. Każda reguła, która podkreśla SŁOWA w miejscach z zapisem, ma tu bliźniaka na WEWNĘTRZNYM spanie słowa (.fon-t,
   fonOwin) - nie na samym .fon: kreska zadeklarowana na .fon przechodzi na blok ::before i stała też pod zapisem (zrzut Edge
   2026-10-02). Słowo ma JEDNĄ kreskę, więc pierwszeństwo ustawia swoistość: falista błędu = czerwona trudnej frazy > szara
   „zrobione” (:where zeruje jej selektor). Nowa reguła z text-decoration na słowach = bliźniak tutaj (pilnują tego testy_fonetyka,
   grupa 13, i scripts/testy_fonetyka_css.js w Edge). */
html:not(.fon-wyl) :where(.kartka-segment.zrobione .kartka-zrodlo) .fon[data-fon] > .fon-t {
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 6px;
  text-decoration-color: var(--border-2); text-decoration-skip-ink: none;
}
html:not(.fon-wyl) :is(.trudne-fraza, .ai-wstawka) .fon[data-fon] > .fon-t {
  text-decoration: underline; text-decoration-color: var(--rosso); text-decoration-thickness: 2px;
  text-underline-offset: 3px; text-decoration-skip-ink: none;
}
html:not(.fon-wyl) :is(.czesc-zle, .mow-poprawka-blad) .fon[data-fon] > .fon-t {
  text-decoration: underline wavy var(--rosso); text-decoration-thickness: 2px; text-underline-offset: .22em;
  text-decoration-skip-ink: none;
}
/* Interpunkcja przy słowie (fonOwin): atomowy inline-block zostawiał przed sobą miejsce łamania, więc kropka albo „。”
   spadała sama na początek następnego wiersza (zmierzone w dymku 226 px, przegląd frontu 2026-10-02). */
html:not(.fon-wyl) .fon-grupa { white-space: nowrap; }
/* Miejsce ZAREZERWOWANE, zanim zapis dojedzie (zh, ja, ar, hi z modelu): pojedyncza linijka (słowo na karcie, kwestia bota,
   dymek, kafel) dostaje z góry tyle miejsca, ile zajmie zapis - wiersz nie skacze, gdy przyjdzie. Wielolinijkowe (kartka
   Czytania, linijka filmu) mają stałą interlinię, która mieści zapis z samego założenia (.fon-jest niżej). */
/* Przezroczysta górna ramka, a nie padding ani margines: te elementy mają własne odstępy (zdanie przykładowe na karcie ma
   padding 12 px i margines 16 px), a ramka dokłada wysokość bez ich nadpisywania. */
html:not(.fon-wyl) .fon-czeka.fon-blok { border-top: max(0.7em, 13px) solid transparent; }
html:not(.fon-wyl) .fon-czeka.fon-blok.fon-inline { display: inline-block; }
/* Kartka Czytania: DWIE kratki na wiersz, zapis siedzi w górnej - tekst dalej stoi na liniach zeszytu. */
html:not(.fon-wyl) .kartka.fon-jest .kartka-akapit { line-height: calc(var(--kartka-krok, 26px) * 2); }
html:not(.fon-wyl) .film-zrodlo.fon-jest { line-height: 2.35; }
html:not(.fon-wyl) .mow-bot-tekst.fon-jest { line-height: 2.1; }
/* Dymek z zapisem: „+N” i gwiazdka wiszą na górnej krawędzi pigułki - wyższa góra, żeby nie siadały na pierwszej sylabie. */
html:not(.fon-wyl) .mow-dymek:has(.fon-gotowe, .fon-czeka) { padding-top: 11px; }
/* Arabski: słowo z zapisem jest osobnym blokiem, a między blokami stoją same spacje - bez kierunku od prawej ułożyłyby się
   w zdaniu od lewej (odwrócona kolejność słów). Kartka Czytania dostaje kierunek na całym akapicie, żeby zdania też szły od prawej. */
html:not(.fon-wyl) .fon-rtl { direction: rtl; unicode-bidi: isolate; }
/* Arabska KARTKA: kierunek od prawej zależy od JĘZYKA czytanki (klasa kartka-rtl), a nie od tego, czy widać zapis - do
   2026-10-02 stał pod fon-rtl, więc przełącznik zapisu przestawiał cały układ (przegląd frontu). Glosa po naszemu, tłumaczenie
   fragmentu i linijka próby są w języku INTERFEJSU: izolowane od lewej, inaczej polskie zdanie dostawało kropkę na początku
   („.Dziękuję bardzo”), a pole próby pisało od prawej. */
.kartka.kartka-rtl .kartka-akapit { direction: rtl; }
.kartka.kartka-rtl :is(.kartka-tlumaczenie, .frag-tlumaczenie, .kartka-proba) { direction: ltr; unicode-bidi: isolate; }

/* ===== MAPA SŁÓW – MODAL ===== */
.wordmap-overlay {
  position: fixed; inset: 0; z-index: 2000;
  /* Bez backdrop-filter: rozmywanie tła każe przeglądarce przerysowywać całą stronę pod
     spodem w KAŻDEJ klatce. Przy mapie z ~1000 słówek zbijało to płynność do 1 FPS
     (zmierzone). Ciemniejsze tło daje ten sam efekt oddzielenia za darmo. */
  background: rgba(15, 23, 42, 0.68);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: fadeIn 0.2s ease;
}
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }

.wordmap-modal {
  background: var(--crema);
  border-radius: 24px;
  width: 100%; max-width: 900px;
  max-height: 85vh;
  display: flex; flex-direction: column;
  box-shadow: 0 24px 80px rgba(0,0,0,0.3);
  overflow: hidden;
  animation: slideUp 0.3s cubic-bezier(.4,0,.2,1);
}
@keyframes slideUp {
  from { transform: translateY(30px); opacity:0; }
  to   { transform: translateY(0);    opacity:1; }
}

.wordmap-header {
  padding: 20px 24px 16px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--border-warm-soft);
  background: var(--card-bg);
  flex-shrink: 0;
}
.wordmap-title {
  font-size: 1.2rem; font-weight: 800; display: flex; align-items: center; gap: 10px;
}
.wordmap-controls {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.wordmap-close {
  background: none; border: none; font-size: 1.4rem;
  cursor: pointer; color: var(--grigio); padding: 4px;
  transition: var(--transition);
}
.wordmap-close:hover { color: var(--rosso); transform: scale(1.2); }

.wordmap-search {
  padding: 8px 16px; border-radius: 50px;
  border: 2px solid var(--border-warm); background: var(--crema);
  font-size: 0.88rem; outline: none;
  /* Nie sztywne 180 px: na waskim ekranie ten jeden element wychodzil poza krawedz
     i to on generowal przewijanie w bok w calej mapie slowek. */
  flex: 1 1 140px; min-width: 0; max-width: 180px;
  transition: var(--transition);
}
.wordmap-search:focus { border-color: var(--oro); }

.wordmap-body {
  overflow-y: auto; padding: 20px 24px; flex: 1;
}

/* ===== SŁUCHANIE: film z YouTube + napisy pod spodem =====
   Odtwarzacz zostaje ORYGINALNY (IFrame Player API), bo to jedyny dozwolony sposób odtwarzania
   i jednocześnie ten, który użytkownik zna: pauza, prędkość, jakość i napisy YouTube'a działają
   dokładnie tak, jak się spodziewa. My dokładamy pod spodem drugą warstwę - własne napisy,
   pokolorowane jego własną talią. */
.film-formularz { max-width: 760px; margin: 0 auto; }
.film-pole { margin-bottom: 14px; }
.film-pole label { display: block; font-size: 0.8rem; font-weight: 800; color: var(--grigio); margin-bottom: 6px; }
.film-jak {
  margin: 0 0 16px; padding: 12px 14px; border-radius: 12px;
  background: var(--crema); border: 1px solid var(--border-warm-soft);
  font-size: 0.82rem; line-height: 1.6; color: var(--grigio);
}
.film-jak b { color: var(--testo); }
.film-jak ol { margin: 8px 0 0; padding-left: 20px; }

/* Odtwarzacz trzyma proporcje 16:9 samodzielnie - iframe od YouTube'a dostaje sztywne
   width/height, które przy zmianie szerokości panelu rozjeżdżałyby się z kontenerem. */
.film-ramka {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  border-radius: 14px; overflow: hidden; background: #000; margin-bottom: 14px;
}
.film-ramka iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.film-pasek { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.film-tytul { font-weight: 800; font-size: 1.02rem; flex: 1; min-width: 140px; }

/* PASEK NARZĘDZI POD NAPISAMI.
   Dwie grupy rozepchnięte na boki: po lewej to, co zmienia WIDOK (przełączniki), po prawej
   to, co zmienia MATERIAŁ (fiszki, ćwiczenie, udostępnienie, usunięcie). Kreska u góry
   oddziela pasek od napisów - bez niej przyklejał się do ostatniej linijki i wyglądał
   jak jej część. */
.film-akcje {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
.film-akcje-lewo, .film-akcje-prawo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.film-akcje .kartka-przelacznik { margin: 0; }
/* Usunięcie jest jedyną akcją nieodwracalną i jedyną, która czerwienieje - dopiero pod
   kursorem, żeby pasek nie krzyczał kolorem przy każdym otwarciu filmu. */
.ppt-akcja-usun:hover { border-color: var(--rosso); color: var(--rosso); }
/* „Mapa poziomów" (film z fiszkami w talii, od 2026-09-27) to akcja, więc w barwie przycisku (granat, w ciemnym
   motywie żółty), a nie zielonym „aktywna": zieleń znaczy w kanwie „łatwe / dobrze" (CLAUDE.md, STYL KANWY). */
.film-akcje .ppt-akcja.ppt-mapa { background: var(--oro); border-color: var(--oro); color: var(--na-akcencie); }
.film-akcje .ppt-akcja.ppt-mapa:hover { opacity: 0.9; }
@media (max-width: 640px) {
  /* Na telefonie dwie grupy jedna pod drugą, każda rozciągnięta na całą szerokość -
     rozpychanie na boki daje przy wąskim ekranie jeden przycisk w lewym rogu i jeden
     w prawym, z dziurą pośrodku. */
  .film-akcje { flex-direction: column; align-items: stretch; }
  .film-akcje-lewo, .film-akcje-prawo { justify-content: flex-start; }
}

/* NAPISY: JEDNA LINIJKA - ta, która właśnie leci, i nic poza nią.
   Nie jest to okrojona lista, tylko inny sposób patrzenia. Lista napisów zaprasza do czytania
   WZROKIEM, w swoim tempie, z filmem gdzieś w tle - a tu chodzi o coś dokładnie odwrotnego:
   słuchać i mieć pod ręką dokładnie to jedno zdanie, które właśnie pada. Wszystko inne na
   ekranie ciągnęłoby oko do przodu albo do tyłu.

   Wysokość jest STAŁA, choć tekst zmienia długość. Blok, który rośnie i maleje co kilka
   sekund, przesuwałby pod spodem całą stronę, a nad sobą - odtwarzacz. */
.film-teraz {
  position: relative; min-height: 104px;
  display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 16px 18px; border-radius: 14px;
  background: var(--crema); border: 1px solid var(--border-warm-soft);
}
/* Gaśnie POWOLI (0.75 s), zapala się SZYBKO (0.2 s), i ta asymetria jest celowa: zdanie ma
   być czytelne od pierwszej chwili, w której pada, a znikać na tyle łagodnie, żeby ruch na
   dole ekranu nie odciągał wzroku od filmu. */
.film-teraz-kwestia { width: 100%; opacity: 0; transition: opacity 0.75s ease; }
.film-teraz-kwestia.widoczna { opacity: 1; transition: opacity 0.2s ease; }
.film-zrodlo { display: block; font-size: 1.06rem; line-height: 1.55; font-weight: 600; }
.film-slowo { position: relative; }

/* PIŁECZKA NAD SŁOWEM, KTÓRE WŁAŚNIE PADA - jak w karaoke.
   Jeden element na całą linijkę, przestawiany transformem, a NIE kropka doklejana do każdego
   słowa: dzięki temu przejście między słowami jest ciągłym ruchem tej samej piłeczki, a nie
   gaśnięciem jednej i zapaleniem drugiej. Element leży poza tekstem (position:absolute
   w .film-teraz), więc pojawienie się go niczego nie przesuwa. */
.film-pileczka {
  position: absolute; left: 0; top: 0; width: 14px; height: 14px;
  margin: -7px 0 0 -7px;              /* transform celuje w ŚRODEK piłeczki, nie w róg */
  pointer-events: none; opacity: 0;
  transition: transform 0.34s cubic-bezier(.34,.9,.4,1), opacity 0.25s ease;
}
.film-pileczka.widoczna { opacity: 1; }
/* Skok siedzi na OSOBNYM elemencie w środku, bo rodzic ma już swój transform (pozycję nad
   słowem). Dwie animacje na jednej właściwości wykluczają się - wygrywa ostatnia i piłeczka
   albo stoi, albo skacze w rogu ekranu. */
.film-pileczka i {
  display: block; width: 100%; height: 100%; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%,
              color-mix(in srgb, var(--primary) 30%, #fff), var(--primary) 72%);
  box-shadow: 0 3px 7px color-mix(in srgb, var(--primary) 42%, transparent);
  animation: film-skok 1.9s ease-in-out infinite;
}
/* POWOLI i płytko: piłeczka ma prowadzić wzrok wzdłuż zdania, a nie zabierać go z tekstu.
   Wysokie, szybkie odbicie w linii, którą się właśnie czyta, przeszkadza zamiast pomagać. */
@keyframes film-skok {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}
@media (prefers-reduced-motion: reduce) {
  .film-pileczka i { animation: none; }
  .film-pileczka { transition: opacity 0.25s ease; }
}
/* Napisy w języku interfejsu: NAD oryginałem i wyraźnie mniejsze. Mają być podpowiedzią dla
   oka, które się zacięło, a nie drugim tekstem do czytania - stąd i rozmiar, i wyszarzenie. */
.film-tlum { display: block; font-size: 0.76rem; color: var(--grigio); line-height: 1.45; margin-bottom: 5px; }
.film-tlum:empty { display: none; }
/* Podpowiedź na pustym miejscu, zanim film ruszy - znika przy pierwszej kwestii i nie wraca. */
.film-teraz-podpowiedz {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: 16px 18px; font-size: 0.85rem; color: var(--grigio);
  transition: opacity 0.4s ease;
}

/* MODUŁ POZIOMÓW NAD FILMEM - plan nauki z filmu rozbity na etapy (patrz etapy_planu w db.php, rysujSciezkePlanu).
   Kółka na linii, a nie lista albo pasek postępu, i to jest cała różnica: lista mówi „masz 240 słówek do zrobienia"
   i przytłacza, a ścieżka mówi „jesteś na trzecim z ośmiu" - ta sama liczba, ale z widocznym końcem i śladem tego,
   co już za tobą. Od 2026-09-27 w barwach ścieżki poziomów (Alek: „zrób w obecnym stylu Lingarii"): niebieska karta
   #2463E9 stała w obu motywach jak każdy ekran marki, białe kółka z żółtym pierścieniem postępu, kłódka i ptaszek
   w plakietce zamiast słów „zamknięty" i „umiem 0%" pod każdą kropką. Cała karta jest JEDNYM przyciskiem do ścieżki. */
.plan-sciezka { margin-bottom: 12px; }
.plan-modul {
  width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "glowa strzalka" "kolka kolka";
  align-items: center; gap: 12px 14px; padding: 14px 16px 16px; border: none; border-radius: 22px; cursor: pointer;
  background: #2463E9; color: #FFFFFF; font: inherit; text-align: start;
  box-shadow: 0 18px 30px -24px rgba(8, 18, 70, 0.9);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.plan-modul:hover { transform: translateY(-2px); box-shadow: 0 20px 34px -20px rgba(8, 18, 70, 0.95); }
.plan-modul:focus-visible { outline: 3px solid var(--zolty); outline-offset: 3px; }
.plan-modul-glowa { grid-area: glowa; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.plan-modul-tytul {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-naglowek); font-weight: 800; font-size: 1.15rem; line-height: 1.2; letter-spacing: -0.01em;
}
.plan-modul-tytul .ico { margin: 0; color: var(--zolty); }
.plan-modul-meta { font-size: 0.82rem; font-weight: 600; color: #EEF3FF; }
/* Strzałka w kółku (pigułka ze strzałką z kanwy): białe kółko z granatową strzałką; pod kursorem żółte. */
.plan-modul-strzalka {
  grid-area: strzalka; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: #FFFFFF; color: #17183B; transition: background-color 0.15s ease;
}
.plan-modul-strzalka .ico { margin: 0; line-height: 1; }
.plan-modul:hover .plan-modul-strzalka { background: var(--zolty); }
[dir="rtl"] .plan-modul-strzalka .ico { transform: scaleX(-1); }
.plan-kolka { grid-area: kolka; display: flex; align-items: center; flex-wrap: nowrap; min-width: 0; overflow: hidden; padding: 3px 2px; }
/* Kółko poziomu jak na ścieżce, tylko mniejsze: żółty łuk = odsetek „łatwych" na półprzezroczystym torze. */
.plan-kolko {
  position: relative; flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: conic-gradient(var(--zolty) calc(var(--pct, 0) * 1%), rgba(255, 255, 255, 0.3) 0);
  display: grid; place-items: center;
}
.plan-kolko::before { content: ''; position: absolute; inset: 4px; border-radius: 50%; background: #FFFFFF; }
.plan-kolko b { position: relative; font-family: var(--font-naglowek); font-weight: 800; font-size: 1rem; line-height: 1; color: #17183B; }
.plan-kolko.zrobiony { background: #FFFFFF; }
.plan-kolko.zrobiony::before { background: var(--zolty); }
.plan-kolko.biezacy { box-shadow: 0 0 0 3px #2463E9, 0 0 0 5px var(--zolty); }
.plan-kolko.zamkniety { background: transparent; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.45); }
.plan-kolko.zamkniety::before { background: transparent; }
.plan-kolko.zamkniety b { color: rgba(255, 255, 255, 0.85); }
.plan-kolko-znak {
  position: absolute; right: -4px; bottom: -3px; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center; font-size: 0.58rem; box-shadow: 0 0 0 2px #2463E9;
}
.plan-kolko-znak .ico { margin: 0; line-height: 1; }
.plan-kolko.zrobiony .plan-kolko-znak { background: #35A64D; color: #17183B; }
.plan-kolko.zamkniety .plan-kolko-znak { background: #17183B; color: #FFFFFF; }
/* Łącznik między kółkami: pełny biały za zaliczonym poziomem, półprzezroczysty przed - jak droga na ścieżce. */
.plan-lacznik { flex: 1 1 8px; min-width: 6px; max-width: 22px; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.35); }
.plan-lacznik.przebyty { background: #FFFFFF; }
.plan-kolka-wiecej { flex: none; padding: 0 6px; font-size: 0.8rem; font-weight: 800; color: #EEF3FF; }
@media (prefers-reduced-motion: reduce) { .plan-modul, .plan-modul-strzalka { transition: none; } .plan-modul:hover { transform: none; } }

/* OKNO PLANU NAUKI. Pokazuje się PRZED dodaniem słówek, więc musi dać się zamknąć bez skutków
   ubocznych - użytkownik, który je odrzuci, ma dostać dokładnie to, co dostawał wcześniej. */
.plan-modal { max-width: 620px; }
.plan-naglowek { padding: 20px 22px 0; }
.plan-tytul { font-size: 1.06rem; font-weight: 800; margin-bottom: 8px; }
.plan-wstep { font-size: 0.88rem; line-height: 1.65; color: var(--grigio); margin: 0 0 4px; }
.plan-opcje { display: grid; gap: 10px; padding: 16px 22px 4px; }
.plan-opcja {
  display: block; width: 100%; text-align: left; cursor: pointer; font: inherit; color: var(--testo);
  padding: 13px 15px; border-radius: 13px; border: 2px solid var(--border-warm-soft);
  background: var(--card-bg); transition: var(--transition);
}
.plan-opcja:hover { border-color: var(--oro); }
.plan-opcja.wybrana { border-color: var(--oro); background: var(--bg-highlight); }
.plan-opcja-glowa { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.plan-opcja-nazwa { font-weight: 800; font-size: 0.94rem; }
.plan-odznaka {
  font-size: 0.68rem; font-weight: 800; padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--verde) 15%, transparent); color: var(--zielen-gleboka);
}
.plan-odznaka.ostrzezenie { background: color-mix(in srgb, var(--rosso) 15%, transparent); color: var(--rosso); }
.plan-opcja-opis { font-size: 0.79rem; color: var(--grigio); line-height: 1.55; }
.plan-opcja-data { font-size: 0.79rem; font-weight: 700; margin-top: 5px; }
.plan-akcje { display: flex; flex-direction: column; gap: 8px; padding: 14px 22px 20px; }
.plan-akcje .btn { margin: 0; }
.plan-pomin {
  background: none; border: none; font: inherit; font-size: 0.8rem; color: var(--grigio);
  cursor: pointer; text-decoration: underline; padding: 4px;
}
.plan-pomin:hover { color: var(--testo); }

/* CZEKANIE NA NAPISY. Pobranie idzie przez dwa cudze serwery i potrafi zająć kilkanaście
   sekund - na tyle długo, że sam kręcioł zaczyna wyglądać jak zawieszenie. Dlatego pod nim
   lecą ciekawostki o portalu: to jedyne miejsce, w którym użytkownik ma chwilę bezczynności
   i nie odbieramy mu za to niczego innego. */
.film-ladowanie {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 20px; padding: 56px 20px; text-align: center; min-height: 320px;
}
.film-ladowanie .spinner { width: 40px; height: 40px; border-width: 4px; }
.film-ladowanie-tytul { font-weight: 800; font-size: 1rem; }
.film-ladowanie-podtytul { font-size: 0.82rem; color: var(--grigio); margin-top: -12px; }
/* Dwie warstwy ruchu naraz i każda robi co innego: `opacity` przełącza się z JS-a przy zmianie
   ciekawostki (długie, spokojne przejście), a `transform` tętni bez końca z CSS-a. Rozdzielenie
   ich na różne właściwości jest tu konieczne - gdyby puls też szedł po opacity, animacja
   nadpisywałaby przejście i tekst gasłby skokami. */
.film-ciekawostka {
  max-width: 480px; min-height: 3.6em; font-size: 0.9rem; line-height: 1.75; color: var(--grigio);
  opacity: 0; transition: opacity 1.4s ease;
  animation: film-tetno 4.2s ease-in-out infinite;
}
.film-ciekawostka.widoczna { opacity: 1; }
@keyframes film-tetno { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.018); } }
@media (prefers-reduced-motion: reduce) { .film-ciekawostka { animation: none; } }

/* =========================================================
   MINI-GRA „ZBIJ BĄBELKI" - na czas przygotowania filmu
   =========================================================
   Bąbelki jadą do góry SAMĄ ANIMACJĄ CSS na własności `transform`, czyli na wątku
   kompozytora. To nie jest kosmetyka, tylko warunek postawiony tej grze: pod spodem lecą
   zapytania po napisy i lematyzację, a gra, która co klatkę liczyłaby pozycje w JavaScripcie,
   zabierałaby czas dokładnie temu procesowi, który ma umilać. JavaScript dotyka tu wyłącznie
   trzech momentów: narodzin bąbelka, kliknięcia i sprzątania.

   --droga ustawia JS raz na start (wysokość planszy + zapas), bo plansza ma różną wysokość
   na telefonie i na pulpicie, a keyframes nie umieją jej odczytać same. */
.film-gra { width: 100%; max-width: 480px; }
.wgr-panel .film-gra { margin: 14px auto 0; text-align: left; }
.film-gra-gora {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 0.78rem; color: var(--grigio); margin-bottom: 6px;
}
.film-gra-wynik { font-weight: 800; color: var(--verde); font-variant-numeric: tabular-nums; }
.film-gra-plansza {
  position: relative; height: 150px; overflow: hidden;
  border: 1px dashed var(--border-warm); border-radius: 16px;
  background: var(--bg-soft);
  /* Bąbelki wynurzają się i znikają przy krawędziach, zamiast ucinać się w pół słowa. */
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
}
.film-babel {
  position: absolute; bottom: -40px; left: 0;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 13px; border-radius: 999px; white-space: nowrap;
  font-size: 0.8rem; font-weight: 700; color: var(--testo);
  background: var(--card-bg); border: 1px solid var(--border-warm);
  box-shadow: 0 3px 10px -4px rgba(15, 23, 42, 0.25);
  cursor: pointer; user-select: none;
  /* touch-action: bąbelek ma reagować na stuknięcie, a nie zaczynać przewijanie strony. */
  touch-action: manipulation;
  animation: film-babel-plyn var(--czas, 8s) linear forwards;
}
.film-babel:hover { border-color: var(--verde); }
@keyframes film-babel-plyn {
  from { transform: translateY(0); }
  to   { transform: translateY(calc(-1 * var(--droga, 200px))); }
}
/* Pęknięcie: bąbelek puchnie i gaśnie, a w środku zostaje tłumaczenie z „+1". Animacja
   przejmuje `transform`, więc unoszenie się zatrzymuje samo - pęknięty bąbelek stoi
   w miejscu, w którym go trafiono. */
.film-babel.pekniety {
  animation: film-babel-pyk 0.42s ease-out forwards;
  pointer-events: none; border-color: var(--verde); color: var(--verde);
}
@keyframes film-babel-pyk {
  0%   { transform: scale(1);    opacity: 1; }
  35%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(0.9);  opacity: 0; }
}
.film-babel-plus { font-weight: 800; color: var(--verde); }
/* Mikro-cząstki: sześć kropek rozbiegających się z miejsca pęknięcia. Bez biblioteki
   i bez canvasu - kierunek każdej siedzi w zmiennych --x/--y nadanych przy tworzeniu. */
.film-iskra {
  position: absolute; width: 6px; height: 6px; border-radius: 50%;
  background: var(--verde); pointer-events: none;
  animation: film-iskra-lot 0.5s ease-out forwards;
}
@keyframes film-iskra-lot {
  from { transform: translate(0, 0) scale(1); opacity: 0.9; }
  to   { transform: translate(var(--x, 0), var(--y, 0)) scale(0.2); opacity: 0; }
}

@media (max-width: 560px) { .film-gra-plansza { height: 120px; } }

/* Bez ruchu gra ZOSTAJE, ale przestaje być zręcznościowa: bąbelki po prostu stoją tam, gdzie
   się pojawiły, i czekają na kliknięcie. Odbieranie jej w całości byłoby karą za ustawienie
   w systemie, a klikanie w napisy działa tak samo dobrze bez unoszenia. */
@media (prefers-reduced-motion: reduce) {
  .film-babel { animation: none; bottom: auto; }
  .film-babel.pekniety { animation: none; opacity: 0; transition: opacity 0.25s ease; }
  .film-iskra { display: none; }
}

/* Wygaszanie ekranu czekania przy wejściu w odtwarzacz. Na czas przenikania loader idzie
   na warstwę NAD odtwarzaczem (position:absolute), bo inaczej przez te 0,4 s stałyby jeden
   pod drugim i cała strona podskoczyłaby o wysokość ekranu ładowania. */
#widokFilmow { position: relative; }
#filmLadowanie.gasnie {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: var(--bg); opacity: 0; transition: opacity 0.4s ease;
}
@media (prefers-reduced-motion: reduce) { #filmLadowanie.gasnie { transition: none; } }

/* KAFELKI FILMÓW (2026-09-25, Alek: „i to samo w słuchaniu w wyborze piosenek czy podcastów czy filmów, które już
   dodaliśmy. Też prostokąty ładne, np. 3–4 na szerokość"). Ta sama siatka, co okno paczek: kadr 16:9 na górze,
   przycisk odtwarzania na kadrze, pasek opanowania na dole kadru, a jak w YouTube - czas, do którego film
   obejrzano, w rogu. „Moje filmy" pod formularzem i okno „Wszystkie" rysuje JEDNA funkcja (kafelekFilmuHtml). */
.film-lista, #filmyListaBody {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; align-content: start;
  grid-auto-rows: max-content;   /* jak w oknie paczek: kafelek z overflow: hidden nie może się zgniatać */
}
.film-lista { margin-top: 10px; }
#filmyListaBody > .wordmap-empty { grid-column: 1 / -1; }
#filmyListaOverlay .wordmap-modal { max-width: 1080px; }
.film-kafelek {
  position: relative; display: flex; flex-direction: column; min-width: 0; padding: 0; overflow: hidden;
  text-align: left; cursor: pointer; border-radius: 16px; border: 2px solid var(--border-warm);
  background: var(--card-bg); font: inherit; color: var(--testo);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.film-kafelek:hover, .film-kafelek:focus-visible { border-color: var(--oro); transform: translateY(-3px); box-shadow: var(--shadow-hover); }
.film-kafelek:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
.film-kafelek.biezacy { border-color: var(--oro); }
.film-kafelek-okladka { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; background: var(--bg-soft); }
.film-kafelek-okladka img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .35s ease;
}
.film-kafelek:hover .film-kafelek-okladka img { transform: scale(1.05); }
.film-kafelek-graj {
  position: absolute; left: 50%; top: 50%; width: 48px; height: 48px; margin: -24px 0 0 -24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: #fff; background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(3px); transition: transform .2s ease, background .2s ease;
}
.film-kafelek-graj .ico { margin: 0 0 0 3px; font-size: 1.2rem; }
.film-kafelek:hover .film-kafelek-graj { transform: scale(1.15); background: var(--marka-czerwony); }
.film-kafelek-czas {
  position: absolute; right: 8px; bottom: 12px; padding: 2px 6px; border-radius: 6px;
  background: rgba(15, 23, 42, .78); color: #fff; font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.film-kafelek-pasek { position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: rgba(15, 23, 42, .28); }
.film-kafelek-pasek > span { display: block; height: 100%; width: var(--postep, 0%); background: var(--marka-zielony); }
/* Kosz tylko w oknie „Wszystkie" - jak dotąd przy wierszu. <span role="button">, bo kafelek JEST przyciskiem. */
.film-kafelek-usun {
  position: absolute; top: 8px; right: 8px; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--grigio);
  background: color-mix(in srgb, var(--card-bg) 86%, transparent); backdrop-filter: blur(6px);
}
.film-kafelek-usun:hover, .film-kafelek-usun:focus-visible { color: var(--rosso); }
.film-kafelek-usun .ico { margin: 0; }
.film-kafelek .opis {
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 6px; row-gap: 2px; padding: 10px 12px 12px; min-width: 0;
}
.film-kafelek .nazwa {
  flex: 1 1 100%; font-weight: 800; font-size: 0.92rem; line-height: 1.25; overflow: hidden; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.film-kafelek .meta { font-size: 0.74rem; color: var(--grigio); margin-top: 2px; }
.film-kafelek .opis > .film-kafelek-ma, .film-kafelek .opis > .film-kafelek-fiszki { flex-basis: 100%; }
.film-kafelek .opis > .film-kafelek-fiszki { justify-content: center; }
@media (max-width: 560px) {
  .film-lista, #filmyListaBody { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .film-kafelek .opis { padding: 8px 10px 10px; }
  .film-kafelek .nazwa { font-size: .86rem; }
  .film-kafelek-graj { width: 40px; height: 40px; margin: -20px 0 0 -20px; }
}
@media (prefers-reduced-motion: reduce) {
  .film-kafelek, .film-kafelek-okladka img, .film-kafelek-graj { transition: none; }
  .film-kafelek:hover, .film-kafelek:focus-visible { transform: none; }
  .film-kafelek:hover .film-kafelek-okladka img, .film-kafelek:hover .film-kafelek-graj { transform: none; }
}
.wordmap-kat-section {
  margin-bottom: 24px;
  /* Przy ~1000 słówkach mapa to kilka tysięcy węzłów DOM. content-visibility pozwala
     przeglądarce w ogóle nie renderować sekcji poza ekranem, a contain-intrinsic-size
     daje jej zgrubną wysokość, żeby pasek przewijania nie skakał. */
  content-visibility: auto;
  contain-intrinsic-size: auto 320px;
}
.wordmap-kat-title {
  font-size: 0.75rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 1px; color: var(--grigio);
  margin-bottom: 10px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border-warm-soft);
  display: flex; align-items: center; justify-content: space-between;
}
.wordmap-kat-delall {
  border: none; background: transparent; cursor: pointer; font-size: 0.9rem;
  opacity: 0.55; padding: 2px 4px; border-radius: 6px; line-height: 1;
}
.wordmap-kat-delall:hover { opacity: 1; background: var(--bg-error-soft); }

.wordmap-grid {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.word-chip {
  background: var(--card-bg);
  border-radius: 50px;
  padding: 7px 16px;
  font-size: 0.88rem; font-weight: 600;
  border: 2px solid var(--border-warm);
  cursor: default;
  /* Tylko realnie zmieniane właściwości zamiast "all" - przy tysiącu chipów animowanie
     wszystkiego niepotrzebnie obciąża przeglądarkę przy każdym odświeżeniu listy */
  transition: border-color .3s cubic-bezier(.4,0,.2,1), background .3s cubic-bezier(.4,0,.2,1), transform .3s cubic-bezier(.4,0,.2,1);
  display: flex; align-items: center; gap: 6px;
  line-height: 1.2;
  user-select: none;
}
.word-chip:hover { border-color: var(--oro); transform: scale(1.04); }
.word-chip .it { color: var(--testo); }
.word-chip .sep-dot { color: var(--muted-light); font-size: 0.7rem; }
.word-chip .pl { color: var(--grigio); font-size: 0.8rem; font-weight: 400; }
.word-chip .emotka { font-size: 1rem; }
.word-chip .chip-del {
  cursor: pointer;
  color: var(--muted-light);
  font-size: 0.85rem;
  margin-left: 2px;
  transition: var(--transition);
}
.word-chip .chip-del:hover { color: var(--rosso); transform: scale(1.2); }
/* Słówko do edycji (2026-09-25): klik w chip otwiera okno edycji. Ikona wychodzi przy najechaniu, a na ekranie
   dotykowym (bez najechania) stoi przygaszona - inaczej nikt by nie wiedział, że chip da się kliknąć. */
.word-chip.edytowalny { cursor: pointer; }
.word-chip.edytowalny:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }
.word-chip .chip-edit { font-size: 0.72rem; color: var(--muted-light); opacity: 0; transition: opacity .2s; }
.word-chip.edytowalny:hover .chip-edit, .word-chip.edytowalny:focus-visible .chip-edit { opacity: 1; color: var(--oro); }
@media (hover: none) { .word-chip .chip-edit { opacity: .6; } }
/* Słówko ponad limit konta darmowego - widoczne, ale wyraźnie wyłączone z nauki */
.word-chip.locked {
  background: var(--bg-soft); border-color: var(--border); border-style: dashed;
  opacity: 0.72; cursor: not-allowed;
}
.word-chip.locked:hover { border-color: var(--border); transform: none; }
/* Zamek z planu nauki prowadzi do mapy poziomów - klika się, w odróżnieniu od zamka limitu. */
.word-chip.locked.etap { cursor: pointer; }
.word-chip.locked.etap:hover { border-color: var(--oro); }
.word-chip.locked .it { color: var(--grigio); }
/* Baner o zablokowanych słówkach: informacja, nie ostrzeżenie - stąd błękit, a nie dawny
   bursztyn (którego w palecie już nie ma). */
.locked-banner {
  background: var(--bg-info-soft); border: 1px solid var(--border-2); border-radius: 12px;
  padding: 10px 14px; font-size: 0.8rem; color: var(--muted-dark); line-height: 1.5; margin-top: 12px;
}
.locked-banner strong { font-weight: 800; }

/* ===== PACZKI: TRYB WYBIERANIA W MAPIE SŁÓWEK ===== */
/* Przycisk startu paczki był stylowany jak główne CTA (pełny .btn-oro) i zdominował pasek -
   to akcja poboczna, więc dostaje ten sam stonowany, przerywany styl co "pokaż mapę" */
/* Chip w trybie wybierania - całość klikalna, plus zamiast krzyżyka */

/* ===== PASSA NAUKI (STREAK) ===== */
.streak-badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 7px 13px; border-radius: 50px;
  border: 2px solid var(--border); background: var(--bg-soft);
  color: var(--testo); font-family: inherit; font-size: 0.88rem; font-weight: 800;
  cursor: pointer; transition: var(--transition);
}
.streak-badge:hover { background: var(--border); border-color: var(--border-2); }
/* OGIEŃ PASSY - cztery rysunki SVG zamiast jednej ikonki (assets/img/ogien): mocny, gdy dziś
   już zaliczone; przygaszony po jednym dniu przerwy; zgaszony po dwóch (żyje jeszcze na
   zamrożeniach); zabity, gdy passa przepadła. Rysunek siedzi w shadow roocie gospodarza
   (zamontujOgien), więc jego <style> i @keyframes nie wychodzą na stronę. */
#streakFlame { display: inline-block; width: 18px; height: 22px; line-height: 0; }
#streakBigFlame { width: 64px; height: 77px; margin: 0 auto 8px; line-height: 0; font-size: 3.2rem; }
.ogien-inline { display: inline-block; width: 16px; height: 19px; vertical-align: -4px; margin-right: 4px; line-height: 0; }
/* Dymek passy pod licznikiem (treść: passaDymekHtml, styl w sekcji 22 na końcu arkusza). */
.streak-wrap { position: relative; }
.streak-popover {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 300; width: 320px; box-sizing: border-box;
  background: var(--card-bg); border: 1.5px solid var(--border); border-radius: 24px; box-shadow: 0 18px 40px -12px rgba(23, 24, 59, 0.28);
  padding: 16px; color: var(--testo);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.streak-wrap:hover .streak-popover { opacity: 1; visibility: visible; transform: translateY(0); }
/* Niewidoczny mostek, żeby przejście kursora znad odznaki na kartę nie zamykało podglądu */
.streak-popover::before { content: ''; position: absolute; top: -10px; left: 0; right: 0; height: 10px; }
@media (hover: none) { .streak-popover { display: none; } }

.renew-box {
  margin-top: 12px; padding: 12px 14px; background: var(--crema); border-radius: 12px;
}

/* ===== KOD RABATOWY (w akordeonie kontenera Premium) ===== */
.promo-row { display: flex; gap: 6px; margin-top: 10px; }
.promo-row .auth-input { margin-bottom: 0; flex: 1; text-transform: uppercase; }
.promo-row button { width: auto; margin: 0; padding: 0 16px; white-space: nowrap; }
.promo-applied {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 10px; padding: 9px 12px; border-radius: 12px;
  background: var(--bg-success-soft); border: 1px solid var(--zielen-pastel); font-size: 0.8rem; font-weight: 700;
}
.promo-applied .promo-drop {
  background: none; border: none; padding: 0; font-family: inherit; font-size: inherit;
  color: var(--rosso); cursor: pointer; font-weight: 800;
}
.promo-error { margin-top: 8px; font-size: 0.78rem; color: var(--rosso); font-weight: 700; }

/* ===== ZGODA NA NATYCHMIASTOWE URUCHOMIENIE ===== */
.buy-consent {
  display: flex; align-items: flex-start; gap: 8px; margin-top: 14px;
  font-size: 0.78rem; color: var(--grigio); line-height: 1.5; cursor: pointer;
}
.buy-consent input { margin-top: 2px; flex-shrink: 0; width: 15px; height: 15px; accent-color: var(--oro); }
.buy-consent-note {
  margin-top: 6px; padding: 8px 11px; border-radius: 9px;
  background: var(--crema); font-size: 0.73rem; color: var(--grigio); line-height: 1.5;
}
/* Odsylacz do regulaminu tuz pod zgoda. Musi byc POD reka w chwili, w ktorej ktos decyduje
   o zrzeczeniu sie prawa do odstapienia - szukanie go w stopce w trakcie zakupu znaczy
   wyjscie z okna platnosci. Celowo drobny i szary: to przypis, nie druga oferta. */
.buy-consent-link {
  margin-top: 5px; font-size: 0.7rem; color: var(--muted-light); line-height: 1.45;
}
.buy-consent-link a { color: var(--grigio); text-decoration: underline; }
.buy-consent-link a:hover { color: var(--testo); }

/* Stan „zaplacisz dzis, zaczniesz za dwa tygodnie" - jedyny, ktory zaskakuje, wiec jedyny
   z kolorem. Zgoda zaznaczona wraca do spokojnego tla: tam nie ma o czym ostrzegac.
   Bursztyn domieszany do tla KARTY, a napis w kolorze tekstu motywu: dawne #fff8e1 z brazowym
   napisem stalo w ciemnym motywie jasna plama na granatowym tle. */
.buy-consent-note.czeka {
  background: color-mix(in srgb, #D97706 14%, var(--card-bg)); color: var(--testo); font-weight: 600;
  border: 1px solid color-mix(in srgb, #D97706 45%, transparent);
}

/* ===== WYBÓR WALUTY ===== */
.currency-switch {
  display: flex; gap: 4px; justify-content: center; margin: 0 0 12px;
  background: var(--crema); border-radius: 50px; padding: 4px; width: fit-content; margin-inline: auto;
}
.currency-opt {
  border: none; background: transparent; border-radius: 50px; padding: 6px 16px;
  font-family: inherit; font-size: 0.76rem; font-weight: 800; color: var(--grigio);
  cursor: pointer; transition: var(--transition);
}
.currency-opt:hover { color: var(--testo); }
.currency-opt.active { background: var(--zolty); color: var(--granat); }

/* Skrót do Społeczności pod kaflami metod dodawania. Celowo płaski i cichy - to podpowiedź,
   że słówek nie trzeba skądś przynosić, a nie kolejny formularz do wypełnienia. */
/* Wierszy jest teraz kilka pod rząd, więc odstęp musi być MIĘDZY nimi, a nie tylko pod
   ostatnim - ujemny margines u góry zostaje wyłącznie przy pierwszym (patrz :first-of-type). */
.add-method-skrot {
  display: flex; align-items: center; gap: 8px; width: 100%; margin: 0 0 6px;
  padding: 8px 10px; border-radius: 10px; border: 1px dashed var(--border-warm-dash);
  background: none; font-family: inherit; font-size: 0.76rem; font-weight: 700;
  color: var(--grigio); cursor: pointer; transition: var(--transition); text-align: left;
}
.add-method-skrot:first-of-type { margin-top: -6px; }
.add-method-skrot:last-of-type  { margin-bottom: 14px; }
.add-method-skrot:hover { border-color: var(--oro); color: var(--oro); }
.add-method-skrot > span { flex: 1; min-width: 0; }
.add-method-skrot .ico { font-size: 1rem; flex-shrink: 0; }

/* Test ze zrozumienia pod tekstem. Ten sam jezyk wizualny co pasek odsluchu - przyklejony
   do dolu, z cieniem odcinajacym go od tekstu - bo to ta sama rola: rzecz, ktora dzieje sie
   TERAZ, podczas gdy tresc zostaje na swoim miejscu. */
.tq-panel {
  position: sticky; bottom: 12px; z-index: 60; margin-top: 14px; text-align: left;
  background: var(--card-bg); border: 1px solid var(--border-warm-soft); border-radius: 18px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.14); padding: 12px 14px;
  animation: odsluchWjazd 0.35s cubic-bezier(.22,1,.36,1);
}
.tq-gora { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; font-weight: 800;
  color: var(--grigio); margin-bottom: 10px; }
.tq-licznik { margin-left: auto; font-weight: 700; }
.tq-zamknij { border: none; background: transparent; color: var(--grigio); cursor: pointer;
  font-size: 1.15rem; line-height: 1; padding: 0 2px; }
.tq-zamknij:hover { color: var(--testo); }
/* Odpowiedzi jedna pod druga, nie w dwoch kolumnach jak w odsluchu: tam sa pojedyncze slowa,
   tutaj cale zdania i w dwoch kolumnach lamalyby sie na cztery linijki. */
.tq-opcje { grid-template-columns: 1fr; }
.tq-ocena { margin-top: 10px; font-size: 0.85rem; font-weight: 700; line-height: 1.5; }
.tq-ocena.dobrze { color: var(--verde); }
.tq-ocena.zle { color: var(--rosso); }
.tq-bez-punktow { display: block; font-weight: 600; font-size: 0.76rem; color: var(--grigio); margin-top: 2px; }
.tq-koniec { font-size: 0.95rem; font-weight: 800; text-align: center; margin-bottom: 10px; }

/* Publiczny profil gracza. Modal jest szeroki i ma WLASNE przewijanie: wczesniej wnetrze
   bylo zwyklym divem z paddingiem, a .wordmap-modal ma overflow: hidden i max-height 85vh -
   przy powiekszeniu strony dol profilu byl obciety i nie dalo sie do niego dojechac. */
/* ===== PROFIL GRACZA - PANEL WYSUWANY Z PRAWEJ =====
   Profil nie jest oknem na srodku ekranu, tylko kolumna przy krawedzi. Powod: tresci jest
   siedem sekcji i zadna z nich nie jest "glowna" - to lista do przeczytania z gory na dol,
   a nie jedna rzecz do obejrzenia. Okno na srodku rozkladalo je na dwie kolumny i kazalo
   skakac wzrokiem w zygzak; kolumna czyta sie jednym ruchem.

   Panel stoi po PRAWEJ. Lewa krawedz jest w tej aplikacji zajeta: stamtad wychodzi nawigacja
   i stamtad zaczyna sie czytanie kazdego ekranu. Profil jest wtraceniem obok glownej pracy,
   a nie kolejnym poziomem nawigacji, wiec ma sie otwierac po stronie, na ktorej niczego nie
   zaslania.

   Panel jest CALY przewijalny (nie tylko jego srodek), wiec dlugi profil nie robi
   zagniezdzonego paska przewijania obok paska strony. */
.wordmap-overlay.profil-overlay { justify-content: flex-end; align-items: stretch; padding: 0; }

.profil-panel {
  position: relative;
  background: var(--crema);
  /* Szerzej niz pierwotne 440 px: profil niesie teraz komplet - liczniki, wykres, galerie,
     najtrudniejsze slowka - i w waskiej kolumnie kazda z tych sekcji byla scisnieta.
     Nadal kolumna przy krawedzi, a nie okno na srodku: siedem sekcji czyta sie z gory na dol. */
  width: 46vw; min-width: 380px; max-width: 720px;
  height: 100%;
  border-radius: 24px 0 0 24px;
  box-shadow: 0 24px 80px rgba(0,0,0,0.32);
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  animation: profilWjazd 0.28s cubic-bezier(.22,1,.36,1);
}
/* Na telefonie 22vw to pasek szerokosci kciuka - tam panel bierze caly ekran i traci
   zaokraglenie, bo nie ma juz krawedzi, przy ktorej mialoby stac. */
@media (max-width: 560px) {
  .profil-panel { width: 100%; min-width: 0; max-width: none; border-radius: 0; }
}
@keyframes profilWjazd { from { transform: translateX(100%); } to { transform: translateX(0); } }
@media (prefers-reduced-motion: reduce) { .profil-panel { animation: none; } }

.profil-tresc { display: flex; flex-direction: column; gap: 14px; padding: 18px; }
/* Krzyzyk stoi przy krawedzi od strony STRONY, nie od strony ekranu - czyli tam, skad
   przychodzi kursor po otwarciu panelu. Plywa nad trescia, wiec nie zabiera miejsca
   naglowkowi i zostaje pod reka takze po przewinieciu panelu w dol. */
.profil-zamknij {
  position: sticky; top: 0; z-index: 3;
  align-self: flex-start; margin: -6px 0 -34px -6px;
  background: var(--card-bg); border-radius: 50%;
}


/* Lista obserwujacych/obserwowanych - wysuwa sie w miejsce tresci profilu, bo to dalej ten
   sam panel i ta sama droga powrotna (strzalka u gory). */
/* PADDING U GORY NIE JEST KOSMETYKA - bez niego rzad listy laduje POD krzyzykiem panelu.
   Krzyzyk plywa nad trescia (.profil-zamknij ma margin-bottom -34px, zeby nie zabierac miejsca
   naglowkowi), a rzad listy zaczyna sie od okraglej strzalki powrotu. Zmierzone w przegladarce:
   krzyzyk zajmuje 12-45 px od gory panelu, rzad listy startowal na 25 px - czyli 20 px pokrycia
   i dwa okragle przyciski narysowane jeden na drugim. Na samym profilu tego nie widac, bo tam
   pod krzyzykiem jest tlo glowki, a nie drugi przycisk. Po odsunieciu strzalka zaczyna sie na
   51 px: dwa rozne wyjscia (zamknij panel / wroc do profilu) wygladaja jak dwa przyciski,
   a nie jak jeden zle narysowany. */
.profil-lista-gora {
  display: flex; align-items: center; gap: 8px; margin-bottom: 4px; padding-top: 26px;
}
.profil-lista-wroc {
  width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--card-bg); color: var(--testo);
  font-size: 0.9rem; line-height: 1;
}
.profil-osoba {
  display: flex; align-items: center; gap: 10px; width: 100%; cursor: pointer;
  padding: 9px 10px; border: none; border-radius: 12px; background: none;
  font-family: inherit; color: inherit; text-align: left;
}
.profil-osoba:hover { background: var(--bg-soft); }
.profil-osoba-nick { font-weight: 700; font-size: 0.88rem; }
.profil-osoba-xp { margin-left: auto; font-size: 0.76rem; color: var(--grigio); white-space: nowrap; }
.profil-pusto { font-size: 0.82rem; color: var(--grigio); padding: 12px 2px; line-height: 1.5; }

/* „…i jeszcze 31" to PRZYCISK, a nie podpis: klik dociąga kolejną partię galerii w miejscu (dograjGalerieTworcy). Kafle galerii
   (.pp-gal-*) stoją w sekcji 22 na końcu arkusza. */
.profil-galeria-wiecej {
  display: block; width: 100%; margin-top: 10px; padding: 9px 14px; cursor: pointer;
  border: 1px solid var(--border-warm-soft); border-radius: 12px; background: var(--crema);
  font-family: inherit; font-size: 0.78rem; font-weight: 700; color: var(--grigio);
  transition: var(--transition);
}
.profil-galeria-wiecej:hover:not(:disabled) { background: var(--bg-soft); color: var(--testo); }
.profil-galeria-wiecej:disabled { cursor: default; opacity: 0.6; }
.profil-galeria-pusto {
  padding: 18px 14px; border-radius: 12px; background: var(--crema);
  border: 1px dashed var(--border-warm-soft);
  font-size: 0.78rem; color: var(--grigio); text-align: center;
}
/* ===== PROFIL: części wspólne z listą obserwujących =====
   Głowa, karty, wykres i galeria profilu w stylu kanwy stoją w sekcji 22 na końcu arkusza (2026-10-06). */
.profil-awatar-wrap { position: relative; display: inline-block; }
/* Zapełnienie talii na koncie darmowym - liczba na przyciemnieniu, WPROST na awatarze (profilZapelnienieHtml). */
.profil-zapelnienie {
  position: absolute; inset: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 42, 0.42);
  color: #fff; font-weight: 800; font-size: 0.86rem; letter-spacing: -0.01em;
  pointer-events: none;
}
.profil-wykres { width: 100%; min-width: 0; }
.profil-wykres svg { width: 100%; display: block; }
.profil-naglowek {
  text-align: left; font-weight: 800; font-size: 0.86rem; line-height: 1.35;
  letter-spacing: -0.005em; margin: 18px 0 9px;
}
/* Kod z maila: szesc osobnych prostokatow zamiast jednego pola tekstowego.
   Nie chodzi o ozdobe. Pole z szescioma cyframi pod rzad kaze je liczyc, zeby sprawdzic,
   czy przepisalo sie wszystkie; osobne prostokaty pokazuja to jednym spojrzeniem, a przy
   pomylce widac, KTORA cyfre poprawic. Telefony pokazuja tu klawiature numeryczna, a kod
   z SMS-a/maila podstawia sie sam (autocomplete=one-time-code na pierwszym polu). */
.kod-pola { display: flex; gap: 8px; justify-content: center; margin: 0 0 14px; }
.kod-pole {
  width: 46px; height: 56px; flex: 0 1 46px; min-width: 0;
  text-align: center; font-size: 1.5rem; font-weight: 800; color: var(--testo);
  font-family: inherit; background: var(--crema);
  border: 2px solid var(--border-warm); border-radius: 12px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  -moz-appearance: textfield;
}
.kod-pole::-webkit-outer-spin-button, .kod-pole::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.kod-pole:focus { outline: none; border-color: var(--oro); box-shadow: 0 0 0 3px color-mix(in srgb, var(--oro) 18%, transparent); }
.kod-pole.pelne { border-color: var(--oro); }
/* Na waskich ekranach szesc pol po 46 px nie miesci sie razem z odstepami. */
@media (max-width: 380px) {
  .kod-pola { gap: 5px; }
  .kod-pole { width: 40px; height: 50px; flex-basis: 40px; font-size: 1.25rem; }
}

/* Wysylka probki szablonu maila. Wydzielona ramka, bo to jedyne miejsce w tej karcie,
   ktore cos ROBI - reszta tylko pokazuje historie. */
.mail-probka { background: var(--crema); border: 1px solid var(--border-warm); border-radius: 10px;
  padding: 11px 13px; margin-bottom: 14px; }

/* Pasek awarii serwera w konsoli. Celowo krzykliwy: to jedyna rzecz w tym panelu, ktora
   nie moze zostac przeoczona, bo mowi o czyms, czego nie widac nigdzie indziej -
   dzialajaca strona z padnietymi kopiami wyglada dokladnie tak samo jak zdrowa. */
.admin-alarm {
  /* Kolory WPROST, nie ze zmiennych motywu. --rosso to jasna czerwien (#F87171), a
     --bianco wcale nie jest biale (#1E293B) - razem daly ciemny napis na jasnym tle,
     czyli kontrast ponizej 3:1 na czyms, co ma krzyczec. --srednie jest w tej palecie
     NIEBIESKIE, wiec ostrzezenie wygladaloby na informacje. */
  background: #B91C1C; color: #FFFFFF; padding: 11px 16px; flex-shrink: 0;
  font-size: 0.82rem; line-height: 1.5; border-bottom: 1px solid rgba(0,0,0,0.2);
}
.admin-alarm.uwaga { background: #B45309; }
.admin-alarm.hidden { display: none; }
.admin-alarm-poz { display: flex; gap: 9px; align-items: flex-start; }
.admin-alarm-poz + .admin-alarm-poz { margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.28); }
.admin-alarm-tytul { font-weight: 800; }
.admin-alarm-opis { opacity: 0.92; }

/* Pasek stanu tlumaczen nad spisem okienek. Bez niego zapis konczy sie slowem
   „dotlumacza sie same” i trzeba w to uwierzyc - a to jedyne miejsce, gdzie widac,
   czy rzeczywiscie sie dotlumaczyly. */
.i18n-stan { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px;
  padding: 8px 11px; background: var(--crema); border: 1px solid var(--border-warm);
  border-radius: 10px; font-size: 0.76rem; color: var(--grigio); }
.i18n-stan #i18nStanTekst { flex: 1; min-width: 180px; }
.i18n-stan b { color: var(--testo); }

/* Podsumowanie historii nauki. Kafelki, bo to sa liczby do rzucenia okiem, a nie tabela
   do czytania - trzy w rzędzie mieszczą się w bocznym panelu ustawień. */
.hist-kafelki { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 14px; }
.hist-kafelek { background: var(--crema); border: 1px solid var(--border-warm); border-radius: 12px;
  padding: 10px 6px; text-align: center; }
.hist-ikona { font-size: 1.1rem; line-height: 1; }
.hist-liczba { font-size: 1.25rem; font-weight: 800; color: var(--testo); line-height: 1.2; margin-top: 3px; }
.hist-etykieta { font-size: 0.68rem; font-weight: 700; color: var(--grigio); line-height: 1.3; }
.hist-dopisek { font-size: 0.62rem; color: var(--muted-light); margin-top: 2px; }
.hist-prog { margin: 0 0 14px; }
.hist-prog-tor { height: 7px; border-radius: 4px; background: var(--bg-soft); overflow: hidden; }
.hist-prog-fill { height: 100%; border-radius: 4px; background: var(--marka-zielony); transition: width 0.6s ease; }
.hist-prog-opis { font-size: 0.72rem; font-weight: 700; color: var(--grigio); margin-top: 5px; text-align: center; }
.hist-fakty { margin-top: 10px; display: grid; gap: 4px; font-size: 0.74rem; color: var(--grigio); line-height: 1.5; }
.hist-pusto { text-align: center; padding: 18px 12px; background: var(--crema); border-radius: 12px;
  color: var(--grigio); font-size: 0.85rem; line-height: 1.5; }
@media (max-width: 380px) { .hist-kafelki { grid-template-columns: repeat(2, 1fr); } }

/* Spis okienek w panelu admina. Zwinięte, bo jest ich kilkanaście, a poprawia się jedno. */
.popup-poz { border: 1px solid var(--border-warm); border-radius: 10px; margin-bottom: 8px; background: var(--card-bg); }
.popup-poz > summary { cursor: pointer; padding: 10px 12px; font-weight: 700; font-size: 0.88rem;
  list-style: none; user-select: none; display: flex; align-items: center; gap: 8px; }
.popup-poz > summary::-webkit-details-marker { display: none; }
.popup-poz > summary::before { content: '\25B8'; color: var(--grigio); }
.popup-poz[open] > summary::before { content: '\25BE'; }
.popup-zmieniony { font-size: 0.7rem; font-weight: 800; color: var(--oro); margin-left: auto; }
.popup-tresc { padding: 0 12px 12px; }
.popup-kiedy { font-size: 0.78rem; line-height: 1.6; color: var(--grigio); margin: 0 0 12px;
  border-left: 3px solid var(--border-warm); padding-left: 10px; }
.popup-pole { margin-bottom: 10px; }
.popup-pole label { display: block; font-size: 0.75rem; font-weight: 700; color: var(--grigio); margin-bottom: 4px; }
.popup-pole textarea { width: 100%; box-sizing: border-box; resize: vertical; font-family: inherit; }
.popup-brak { font-size: 0.75rem; color: var(--rosso); font-weight: 700; }
.popup-stan { font-size: 0.75rem; margin: 0; }

.faktura-info { font-size: 0.72rem; color: var(--grigio); line-height: 1.5; margin-top: 8px; }

/* Kolory chipów wg poziomu */
.wordmap-nowe   .word-chip { border-color: var(--border); }
.wordmap-latwe  .word-chip { border-color: var(--wordmap-latwe-border); background: var(--bg-success-grad-a); }
.wordmap-srednie .word-chip { border-color: var(--wordmap-srednie-border); background: var(--bg-warn-soft); }
.wordmap-trudne  .word-chip { border-color: var(--wordmap-trudne-border); background: var(--bg-error-soft); }

.wordmap-empty {
  text-align: center; padding: 40px; color: var(--grigio); font-size: 0.9rem;
}

/* Przycisk mapy przy statbox */
.stat-map-btn {
  display: block; width: 100%; margin-top: 6px;
  background: none; border: 1px dashed var(--border-warm-dash);
  border-radius: 8px; padding: 4px;
  font-size: 0.7rem; color: var(--grigio);
  cursor: pointer; transition: var(--transition);
}
.stat-map-btn:hover { background: var(--crema); border-color: var(--oro); color: var(--oro); }

/* ===== SCORE BADGE ===== */
.score-display {
  background: linear-gradient(135deg, var(--zielen-gleboka), var(--zielen-pastel));
  color: white;
  border-radius: 14px;
  padding: 14px;
  text-align: center;
  margin-top: 8px;
}
.score-num { font-size: 2rem; font-weight: 800; }
.score-label { font-size: 0.8rem; opacity: 0.9; }

/* ===== GRA W PARY ===== */
.game-topbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
@keyframes pulseUrgent {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}
.game-board {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 22px;
}
.game-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.game-tile {
  position: relative;
  background: var(--card-bg);
  border: 2px solid var(--border-warm);
  border-radius: 16px;
  padding: 20px 18px;
  min-height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: var(--transition);
  user-select: none;
}
.game-tile:hover { border-color: var(--oro); transform: translateY(-1px); }
.game-tile.selected { border-color: var(--oro); background: var(--bg-gold-soft); box-shadow: var(--shadow-hover); }
.game-tile.matched {
  background: var(--bg-success-soft);
  border-color: var(--verde);
  color: var(--verde);
  cursor: default;
  opacity: 0.55;
  transform: none;
}
.game-tile.cleared {
  background: transparent;
  border: 2px dashed var(--border-warm);
  box-shadow: none;
  cursor: default;
  opacity: 0.4;
}
.game-tile.wrong {
  border-color: var(--rosso);
  background: var(--bg-error-soft);
  animation: shakeTile 0.35s ease;
}
.game-tile.refilled { animation: popInTile 0.3s ease; }
@keyframes shakeTile {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}
@keyframes popInTile {
  0%   { transform: scale(0.85); opacity: 0.4; }
  100% { transform: scale(1);    opacity: 1; }
}
.game-tile.audio-only {
  background: var(--audio-tile-bg);
  border-color: var(--audio-tile-border);
  gap: 4px;
}
.game-tile.audio-only.selected { border-color: var(--oro); background: var(--bg-gold-soft); }
.game-tile.audio-only.matched  { background: var(--bg-success-soft); border-color: var(--verde); }

/* Fala audio "dyktafonu" na kafelku "tylko dźwięk" - w spoczynku delikatnie pulsuje
   (żeby było widać, że to coś do odsłuchania), a w trakcie mówienia paski reagują
   na realną amplitudę odtwarzanego audio (patrz hookWaveToAudio w JS). */
.audio-wave {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  height: 26px;
}
.audio-wave span {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--audio-tile-border);
  height: 8px;
  animation: audioIdlePulse 1.4s ease-in-out infinite;
}
.audio-wave span:nth-child(2) { animation-delay: 0.15s; }
.audio-wave span:nth-child(3) { animation-delay: 0.3s; }
.audio-wave span:nth-child(4) { animation-delay: 0.45s; }
.audio-wave span:nth-child(5) { animation-delay: 0.3s; }
.audio-wave span:nth-child(6) { animation-delay: 0.15s; }
.audio-wave span:nth-child(7) { animation-delay: 0s; }
@keyframes audioIdlePulse {
  0%, 100% { height: 6px; opacity: 0.55; }
  50%      { height: 16px; opacity: 1; }
}
.audio-wave.speaking span {
  animation: none;
  background: var(--oro);
  transition: height 0.08s ease;
}
.game-tile.audio-only.selected .audio-wave span { background: var(--oro); }
.game-tile.audio-only.matched  .audio-wave span { background: var(--verde); }

/* Pasek poziomu trudności - tylko po włoskiej (lewej) stronie, widoczny niezależnie od stanu karty */
.game-tile[data-side="left"].lvl-latwe::before,
.game-tile[data-side="left"].lvl-srednie::before,
.game-tile[data-side="left"].lvl-trudne::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 6px;
  border-radius: 16px 0 0 16px;
}
.game-tile[data-side="left"].lvl-latwe::before   { background: var(--verde); }
.game-tile[data-side="left"].lvl-srednie::before { background: var(--srednie); }
.game-tile[data-side="left"].lvl-trudne::before  { background: var(--rosso); }

/* ===== SUWAKI TRUDNOŚCI ===== */
.diff-slider-row { margin-bottom: 14px; }
.diff-slider-row .diff-label {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--grigio);
  margin-bottom: 4px;
}
.diff-slider-row input[type="range"] {
  width: 100%;
  accent-color: var(--chart-latwe);
  cursor: pointer;
}
/* .diff-slider-row zostaje wylacznie dla suwaka czestosci szybkiego testu w panelu admina;
   warianty .diff-srednie / .diff-trudne usunieto razem z suwakami rozkladu trudnosci. */

/* ===== RANKING ===== */
.leaderboard-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.leaderboard-table td { padding: 8px 6px; border-bottom: 1px solid var(--border-warm-2); }
.leaderboard-table tr.leaderboard-subrow td { padding: 0 6px 8px; border-bottom: 1px solid var(--border-warm-2); }
.leaderboard-table tr:nth-last-child(2) td, .leaderboard-table tr:last-child td { border-bottom: none; }
.leaderboard-table tr.leaderboard-divider td {
  padding: 10px 6px 4px; border-bottom: none; font-size: 0.7rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--grigio);
}
.leaderboard-rank { font-weight: 800; width: 32px; }
.leaderboard-player { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.leaderboard-avatar-img, .leaderboard-avatar-fallback {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
}
.leaderboard-avatar-img { object-fit: cover; }
.leaderboard-avatar-fallback {
  background: #78828C; color: white;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.75rem; font-weight: 800; text-transform: uppercase;
}
.leaderboard-time { font-weight: 700; color: var(--verde); text-align: right; }
.leaderboard-meta { color: var(--grigio); font-size: 0.75rem; }
.leaderboard-sub { color: var(--grigio); font-size: 0.7rem; opacity: 0.85; }
.leaderboard-empty { text-align: center; color: var(--grigio); font-size: 0.85rem; padding: 12px 0; }


/* =========================================================================================
   STYL KANWY - ZALOGOWANA APLIKACJA (2026-09-26)
   =========================================================================================
   Alek po zatwierdzeniu plansz na kanwie: „bazując na wyglądzie aplikacji odśwież aplikację
   desktopową, dodając te style, kolory, treści w samą grę na desktopie również … mechanizmy
   wewnątrz strony desktopowej, tam również ilustracje, kolory, grafiki". Strona główna dostała
   ten język tego samego dnia (sekcje lp-*), aplikacja mobilna też - zalogowana część strony
   była ostatnim miejscem ze starą marką (grafit, zielony akcent, Fredoka, cienie).

   CO JEST WZOREM: plansze kanwy (Nauka, Fiszki, Fiszki - odpowiedź, Koniec powtórki, Cel dnia,
   Premium, Słuchanie, Czytanie, Mówienie). Plansze są telefonem (390 px), więc na komputer idzie
   JĘZYK, nie układ 1:1: barwy (granat, żółty akcent, barwy logo na poziomach i trybach), kroje
   (Outfit 800 w nagłówkach i dużych liczbach, Figtree w tekście), kształty (pigułki, karty 24 px
   z obwódką zamiast cienia, kółko ze strzałką w głównym przycisku) i ilustracje
   (assets/img/ilustracje/*.webp). Układ zostaje desktopowy: panel boczny, szersze siatki.

   DLACZEGO OSOBNA SEKCJA NA KOŃCU ARKUSZA, a nie poprawki rozsiane po jedenastu tysiącach linii:
   ten sam wygląd musi wygrać ze starymi regułami przy RÓWNEJ specyficzności, a tu stoi po nich.
   Paleta (tokeny w :root) i role --oro / --verde zmieniły się u źródła; tutaj są KSZTAŁTY
   i ekrany marki. Reguły ciemnego motywu, które mają wyższą specyficzność, dalej wygrywają -
   dlatego wszystko, co ma inne barwy w ciemnym, idzie przez tokeny, a nie przez drugi zestaw
   selektorów z :root[data-theme="dark"].
   Kolorowe ekrany marki (Czytanie niebieskie, Słuchanie czerwone, Mówienie zielone, cel dnia,
   ściana Premium) są STAŁE w obu motywach - marka nie zmienia koloru razem z motywem, tak samo
   jak na stronie głównej.
   ========================================================================================= */

/* ---------- 1. NAGŁÓWEK ---------- */
/* Logo w ciemnym motywie Z SYSTEMU. Reguła [data-theme="dark"] .logo-marka.wg-motywu zna tylko przełącznik ręczny,
   więc przy ciemnym systemie i bez wyboru w Ustawieniach czarny napis stał na granacie (zmierzone na zrzucie: logo
   ledwo widoczne w nagłówku aplikacji). Strona główna naprawiła to u siebie (.lp-header-logo) - tu to samo dla
   każdego logo, które idzie za motywem. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-marka.wg-motywu { content: url('../../assets/img/logo-biale.png'); }
}
.app-header { border-bottom: 1.5px solid var(--border); }
/* Okrągłe przyciski 40 px na białym tle z obwódką - „Wgraj zdjęcie" i przełącznik języka z planszy Nauka. */
.header-theme {
  width: 40px; height: 40px; border: none; background: var(--card-bg); color: var(--testo);
  box-shadow: 0 0 0 1.5px var(--border);
}
.header-theme:hover { background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--oro); }
.header-lang {
  height: 40px; padding: 0 4px 0 8px; gap: 4px; border-radius: 999px;
  background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border);
}
.header-lang-caret {
  width: 26px; height: 26px; padding: 0; border-radius: 999px; background: transparent;
  color: var(--testo); font-size: 0.72rem; opacity: 1;
}
.header-lang-caret:hover { background: var(--bg-soft); }
.header-lang-menu, .mode-tab-menu, .custom-select-menu, .card-menu {
  border: 1.5px solid var(--border); border-radius: 18px; padding: 6px;
  box-shadow: 0 18px 40px -18px rgba(23, 24, 59, 0.45);
}
.header-lang-item, .mode-tab-item, .custom-select-item, .card-menu-item { border-radius: 12px; }
/* Zakładki trybów - pigułki na białym pasku. AKTYWNA jest ŻÓŁTA z granatem w obu motywach:
   tak stoi zakładka „Nauka" na planszach (żółta pigułka pod ikoną). Dawniej wypełnienie akcentem. */
.mode-tabs { background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border); padding: 4px; gap: 4px; }
.mode-tab { color: var(--grigio); font-weight: 700; padding: 9px 18px; }
.mode-tab:hover { background: var(--bg-soft); color: var(--testo); }
.mode-tab.active, .mode-tab.active:hover { background: var(--zolty); color: var(--granat); box-shadow: none; }
.mode-tab-item.active { background: var(--bg-highlight); color: var(--testo); }
.mode-tab-item.active b { color: var(--testo); }
.streak-badge {
  border: none; background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border);
  padding: 8px 14px; min-height: 40px;
}
.streak-badge:hover { background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--oro); border-color: transparent; }
.header-konto { background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border); }
.header-konto .awatar-pierscien .account-avatar { box-shadow: 0 0 0 2px var(--card-bg); }
.header-konto-akcja { background: transparent; color: var(--testo); width: 34px; height: 34px; }
.header-konto-akcja:hover { background: var(--bg-soft); }
.pw-licznik { border-color: var(--card-bg); }
/* Szyna rankingu: płaska karta z obwódką; własny wiersz w żółtej poświacie wyboru (dawniej zieleń „dobrze"). */
.rank-rail { border-radius: 24px; box-shadow: none; border: 1.5px solid var(--border); background: var(--card-bg); }
.rank-row.me { background: var(--bg-highlight); }

/* SZYNA RANKINGU A TREŚĆ. Szyna (230 px przy prawej krawędzi) wchodzi od 1400 px, a treść ma 1100 px na środku -
   między 1400 a 1640 px prawa krawędź karty fiszki chowała się pod rankingiem (zmierzone na 1440 px: 84 px karty
   razem z głośnikiem pod szyną, tak samo przed zmianą stylu). W tym przedziale treść zwęża się o szerokość szyny
   z obu stron, zamiast przesuwać się w lewo - po lewej stoi szyna reklamowa kont darmowych (od 1500 px). */
@media (min-width: 1400px) and (max-width: 1639px) {
  body:has(#rankRail:not(.hidden)):not(.focus-mode) .app-body { max-width: calc(100vw - 540px); }
}

/* ---------- 2. KARTY, NAGŁÓWKI KART, POLA ---------- */
/* Karta płaska z obwódką 1,5 px - tak stoją wszystkie białe kafle na planszach. Cień został
   w tokenie --shadow (śladowy), więc tu go nie ma wcale. */
.card { border-radius: 24px; border: 1.5px solid var(--border); box-shadow: none; }
.card-title { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.08em; color: var(--grigio); }
.card-menu-btn { border-radius: 999px; }
/* Pola tekstowe: zaokrąglone 14 px, lawendowa obwódka, fokus w akcencie (patrz --oro). */
.auth-input {
  border-radius: 14px; border-width: 1.5px; border-color: var(--border-2);
  background: var(--card-bg); color: var(--testo);
}
.pomoc-rozwijana > summary { border-radius: 14px; }
.upload-zone { border-radius: 18px; border-width: 1.5px; }
.upload-hint-note { border-radius: 14px; }
.spinner { border-color: var(--border); border-top-color: var(--oro); }

/* ---------- 3. OKNA (wordmap-overlay: mapa słówek, ustawienia paczek, wszystkie „okienka") ---------- */
.wordmap-overlay { background: rgba(23, 24, 59, 0.62); }
.wordmap-modal { border-radius: 28px; background: var(--crema); box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.55); }
.wordmap-header { border-bottom: 1.5px solid var(--border); }
.wordmap-title { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.3rem; letter-spacing: -0.01em; }
.wordmap-close {
  width: 40px; height: 40px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--testo); font-size: 1.2rem; padding: 0;
}
.wordmap-close:hover { color: var(--testo); background: var(--border); transform: none; }

/* Powiadomienie (toast) - granatowa pigułka z białym napisem, jak na planszy „Fiszki" („Oznaczono jako łatwe").
   W ciemnym motywie odwrotnie (jasna na granacie), tak samo jak w aplikacji (toastTlo/toastTekst).
   Kolorowa kreska z lewej zostaje jako rodzaj komunikatu: zielona dobrze, czerwona błąd, żółta ostrzeżenie. */
.toast {
  background: var(--testo); color: var(--crema); border-radius: 18px;
  border-left: 5px solid var(--marka-zielony); box-shadow: 0 16px 34px -16px rgba(0, 0, 0, 0.55);
}
.toast.error { border-color: var(--marka-czerwony); }
.toast.warning { border-color: var(--zolty); }
.toast a { color: inherit; }

/* ---------- 4. FISZKI: PASEK NAD KARTĄ, NAWIGACJA, „POKAŻ ODPOWIEDŹ" ---------- */
.fiszka-counter {
  background: var(--card-bg); border: none; box-shadow: 0 0 0 1.5px var(--border);
  font-weight: 800; color: var(--testo); font-variant-numeric: tabular-nums;
}
.fiszka-nav-select {
  background: var(--card-bg); border: 1.5px solid var(--border); font-weight: 700; padding: 7px 14px;
}
/* PIGUŁKA POZIOMU W PEŁNYM KOLORZE (plansza „Fiszki"): łatwe - zieleń logo z granatowym napisem
   (biały miałby 3,1 : 1), średnie i trudne - z białym, nowe - neutralna. Dawniej blade tło
   z kolorowym napisem, czyli inny język niż ramka karty i przyciski ocen pod nią. */
.level-badge { padding: 5px 12px; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; }
.badge-nowe    { background: var(--border); color: var(--testo); }
.badge-latwe   { background: var(--marka-zielony); color: var(--granat); }
.badge-srednie { background: var(--marka-niebieski); color: #FFFFFF; }
.badge-trudne  { background: var(--marka-czerwony); color: #FFFFFF; }
.fiszka-toggles { font-weight: 700; color: var(--grigio); }
.card-delete-btn { width: 36px; height: 36px; border-radius: 999px; opacity: 0.75; display: inline-flex; align-items: center; justify-content: center; }
.card-delete-btn:hover { background: var(--bg-soft); opacity: 1; transform: none; }
/* Strzałki nawigacji - białe kółka z obwódką jak „Wróć" na planszach; napis pozycji w Outfit. */
.nav-arrow { border: none; box-shadow: 0 0 0 1.5px var(--border); color: var(--testo); font-size: 1.1rem; }
.nav-arrow:hover:not(:disabled) { box-shadow: 0 0 0 1.5px var(--oro); color: var(--testo); transform: scale(1.06); }
.nav-pos { font-family: var(--font-naglowek); font-weight: 800; color: var(--testo); font-variant-numeric: tabular-nums; }
/* PRZYCISK ODMIANY obok głośnika. Głośnik jest od dziś granatowym kółkiem 42 px w rogu (top/right 12 px,
   komponenty/fiszka.php), więc stary przycisk z right: 54px wjeżdżał mu w bok. Stoi o kółko dalej
   (12 + 42 + 8 = 62 px) i jest tym samym kształtem w wersji cichej: białe kółko z obwódką, granatowa ikona. */
.odmiana-btn {
  top: 12px; right: 62px; width: 42px; height: 42px; padding: 0; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--card-bg); color: var(--testo); opacity: 1; font-size: 1rem;
  box-shadow: 0 0 0 1.5px var(--border);
}
.odmiana-btn:hover { transform: scale(1.06); box-shadow: 0 0 0 1.5px var(--oro); }
/* „POKAŻ ODPOWIEDŹ" (plansza „Fiszki"): granatowa pigułka z okiem w żółtym kółku, w miejscu, w którym po
   obrocie staną oceny. Widać ją tylko przy karcie od przodu - sam CSS patrzy na klasę .flipped, którą i tak
   stawia setFlipped(), więc nie ma drugiego stanu do pilnowania w JS. */
.pokaz-odpowiedz {
  --kolko-strzalka: var(--oko-granatowe);
  display: flex; width: 100%; max-width: 440px; margin: 2px auto 4px;
}
:root[data-theme="dark"] .pokaz-odpowiedz { --kolko-strzalka: var(--oko-zolte); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .pokaz-odpowiedz { --kolko-strzalka: var(--oko-zolte); } }
#cardContent:has(#flipInner.flipped) .pokaz-odpowiedz { display: none; }

/* ---------- 5. PANEL BOCZNY: „DODAJ SŁÓWKA" ---------- */
.add-method-tab {
  border-radius: 14px; border: 1.5px solid var(--border); background: var(--card-bg);
  color: var(--testo); padding: 10px 8px; font-size: 0.78rem;
}
.add-method-tab .ico { color: var(--testo); }
.add-method-tab.active .ico { color: inherit; }
/* Trzy drogi do słówek, które prowadzą do innego trybu - w barwach tych trybów z planszy Nauka:
   Czytanie niebieskie, Słuchanie czerwone, Społeczność granatowa. Kwadrat ikony 30 px (jak w Stylu kanwy),
   biała karta z obwódką zamiast przerywanej ramki - przerywana została dla stref upuszczania pliku. */
.add-method-skrot {
  border: 1.5px solid var(--border); border-style: solid; background: var(--card-bg);
  border-radius: 16px; color: var(--testo); font-weight: 800; min-height: 48px; padding: 8px 10px 8px 8px;
}
.add-method-skrot > .ico:first-child {
  width: 32px; height: 32px; flex-shrink: 0; border-radius: 10px; margin: 0;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  background: var(--oro); color: var(--na-akcencie); font-size: 0.95rem;
}
.add-method-skrot > .ico:first-child::before { line-height: 1; }
.add-method-skrot[onclick*="teksty"] > .ico:first-child { background: var(--marka-niebieski); }
.add-method-skrot[onclick*="filmy"] > .ico:first-child { background: var(--marka-czerwony); }
.add-method-skrot:hover { border-color: var(--oro); color: var(--testo); }

/* ---------- 6. KARTA „TWOJE FISZKI" (panel Postęp) ----------
   Granatowa karta z ilustracją, żółtą liczbą i białymi kaflami poziomów - karta „Twoje fiszki" z planszy
   Nauka przeniesiona do panelu bocznego. Granat jest STAŁY w obu motywach (to karta marki, nie tło), więc
   wszystko w środku ma wpisane barwy marki, a nie tokeny motywu. W ciemnym motywie odcina się od granatowych
   kart obwódką. Kafle poziomów są BIAŁE (jak białe pigułki słówek na planszy), liczby w barwach logo. */
.karta-fiszek {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--granat); border-color: var(--granat); color: #FFFFFF;
}
:root[data-theme="dark"] .karta-fiszek { border-color: #2E3068; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .karta-fiszek { border-color: #2E3068; } }
/* Ilustracja w prawym górnym rogu, liczba i podpis w lewej kolumnie POD sobą - obok liczby podpis wchodził
   na rysunek (zmierzone na zrzucie 1440 px: „słówek w talii" na postaci). */
.karta-fiszek-ilustracja {
  position: absolute; top: 4px; right: -16px; width: 136px; height: 136px; z-index: -1;
  pointer-events: none; user-select: none;
}
.karta-fiszek .card-title { color: var(--zolty); margin-bottom: 6px; max-width: calc(100% - 96px); }
.karta-fiszek .card-title .ico { color: var(--zolty); }
.karta-fiszek-liczba { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 4px 0 18px; min-height: 90px; max-width: calc(100% - 104px); }
.karta-fiszek-liczba b {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 4.4rem; line-height: 0.82;
  letter-spacing: -0.03em; color: var(--zolty); font-variant-numeric: tabular-nums;
}
.karta-fiszek-liczba span { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; line-height: 1.1; color: #FFFFFF; }
.karta-fiszek .stat-box { background: #FFFFFF; border: 2px solid transparent; border-radius: 16px; }
.karta-fiszek .stat-box .count { font-family: var(--font-naglowek); font-size: 1.7rem; }
.karta-fiszek .stat-box .label { color: #4A4B6B; font-weight: 700; }
.karta-fiszek .stat-nowe .count { color: #2E3055; }
.karta-fiszek .stat-latwe .count { color: #1F7A35; }
.karta-fiszek .stat-srednie .count { color: #2463E9; }
.karta-fiszek .stat-trudne .count { color: #DB2727; }
.karta-fiszek .stat-box:hover { border-color: var(--zolty); transform: translateY(-2px); }
.karta-fiszek .stat-box.active-filter { border-color: var(--zolty); background: #FFF4D6; }
.karta-fiszek .stat-map-btn { color: #D4D5F0; border-color: rgba(212, 213, 240, 0.35); background: transparent; }
.karta-fiszek .stat-map-btn:hover { color: var(--granat); border-color: var(--zolty); background: var(--zolty); }
.karta-fiszek .progress-label { color: #D4D5F0; font-weight: 700; }
.karta-fiszek .progress-bar { background: rgba(255, 255, 255, 0.16); }
.karta-fiszek .progress-fill { background: var(--marka-zielony); }
.karta-fiszek .btn-grigio { background: var(--zolty); color: var(--granat); box-shadow: none; }
.karta-fiszek .btn-grigio:hover { box-shadow: 0 10px 22px -12px rgba(255, 200, 61, 0.8); }
.karta-fiszek .btn-kreskowany { background: transparent; color: #FFFFFF; border: 2px solid rgba(255, 255, 255, 0.85); }
.karta-fiszek .btn-kreskowany .ico { color: #FFFFFF; }
.karta-fiszek .btn-kreskowany:hover { border-color: var(--zolty); color: var(--zolty); }
.karta-fiszek .btn-kreskowany:hover .ico { color: var(--zolty); }
.karta-fiszek .locked-banner { background: rgba(255, 255, 255, 0.1); color: #FFFFFF; border-color: rgba(255, 255, 255, 0.2); }
.karta-fiszek .locked-banner a { color: var(--zolty); }
.karta-fiszek .ad-sidebar { border-top-color: rgba(255, 255, 255, 0.18); }
.karta-fiszek .ad-sidebar-label { color: #D4D5F0; }

/* ---------- 7. PUSTA TALIA = „PIERWSZE SŁÓWKA" ----------
   Plansza Nauka: granatowa karta z ilustracją i żółtym napisem, pod nią kolorowe kafle trybów z ilustracjami
   (Zdjęcie żółte, Czytanie niebieskie, Słuchanie czerwone) i biały wiersz do Społeczności. Na komputerze kafle
   stoją w jednym rzędzie obok siebie zamiast 2 × 2. */
.empty-state { text-align: left; padding: 8px 0 20px; color: var(--grigio); }
.pusta-talia-glowa {
  position: relative; overflow: hidden; isolation: isolate; border-radius: 28px;
  background: var(--granat); color: #FFFFFF; padding: 30px 32px 28px; min-height: 196px;
}
.pusta-talia-glowa img {
  position: absolute; right: -12px; top: -10px; width: 214px; height: 214px; z-index: -1; pointer-events: none;
}
.pusta-talia-glowa .pusta-talia-etykieta {
  font-size: 0.78rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--zolty);
}
.empty-state .pusta-talia-glowa h3 {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 2.4rem; line-height: 1.02; letter-spacing: -0.02em;
  color: #FFFFFF; margin: 8px 0 10px; max-width: 460px;
}
.pusta-talia-glowa p { font-size: 1rem; font-weight: 500; line-height: 1.55; color: #D4D5F0; max-width: 470px; margin: 0; }
/* Tekst głowy nie wchodzi na ilustrację także w zwężonej kolumnie (1400–1640 px obok szyny rankingu) i na telefonie. */
.pusta-talia-glowa > :not(img) { max-width: min(470px, calc(100% - 190px)); }
@media (max-width: 768px) {
  .pusta-talia-glowa { padding: 22px 20px; min-height: 0; }
  .pusta-talia-glowa img { width: 128px; height: 128px; top: -6px; right: -14px; }
  .pusta-talia-glowa > :not(img) { max-width: calc(100% - 96px); }
  .empty-state .pusta-talia-glowa h3 { font-size: 1.9rem; }
}
/* ---------- 7a. POWITANIE DNIA W MIEJSCU KARTY (2026-09-28) ----------
   Alek: „Na aplikacji mobilnej gdy wejdę w naukę ładnie mnie wita aplikacja i pokazuje, że czeka na ciebie 20 słówek
   do nauki i że zajmie mi to kilka minut … pojawia się ładna postać i zachęca do kliknięcia i zrobienia krótkiej lekcji.
   Powinniśmy to dodać na desktop, bo tego nie ma. Ten modal będzie wyświetlał się tylko raz dziennie i pojawiać się ma
   zamiast widoku kart FISZEK (w tym samym polu, gdzie normalnie są fiszki i miniquizy)”. To granatowa karta „Twoje fiszki”
   z aplikacji (KartaGranatowa w lingaria-app/src/app/(aplikacja)/(zakladki)/nauka.tsx) na nakładce półmetka: stoi
   w #flashcard-area zamiast fiszki, a karta czeka pod nią nietknięta. Barwy stałe w obu motywach, jak każdy ekran marki;
   przycisk z kółkiem w wariancie na granacie (.na-granacie). Odcinki paska poziomów w jaśniejszych barwach logo (zieleń
   i czerwień, błękit jak w ciemnym motywie), bo #2463E9 i #DB2727 mają na granacie 2,8 i 3,0 : 1. */
.polmetek.powitanie-dnia {
  --plansza-tlo: var(--granat);
  background: var(--granat); color: #FFFFFF; box-shadow: none; border-radius: 28px;
  align-items: stretch; justify-content: flex-start; padding: 0; overflow-y: auto;
}
/* Poświata STOI: pulsująca (polmetekPoswiata, skala do 1,1) wystawała przy inset 0 poza planszę z overflow-y: auto
   i co pół cyklu w planszy pojawiał się pasek przewijania (zmierzone 2026-09-28: scrollHeight 666 przy 634 px). */
.polmetek.powitanie-dnia::before {
  inset: 0; background: radial-gradient(circle at 84% 30%, rgba(255, 200, 61, 0.18) 0, transparent 46%); animation: none;
}
/* W ciemnym motywie granat planszy stoi na prawie czarnym tle i krawędź ginie: ta sama obwódka, co karta „Twoje fiszki”
   w panelu obok (.karta-fiszek) i KartaGranatowa w aplikacji. */
:root[data-theme="dark"] .polmetek.powitanie-dnia { box-shadow: inset 0 0 0 1.5px #2E3068; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .polmetek.powitanie-dnia { box-shadow: inset 0 0 0 1.5px #2E3068; } }
.witaj-karta {
  position: relative; isolation: isolate; width: 100%; min-height: 100%;
  display: flex; flex-direction: column; gap: 14px; padding: 34px 36px 26px; text-align: left;
}
.polmetek.powitanie-dnia.wjazd .witaj-karta { animation: witajWjazd 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes witajWjazd { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }
.witaj-ilustracja {
  position: absolute; right: -8px; top: -4px; width: 290px; height: 290px; z-index: -1; pointer-events: none;
}
.polmetek.powitanie-dnia.wjazd .witaj-ilustracja { animation: witajPostac 0.7s cubic-bezier(0.22, 1.4, 0.36, 1) 0.1s both; }
@keyframes witajPostac { from { transform: translateY(24px) scale(0.92); opacity: 0; } to { transform: none; opacity: 1; } }
/* Tekst obok postaci nie wchodzi na nią, także w zwężonej kolumnie (1400–1640 px obok szyny rankingu). */
.witaj-karta > :not(.witaj-ilustracja) { max-width: min(520px, calc(100% - 240px)); }
.witaj-etykieta { font-size: 0.78rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--zolty); }
.witaj-tytul {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 2.1rem; line-height: 1.08; letter-spacing: -0.02em;
  color: #FFFFFF; margin-top: -6px; overflow-wrap: anywhere; text-wrap: balance;
}
.witaj-liczba-wiersz { display: flex; align-items: flex-end; gap: 14px; margin-top: 4px; }
.witaj-liczba {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 6.6rem; line-height: 0.8; letter-spacing: -0.03em;
  color: var(--zolty); font-variant-numeric: tabular-nums;
}
.witaj-czeka {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 1.45rem; line-height: 1.12; color: #FFFFFF;
  max-width: 250px; padding-bottom: 2px;
}
.witaj-opis { font-size: 1rem; font-weight: 500; line-height: 1.55; color: #D4D5F0; margin: 0; }
.witaj-pasek { display: flex; gap: 4px; height: 12px; margin-top: 4px; }
.witaj-pasek span { border-radius: 999px; min-width: 6px; }
.witaj-legenda { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 0.86rem; font-weight: 700; color: #FFFFFF; font-variant-numeric: tabular-nums; }
.witaj-legenda span { display: inline-flex; align-items: center; gap: 7px; }
.witaj-legenda i { display: inline-block; width: 9px; height: 9px; border-radius: 999px; }
.witaj-pasek .witaj-nowe, .witaj-legenda .witaj-nowe { background: #D4D5F0; }
.witaj-pasek .witaj-latwe, .witaj-legenda .witaj-latwe { background: #4CC266; }
.witaj-pasek .witaj-srednie, .witaj-legenda .witaj-srednie { background: #3B82F6; }
.witaj-pasek .witaj-trudne, .witaj-legenda .witaj-trudne { background: #EF4444; }
.witaj-talia { font-size: 0.82rem; font-weight: 600; color: #D4D5F0; }
.polmetek.powitanie-dnia .witaj-akcje { justify-content: flex-start; margin-top: 6px; }
.polmetek.powitanie-dnia .witaj-akcje .btn-strzalka { min-width: 300px; }
.polmetek.powitanie-dnia .witaj-hint { color: #A9ABD6; margin-top: -4px; }
@media (max-width: 768px) {
  .witaj-karta { padding: 24px 20px 20px; gap: 12px; }
  .witaj-ilustracja { width: 140px; height: 140px; right: -12px; top: -4px; }
  .witaj-karta > :not(.witaj-ilustracja) { max-width: 100%; }
  .witaj-karta > .witaj-etykieta, .witaj-karta > .witaj-tytul { max-width: calc(100% - 110px); }
  .witaj-tytul { font-size: 1.7rem; }
  .witaj-liczba { font-size: 5rem; }
  .witaj-czeka { font-size: 1.2rem; }
  .polmetek.powitanie-dnia .witaj-akcje .btn-strzalka { min-width: 0; width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .polmetek.powitanie-dnia.wjazd .witaj-karta, .polmetek.powitanie-dnia.wjazd .witaj-ilustracja { animation: none; }
}

/* ---------- 7b. KONIEC POWTÓRKI DNIA W MIEJSCU KARTY (2026-09-28) ----------
   Alek: „Dostanę planszę, że 20 słówek na dzień zostało odświeżonych? I potem powinna być informacja, że możesz uczyć się
   dalej”. Żółty ekran „Koniec powtórki” z aplikacji (KoniecPowtorki w nauka/fiszki.tsx: biała pigułka, ilustracja koniec.webp
   w prawym górnym rogu, granatowa liczba słówek) na nakładce półmetka; granatowa pigułka z żółtym kółkiem (.na-kolorze).
   Barwy stałe w obu motywach, jak każdy ekran marki. Granat na żółtym ma 11 : 1, podpowiedź klawiszy #5C4A12 ma 5,7 : 1. */
.polmetek.koniec-dnia {
  --plansza-tlo: var(--zolty);
  background: var(--zolty); color: var(--granat); box-shadow: none; border-radius: 28px;
  align-items: stretch; justify-content: flex-start; padding: 0; overflow-y: auto;
}
.polmetek.koniec-dnia::before { inset: 0; background: radial-gradient(circle at 82% 28%, rgba(255, 255, 255, 0.38) 0, transparent 46%); animation: none; }
.kd-karta {
  position: relative; isolation: isolate; width: 100%; min-height: 100%;
  display: flex; flex-direction: column; gap: 8px; padding: 30px 36px 26px; text-align: left;
}
.polmetek.koniec-dnia.wjazd .kd-karta { animation: witajWjazd 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.kd-ilustracja { position: absolute; right: -14px; top: -8px; width: 300px; height: 300px; z-index: -1; pointer-events: none; }
.polmetek.koniec-dnia.wjazd .kd-ilustracja { animation: witajPostac 0.7s cubic-bezier(0.22, 1.4, 0.36, 1) 0.1s both; }
.kd-karta > :not(.kd-ilustracja) { max-width: min(520px, calc(100% - 250px)); }
.kd-pigulka {
  align-self: flex-start; padding: 6px 14px; border-radius: 999px; background: #FFFFFF; color: var(--granat);
  font-size: 0.82rem; font-weight: 700;
}
.kd-tytul {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 2.1rem; line-height: 1.08; letter-spacing: -0.02em;
  color: var(--granat); margin-top: 8px; text-wrap: balance;
}
.kd-liczba {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 7rem; line-height: 0.84; letter-spacing: -0.04em;
  color: var(--granat); font-variant-numeric: tabular-nums; margin-top: 8px;
}
.kd-slowka { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.6rem; line-height: 1.1; color: var(--granat); }
.kd-czas { font-size: 1.05rem; font-weight: 700; color: var(--granat); }
/* Wynik quizu powtórki (2026-10-07): biała pigułka z zielonym kółkiem i fajką, jak „zaliczone” na planszach marki. Fajka
   granatowa na zieleni logo (biel na #35A64D ma 3,1 : 1), napis granatowy na bieli. */
.kd-quiz {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 8px; margin-top: 4px;
  padding: 5px 14px 5px 5px; border-radius: 999px; background: #FFFFFF; color: var(--granat);
  font-size: 0.95rem; font-weight: 700; line-height: 1.3;
}
.kd-quiz .ico {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 26px; height: 26px; margin: 0;
  border-radius: 50%; background: var(--marka-zielony, #35A64D); color: var(--granat); font-size: 0.8rem; line-height: 1;
}
.kd-opis { font-size: 1rem; font-weight: 500; line-height: 1.55; color: var(--granat); margin: 8px 0 0; }
.polmetek.koniec-dnia .kd-akcje { justify-content: flex-start; margin-top: 8px; }
.polmetek.koniec-dnia .kd-akcje .btn-strzalka { min-width: 300px; }
.polmetek.koniec-dnia .kd-hint { color: #5C4A12; margin-top: -2px; }
/* CO DALEJ: białe kafelki na żółtym (jak kafle trybów w Nauce aplikacji: kwadrat ikony w barwie marki, nazwa i jedno
   zdanie). Pod postacią, więc na całą szerokość planszy, nie w kolumnie obok ilustracji. Paczki niebieskie, Społeczność
   zielona z granatową ikoną (biała na zieleni 3,1 : 1). Kafelek mini testu zniknął 2026-10-07 (quiz jest w powtórce). */
.kd-karta > .kd-dalej { max-width: none; margin-top: 14px; }
.kd-dalej-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.15rem; color: var(--granat); margin-bottom: 10px; }
/* auto-fit: schowany kafelek (konto bez żadnego zbioru) nie zostawia dziury w rzędzie. */
.kd-kafle { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; }
.kd-kafel {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; text-align: left; font: inherit; cursor: pointer;
  padding: 14px; border-radius: 18px; background: #FFFFFF; color: var(--granat); border: 1.5px solid rgba(23, 24, 59, 0.1);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.kd-kafel:hover { transform: translateY(-2px); box-shadow: 0 8px 20px -10px rgba(23, 24, 59, 0.45); }
.kd-kafel:focus-visible { outline: 3px solid var(--granat); outline-offset: 2px; }
.kd-kafel b { font-size: 0.95rem; font-weight: 800; line-height: 1.25; }
.kd-kafel small { font-size: 0.8rem; line-height: 1.4; color: #4A4B6A; }
.kd-kafel-ikona {
  display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 12px;
  margin-bottom: 6px; font-size: 1.15rem;
}
.kd-kafel-ikona .ico { margin: 0; }
.kd-ik-paczki { background: #2463E9; color: #FFFFFF; }
.kd-ik-spolecznosc { background: #35A64D; color: var(--granat); }
.polmetek.zamrozona .kd-kafel { pointer-events: none; opacity: 0.55; }
@media (prefers-reduced-motion: reduce) { .kd-kafel { transition: none; } .kd-kafel:hover { transform: none; } }
@media (max-width: 768px) {
  .kd-karta { padding: 24px 20px 20px; }
  .kd-ilustracja { width: 150px; height: 150px; right: -14px; top: -6px; }
  .kd-karta > :not(.kd-ilustracja) { max-width: 100%; }
  .kd-karta > .kd-pigulka, .kd-karta > .kd-tytul { max-width: calc(100% - 120px); }
  .kd-tytul { font-size: 1.7rem; }
  .kd-liczba { font-size: 5.2rem; }
  .kd-slowka { font-size: 1.3rem; }
  .polmetek.koniec-dnia .kd-akcje .btn-strzalka { min-width: 0; width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .polmetek.koniec-dnia.wjazd .kd-karta, .polmetek.koniec-dnia.wjazd .kd-ilustracja { animation: none; }
}
.empty-state .empty-icon { display: none; }
/* Dwa na dwa jak na planszy, a w jednym rzędzie dopiero wtedy, gdy kolumna treści ma ~800 px (między 1180 a 1400 px
   okna i od 1640 px - pomiędzy stoi szyna rankingu i kolumna się zwęża). Przy auto-fit wychodziło 3 + 1. */
.empty-state-methods {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
  justify-content: stretch; margin-top: 18px;
}
@media (min-width: 1180px) and (max-width: 1399px), (min-width: 1640px) {
  .empty-state-methods { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 420px) { .empty-state-methods { grid-template-columns: minmax(0, 1fr); } }
.empty-state-method {
  position: relative; overflow: hidden; align-items: flex-start; text-align: left; gap: 6px;
  min-height: 188px; padding: 118px 16px 16px; border: none; border-radius: 24px;
  background: var(--zolty); color: var(--granat); min-width: 0;
}
.empty-state-method:hover { transform: translateY(-3px); box-shadow: 0 16px 30px -18px rgba(23, 24, 59, 0.6); }
.empty-state-method img.tryb-ilustracja {
  position: absolute; left: 10px; top: -4px; width: 124px; height: 124px; pointer-events: none;
}
.empty-state-method .empty-state-method-icon { display: none; }
.empty-state-method strong { font-family: var(--font-naglowek); font-size: 1.12rem; font-weight: 800; line-height: 1.12; color: inherit; }
.empty-state-method small { font-size: 0.82rem; font-weight: 500; line-height: 1.4; color: inherit; }
/* Pigułka trybu stoi POD ilustracją, na początku kolumny tekstu - tak jak na planszy Nauka. */
.empty-state-method .tryb-pigulka {
  align-self: flex-start; margin-bottom: 2px;
  display: inline-flex; align-items: center; min-height: 24px; padding: 0 10px; border-radius: 999px;
  background: #FFFFFF; color: var(--granat); font-size: 0.72rem; font-weight: 800;
}
.empty-state-method.tryb-excel { background: var(--marka-zielony); color: var(--granat); }
.empty-state-method.tryb-czytanie { background: #2463E9; color: #FFFFFF; }
.empty-state-method.tryb-sluchanie { background: #DB2727; color: #FFFFFF; }
.empty-state-method.tryb-excel .tryb-ikona-duza {
  position: absolute; left: 22px; top: 30px; width: 76px; height: 76px; border-radius: 22px;
  display: flex; align-items: center; justify-content: center; font-size: 2.2rem; line-height: 1;
  background: #FFFFFF; color: var(--granat); box-shadow: 0 0 0 2.5px var(--granat);
}
.pusta-talia-spolecznosc {
  display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 14px; min-height: 58px;
  padding: 10px 16px; border: 1.5px solid var(--border); border-radius: 20px; background: var(--card-bg);
  color: var(--testo); font-family: inherit; font-size: 0.98rem; font-weight: 800; text-align: left; cursor: pointer;
  transition: var(--transition);
}
.pusta-talia-spolecznosc:hover { border-color: var(--oro); }
.pusta-talia-spolecznosc .pts-ikona {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 12px; display: flex; align-items: center; justify-content: center;
  background: var(--oro); color: var(--na-akcencie);   /* granat w jasnym, żółty w ciemnym - granat na granacie znikał */
}
.pusta-talia-spolecznosc .pts-ikona .ico { margin: 0; }
.pusta-talia-spolecznosc > .ico:last-child { margin-left: auto; color: var(--grigio); }
.empty-state.dragover { border-radius: 28px; background: var(--bg-highlight); }
.empty-state.dragover .empty-state-method { outline: 3px dashed var(--granat); outline-offset: -8px; background: var(--zolty); }

/* ---------- 8. EKRANY TRYBÓW: CZYTANIE (niebieski), SŁUCHANIE (czerwony), MÓWIENIE (zielony) ----------
   Nagłówek trybu w barwie z planszy, z ilustracją po prawej: etykieta wersalikami, duży tytuł Outfit, zdanie
   o tym, co się tu robi. Pod nim zostaje biała kartka / formularz - to one są narzędziem, a nagłówek mówi,
   GDZIE się jest (dawniej każdy tryb zaczynał się tym samym szarym napisem nad kartką). */
.tryb-hero {
  position: relative; overflow: hidden; isolation: isolate; border-radius: 28px;
  padding: 26px 30px 26px; margin: 0 0 18px; min-height: 176px; text-align: left;
  display: flex; flex-direction: column; justify-content: center;
}
.tryb-hero > :not(img) { max-width: calc(100% - 170px); }
.tryb-hero-ilustracja { position: absolute; right: -8px; top: 50%; width: 200px; height: 200px; margin-top: -100px; z-index: -1; pointer-events: none; }
.tryb-hero-etykieta { font-size: 0.8rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; }
.tryb-hero-tytul {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 2.6rem; line-height: 1; letter-spacing: -0.02em;
  margin: 4px 0 10px;
}
.tryb-hero-opis { font-size: 0.96rem; font-weight: 500; line-height: 1.55; max-width: 560px; margin: 0; }
.tryb-hero-czytanie { background: #2463E9; color: #FFFFFF; }
.tryb-hero-sluchanie { background: #DB2727; color: #FFFFFF; }
.tryb-hero-mowienie { background: #35A64D; color: #17183B; }
.tryb-hero .tryb-hero-opis { color: inherit; opacity: 0.95; }
@media (max-width: 768px) {
  .tryb-hero { padding: 20px 20px 22px; min-height: 0; }
  .tryb-hero-ilustracja { width: 120px; height: 120px; top: -6px; margin-top: 0; right: -18px; opacity: 0.95; }
  .tryb-hero-tytul { font-size: 2rem; }
  .tryb-hero > :not(img) { max-width: calc(100% - 96px); }
}
/* Czytanie: intro ma klasę .tekst-intro (szary tekst pod paskiem) - w głowie bierze barwę głowy. Podpowiedź
   „Tytuł i poziom dobierze AI" została nad kartką jako cichy podpis pola. */
.tryb-hero .tekst-intro { color: inherit; margin: 0; }
.tekst-formularz-pasek { margin: 0 0 6px; }
.tekst-formularz-pasek .kartka-meta { font-weight: 700; }
/* Słuchanie: formularz linku stoi w białej karcie pod czerwoną głową. */
#filmFormularz .film-formularz { background: var(--card-bg); border: 1.5px solid var(--border); border-radius: 24px; padding: 20px; }
#filmFormularz .film-pole label { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; color: var(--testo); }
/* Mówienie: głowa mapy rozmów zielona (plansza „Mówienie"), kafelki rozmów białe z okładką. */
.mow-mapa .tryb-hero-mowienie { margin-bottom: 16px; }
.mow-mapa .tryb-hero-mowienie .mow-mapa-opis { color: #17183B; text-align: left; font-size: 0.95rem; font-weight: 500; line-height: 1.55; margin: 0; max-width: calc(100% - 170px); }
@media (max-width: 768px) { .mow-mapa .tryb-hero-mowienie .mow-mapa-opis { max-width: calc(100% - 96px); } }
.mow-mapa-podtytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.3rem; color: var(--testo); margin: 4px 0 12px; }

/* ---------- 9. MÓWIENIE: KAFELKI ROZMÓW ---------- */
.mow-kafelek { border-radius: 24px; border: 1.5px solid var(--border); background: var(--card-bg); box-shadow: none; }
.mow-kafelek-foto { border-radius: 23px 23px 0 0; height: 150px; }
.mow-kafelek:hover { border-color: var(--oro); box-shadow: 0 16px 30px -20px rgba(23, 24, 59, 0.5); }
.mow-kafelek-glowa b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.12rem; letter-spacing: -0.01em; }
/* Tytuł ma pierwszeństwo przed pigułkami (Edytuj, CEFR): w kafelku ~250 px szerokości ściskały go do 64 px i „W sklepie”
   łamało się na dwie linie po jednym słowie (zrzut 2026-09-26). Tytuł bierze co najmniej 8em, a pigułki przechodzą niżej. */
.mow-kafelek-glowa { flex-wrap: wrap; row-gap: 6px; }
.mow-kafelek-glowa b { flex: 1 1 8em; }
/* Poziom CEFR i „znasz X%” na kafelkach czytanki, utworu i rozmowy na tablicy Społeczności (2026-10-03) wyglądają tak samo
   jak na mapie Mówienia: jedna pigułka, jedna reguła (klasa `znasz` na plakietce stawia kafelekTekstu i kafelekUtworu). Przy 0% klasy nie ma
   i plakietka zostaje cicha: żółte wyróżnienie zera ciągnęło wzrok do braku wiedzy, a gość (bez talii) miał je na każdym kaflu. */
.mow-cefr { border: none; background: var(--oro); color: var(--na-akcencie); font-weight: 800; font-size: 0.7rem; padding: 3px 10px; }   /* granat na białej karcie, żółty na granatowej (ciemny motyw) */
.mow-kafelek-znasz { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 999px; background: var(--zolty); color: var(--granat); font-weight: 800; }
.mow-kafelek-znasz.duzo { color: var(--granat); }
/* OSTATNIO OTWIERANE (2026-09-28): dopisek nad nagłówkiem kafelka. Najświeższa rozmowa w obrysie akcentu (granat, w ciemnym motywie
   żółty) - nie w żółtym wypełnieniu, bo to już znaczy „znasz X%” w stopce; kolejne otwierane cicho, jak opis kafelka. */
.mow-kafelek-ostatnio { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; font-size: 0.74rem; font-weight: 600; color: var(--grigio); }
.mow-kafelek-ostatnio .ico { font-size: 0.8rem; margin: 0; line-height: 1; }
.mow-kafelek-ostatnio.najnowszy { padding: 2px 10px; border-radius: 999px; border: 1.5px solid var(--oro); color: var(--oro); font-weight: 800; }
/* „Twórca edytował ten zbiór …” / „Edytowano …” (2026-09-29, etykietaEdycjiHtml): CICHY dopisek, a nie plakietka. To informacja
   „coś się zmieniło od twojej wersji”, nie wezwanie do działania, więc bez tła i bez akcentu: szary krój metadanych, jak
   „otwierane wczoraj” obok. Napis nie łamie się w dwie linie (wąski kafelek tablicy na telefonie) - ucina się wielokropkiem,
   a pełną datę daje dymek z title. --grigio ma własną wartość w obu motywach. */
.edycja-znak { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start; max-width: 100%; min-width: 0;
  font-size: 0.72rem; font-weight: 600; line-height: 1.3; color: var(--grigio); font-style: normal; letter-spacing: 0; text-transform: none; }
.edycja-znak .ico { font-size: 0.74rem; margin: 0; line-height: 1; flex-shrink: 0; }
.edycja-znak > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tekst-wiersz-txt .edycja-znak { display: flex; margin-top: 3px; }
.community-tile .edycja-znak { margin: 2px 0 4px; }
#communityDetailMeta .edycja-znak { margin-left: 8px; vertical-align: middle; }
.mow-poziom-pill { border-radius: 999px; font-weight: 800; }
.mow-poziom-pill.ukonczony { background: var(--marka-zielony); border-color: var(--marka-zielony); color: var(--granat); }
.mow-poziom-pill:not(.ukonczony):not(.zablokowany) { background: var(--oro); border-color: var(--oro); color: var(--na-akcencie); }
.mow-poziom-pill.zablokowany { background: var(--bg-soft); border-color: var(--bg-soft); color: var(--grigio); }

/* ---------- 10. QUIZ ---------- */
/* Pasek postępu serii: zieleń logo 8 px na lawendowym torze - ten sam, co pasek porcji na planszy „Fiszki". */
.quiz-progress-track { height: 8px; background: var(--border); }
.quiz-badge { color: var(--grigio); }
.quiz-heading { font-family: var(--font-naglowek); font-weight: 800; letter-spacing: -0.01em; }
/* „SPRAWDŹ" to główny przycisk - granatowa pigułka z półką (w ciemnym żółta); „Dalej →" po odpowiedzi
   zostaje niebieski z logo, żeby zmiana stanu była widać bez czytania napisu. */
.quiz-sprawdz { --polka-kolor: var(--oro); }
.quiz-slowo-opcja { background: var(--card-bg); border-width: 1.5px; border-color: var(--border); border-radius: 18px; }
.mini-exam-input-row input { border-radius: 16px; border-width: 1.5px; background: var(--card-bg); }
.quiz-koniec-kafel { border-radius: 20px; border-width: 1.5px; }
.quiz-koniec-kafel .liczba { font-family: var(--font-naglowek); font-size: 2rem; }
.quiz-koniec-kafel.dobre { background: var(--marka-zielony); border-color: var(--marka-zielony); }
.quiz-koniec-kafel.dobre .liczba, .quiz-koniec-kafel.dobre .podpis { color: #17183B; }
.quiz-koniec-kafel.zle { background: var(--marka-czerwony); border-color: var(--marka-czerwony); }
.quiz-koniec-kafel.zle .liczba, .quiz-koniec-kafel.zle .podpis { color: #FFFFFF; }
/* KONIEC SERII = „Powtórka zrobiona!" z planszy: żółta karta z ilustracją i zdaniem o wyniku pod nią. Do 2026-09-27
   ilustracja chowała się, gdy w karcie stanęła postać z konsoli admina - postaci odeszły, ilustracja stoi zawsze. */
.quiz-koniec { position: relative; overflow: hidden; isolation: isolate; border-radius: 28px; background: var(--zolty); color: var(--granat); padding: 24px 24px 22px; }
.quiz-koniec-ilustracja { display: block; width: 190px; height: 190px; margin: -12px auto 4px; pointer-events: none; }
.quiz-koniec .quiz-koniec-kafel.xp { background: #FFFFFF; border-color: #FFFFFF; }
.quiz-koniec .quiz-koniec-kafel.xp .liczba { color: #17183B; }
.quiz-koniec .quiz-koniec-kafel.xp .podpis { color: #4A4B6B; }
.quiz-koniec .quiz-koniec-pasek-tlo { background: rgba(23, 24, 59, 0.14); }
.quiz-koniec .btn-verde { background: var(--granat); color: #FFFFFF; }
.quiz-koniec .btn-grigio { background: #FFFFFF; color: var(--granat); box-shadow: none; }
/* Zdanie o wyniku (kwestia z trzech wariantów na pasmo) - pod ilustracją, nad kaflami liczb. Liczby w nim są
   pogrubione już w tłumaczeniu (<strong>), więc tu dostają tylko pełną wagę kroju. */
.quiz-koniec-zdanie {
  margin: 0 auto 18px; max-width: 480px; text-align: center; text-wrap: balance;
  font-size: 1.12rem; font-weight: 600; line-height: 1.5; color: #17183B;
}
.quiz-koniec-zdanie strong { font-weight: 800; }
.quiz-koniec .quiz-zajawka-pasek { background: rgba(255, 255, 255, 0.55); border-color: rgba(23, 24, 59, 0.2); }

/* ---------- 11. PÓŁMETEK, CEL DNIA ---------- */
.polmetek { border-radius: 28px; }
.polmetek-pct { font-family: var(--font-naglowek); font-weight: 800; }
.polmetek-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.6rem; letter-spacing: -0.01em; }
/* CEL DNIA: plansza startowa ŻÓŁTA (propozycja, jak „Sprawdźmy, co już pamiętasz"), zakończenie ZIELONE
   z ilustracją (plansza „Cel dnia"). Stałe barwy w obu motywach - to ekran marki w miejscu karty. */
.polmetek.cel-slowek { --cs-akcent: #17183B; background: var(--zolty); color: var(--granat); box-shadow: none; }
.polmetek.cel-slowek::before { display: none; }
.polmetek.cel-slowek.koniec { background: #35A64D; }
.polmetek.cel-slowek .polmetek-tytul { font-size: 2rem; line-height: 1.05; color: #17183B; }
.polmetek.cel-slowek .polmetek-opis { color: #17183B; font-weight: 500; }
.polmetek.cel-slowek .polmetek-hint { color: rgba(23, 24, 59, 0.7); }
.polmetek.cel-slowek .cs-ikona {
  width: 76px; height: 76px; margin: 0 auto 6px; border-radius: 999px; background: #17183B; color: #FFC83D;
  display: flex; align-items: center; justify-content: center; font-size: 2rem;
}
.polmetek.cel-slowek .cs-ikona .ico { margin: 0; }
.cs-ilustracja { display: none; width: 200px; height: 200px; margin: -14px auto 0; pointer-events: none; }
.polmetek.cel-slowek.koniec .cs-ilustracja { display: block; }
.polmetek.cel-slowek.koniec .cs-ikona { display: none; }
.polmetek.cel-slowek .cs-glowny { --polka-kolor: #17183B; background: #17183B; color: #FFFFFF; }
.polmetek.cel-slowek .cs-karta { background: #FFFFFF; color: #17183B; border: none; box-shadow: 0 10px 22px -14px rgba(23, 24, 59, 0.55); }
.polmetek.cel-slowek .cs-karta .cs-tlum { color: #4A4B6B; }
.polmetek.cel-slowek .cs-karta.zaliczone { box-shadow: inset 0 0 0 2.5px #17183B, 0 10px 22px -14px rgba(23, 24, 59, 0.55); }
/* Fajka zaliczonego słówka w ROGU karty: granatowe kółko z żółtym ptaszkiem, jak kafel „dziś” w KoniecCelu aplikacji.
   Wewnątrz karty (top 6 px, right 8 px) wchodziła na dłuższe słówka - zmierzone na zrzucie 2026-09-27: „il formaggio”
   w karcie 140 px sięga 125 px, ptaszek zaczyna się na 116 px. */
.polmetek.cel-slowek .cs-karta .cs-fajka {
  top: -9px; right: -9px; width: 24px; height: 24px; margin: 0; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; font-size: 0.7rem; line-height: 1;
  background: #17183B; color: #FFC83D; box-shadow: 0 0 0 2px #FFFFFF;
}
.polmetek.cel-slowek .cs-karta .cs-poziom { background: #FFFFFF; border-color: #C9CAE8; color: #4A4B6B; }
.polmetek.cel-slowek .cs-karta .cs-poziom.latwe { background: #35A64D; border-color: #35A64D; color: #17183B; }
.polmetek.cel-slowek .cs-karta .cs-poziom.srednie { background: #2463E9; border-color: #2463E9; color: #FFFFFF; }
.polmetek.cel-slowek .cs-karta .cs-poziom.trudne { background: #DB2727; border-color: #DB2727; color: #FFFFFF; }
.polmetek.cel-slowek .cs-nie { color: #17183B; }
/* PASEK TRZECH DNI na zakończeniu celu (2026-09-27, Alek: „tak” na pasek jak w aplikacji). Wzór: KafelDnia w KoniecCelu
   aplikacji - dziś granatowy kafel z żółtym ptaszkiem („Zaliczone, właśnie teraz”), jutro i pojutrze przerywana granatowa
   obwódka na rozjaśnionej zieleni („Utrwalenie, w fiszkach”). Do tego dnia strona mówiła o powrocie tylko zdaniem
   w opisie („wrócimy do nich jutro (piątek) i pojutrze (sobota)”), a aplikacja pokazywała to kaflami. Stałe barwy
   w obu motywach, jak cała plansza. Na planszy startowej pasek jest pusty i schowany (steruje tym .koniec). */
.cs-dni { display: none; }
.polmetek.cel-slowek.koniec .cs-dni { display: flex; gap: 8px; max-width: 460px; margin: 14px auto 16px; text-align: left; }
.cs-dzien {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 8px;
  padding: 10px; border-radius: 20px; border: 2px dashed #17183B; background: rgba(255, 255, 255, 0.16); color: #17183B;
}
.cs-dzien.dzis { padding: 12px; border: none; background: #17183B; color: #FFFFFF; }
.cs-dzien-znak {
  width: 28px; height: 28px; box-sizing: border-box; border-radius: 999px; border: 2px dashed #17183B;
  display: flex; align-items: center; justify-content: center;
}
.cs-dzien.dzis .cs-dzien-znak { border: none; background: #FFC83D; color: #17183B; font-size: 0.85rem; }
.cs-dzien-znak .ico { margin: 0; line-height: 1; }
.cs-dzien-kto { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cs-dzien-nazwa { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.06rem; line-height: 1.1; }
.cs-dzien-tyg { font-size: 0.78rem; font-weight: 600; line-height: 1.3; }
.cs-dzien.dzis .cs-dzien-tyg { color: #C9CAE8; }
.cs-dzien-stan { display: block; font-size: 0.84rem; font-weight: 800; line-height: 1.25; }
.cs-dzien.dzis .cs-dzien-stan { color: #FFC83D; }
.cs-dzien-kiedy { display: block; font-size: 0.78rem; font-weight: 600; line-height: 1.25; }
.cs-dzien-nazwa, .cs-dzien-tyg { overflow-wrap: anywhere; }
@media (max-width: 420px) { .cs-dzien { padding: 8px; gap: 6px; } .cs-dzien.dzis { padding: 10px; } }

/* PÓŁMETEK W STYLU KANWY (2026-09-27): niebieska plansza marki - ten sam błękit, co ścieżka poziomów i pasek paczki, bo
   połowa paczki albo poziomu to miejsce NA tej drodze - z postacią z Higgsfielda nad liczbą (wędrowczyni wskazująca
   dalej, przy 92% talii drabina do gwiazdki), żółtym procentem jak żółty łuk postępu na kółkach ścieżki i białym tekstem.
   Stałe barwy w obu motywach. Do tego dnia biała karta z zieloną obwódką i zielonym procentem, a zieleń znaczy w kanwie
   „łatwe / dobrze”, nie „jesteś w połowie”. Klasa .polowa = półmetek bez wariantu (pokazPolmetek). */
.polmetek.polowa { background: #2463E9; color: #FFFFFF; box-shadow: none; }
.polmetek.polowa::before { background: radial-gradient(circle at 50% 42%, rgba(255, 255, 255, 0.22) 0, transparent 55%); }
.polmetek.polowa .polmetek-ilustracja[src] {
  display: block; width: 176px; height: 176px; margin: -8px auto -2px; pointer-events: none;
  filter: drop-shadow(0 14px 16px rgba(8, 18, 70, 0.35));
  animation: brawoPostac 0.9s cubic-bezier(.34, 1.56, .64, 1) 0.1s both;
}
.polmetek.polowa .polmetek-pct { color: var(--zolty); text-shadow: none; }
.polmetek.polowa .polmetek-tytul { color: #FFFFFF; font-size: 2rem; line-height: 1.05; }
.polmetek.polowa .polmetek-opis { color: #EEF3FF; font-weight: 500; }
.polmetek.polowa .polmetek-hint { color: rgba(238, 243, 255, 0.85); }
@media (max-height: 640px), (max-width: 520px) {
  .polmetek.polowa .polmetek-ilustracja[src] { width: 128px; height: 128px; }
  .polmetek.polowa .polmetek-tytul { font-size: 1.6rem; }
}
/* NOWY REKORD COMBO W BARWACH MARKI (2026-09-27): żółta plansza jak „Brawo” (żółty to w kanwie barwa święta), granatowa
   liczba, białe promienie i granatowe pioruny; efekty bez zmian (błysk, fanfara, dwa trzęsienia, trzy salwy konfetti -
   Alek: „jak 50% w nauce, tylko inny kolor tła i więcej szalonych efektów”), konfetti w barwach logo (REKORD_KONFETTI).
   Dawniej złoto #F59E0B zmieszane z tłem karty - w ciemnym motywie prawie czarne. Stałe barwy w obu motywach. */
.polmetek.rekord { background: var(--zolty); color: #17183B; box-shadow: none; }
.polmetek.rekord::before { background: radial-gradient(circle at 50% 45%, rgba(255, 255, 255, 0.55) 0, transparent 55%); }
.polmetek.rekord::after { background: repeating-conic-gradient(from 0deg at 50% 50%, rgba(255, 255, 255, 0.3) 0deg 10deg, transparent 10deg 30deg); }
.polmetek.rekord .polmetek-pct { color: #17183B; text-shadow: none; }
.polmetek.rekord .polmetek-tytul, .polmetek.rekord .polmetek-opis { color: #17183B; }
.polmetek.rekord .polmetek-hint { color: rgba(23, 24, 59, 0.7); }
.polmetek.rekord .rekord-piorun { color: #17183B; }
/* PANEL COMBO W BARWACH MARKI (2026-09-27, Alek: „tak, przejdź na barwy marki”): pełna plansza w barwie progu
   (--nak-kolor z COMBO_PANEL_BARWY - niebieski przy 5 z rzędu, czerwony przy 10), żółta liczba jak na półmetku, biały
   tekst, żółte pioruny i żółty pasek odliczania. Do tego dnia fiolet albo złoto zmieszane w 14% z tłem karty, z obwódką.
   Stałe barwy w obu motywach, jak każda plansza marki. Kontrast policzony: biały na #DB2727 4,8 : 1, na #2463E9 5,2 : 1, więc opis i podpowiedź są w pełnej bieli (biel
   w 82% dawała na czerwieni 3,7 : 1). */
.polmetek.combo { background: var(--nak-kolor, #2463E9); color: #FFFFFF; box-shadow: none; }
.polmetek.combo::before { background: radial-gradient(circle at 50% 45%, rgba(255, 255, 255, 0.22) 0, transparent 55%); }
.polmetek.combo .polmetek-pct { color: var(--zolty); text-shadow: none; }
.polmetek.combo .polmetek-tytul { color: #FFFFFF; }
.polmetek.combo .polmetek-opis { color: #FFFFFF; font-weight: 500; }
.polmetek.combo .polmetek-hint { color: #FFFFFF; }
.polmetek.combo .rekord-piorun { color: var(--zolty); }
.polmetek.combo.auto .polmetek-tresc::after { background: var(--zolty); }
/* Główny przycisk na obu planszach: granatowa pigułka z żółtym kółkiem w OBU motywach (w ciemnym akcent jest żółty,
   a żółta pigułka na żółtej planszy rekordu znikała). */
.polmetek:is(.polowa, .rekord, .combo) #polmetekDalej {
  --polka-kolor: #17183B; background: #17183B; color: #FFFFFF;
  --kolko-tlo: var(--zolty); --kolko-strzalka: var(--strzalka-granatowa);
}
/* ---------- 11b. ŚCIEŻKA POZIOMÓW PACZKI I PLANSZA „BRAWO" (2026-09-26) ----------
   Alek (z rysunkiem ścieżki): „Brakuje wejścia w poziomy … poziom 1 15 słów, poziom 2 15 słów … pomiędzy te poziomy
   ładne postaci … Zrób to dużo lepiej niż ja". Pełny ekran na błękicie z logo - stały w obu motywach, jak każdy ekran
   marki (ściana Premium, plansze celu dnia). Poziomy od dołu do góry, na zmianę przy lewej i prawej, przerywana droga
   między kółkami (SVG liczony w JS z położenia kółek), postaci z Higgsfielda w PRZERWACH między poziomami - zawsze po
   tej stronie, po której pod spodem jest pusta kolumna poziomu, więc postać nie wchodzi na kartę.
   Barwy chipów słówek jak wszędzie w aplikacji (łatwe zielone, średnie niebieskie, trudne czerwone, nowe białe z lawendą):
   chipy stoją na BIAŁEJ karcie, więc niebieskie średnie się nie gubią. Żółty zostaje dla postępu i „tu jesteś". */
.sciezka {
  position: fixed; inset: 0; z-index: 1900;   /* nad aplikacją, pod mapą słówek i Ustawieniami (2000) */
  display: flex; flex-direction: column;
  background: #2463E9; color: #FFFFFF; font-family: var(--font-tekst);
}
.sciezka.hidden { display: none !important; }
.sciezka-glowa {
  flex: none; display: flex; align-items: flex-start; gap: 16px;
  width: 100%; max-width: 900px; margin: 0 auto; padding: 18px clamp(16px, 4vw, 32px) 8px;
}
.sciezka-zamknij {
  flex: none; width: 44px; height: 44px; border-radius: 999px; border: none; cursor: pointer; margin-top: 2px;
  background: #FFFFFF; color: #17183B; font-size: 1.25rem;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 22px -14px rgba(8, 18, 70, 0.9);
}
.sciezka-zamknij .ico { margin: 0; }
.sciezka-zamknij:hover { background: var(--zolty); }
.sciezka :focus-visible { outline: 3px solid var(--zolty); outline-offset: 3px; }
.sciezka-glowa-tresc { min-width: 0; flex: 1; }
.sciezka-pigulka {
  display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 0 12px; border-radius: 999px;
  background: #FFFFFF; color: #17183B; font-size: 0.78rem; font-weight: 800; letter-spacing: 0.02em;
}
.sciezka-pigulka .ico { margin: 0; color: #2463E9; }
.sciezka-tytul {
  margin: 8px 0 6px; font-family: var(--font-naglowek); font-weight: 800; font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  line-height: 1.05; letter-spacing: -0.02em; color: #FFFFFF; text-wrap: balance; overflow-wrap: anywhere;
}
.sciezka-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; font-size: 0.92rem; font-weight: 600; color: #EEF3FF; }
.sciezka-meta b { color: #FFFFFF; font-weight: 800; }
.sciezka-meta-pasek { flex: 1 1 140px; max-width: 240px; height: 10px; border-radius: 999px; background: rgba(255, 255, 255, 0.24); overflow: hidden; }
.sciezka-meta-pasek i { display: block; height: 100%; border-radius: inherit; background: var(--zolty); transition: width 0.6s ease; }

.sciezka-plansza { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; }
.sciezka-trasa { position: relative; width: 100%; max-width: 820px; margin: 0 auto; padding: 8px clamp(12px, 3vw, 24px) 28px; }
.sciezka-droga { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.sciezka-droga .przed { fill: none; stroke: rgba(255, 255, 255, 0.5); stroke-width: 6; stroke-linecap: round; stroke-dasharray: 12 14; }
.sciezka-droga .za { fill: none; stroke: #FFFFFF; stroke-width: 8; stroke-linecap: round; }
.sciezka-trasa > :not(.sciezka-droga) { position: relative; }

/* META na górze: postać z flagą na wzgórzu, pod nią napis. Droga kończy się u stóp wzgórza. */
.sciezka-meta-wezel { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0 0 8px; }
.sciezka-meta-wezel img { width: 190px; height: 190px; pointer-events: none; filter: drop-shadow(0 14px 16px rgba(8, 18, 70, 0.35)); }
.sciezka-meta-wezel.komplet img { animation: sciezkaUnos 2.6s ease-in-out infinite alternate; }
.sciezka-meta-napis {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 16px; border-radius: 999px;
  background: #17183B; color: #FFFFFF; font-weight: 800; font-size: 0.9rem;
}
.sciezka-meta-napis .ico { margin: 0; color: var(--zolty); }
.sciezka-meta-wezel.komplet .sciezka-meta-napis { background: var(--zolty); color: #17183B; }
.sciezka-meta-wezel.komplet .sciezka-meta-napis .ico { color: #17183B; }

/* RZĄD POZIOMU: kółko przy lewej albo prawej, karta po stronie środka, pusta kolumna przy krawędzi (tam schodzi postać
   z przerwy nad rzędem). */
.sciezka-rzad {
  display: grid; align-items: center; column-gap: 18px; padding: 10px 0;
  grid-template-columns: minmax(0, 17%) 104px minmax(0, 1fr);
  grid-template-areas: "pusto wezel karta";
}
.sciezka-rzad.prawo { grid-template-columns: minmax(0, 1fr) 104px minmax(0, 17%); grid-template-areas: "karta wezel pusto"; }
.sciezka-wezel {
  grid-area: wezel; position: relative; justify-self: center;
  width: 104px; height: 104px; border-radius: 50%; border: none; padding: 0; cursor: pointer;
  /* Pierścień postępu: żółty łuk = odsetek „łatwych" w poziomie, na półprzezroczystym torze. */
  background: conic-gradient(var(--zolty) calc(var(--pct, 0) * 1%), rgba(255, 255, 255, 0.3) 0);
  display: grid; place-items: center;
  box-shadow: 0 16px 26px -16px rgba(8, 18, 70, 0.95);
  transition: transform 0.2s cubic-bezier(.34, 1.56, .64, 1);
}
.sciezka-wezel::before { content: ''; position: absolute; inset: 9px; border-radius: 50%; background: #FFFFFF; }
.sw-nr { position: relative; font-family: var(--font-naglowek); font-weight: 800; font-size: 2.4rem; line-height: 1; color: #17183B; }
.sciezka-wezel:not(.zamkniety):hover { transform: translateY(-3px) scale(1.05); }
.sciezka-wezel.zrobiony { background: #FFFFFF; }
.sciezka-wezel.zrobiony::before { background: var(--zolty); }
/* Zamknięte kółko i karta są NIEPRZEZROCZYSTE, w barwie tła z białą obwódką: droga biegnie przez środki kółek, a przez
   półprzezroczyste prześwitywała w środku kółka i pod kartą (zrzut 2026-09-26). Tło jaśniejsze o ton (#3A73EB) dawało
   białemu tekstowi 4,35 : 1, poniżej progu 4,5 : 1 dla drobnego tekstu - tło strony daje 5,2 : 1. */
.sciezka-wezel.zamkniety { background: #2463E9; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.45); cursor: not-allowed; }
.sciezka-wezel.zamkniety::before { background: transparent; }
.sciezka-wezel.zamkniety .sw-nr { color: rgba(255, 255, 255, 0.8); }
.sw-odznaka {
  position: absolute; right: -4px; bottom: 0; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; font-size: 1rem; box-shadow: 0 0 0 4px #2463E9;
}
.sw-odznaka .ico { margin: 0; line-height: 1; }
.sciezka-wezel.zrobiony .sw-odznaka { background: #35A64D; color: #17183B; }
.sciezka-wezel.zamkniety .sw-odznaka { background: #17183B; color: #FFFFFF; }
/* „Tu jesteś": pulsująca żółta obwódka wokół kółka i chorągiewka nad nim. */
.sciezka-wezel.biezacy::after {
  content: ''; position: absolute; inset: -12px; border-radius: 50%; border: 4px solid var(--zolty);
  animation: sciezkaPuls 1.9s ease-out infinite; pointer-events: none;
}
@keyframes sciezkaPuls { 0% { transform: scale(0.9); opacity: 1; } 100% { transform: scale(1.2); opacity: 0; } }
.sw-tu {
  position: absolute; left: 50%; bottom: calc(100% + 16px); transform: translateX(-50%);
  white-space: nowrap; padding: 6px 12px; border-radius: 999px; background: var(--zolty); color: #17183B;
  font-size: 0.78rem; font-weight: 800; box-shadow: 0 10px 20px -12px rgba(8, 18, 70, 0.9); pointer-events: none;
}
.sw-tu::after { content: ''; position: absolute; left: 50%; top: 100%; margin-left: -7px; border: 7px solid transparent; border-top-color: var(--zolty); }

.sciezka-karta {
  grid-area: karta; position: relative; min-width: 0; width: 100%; max-width: 360px; text-align: left; cursor: pointer;
  border: none; border-radius: 24px; padding: 16px 18px 14px; font: inherit;
  background: #FFFFFF; color: #17183B;
  box-shadow: 0 18px 30px -22px rgba(8, 18, 70, 0.95);
  transition: transform 0.18s ease;
}
.sciezka-rzad.lewo .sciezka-karta { justify-self: start; }
.sciezka-rzad.prawo .sciezka-karta { justify-self: end; }
.sciezka-karta:not(.zamkniety):hover { transform: translateY(-2px); }
.sk-glowa { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sk-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.25rem; letter-spacing: -0.01em; }
.sk-stan {
  flex: none; display: inline-flex; align-items: center; gap: 5px; min-height: 26px; padding: 0 10px; border-radius: 999px;
  font-size: 0.76rem; font-weight: 800; background: #ECEDF6; color: #17183B;
}
.sk-stan .ico { margin: 0; }
.sk-stan.zrobiony { background: #35A64D; }
.sk-stan.biezacy { background: var(--zolty); }
.sk-meta { margin-top: 4px; font-size: 0.84rem; font-weight: 600; color: #4A4B6B; display: flex; flex-wrap: wrap; gap: 2px 10px; }
.sk-meta .ico { margin: 0 3px 0 0; }
.sk-pasek { margin-top: 10px; height: 8px; border-radius: 999px; background: #E3E4EF; overflow: hidden; }
.sk-pasek i { display: block; height: 100%; border-radius: inherit; background: #35A64D; }
.sk-slowa { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.sk-slowo {
  display: inline-block; max-width: 100%; padding: 4px 11px; border-radius: 999px; font-size: 0.82rem; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: #FFFFFF; color: #17183B; box-shadow: inset 0 0 0 1.5px #C9CAE8;
}
.sk-slowo.latwe { background: #35A64D; color: #17183B; box-shadow: none; }
.sk-slowo.srednie { background: #2463E9; color: #FFFFFF; box-shadow: none; }
.sk-slowo.trudne { background: #DB2727; color: #FFFFFF; box-shadow: none; }
.sk-slowo.wiecej { background: #17183B; color: #FFFFFF; box-shadow: none; }
.sk-cta { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-weight: 800; font-size: 0.92rem; }
.sk-cta i.ico {
  margin: 0; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: #17183B; color: var(--zolty); font-size: 0.9rem;
}
.sk-zamek { margin-top: 10px; font-size: 0.84rem; font-weight: 700; display: flex; gap: 6px; align-items: flex-start; }
.sk-zamek .ico { margin: 2px 0 0; }
.sciezka-karta.zamkniety { background: #2463E9; color: #FFFFFF; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.3); cursor: not-allowed; }
.sciezka-karta.zamkniety .sk-meta { color: #EEF3FF; }
.sciezka-karta.zamkniety .sk-stan { background: #17183B; color: #FFFFFF; }
.sciezka-karta.zamkniety .sk-pasek { background: rgba(255, 255, 255, 0.22); }
.sciezka-karta.zamkniety .sk-slowo { opacity: 0.6; }
.sk-klodka { display: inline-flex; align-items: center; gap: 4px; }

/* PRZERWA między poziomami: droga przechodzi przez jej środek, postać stoi przy krawędzi i schodzi w pustą kolumnę
   poziomu pod sobą. */
.sciezka-przerwa { height: 96px; position: relative; }
.sciezka-postac {
  position: absolute; bottom: -56px; width: 17%; max-width: 150px; min-width: 96px; height: auto; aspect-ratio: 1;
  pointer-events: none; user-select: none;
  filter: drop-shadow(0 12px 14px rgba(8, 18, 70, 0.35));
  animation: sciezkaUnos 4.6s ease-in-out infinite alternate;
}
.sciezka-przerwa.lewo .sciezka-postac { left: 0; }
.sciezka-przerwa.prawo .sciezka-postac { right: 0; }
@keyframes sciezkaUnos { from { translate: 0 0; } to { translate: 0 -8px; } }
.sciezka-rzad.sciezka-start { padding: 0 0 4px; }
.sciezka-start span {
  display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 14px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.18); color: #FFFFFF; font-weight: 800; font-size: 0.82rem;
}
.sciezka-start span .ico { margin: 0; }

/* Zamknięty poziom po kliknięciu drży (translate, nie transform - transform trzyma podskok pod kursorem). */
.sciezka-rzad.trzes .sciezka-wezel, .sciezka-rzad.trzes .sciezka-karta { animation: sciezkaTrzes 0.42s ease; }
@keyframes sciezkaTrzes { 0%, 100% { translate: 0; } 20% { translate: -7px; } 40% { translate: 6px; } 60% { translate: -4px; } 80% { translate: 3px; } }
/* Wjazd: rzędy wskakują od dołu jeden po drugim (--i = kolejność od dołu). */
.sciezka.wjazd .sciezka-rzad { animation: sciezkaWjazd 0.5s cubic-bezier(.34, 1.4, .64, 1) both; animation-delay: calc(var(--i, 0) * 70ms); }
@keyframes sciezkaWjazd { from { opacity: 0; transform: translateY(26px) scale(0.96); } to { opacity: 1; transform: none; } }
/* Poziom zaliczony, odkąd ścieżka była ostatnio otwarta - jeden podskok kółka. */
.sciezka-wezel.swiezo { animation: sciezkaSwiezo 0.9s cubic-bezier(.34, 1.56, .64, 1) 0.4s both; }
@keyframes sciezkaSwiezo { 0% { transform: scale(0.6) rotate(-12deg); } 60% { transform: scale(1.15) rotate(6deg); } 100% { transform: none; } }

.sciezka-stopka {
  flex: none; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 10px 16px;
  padding: 12px clamp(16px, 4vw, 32px) max(14px, env(safe-area-inset-bottom)); background: #204EB8;
}
.sciezka-legenda { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 0.8rem; font-weight: 700; color: #EEF3FF; }
.sciezka-legenda .sk-slowo { font-size: 0.74rem; padding: 3px 9px; }
.sciezka-zasada { font-size: 0.8rem; color: #EEF3FF; max-width: 380px; }
.sciezka-cala {
  display: inline-flex; align-items: center; gap: 10px; min-height: 46px; padding: 0 8px 0 18px; border-radius: 999px; border: none;
  cursor: pointer; background: #FFFFFF; color: #17183B; font: inherit; font-weight: 800; font-size: 0.95rem;
}
.sciezka-cala i.ico { margin: 0; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: #17183B; color: var(--zolty); }
.sciezka-cala:hover { background: var(--zolty); }
.sciezka-ladowanie { display: flex; justify-content: center; padding: 60px 0; }
.sciezka-ladowanie .spinner { border-color: rgba(255, 255, 255, 0.35); border-top-color: #FFFFFF; }

@media (max-width: 640px) {
  .sciezka-glowa { gap: 12px; padding-top: 14px; }
  .sciezka-zamknij { width: 40px; height: 40px; }
  .sciezka-rzad { grid-template-columns: 78px minmax(0, 1fr); grid-template-areas: "wezel karta"; column-gap: 12px; }
  .sciezka-rzad.prawo { grid-template-columns: minmax(0, 1fr) 78px; grid-template-areas: "karta wezel"; }
  .sciezka-wezel { width: 78px; height: 78px; }
  .sciezka-wezel::before { inset: 7px; }
  .sw-nr { font-size: 1.8rem; }
  .sw-odznaka { width: 30px; height: 30px; font-size: 0.85rem; box-shadow: 0 0 0 3px #2463E9; }
  .sciezka-karta { max-width: none; padding: 14px 14px 12px; }
  .sciezka-przerwa { height: 104px; }
  .sciezka-postac { width: 92px; min-width: 0; bottom: 4px; }
  .sciezka-meta-wezel img { width: 150px; height: 150px; }
  .sciezka-stopka { gap: 8px; }
  .sciezka-zasada { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sciezka-wezel.biezacy::after, .sciezka-postac, .sciezka-meta-wezel.komplet img,
  .sciezka.wjazd .sciezka-rzad, .sciezka-wezel.swiezo, .sciezka-rzad.trzes .sciezka-wezel, .sciezka-rzad.trzes .sciezka-karta { animation: none; }
  .sciezka-wezel, .sciezka-karta { transition: none; }
}

/* Kafelek w oknie „Ćwicz słowa z paczki": ile poziomów ma paczka (plakietka na okładce). Lewy górny róg dzieli
   z pieczątką kompletu (prawy zajmują przyciski kafelka), więc oba siedzą w jednym rzędzie (.wp-rog). */
.wp-rog { position: absolute; left: 8px; top: 8px; display: flex; align-items: center; gap: 6px; pointer-events: none; }
.wp-rog .wp-komplet { position: static; }
.wp-poziomy {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 26px; padding: 0 10px; border-radius: 999px; background: #2463E9; color: #FFFFFF;
  font-size: 0.74rem; font-weight: 800; box-shadow: 0 6px 14px -8px rgba(8, 18, 70, 0.8);
}
.wp-poziomy .ico { margin: 0; color: var(--zolty); }

/* PLANSZA „BRAWO" - ten sam mechanizm, co półmetek (w miejscu karty, klawisze, wjazd), własny wygląd: żółta plansza
   z postacią, granatowy stoper z łącznym czasem nauki poziomu, białe kafle z najtrudniejszym słówkiem i punktami.
   Wszystko, czego inne warianty nie używają, jest domyślnie schowane klasą, a nie atrybutem hidden (pułapka z CLAUDE.md:
   hidden przegrywa z display klasy). */
.polmetek-ilustracja, .polmetek-pigulka, .polmetek-licznik-etykieta { display: none; }
.polmetek.brawo {
  background: var(--zolty); color: #17183B; box-shadow: none;
  align-items: flex-start; overflow-y: auto; padding: 22px 24px 18px;
}
.polmetek.brawo::before { display: none; }
.polmetek.brawo .polmetek-tresc {
  width: 100%; max-width: 640px; margin: auto 0; text-align: left;
  display: grid; grid-template-columns: minmax(0, 1fr) 200px; column-gap: 12px;
  grid-template-areas: "pigulka ilustracja" "tytul ilustracja" "opis ilustracja" "licznik licznik" "staty staty" "akcje akcje" "hint hint";
}
.polmetek.brawo .polmetek-ilustracja {
  grid-area: ilustracja; display: block; width: 200px; height: 200px; align-self: center; pointer-events: none;
  animation: brawoPostac 0.9s cubic-bezier(.34, 1.56, .64, 1) 0.15s both;
}
@keyframes brawoPostac { from { transform: translateY(40px) scale(0.6) rotate(-8deg); opacity: 0; } to { transform: none; opacity: 1; } }
.polmetek.brawo .polmetek-pigulka {
  grid-area: pigulka; justify-self: start; align-self: end; display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 14px; border-radius: 999px; background: #17183B; color: #FFFFFF; font-size: 0.82rem; font-weight: 800;
}
.polmetek.brawo .polmetek-pigulka .ico { margin: 0; color: var(--zolty); }
.polmetek.brawo .polmetek-tytul { grid-area: tytul; margin-top: 8px; font-size: clamp(2.2rem, 5vw, 3rem); line-height: 1; letter-spacing: -0.02em; color: #17183B; }
.polmetek.brawo .polmetek-opis { grid-area: opis; color: #17183B; font-weight: 500; margin-top: 8px; }
.polmetek.brawo .polmetek-licznik {
  grid-area: licznik; margin-top: 16px; display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 14px;
  padding: 14px 18px; border-radius: 22px; background: #17183B; color: #FFFFFF;
}
.polmetek.brawo .polmetek-licznik::before {
  content: ''; grid-row: span 2; width: 58px; height: 58px; border-radius: 50%; background: var(--zolty);
  /* Tarcza stopera: wskazówka obraca się, dopóki licznik nabija czas (klasa .liczy). */
  background-image: linear-gradient(#17183B, #17183B);
  background-size: 4px 22px; background-repeat: no-repeat; background-position: center 8px;
  box-shadow: inset 0 0 0 4px #FFFFFF;
}
.polmetek.brawo.liczy .polmetek-licznik::before { animation: brawoWskazowka 0.9s linear infinite; }
@keyframes brawoWskazowka { to { transform: rotate(360deg); } }
.polmetek.brawo .polmetek-licznik-etykieta { display: block; font-size: 0.82rem; font-weight: 700; color: #D4D5F0; }
.polmetek.brawo .polmetek-pct {
  font-size: clamp(2.2rem, 6vw, 2.9rem); color: var(--zolty); text-shadow: none; letter-spacing: -0.01em; line-height: 1.05;
}
.polmetek.brawo .polmetek-staty { grid-area: staty; margin: 10px 0 0; max-width: none; background: transparent; border: none; padding: 0; }
.brawo-kafle { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
.brawo-kafel { border-radius: 20px; background: #FFFFFF; padding: 12px 16px; min-width: 0; }
.brawo-kafel-etykieta { font-size: 0.78rem; font-weight: 700; color: #4A4B6B; display: flex; align-items: center; gap: 6px; }
.brawo-kafel-etykieta .ico { margin: 0; color: #DB2727; }
.brawo-slowo { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.3rem; color: #17183B; overflow-wrap: anywhere; margin-top: 2px; }
.brawo-slowo small { font-family: var(--font-tekst); font-weight: 600; font-size: 0.85rem; color: #4A4B6B; }
.brawo-kafel-dol { font-size: 0.8rem; font-weight: 700; color: #DB2727; margin-top: 2px; }
.brawo-kafel.xp { background: #35A64D; display: flex; flex-direction: column; justify-content: center; text-align: center; }
.brawo-kafel.xp .brawo-slowo { font-size: 1.6rem; }
.brawo-kafel.xp .brawo-kafel-etykieta { color: #17183B; justify-content: center; }
.polmetek.brawo .polmetek-akcje { grid-area: akcje; justify-content: flex-start; margin-top: 16px; }
.polmetek.brawo #polmetekDalej { --polka-kolor: #17183B; background: #17183B; color: #FFFFFF; }
.polmetek.brawo #polmetekDrugi { background: #FFFFFF; color: #17183B; box-shadow: none; }
.polmetek.brawo .polmetek-hint { grid-area: hint; color: rgba(23, 24, 59, 0.7); }
@media (max-width: 640px) {
  .polmetek.brawo { padding: 18px 16px 14px; }
  .polmetek.brawo .polmetek-tresc { grid-template-columns: minmax(0, 1fr) 118px; }
  .polmetek.brawo .polmetek-ilustracja { width: 118px; height: 118px; }
  .brawo-kafle { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .polmetek.brawo .polmetek-ilustracja, .polmetek.brawo.liczy .polmetek-licznik::before { animation: none; }
}

/* ---------- 11c. PLANSZA „COMBO ZAKOŃCZONE” (2026-10-02, pokazComboKoniec w JS) ----------
   Alek: „Gdy zakończy się passa COMBO to wtedy wyświetlaj w fiszkach ekran, że COMBO zakończone, miałeś [x] combo, dodaj do tego
   ładną grafikę”. Ten sam szkielet, co „Brawo” (tekst po lewej, postać z Higgsfielda po prawej, granatowy licznik, biały kafel),
   tło w barwie panelu serii, który uczeń w niej widział (--nak-kolor: niebieski do 9 z rzędu, czerwony od 10), żółte, gdy seria
   jest rekordem konta (.seria-rekord, granatowy tekst, jak NOWY REKORD). Stałe barwy w obu motywach, jak każda plansza marki.
   Biały tekst na #2463E9 ma 5,2 : 1, na #DB2727 4,8 : 1 (policzone przy panelu combo), więc bez przezroczystości.
   OBRAZ KOŃCA SERII bez nowej grafiki: zamki z tła COMBO (body.combo-t*) zostają na planszy jako faktura i gasną z jasnych do
   cichego wzoru, a w granatowym liczniku zamek w żółtym kole traci poświatę razem z żarzącą się liczbą - seria była, już jej nie ma.
   Przy ograniczonym ruchu od razu stan końcowy. Maska zamiast koloru w SVG: jeden rysunek jest biały na niebieskim i czerwonym,
   a granatowy na żółtym. ::before z inset 0 i bez skalowania: pulsująca poświata półmetka (skala 1,1) wystawała i przy
   overflow-y: auto dawała pasek przewijania (ta sama pułapka, co na planszach dnia). */
.polmetek.seria {
  --plansza-tlo: var(--nak-kolor, #2463E9);
  --seria-tekst: #FFFFFF;
  --seria-zamki: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 280'%3E%3Cg fill='%23000' fill-rule='evenodd'%3E%3Cpath d='M30 92V62h3v-5h4v5h3v-5h4v5h3v30h18V72h3v-4h4v4h4v-4h4v4h3v20zM65 92V62h3v-5h4v5h3v-5h4v5h3v30zM53 92v-8a4 4 0 018 0v8z'/%3E%3Cpath d='M262 190v-46h4v-6h5v6h4v-6h5v6h4v46zM272 152v-16h2l8 4-8 4h-2z'/%3E%3Cpath d='M120 252v-22h4v-4h4v4h4v-4h4v4h4v8h14v-6h3v-3h3v3h3v-3h3v3h3v6h14v-8h4v-4h4v4h4v-4h4v4h4v22zM158 252v-7a4 4 0 018 0v7z'/%3E%3C/g%3E%3C/svg%3E");
  --seria-zamek: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 40'%3E%3Cpath fill='%2317183B' fill-rule='evenodd' d='M4 38V4h3v4h1.5V4h3v4h1.5V4h3v34zM32 38V4h3v4h1.5V4h3v4h1.5V4h3v34zM16 38V12h3v4h3.5v-4h3v4h3.5v-4h3v26zM20.5 38v-7a3.5 3.5 0 0 1 7 0v7zM8.5 15h3v6h-3zM36.5 15h3v6h-3z'/%3E%3C/svg%3E");
  background: var(--nak-kolor, #2463E9); color: var(--seria-tekst); box-shadow: none;
  align-items: flex-start; overflow-y: auto; padding: 22px 24px 18px;
}
.polmetek.seria.seria-rekord { --seria-tekst: #17183B; }
.polmetek.seria::before {
  inset: 0; transform: none; background: var(--seria-tekst);
  -webkit-mask: var(--seria-zamki) 0 100% / 300px auto repeat; mask: var(--seria-zamki) 0 100% / 300px auto repeat;
  opacity: 0.1; animation: seriaZamkiGasna 2.6s ease-out 0.2s both;
}
@keyframes seriaZamkiGasna { from { opacity: 0.34; } to { opacity: 0.1; } }
.polmetek.seria .polmetek-tresc {
  width: 100%; max-width: 640px; margin: auto 0; text-align: left;
  display: grid; grid-template-columns: minmax(0, 1fr) 190px; column-gap: 14px;
  grid-template-areas: "pigulka ilustracja" "tytul ilustracja" "opis ilustracja" "licznik licznik" "staty staty" "akcje akcje" "hint hint";
}
.polmetek.seria .polmetek-ilustracja {
  grid-area: ilustracja; display: block; width: 190px; height: 190px; align-self: center; pointer-events: none;
  filter: drop-shadow(0 14px 16px rgba(8, 18, 70, 0.3));
  animation: brawoPostac 0.9s cubic-bezier(.34, 1.56, .64, 1) 0.15s both;
}
.polmetek.seria .polmetek-pigulka {
  grid-area: pigulka; justify-self: start; align-self: end; display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 14px; border-radius: 999px; background: #17183B; color: #FFFFFF; font-size: 0.82rem; font-weight: 800;
}
.polmetek.seria .polmetek-pigulka .ico { margin: 0; color: var(--zolty); }
.polmetek.seria .polmetek-tytul {
  grid-area: tytul; margin-top: 8px; font-family: var(--font-naglowek); font-size: clamp(2rem, 4.6vw, 2.75rem);
  line-height: 1.02; letter-spacing: -0.02em; color: var(--seria-tekst);
}
.polmetek.seria .polmetek-opis { grid-area: opis; color: var(--seria-tekst); font-weight: 500; margin-top: 8px; }
.polmetek.seria .polmetek-licznik {
  grid-area: licznik; margin-top: 16px; display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 16px;
  padding: 14px 18px; border-radius: 22px; background: #17183B; color: #FFFFFF;
}
.polmetek.seria .polmetek-licznik::before {
  content: ''; grid-row: span 2; width: 60px; height: 60px; border-radius: 50%;
  background: var(--zolty) var(--seria-zamek) center 64% / 40px auto no-repeat;
  animation: seriaDogasa 2.6s ease-out 0.3s both;
}
@keyframes seriaDogasa {
  from { box-shadow: 0 0 0 6px rgba(255, 200, 61, 0.35), 0 0 34px 10px rgba(255, 200, 61, 0.7); }
  to   { box-shadow: 0 0 0 0 rgba(255, 200, 61, 0), 0 0 0 0 rgba(255, 200, 61, 0); }
}
.polmetek.seria .polmetek-licznik-etykieta { display: block; font-size: 0.85rem; font-weight: 700; color: #D4D5F0; }
.polmetek.seria .polmetek-pct {
  font-family: var(--font-naglowek); font-size: clamp(2.8rem, 7vw, 3.6rem); line-height: 1; letter-spacing: -0.02em;
  color: var(--zolty); text-shadow: none; animation: seriaZar 2.6s ease-out 0.3s both;
}
@keyframes seriaZar { from { text-shadow: 0 0 22px rgba(255, 200, 61, 0.95), 0 0 3px #FFF4D6; } to { text-shadow: 0 0 0 rgba(255, 200, 61, 0); } }
.polmetek.seria .polmetek-staty { grid-area: staty; margin: 10px 0 0; max-width: none; background: transparent; border: none; padding: 0; }
.seria-kafel {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; column-gap: 12px;
  border-radius: 20px; background: #FFFFFF; color: #17183B; padding: 12px 18px 12px 12px;
}
.seria-kafel-ikona {
  width: 40px; height: 40px; border-radius: 50%; background: #17183B; color: var(--zolty);
  display: flex; align-items: center; justify-content: center; font-size: 1.05rem;
}
.seria-kafel-ikona .ico { margin: 0; line-height: 1; }
.seria-kafel-tekst { display: flex; flex-direction: column; min-width: 0; }
.seria-kafel-etykieta { font-size: 0.78rem; font-weight: 700; color: #4A4B6B; }
.seria-kafel-stan { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; line-height: 1.2; overflow-wrap: anywhere; }
.seria-kafel.brak .seria-kafel-stan { color: #DB2727; }
.seria-kafel:is(.nowy, .pierwszy, .twoj) .seria-kafel-stan { color: #1F7A35; }
.seria-kafel-liczba { font-family: var(--font-naglowek); font-weight: 800; font-size: 2rem; line-height: 1; font-variant-numeric: tabular-nums; }
.polmetek.seria .polmetek-akcje { grid-area: akcje; justify-content: flex-start; margin-top: 16px; }
.polmetek.seria #polmetekDalej {
  --polka-kolor: #17183B; background: #17183B; color: #FFFFFF;
  --kolko-tlo: var(--zolty); --kolko-strzalka: var(--strzalka-granatowa);
}
.polmetek.seria .polmetek-hint { grid-area: hint; color: var(--seria-tekst); }
.polmetek.seria.seria-rekord .polmetek-hint { color: rgba(23, 24, 59, 0.7); }
@media (max-width: 640px) {
  .polmetek.seria { padding: 18px 16px 14px; }
  .polmetek.seria .polmetek-tresc { grid-template-columns: minmax(0, 1fr) 112px; }
  .polmetek.seria .polmetek-ilustracja { width: 112px; height: 112px; }
  .seria-kafel-liczba { font-size: 1.7rem; }
}
@media (prefers-reduced-motion: reduce) {
  .polmetek.seria::before, .polmetek.seria .polmetek-ilustracja, .polmetek.seria .polmetek-licznik::before, .polmetek.seria .polmetek-pct { animation: none; }
}
/* Seria pękła w OSTATNIM pytaniu mini testu: zamiast drugiej planszy końca linijka w podsumowaniu (comboKoniecLiniaHtml),
   granatowa na żółtej planszy, piorun w żółci jak na planszy serii. */
.quiz-koniec-seria {
  display: flex; align-items: center; gap: 10px; margin: 12px 0 0; padding: 10px 14px; border-radius: 16px;
  background: var(--granat); color: #FFFFFF; font-weight: 700; font-size: 0.92rem; line-height: 1.35; text-align: left;
}
.quiz-koniec-seria .ico { margin: 0; color: var(--zolty); flex: 0 0 auto; }

/* ---------- 12. ŚCIANA PREMIUM (#premiumScianaOverlay) ----------
   Reguły cennika („Wybierz plan”, zgoda, „Kup Premium”, akordeony) stoją pod :is(#premiumScianaOverlay, #probneKoniecOverlay):
   okno „To była wersja Premium” jest od 2026-09-27 tym samym granatem, więc cennik ma w nim te same barwy.
   Plansza „Premium": granatowy ekran z ilustracją, żółtą liczbą talii, wyborem planu (wybrany = żółty)
   i żółtym „Kup Premium" z granatowym kółkiem. Stały granat w obu motywach. Kontener zakupu jest tym samym
   komponentem co w Ustawieniach (premiumKontenerHtml), więc barwy „na granacie" stoją tu pod #premiumScianaOverlay,
   a w białej szufladzie Ustawień kontener zostaje jasny. */
#premiumScianaOverlay { background: #17183B; }
#premiumScianaOverlay .sciana-okno { background: #17183B; color: #FFFFFF; }
#premiumScianaOverlay .wordmap-header { background: transparent; border-bottom: none; padding-top: 22px; }
#premiumScianaOverlay .wordmap-title {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 16px; border-radius: 999px;
  background: #FFFFFF; color: #17183B; font-family: var(--font-tekst); font-size: 0.9rem; font-weight: 800;
}
#premiumScianaOverlay .wordmap-title .ico { color: #17183B; }
#premiumScianaOverlay .wordmap-close { background: var(--zolty); color: #17183B; }
#premiumScianaOverlay .wordmap-close:hover { background: #FFD66B; color: #17183B; }
.sciana-glowa { position: relative; min-height: 200px; margin: 0 0 6px; }
.sciana-glowa img { position: absolute; right: -24px; top: -26px; width: 230px; height: 230px; pointer-events: none; }
.sciana-glowa h2 {
  position: relative; max-width: 420px; margin: 12px 0 0; font-family: var(--font-naglowek); font-weight: 800;
  font-size: 2.6rem; line-height: 1.04; letter-spacing: -0.02em; color: #FFFFFF; text-wrap: balance;
}
/* TELEFON (2026-10-11, zgłoszenie Alka): ilustracja 230 px stoi absolutnie w prawym rogu, a tytuł ma do 420 px, więc dopóki
   treść okna nie ma ~630 px, tytuł leży NA ilustracji. Zmierzone w Edge na 375 i 320 px: „Tak działa Premium”, „Pierwsza rozmowa
   za Tobą!”, „Dłuższe rozmowy są w Premium” i każdy inny wariant ściany przecinał obrazek, a obrazek (right: -24px) dawał
   jeszcze przewijanie okna w bok. Poniżej 700 px tytuł i ilustracja stoją obok siebie w siatce: obrazek w swojej kolumnie,
   mniejszy (do 180 px), tytuł skaluje się z szerokością ekranu. Komputer bez zmian. */
@media (max-width: 700px) {
  .sciana-glowa {
    display: grid; grid-template-columns: minmax(0, 1fr) clamp(96px, 32vw, 180px); align-items: center; gap: 10px;
    min-height: 0; margin: 0 0 10px;
  }
  .sciana-glowa img { position: static; grid-column: 2; grid-row: 1; width: 100%; height: auto; aspect-ratio: 1 / 1; }
  .sciana-glowa h2 {
    grid-column: 1; grid-row: 1; max-width: none; margin: 0; font-size: clamp(1.6rem, 8vw, 2.6rem);
    overflow-wrap: break-word; hyphens: auto;
  }
}
#premiumScianaOverlay .limit-opis { color: #FFFFFF; font-size: 1rem; }
#premiumScianaOverlay .limit-spokoj { background: #24265A; color: #FFFFFF; border-radius: 22px; padding: 14px 16px; }
#premiumScianaOverlay .limit-spokoj b { color: #FFFFFF; }
/* Ściana „Twórz własne rozmowy” (wariant tworca_rozmow, 2026-10-06; kanwa „Kreator rozmów Mówienie”, plansza „Konto darmowe: okno Premium”):
   trzy kafle korzyści z ikoną w barwie marki, jak na projekcie, nad tym samym cennikiem co reszta ściany. */
.sciana-korzysci { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.sciana-korzysci li { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: 20px; background: #24265A; color: #FFFFFF; }
.sciana-korzysci-ikona { width: 44px; height: 44px; flex: none; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center; }
.sciana-korzysci-ikona .ico { margin: 0; font-size: 1.2rem; }
.sciana-korzysci-tekst { display: flex; flex-direction: column; gap: 2px; }
.sciana-korzysci-tekst b { font-size: 1rem; font-weight: 800; }
.sciana-korzysci-tekst span { font-size: 0.86rem; line-height: 1.4; color: #C9CAE8; }
#premiumScianaOverlay .przydzial-kiedy .ico { color: var(--zolty); }
#premiumScianaOverlay .pk-baner { display: none; }
#premiumScianaOverlay .pk-sekcja-tytul { font-family: var(--font-naglowek); font-size: 1.5rem; color: #FFFFFF; margin: 8px 0 12px; }
#premiumScianaOverlay .pk-stan { background: #24265A; border: none; border-radius: 22px; color: #FFFFFF; }
#premiumScianaOverlay .pk-stan-glowa { color: #C9CAE8; font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase; }
#premiumScianaOverlay .pk-stan-glowa b { font-family: var(--font-naglowek); font-size: 2rem; color: var(--zolty); text-transform: none; letter-spacing: -0.01em; }
#premiumScianaOverlay .pk-pasek { height: 10px; background: rgba(255, 255, 255, 0.14); }
#premiumScianaOverlay .pk-pasek > span, #premiumScianaOverlay .pk-pasek.ostrzezenie > span { background: var(--zolty); }
#premiumScianaOverlay .pk-archiwum, #premiumScianaOverlay .pk-darmowe, #premiumScianaOverlay .pk-darmowe b,
#premiumScianaOverlay .pk-stan-premium { color: #FFFFFF; }
#premiumScianaOverlay .pk-darmowe { color: #C9CAE8; }
#premiumScianaOverlay .pk-archiwum .ico { color: var(--zolty); }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan { background: transparent; border: 2px solid rgba(255, 255, 255, 0.35); border-radius: 22px; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan:hover { border-color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan.wybrany, :is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan:has(.pk-plan-radio:checked) { background: var(--zolty); border-color: var(--zolty); }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan-nazwa { font-family: var(--font-naglowek); font-size: 1.15rem; letter-spacing: 0; text-transform: none; color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-cena { font-family: var(--font-naglowek); font-size: 2rem; color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-cena-sufiks, :is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan-nota, :is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-cena-stara { color: #D4D5F0; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan.wybrany :is(.pk-plan-nazwa, .pk-cena, .pk-cena-sufiks, .pk-plan-nota, .pk-cena-stara),
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan:has(.pk-plan-radio:checked) :is(.pk-plan-nazwa, .pk-cena, .pk-cena-sufiks, .pk-plan-nota, .pk-cena-stara) { color: #17183B; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-plan-radio { accent-color: #17183B; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-wstazka { background: #DB2727; color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .currency-opt { color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .buy-consent, :is(#premiumScianaOverlay, #probneKoniecOverlay) .buy-consent-link, :is(#premiumScianaOverlay, #probneKoniecOverlay) .buy-consent-link a { color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .buy-consent input { accent-color: var(--zolty); }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zgoda-nota { color: #C9CAE8; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zgoda-nota.czeka { background: rgba(255, 200, 61, 0.14); color: #FFFFFF; }
/* „Kup Premium": żółta pigułka z granatowym kółkiem (wariant na granacie). Kłódkę z przodu zastępuje kółko. */
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zaplac {
  background: var(--zolty); color: #17183B; justify-content: flex-start; min-height: 58px;
  padding: 7px 7px 7px 24px; font-size: 1.05rem; box-shadow: none;
}
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zaplac > .ico:first-child { display: none; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zaplac::after {
  content: ''; flex: none; width: 44px; height: 44px; margin-left: auto; border-radius: 999px;
  background: #17183B var(--strzalka-zolta) center / 22px 22px no-repeat;
}
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-zaplac-nota { color: #C9CAE8; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-akordeon { background: #24265A; border-color: #2E3068; border-radius: 18px; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-akordeon > summary, :is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-akordeon > summary .ico { color: #FFFFFF; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-akordeon .auth-input { background: #17183B; color: #FFFFFF; border-color: #4A4C80; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .faktura-info { color: #C9CAE8; }
/* Korzyści: lista z kolorowymi kwadratami ikon w barwach logo (plansza „Co daje Premium"). */
#premiumScianaOverlay .pk-kafelek { background: transparent; border: none; padding: 6px 0; gap: 14px; }
#premiumScianaOverlay .pk-kafelek > .ico {
  width: 44px; height: 44px; border-radius: 14px; display: flex; align-items: center; justify-content: center;
  margin: 0; font-size: 1.15rem; line-height: 1; background: var(--zolty); color: #17183B;
}
#premiumScianaOverlay .pk-kafelek:nth-child(4n+2) > .ico { background: #DB2727; color: #FFFFFF; }
#premiumScianaOverlay .pk-kafelek:nth-child(4n+3) > .ico { background: #2463E9; color: #FFFFFF; }
#premiumScianaOverlay .pk-kafelek:nth-child(4n+4) > .ico { background: #35A64D; color: #17183B; }
#premiumScianaOverlay .pk-kafelek b { color: #FFFFFF; font-size: 0.98rem; }
#premiumScianaOverlay .pk-kafelek span { color: #C9CAE8; font-size: 0.84rem; }
#premiumScianaOverlay .limit-droga { background: #24265A; border: none; border-radius: 22px; }
#premiumScianaOverlay .limit-droga-tytul { color: #FFFFFF; }
#premiumScianaOverlay .limit-droga-opis { color: #C9CAE8; }
#premiumScianaOverlay .limit-droga .btn-grigio { background: #FFFFFF; color: #17183B; box-shadow: none; }
/* „Może później" - biały napis podkreślony, jak na planszy. Pełna szerokość zostaje (łatwo trafić). */
#premiumScianaOverlay .limit-pozniej { background: transparent; color: #FFFFFF; box-shadow: none; text-decoration: underline; text-underline-offset: 3px; }
#premiumScianaOverlay .limit-pozniej:hover { color: var(--zolty); box-shadow: none; }
:is(#premiumScianaOverlay, #probneKoniecOverlay) .pk-blad { color: #FFB4B4; }

/* ---------- 13. USTAWIENIA I KONTENER ZAKUPU W SZUFLADZIE ---------- */
.pk-sekcja-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.15rem; letter-spacing: -0.01em; }
/* Baner kontenera: granat marki z żółtym napisem zamiast głębokiej zieleni - zieleń jest dziś kolorem
   „dobrze", a Premium na planszach jest granatowe. */
.pk-baner { background: #17183B; color: #FFFFFF; border-radius: 22px; box-shadow: none; }
.pk-baner-tytul { font-family: var(--font-naglowek); font-size: 1.25rem; }
.pk-baner-tytul .ico { color: var(--zolty); }
.pk-stan { border-radius: 20px; border-width: 1.5px; border-color: var(--border); }
.pk-plan { border-radius: 20px; border-width: 1.5px; }
.pk-cena { font-family: var(--font-naglowek); }
.pk-wstazka { background: #DB2727; color: #FFFFFF; }
.pk-kafelek { border-radius: 18px; border-width: 1.5px; border-color: var(--border); }
.pk-kafelek > .ico { color: var(--oro); }
.pk-akordeon { border-radius: 16px; border-width: 1.5px; }
.theme-switch-btn { border-radius: 16px; border-width: 1.5px; background: var(--card-bg); }
.theme-switch-btn.active { background: var(--zolty); border-color: var(--zolty); color: var(--granat); }
.settings-title { letter-spacing: -0.01em; }
.settings-title .ico { color: var(--testo); }

#premiumScianaOverlay #scianaIkona { display: none; }
/* „Zapłać …" w szufladzie Ustawień: ten sam kształt, co główny przycisk z kółkiem (.btn-strzalka), ale przez CSS -
   przycisk rysuje planButtonsHtml, a harness ściany (testy_sciana_premium_front.js) czyta jego klasy. Kłódkę z przodu
   zastępuje kółko ze strzałką, tak jak „Kup Premium" na planszy. */
.pk-zaplac { justify-content: flex-start; min-height: 56px; padding: 6px 6px 6px 24px; text-align: left; }
.pk-zaplac > .ico:first-child { display: none; }
.pk-zaplac::after {
  content: ''; flex: none; width: 44px; height: 44px; margin-left: auto; border-radius: 999px;
  background: var(--przycisk-kolko) var(--przycisk-kolko-strzalka) center / 22px 22px no-repeat;
}

/* MIĘKKA ŚCIANA nad fiszką (80% limitu) - „w kolorach okna Premium", a okno Premium jest od dziś granatowe:
   granatowa karta, żółty główny przycisk, biały obrys drugiego. Dawniej zielona poświata - ta sama zieleń co „dobrze". */
.paywall-miekki { background: #17183B; border: 1.5px solid #17183B; border-radius: 22px; color: #FFFFFF; }
:root[data-theme="dark"] .paywall-miekki { border-color: #2E3068; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .paywall-miekki { border-color: #2E3068; } }
.paywall-miekki-tytul { font-family: var(--font-naglowek); font-size: 1.1rem; }
.paywall-miekki-opis { color: #D4D5F0; }
.paywall-miekki .btn-verde { background: var(--zolty); color: var(--granat); }
.paywall-miekki .btn-grigio { background: transparent; color: #FFFFFF; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.7); }
/* Ilustracja „Premium” w miejscu dawnej postaci z konsoli, a jej zdanie z dymka (paywall_miekki_dymek) - żółte nad
   nagłówkiem. Na wąskim ekranie ilustracja maleje, a przy 380 px schodzi: kolumna tekstu miałaby wtedy 150 px. */
.paywall-miekki { align-items: center; }
.paywall-miekki-ilustracja { width: 132px; height: 132px; flex-shrink: 0; margin: -6px -6px -6px -8px; pointer-events: none; }
.paywall-miekki-zdanie { font-weight: 800; font-size: 0.9rem; line-height: 1.4; color: var(--zolty); margin-bottom: 4px; }
@media (max-width: 520px) { .paywall-miekki-ilustracja { width: 96px; height: 96px; } }
@media (max-width: 380px) { .paywall-miekki-ilustracja { display: none; } }
/* PASEK „ĆWICZYSZ TYLKO…" W STYLU ŚCIEŻKI POZIOMÓW (2026-09-26, Alek: „gdy jestem w paczce, zmień wtedy też design tego,
   że jestem w danej paczce, na taki, jak obecnie działamy (górny kontener)"). Niebieski baner marki jak głowa ścieżki
   poziomów - stały w obu motywach, jak każdy ekran marki. W trybie jednego poziomu w miejscu ikony stoi KÓŁKO POZIOMU
   z żółtym pierścieniem postępu (to samo, co na ścieżce), nad nazwą paczki „Poziom 2 z 6". Fakty o poziomie to pigułki
   na półprzezroczystej bieli, akcje - pigułki, a żółta „Ścieżka poziomów" jest głównym przyciskiem paska: to z niej
   widać, co dalej. Dawniej biała karta z żółtą szyną i pigułki z ramką (to samo, co każda inna karta w aplikacji). */
.paczka-pasek-trybu {
  background: #2463E9; color: #FFFFFF; border: none; border-radius: 26px;
  padding: 14px 16px; gap: 10px 14px; font-size: 0.86rem;
  box-shadow: 0 18px 30px -24px rgba(8, 18, 70, 0.9);
}
.paczka-pasek-trybu.ppt-klikalny:hover { border-color: transparent; box-shadow: 0 20px 34px -20px rgba(8, 18, 70, 0.95); }
.ppt-ikona {
  position: relative; width: 56px; height: 56px; border-radius: 50%; border: none;
  background: #FFFFFF; color: #2463E9; font-size: 1.35rem;
}
.ppt-ikona.poziom { background: conic-gradient(var(--zolty) calc(var(--pct, 0) * 1%), rgba(255, 255, 255, 0.32) 0); }
.ppt-ikona.poziom::before { content: ''; position: absolute; inset: 6px; border-radius: 50%; background: #FFFFFF; }
.ppt-ikona.poziom.zrobiony::before { background: var(--zolty); }
.ppt-ikona.poziom b { position: relative; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.45rem; line-height: 1; color: #17183B; }
.ppt-tytul { color: #EEF3FF; font-weight: 700; display: flex; flex-direction: column; gap: 1px; white-space: normal; }
.ppt-tytul > span { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase; color: #FFF1C7; }
/* Tytuł i linijka liczb pod nim (2026-09-27, zrzut Alka: „Włoski plac” wyglądał, jakby nachodził na „28 słówek”).
   Zmierzone w Edge przy 1024 px: pole tytułu 22,08 px (line-height 1.2), a krój Outfit 800 przy 18,4 px ma 23 px
   wysokości (measureText) - overflow: hidden (wielokropek) przycinał to, co wystawało; od dołu pola do linijki liczb 4 px, więc
   ogonek „p” wisiał tuż nad cyframi. Wysokość linii 1.3 mieści cały krój, a 6 px odstępu oddziela oba wiersze. */
.ppt-tytul b {
  color: #FFFFFF; font-family: var(--font-naglowek); font-size: 1.15rem; letter-spacing: -0.01em; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ppt-meta { color: #EEF3FF; font-size: 0.8rem; margin-top: 6px; }
.ppt-meta b { color: #FFFFFF; }
.ppt-umiesz-tor { width: 76px; height: 7px; background: rgba(255, 255, 255, 0.28); }
.ppt-umiesz-tor i { background: var(--zolty); }
.paczka-pasek-trybu .ppt-akcja, .paczka-pasek-trybu .ppt-wyjscie {
  border: none; background: rgba(255, 255, 255, 0.18); color: #FFFFFF; min-height: 38px; padding: 6px 14px; font-size: 0.82rem;
}
.paczka-pasek-trybu .ppt-akcja:hover, .paczka-pasek-trybu .ppt-wyjscie:hover { background: #FFFFFF; color: #17183B; }
.paczka-pasek-trybu .ppt-akcja.aktywna { background: #FFFFFF; color: #17183B; }
.paczka-pasek-trybu .ppt-akcja.ppt-sciezka { background: var(--zolty); color: #17183B; }
.paczka-pasek-trybu .ppt-akcja.ppt-sciezka:hover { background: #FFFFFF; }
.paczka-pasek-trybu :focus-visible { outline: 3px solid var(--zolty); outline-offset: 2px; }
.ppt-plan { border-top-color: rgba(255, 255, 255, 0.22); color: #EEF3FF; font-size: 0.78rem; padding-top: 10px; gap: 6px; }
.ppt-plan > span:not(.ppt-plan-zasada) { background: rgba(255, 255, 255, 0.14); border: none; color: #FFFFFF; padding: 4px 11px; }
.ppt-plan b { color: #FFFFFF; }
.ppt-plan .ico { color: var(--zolty); }
.ppt-plan-zasada { color: #EEF3FF; font-size: 0.76rem; }
.ppt-plan > span.ppt-cel-gotowy { background: #35A64D; color: #17183B; }
.ppt-plan > span.ppt-cel-gotowy .ico, .ppt-plan > span.ppt-cel-gotowy b { color: #17183B; }
.ppt-plan > span.ppt-premia { background: var(--zolty); color: #17183B; }
.ppt-plan > span.ppt-premia .ico, .ppt-plan > span.ppt-premia b { color: #17183B; }
.paczka-pasek-trybu .ppt-zamek { color: #FFFFFF; }
.paczka-pasek-trybu .ppt-zamek .ico { color: var(--zolty); }
@media (max-width: 720px) {
  .paczka-pasek-trybu { padding: 12px; border-radius: 22px; }
  .ppt-ikona { width: 48px; height: 48px; }
  .ppt-ikona.poziom b { font-size: 1.25rem; }
}

/* ---------- 14. DRUGIE PRZYCISKI, SPOŁECZNOŚĆ ---------- */
/* „Znajdź czytankę / rozmowę w Społeczności" pod Czytaniem i mapą Mówienia: obrysowana pigułka 2 px w barwie akcentu -
   drugi przycisk z planszy („Jeszcze fiszki", „Znajdź film w Społeczności"). Dawniej przerywany niebieski obrys. */
.mow-tworca-btn {
  min-height: 48px; padding: 10px 20px; border: 2px solid var(--oro); border-style: solid;
  background: transparent; color: var(--oro); font-weight: 800; font-size: 0.92rem;
}
.mow-tworca-btn:hover { background: var(--oro); color: var(--na-akcencie); border-style: solid; }
/* Półka 3D z reguły .tworca-akcje .btn, .mow-tworca-btn zostaje dla przycisków w oknie twórcy; obrysowana pigułka jej nie ma
   (półka pod przezroczystym przyciskiem wyglądała jak cień po innym przycisku) i dostaje z powrotem dolną krawędź. */
.mow-tworca-btn { border-bottom-width: 2px; box-shadow: none; background-image: none; }
.mow-tworca-btn:active { transform: translateY(1px); box-shadow: none; }
.community-tile { border-radius: 22px; box-shadow: none; }
.community-tile:hover { box-shadow: 0 20px 40px -18px rgba(23, 24, 59, 0.55); }
#communitySearch { border-width: 1.5px; background: var(--card-bg); }
.community-tile-badge { background: rgba(23, 24, 59, 0.78); }
/* ---------- 15. OKNA MARKI: KOMUNIKATY W STYLU KANWY (2026-09-27) ----------
   Alek po zrzucie „Cel dnia wykonany!” z bobrem z konsoli: „Rezygnujemy z postaci z konsoli, można to usunąć całe,
   i teraz wszystkie powiadomienia (…) będą opierać się na obecnych stylach i postaciach z Higgsfielda”. Okienka, które
   pokazywały postać z dymkiem (gratulacje, kamień milowy, przypomnienie po tygodniu, test ze zrozumienia, zachęta dla
   gościa, koniec godziny Premium), są od tego dnia EKRANAMI MARKI w miniaturze - tym samym językiem, co plansze kanwy
   i ekrany aplikacji (EkranMarki, NaglowekMarki w lingaria-app/src/komponenty/marka.tsx): kolor marki na całe okno,
   granatowe kółko zamknięcia (na granacie żółte), tytuł Outfit 800 obok ilustracji wychodzącej za krawędź, treść
   w kolorze tekstu na tym tle, główny przycisk = pigułka ze strzałką w kółku (.btn-strzalka w .na-kolorze /
   .na-granacie), drugi = biała pigułka (na granacie podkreślony napis, jak „Może później” ściany Premium).
   KOLOR WEDŁUG TEGO, CO OKNO MÓWI, jak w kanwie: zielony = opanowane („dobrze”), niebieski = postęp i Czytanie, żółty =
   powtórka, czerwony = zaproszenie do konta (plansza „Rejestracja”), granat = Premium. Barwy STAŁE w obu motywach
   (okładka nie zmienia koloru z motywem). Tekst: granat na żółtym i zielonym (biały ma na tej zieleni 3,1 : 1), biały
   na niebieskim, czerwonym i granacie; drugi tekst na błękicie #EEF3FF (4,6 : 1).
   Nowe okno komunikatu = ta sama struktura: .okno-marki.tlo-*.na-kolorze > .om-pasek, .om-glowa (.om-ilustracja,
   .om-tytul), .om-tresc (.om-opis, .om-akcje). */
.okno-marki {
  --om-tlo: #FFC83D; --om-tekst: #17183B; --om-tekst2: #2E3055;
  position: relative; display: block; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
  width: 100%; max-width: 560px; max-height: min(90vh, 800px);
  background: var(--om-tlo); color: var(--om-tekst); border-radius: 32px; text-align: left;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.6);
}
.okno-marki.tlo-zielony   { --om-tlo: #35A64D; --om-tekst2: #17183B; }
.okno-marki.tlo-niebieski { --om-tlo: #2463E9; --om-tekst: #FFFFFF; --om-tekst2: #EEF3FF; }
.okno-marki.tlo-czerwony  { --om-tlo: #DB2727; --om-tekst: #FFFFFF; --om-tekst2: #FFFFFF; }
.okno-marki.tlo-granat    { --om-tlo: #17183B; --om-tekst: #FFFFFF; --om-tekst2: #D4D5F0; }
.om-pasek { display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 20px 22px 0; position: relative; z-index: 1; }
.om-pigulka {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; max-width: calc(100% - 60px); padding: 0 16px;
  border-radius: 999px; background: #FFFFFF; color: #17183B; font-size: 0.86rem; font-weight: 800;
}
.om-pigulka .ico { margin: 0; }
.om-zamknij {
  flex: none; margin-left: auto; width: 44px; height: 44px; padding: 0; border: none; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.25rem;
  background: #17183B; color: #FFFFFF; transition: transform 0.15s ease;
}
.om-zamknij .ico { margin: 0; line-height: 1; }
.om-zamknij:hover { transform: scale(1.06); }
.okno-marki.tlo-granat .om-zamknij { background: var(--zolty); color: #17183B; }
.okno-marki :focus-visible { outline: 3px solid #FFFFFF; outline-offset: 3px; }
.okno-marki:is(.tlo-zolty, .tlo-zielony) :focus-visible { outline-color: #17183B; }
/* GŁOWA: tytuł w lewej kolumnie, ilustracja w prawym górnym rogu, wychodzi za prawą krawędź (jak na planszach: right
   −28…−40 przy 390 pt), a u góry zaczyna się tuż pod kółkiem zamknięcia - w pierwszej wersji wchodziła pod nie i kółko
   stało na głowie postaci (zrzut testu ze zrozumienia). Wysokość bierze się z ilustracji, żeby akapit nie wjechał pod jej dół. */
.om-glowa { position: relative; min-height: 184px; padding: 4px 24px 0; }
.om-ilustracja {
  position: absolute; right: -14px; top: -6px; width: 198px; height: 198px; z-index: 0;
  pointer-events: none; user-select: none;
}
.om-tytul {
  position: relative; z-index: 1; margin: 0; padding-top: 8px; max-width: calc(100% - 186px);
  font-family: var(--font-naglowek); font-weight: 800; font-size: 2.2rem; line-height: 1.04; letter-spacing: -0.02em;
  color: var(--om-tekst); text-wrap: balance; overflow-wrap: anywhere;
}
/* Kamień milowy: wielka liczba progu w głowie, a zdanie jako nagłówek pod nią, na pełną szerokość. */
.om-liczba {
  position: relative; z-index: 1; padding-top: 18px; max-width: calc(100% - 186px);
  font-family: var(--font-naglowek); font-weight: 800; font-size: 5.6rem; line-height: 0.9; letter-spacing: -0.04em;
  color: var(--zolty); font-variant-numeric: tabular-nums;
}
.om-tytul.om-tytul-zdanie { max-width: none; padding-top: 0; font-size: 1.75rem; line-height: 1.12; }
.om-tresc { position: relative; z-index: 1; padding: 16px 24px 24px; }
.om-zdanie { margin: 0 0 8px; font-weight: 800; font-size: 1.08rem; line-height: 1.4; color: var(--zolty); }
.om-opis { margin: 0; font-size: 1rem; font-weight: 500; line-height: 1.6; color: var(--om-tekst); }
.om-opis :is(strong, b) { font-weight: 800; }
.om-podpis { margin: 10px 0 0; font-size: 0.88rem; font-weight: 600; line-height: 1.5; color: var(--om-tekst2); }
.om-akcje { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }
.om-akcje .btn { margin: 0; }
.okno-marki .btn.om-drugi { background: #FFFFFF; color: #17183B; box-shadow: none; min-height: 52px; margin-top: 0; }
.okno-marki .btn.om-drugi:hover { box-shadow: 0 10px 22px -14px rgba(8, 18, 70, 0.8); }
.okno-marki.tlo-granat .btn.om-drugi {
  background: transparent; color: #FFFFFF; min-height: 44px; text-decoration: underline; text-underline-offset: 3px;
}
.okno-marki.tlo-granat .btn.om-drugi:hover { color: var(--zolty); box-shadow: none; }
/* Przypomnienie po tygodniu: pasek „opanowane” na żółtym - tor jak pod kaflami końca mini testu, wypełnienie zieleń logo. */
.okno-marki .przypomnienie-pasek { height: 12px; margin-top: 18px; border: none; background: rgba(23, 24, 59, 0.14); }
.okno-marki .przypomnienie-fill { background: var(--marka-zielony); }
.okno-marki .przypomnienie-podpis { color: var(--om-tekst2); font-weight: 700; }
/* Koniec godziny Premium: lista strat na granatowej karcie jak w aplikacji (KartaNaGranacie), kłódki żółte. */
#probneKoniecOverlay .probne-koniec-opis { font-size: 1rem; }
.probne-koniec-straty { margin-top: 16px; padding: 16px 18px; border-radius: 22px; background: #24265A; }
#probneKoniecOverlay .probne-koniec-strata-tytul { margin: 0; color: #FFFFFF; font-size: 0.95rem; }
#probneKoniecOverlay .probne-koniec-lista li { color: #FFFFFF; }
#probneKoniecOverlay .probne-koniec-lista .ico { color: var(--zolty); }
#probneKoniecOverlay .probne-koniec-plany { margin: 22px 0 10px; color: #FFFFFF; font-family: var(--font-naglowek); font-size: 1.2rem; line-height: 1.25; }
#probneKoniecOverlay .loader .spinner { border-color: rgba(255, 255, 255, 0.3); border-top-color: var(--zolty); }
@media (max-width: 560px) {
  .okno-marki { border-radius: 28px; max-height: min(92vh, 800px); }
  .om-pasek { min-height: 58px; padding: 16px 16px 0; }
  .om-glowa { min-height: 132px; padding: 2px 18px 0; }
  .om-ilustracja { width: 140px; height: 140px; right: -18px; top: -4px; }
  .om-tytul { font-size: 1.8rem; max-width: calc(100% - 118px); }
  .om-liczba { font-size: 4.4rem; max-width: calc(100% - 118px); }
  .om-tytul.om-tytul-zdanie { font-size: 1.45rem; }
  .om-tresc { padding: 14px 18px 20px; }
}
/* POWITANIE (#onboardingOverlay) - dwa pytania o język dla konta, które nie przeszło lejka (konto z samego e-maila,
   stare ścieżki). Ten sam język, co kroki lejka w stylu kanwy (.start-overlay[data-kolor]): krok 1 niebieski z kulą
   ziemską (krok1), krok 2 żółty z postacią w podskoku (krok2), białe kafle języków, wybrany granatowy, ostrzeżenie
   „na stałe” na złotej notce jak .lk-notka. Który krok stoi, mówi sam CSS (:has na #onboardingKrok2) - JS przełącza
   kroki jak dotąd. Dawniej biała karta z szarymi przyciskami: jedyne okno pierwszego wejścia w starym wyglądzie.
   Barwy stałe w obu motywach. */
.onboarding-karta {
  position: relative; overflow-x: hidden; max-width: 600px; padding: 26px 26px 28px; border-radius: 32px;
  background: #2463E9; color: #FFFFFF; text-align: left; box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.6);
}
.onboarding-karta:has(#onboardingKrok2:not(.hidden)) { background: #FFC83D; color: #17183B; }
.onboarding-ilustracja { position: absolute; right: -18px; top: -6px; width: 188px; height: 188px; pointer-events: none; user-select: none; }
.onboarding-karta .onboarding-krok,
.onboarding-karta h2,
.onboarding-karta h2 + p { position: relative; max-width: calc(100% - 168px); }
.onboarding-karta .onboarding-krok { color: inherit; opacity: 0.92; letter-spacing: 0.08em; }
.onboarding-karta h2 {
  margin: 10px 0 12px; font-family: var(--font-naglowek); font-weight: 800; font-size: 2rem; line-height: 1.05;
  letter-spacing: -0.02em; color: inherit; text-wrap: balance;
}
.onboarding-karta h2 .ico { display: none; }
.onboarding-karta p { color: inherit; font-size: 0.98rem; font-weight: 500; }
/* Notka jest jednym akapitem z ikoną i <strong> z tłumaczenia (data-i18n-html) - bez flexa, który rozbijał ją na kolumny. */
.onboarding-karta .onboarding-uwaga { background: #FFF6DC; color: #17183B; border-radius: 16px; padding: 12px 14px; font-size: 0.86rem; }
.onboarding-karta .onboarding-uwaga .ico { color: #8A5A00; }
.onboarding-karta .onboarding-podpowiedz { background: #FFFFFF; color: #17183B; border-radius: 16px; font-size: 0.86rem; }
.onboarding-karta .onboarding-lista { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.onboarding-karta .onboarding-jezyk {
  min-height: 52px; border: none; border-radius: 18px; background: #FFFFFF; color: #17183B; font-size: 0.95rem;
}
.onboarding-karta .onboarding-jezyk:hover { transform: translateY(-2px); box-shadow: 0 12px 22px -14px rgba(8, 18, 70, 0.8); }
.onboarding-karta .onboarding-jezyk.wybrany { background: #17183B; color: #FFFFFF; }
/* Polecany (język zdjęcia, z którego ktoś przyszedł) stoi na żółtym kroku 2 - granatowa obwódka, żółta by zniknęła. */
.onboarding-karta .onboarding-jezyk.polecany { box-shadow: 0 0 0 3px #17183B; }
.onboarding-karta .auth-consent { color: #17183B; }
.onboarding-karta .btn-grigio { background: #FFFFFF; color: #17183B; box-shadow: none; }
.onboarding-karta :focus-visible { outline: 3px solid #FFC83D; outline-offset: 2px; }
.onboarding-karta:has(#onboardingKrok2:not(.hidden)) :focus-visible { outline-color: #17183B; }
@media (max-width: 560px) {
  .onboarding-karta { padding: 20px 18px 22px; border-radius: 28px; }
  .onboarding-ilustracja { width: 124px; height: 124px; right: -16px; top: -2px; }
  .onboarding-karta .onboarding-krok, .onboarding-karta h2, .onboarding-karta h2 + p { max-width: calc(100% - 104px); }
  .onboarding-karta h2 { font-size: 1.6rem; }
  .onboarding-karta .onboarding-lista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* WARIANT JASNY (2026-09-27) - okienka-decyzje i formularze z rejestru (słówka w innym języku, post innego języka, kod QR,
   zgłoszenie naruszenia, prześwietlenie tekstu, usunięcie konta, kategorii i języka, zmiana regulaminu, kod z maila,
   ogłoszenie admina). To nie są święta, więc bez koloru marki na całe okno: karta w barwie motywu, u góry KWADRAT IKONY
   W AKCENCIE jak głowa Arkusza w aplikacji (granat z żółtą ikoną, w ciemnym motywie żółty z granatową; przy usuwaniu
   i zgłoszeniu czerwony z białą), tytuł Outfit 800 wyrównany do lewej, treść w kolorze tekstu motywu, główny przycisk
   z kółkiem (.btn-strzalka w barwach motywu), przy usuwaniu czerwona pigułka, drugi = pigułka z obwódką. Dawniej
   wyśrodkowane okno z emotką 2,6 rem, pogrubionym Figtree i szarym tekstem. */
.okno-marki.tlo-jasne { --om-tlo: var(--card-bg); --om-tekst: var(--testo); --om-tekst2: var(--grigio); max-width: 480px; }
.okno-marki.tlo-jasne .om-tresc { padding: 26px 26px 24px; }
.okno-marki.tlo-jasne .om-tytul { max-width: none; padding-top: 0; font-size: 1.7rem; line-height: 1.1; margin-bottom: 10px; }
.okno-marki.tlo-jasne .om-opis { font-size: 0.95rem; }
.okno-marki.tlo-jasne :focus-visible { outline-color: var(--fokus); }
.okno-marki.tlo-jasne .btn.om-drugi { background: var(--card-bg); color: var(--testo); box-shadow: inset 0 0 0 1.5px var(--border-2); min-height: 50px; }
.okno-marki.tlo-jasne .btn.om-drugi:hover { box-shadow: inset 0 0 0 1.5px var(--oro); }
.okno-marki.tlo-jasne .btn-rosso { min-height: 54px; margin: 0; }
.okno-marki.tlo-jasne .auth-input { margin: 16px 0 0; }
.okno-marki.tlo-jasne .start-link { margin: 6px auto 0; }
.om-ikona {
  width: 60px; height: 60px; margin: 0 0 16px; border-radius: 20px;
  display: flex; align-items: center; justify-content: center; font-size: 1.7rem; line-height: 1;
  background: #17183B; color: #FFC83D;
}
.om-ikona .ico { margin: 0; }
.om-ikona.ostrzezenie { background: #DB2727; color: #FFFFFF; }
:root[data-theme="dark"] .om-ikona:not(.ostrzezenie) { background: #FFC83D; color: #17183B; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .om-ikona:not(.ostrzezenie) { background: #FFC83D; color: #17183B; } }
/* Post innego języka: flagi „mój → tego postu” w miejscu kwadratu ikony (wstawia je pokazObcyJezyk). */
.om-flagi { display: flex; align-items: center; gap: 10px; margin: 0 0 16px; min-height: 30px; }
.om-flagi .ico { color: var(--grigio); }
/* Kod QR: białe tło NIEZALEŻNIE od motywu (czytnik szuka ciemnych modułów na jasnym polu). */
.om-qr { display: block; width: fit-content; min-width: 140px; min-height: 120px; margin: 18px auto 0; padding: 10px; border-radius: 16px; background: #FFFFFF; box-shadow: inset 0 0 0 1.5px var(--border); }
.om-qr-link { text-align: center; word-break: break-all; font-size: 0.75rem; font-weight: 500; margin: 10px 0 0; }
.om-komunikat { font-weight: 600; line-height: 1.7; white-space: pre-line; }
.om-kod { margin: 18px 0 0; }
.om-blad { color: var(--rosso); font-size: 0.82rem; font-weight: 600; min-height: 1.2em; margin: 8px 0 0; text-align: center; }
/* Nowe konto a Społeczność: okno otwiera się też z okna twórcy rozmowy (.tworca-okno, z-index 2500) i nad paletką
   (2600), więc stoi wyżej, jak ściana Premium (2700). */
#spolecznoscOdOverlay { z-index: 2700; }
.okno-marki .naruszenie-lista { margin-top: 16px; }
/* ZGŁOŚ PROBLEM (2026-09-27): jasne okno marki jak zgłoszenie naruszenia - ta sama lista powodów (.naruszenie-poz),
   pod nią JEDNO pole zależne od powodu (propozycja przy tłumaczeniu i zdaniu, opis przy reszcie), „daj mi znać”
   i przyciski. Na górze to, czego zgłoszenie dotyczy (słówko = tłumaczenie), żeby było wiadomo, że flaga złapała
   właściwą kartę. */
.zgl-co { margin: 0 0 4px; font-weight: 700; overflow-wrap: anywhere; }
.zgl-co .zgl-slowo { font-weight: 800; }
.zgl-pole { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 12px; }
.zgl-pole label { font-size: 0.86rem; font-weight: 700; color: var(--om-tekst); }
.okno-marki.tlo-jasne .zgl-pole .auth-input { margin: 0; }
.zgl-pole textarea {
  width: 100%; min-height: 64px; padding: 11px 13px; border-radius: 14px; resize: vertical; box-sizing: border-box;
  border: 1.5px solid var(--border-2); background: var(--crema); color: var(--testo); font: inherit; font-size: 0.92rem;
}
.zgl-pole textarea:focus { outline: none; border-color: var(--oro); }
.zgl-powiadom { display: flex; align-items: flex-start; gap: 10px; margin: 4px 0 0; font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.zgl-powiadom input { width: 18px; height: 18px; margin: 1px 0 0; flex: none; accent-color: var(--oro); }
/* Cele w żółtym oknie: białe kafle jak .lk-kafel-cel lejka, wybrany granatowy z żółtym ptaszkiem. */
.okno-marki .om-cele { margin: 16px 0 0; }
.okno-marki .om-cele .start-cel { border: none; border-radius: 18px; background: #FFFFFF; color: #17183B; }
.okno-marki .om-cele .start-cel:hover { box-shadow: 0 12px 22px -14px rgba(23, 24, 59, 0.6); }
.okno-marki .om-cele .start-cel.wybrany { background: #17183B; color: #FFFFFF; }
.okno-marki .om-cele .start-cel-ptak { color: #FFC83D; }
/* Passa: liczba dni Outfit 800 pod płomieniem, jak liczby na kartach marki. */
#streakBigCount { font-family: var(--font-naglowek); font-weight: 800; font-size: 2.2rem; line-height: 1.05; letter-spacing: -0.01em; }
/* Mniejszy wariant głównego przycisku z kółkiem - dwa przyciski w rzędzie (miękka ściana nad fiszką), jak `ciasny`
   w PrzyciskMarki aplikacji. */
/* Plan nauki z filmu (plan_filmu w rejestrze): nagłówek Outfit jak w oknach marki, główny przycisk z kółkiem - napis niesie
   datę ukończenia, więc zostaje długi i zawija się obok kółka zamiast pod nie. */
.plan-tytul { font-family: var(--font-naglowek); font-size: 1.5rem; line-height: 1.12; letter-spacing: -0.01em; }
.plan-modal { border-radius: 28px; }

.btn-strzalka.ciasny { min-height: 48px; padding: 4px 4px 4px 18px; font-size: 0.9rem; }
.btn-strzalka.ciasny::after { width: 40px; height: 40px; background-size: 20px 20px; }
/* ---------- 15a. SAMOUCZEK PO LEJKU: OKNO „FISZKI Z TWOICH MATERIAŁÓW” (2026-10-03) ----------
   Alek: „ma być krótko i w stylu aplikacji, bo ten format wprowadzenia użytkownika jest stary na desktopie i trochę
   zacina”. Żółte okno marki (barwa trybu Zdjęcie) zamiast reflektora, który na stojącym kroku malował 227 razy na sekundę
   (box-shadow w nieskończonej animacji; bez niego 115) i jeździł po top/left/width/height (CLS okna 0,30 przy 1440 × 900,
   1,04 przy 390 × 844). Tu NIC nie pulsuje: wjeżdża samo okno, 0,32 s, wyłącznie transform i opacity. Tło BEZ wjazdu:
   .wordmap-overlay ma fadeIn 0,2 s od zera, a okno staje w tej samej klatce, w której znika okno kodu z maila, więc
   między nimi mignęłaby nieprzyciemniona aplikacja. Barwy stałe w obu motywach, jak każde okno marki; kafle trybów białe,
   ikona w kwadracie w barwie trybu (Mówienie zieleń logo z granatową ikoną, Słuchanie czerwień i Czytanie błękit z białą).
   Wymiary sprawdzone na makiecie z prawdziwymi stylami strony: okno bez przewijania przy 1440 × 900, 1280 × 720,
   1280 × 650 i 390 × 844, przy 360 × 640 przewija się o 9 px. */
#samouczekOverlay { animation: none; }
/* Wjazd BEZ przezroczystości (recenzja 2026-10-03): okno od opacity 0 nad powitaniem dnia przez ~100 ms mieszało ze sobą
   teksty dwóch plansz („5 słówek czeka…” prześwitywało przez żółte okno, kadr 16 filmu z 390 × 844). Samo przesunięcie
   i skala, okno od pierwszej klatki pełne; przy ograniczonym ruchu bez animacji. */
:is(#samouczekOverlay, #demoKoniecOverlay):not(.hidden) :is(.samouczek-okno, .demo-koniec-okno) { animation: samouczekWjazd 0.32s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes samouczekWjazd { from { transform: translateY(14px) scale(0.98); } to { transform: none; } }
.samouczek-okno { max-width: 580px; }
.samouczek-okno .om-tresc { padding-top: 10px; }
/* Głowa niższa niż we wzorcu okien marki (184 px pod ilustrację 198 px): pod dwuwierszowym tytułem zostawało ~110 px
   pustego żółtego przy 1440 × 900, a zamówienie brzmiało „krótko”. */
@media (min-width: 561px) {
  .samouczek-okno .om-glowa { min-height: 156px; }
  .samouczek-okno .om-ilustracja { width: 170px; height: 170px; }
  .samouczek-okno .om-tytul { max-width: calc(100% - 160px); }
}
.samouczek-tryby { margin-top: 20px; padding-top: 16px; border-top: 1.5px solid rgba(23, 24, 59, 0.16); }
.samouczek-tryby-tytul { margin: 0 0 10px; font-size: 0.86rem; font-weight: 800; color: var(--om-tekst); }
.samouczek-tryby-kafle { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 10px; }
.samouczek-tryb {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-height: 44px; margin: 0; padding: 12px;
  border: none; border-radius: 18px; background: #FFFFFF; color: #17183B; font: inherit; text-align: start; cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.2s ease;
}
.samouczek-tryb:hover { transform: translateY(-2px); box-shadow: 0 12px 22px -14px rgba(23, 24, 59, 0.6); }
.samouczek-tryb-ikona { width: 36px; height: 36px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 1.05rem; }
.samouczek-tryb-ikona .ico { margin: 0; line-height: 1; }
.st-mowienie .samouczek-tryb-ikona { background: #35A64D; color: #17183B; }
.st-sluchanie .samouczek-tryb-ikona { background: #DB2727; color: #FFFFFF; }
.st-czytanie .samouczek-tryb-ikona { background: #2463E9; color: #FFFFFF; }
.samouczek-tryb b { font-weight: 800; font-size: 0.95rem; line-height: 1.2; }
.samouczek-tryb small { font-size: 0.78rem; font-weight: 600; line-height: 1.3; color: #2E3055; }
/* Kółko ze strzałką w rogu kafla (recenzja 2026-10-03): klik przenosi do trybu, a bez tego znaku kafle pod nagłówkiem
   „W menu „Fiszki” czekają też:” czytały się jak informacja, nie jak przyciski. Ten sam znak, co na głównym przycisku. */
.samouczek-tryb { position: relative; }
.samouczek-tryb::after {
  content: ''; position: absolute; top: 12px; inset-inline-end: 12px; width: 24px; height: 24px; border-radius: 999px;
  background: #F3F5FB var(--strzalka-granatowa) center / 14px 14px no-repeat;
}
[dir="rtl"] .samouczek-tryb::after { transform: scaleX(-1); }
/* Pierwsza sekunda głucha (planszaZamroz), jak na planszach w miejscu karty: przyciski nie łapią kliknięć (druga warstwa
   obok strażnika w JS), a z głównego zsuwa się zasłona w barwie okna. To wskaźnik „za chwilę zadziała”, nie ozdoba, więc
   gra też przy ograniczonym ruchu (ta sama zasada, co .polmetek.zamrozona). */
:is(.samouczek-okno, .demo-koniec-okno).zamrozona :is(.om-akcje .btn, .samouczek-tryb, .om-zamknij) { pointer-events: none; }
:is(.samouczek-okno, .demo-koniec-okno).zamrozona .btn-strzalka { position: relative; overflow: hidden; }
:is(.samouczek-okno, .demo-koniec-okno).zamrozona .btn-strzalka::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: color-mix(in srgb, var(--om-tlo) 58%, transparent);
  transform-origin: right center; animation: planszaOdmrazanie var(--zamrozenie-ms, 1s) linear forwards;
}
:is(.samouczek-okno, .demo-koniec-okno).zamrozona :is(.om-drugi, .samouczek-tryb) { opacity: 0.55; }
@media (prefers-reduced-motion: reduce) {
  :is(#samouczekOverlay, #demoKoniecOverlay):not(.hidden) :is(.samouczek-okno, .demo-koniec-okno) { animation: none; }
  .samouczek-tryb:hover { transform: none; }
}
/* Kółko przy krawędzi KOŃCOWEJ (po arabsku po lewej): wspólne .btn-strzalka ma margin-left: auto i padding liczony od
   lewej, więc przy dir="rtl" kółko stało tuż przy napisie (zmierzone przy lejku, .lk-stopka). */
:is(.samouczek-okno, .demo-koniec-okno) .btn-strzalka { padding-block: 6px; padding-inline: 24px 6px; }
:is(.samouczek-okno, .demo-koniec-okno) .btn-strzalka::after { margin-left: 0; margin-inline-start: auto; }
/* Drugi przycisk tej samej wysokości co główny (56 px, jak .btn-strzalka; wzorzec okien marki ma 52 px i w jednym rzędzie
   różnica 2 px u góry i u dołu kłuła w oczy, recenzja 2026-10-03). Od 561 px w oknie samouczka oba w jednym rzędzie: główny
   rośnie, „Później” to biała pigułka na szerokość napisu. Okno końca lekcji zostaje w kolumnie: przy „Jeszcze się
   rozglądam” obok „Zapisz postęp i odbierz konto” łamało się w dwie linijki (zrzut 1440 × 900). */
:is(.samouczek-okno, .demo-koniec-okno) .om-akcje .om-drugi { min-height: 56px; }
@media (min-width: 561px) {
  .samouczek-okno .om-akcje { flex-direction: row; align-items: center; }
  .samouczek-okno .om-akcje .btn-strzalka { flex: 1 1 auto; width: auto; }
  .samouczek-okno .om-akcje .om-drugi { flex: 0 0 auto; width: auto; padding: 0 24px; }
}
@media (max-width: 560px) {
  :is(#samouczekOverlay, #demoKoniecOverlay) { padding: 12px; }
  .samouczek-tryb { align-items: center; text-align: center; padding: 10px 8px; }
  .samouczek-tryb small { display: none; }
  .samouczek-tryb::after { top: 6px; inset-inline-end: 6px; width: 20px; height: 20px; background-size: 12px 12px; }
}
/* ---------- 15b. KONIEC LEKCJI PRÓBNEJ (2026-10-03): CZERWONE OKNO MARKI PRZED KONTEM ----------
   Zastąpiło białe .paczka-gratulacje (sekcja KONIEC LEKCJI PRÓBNEJ w JS). Wiersz z aparatem w barwie trybu Zdjęcie: to
   jedyne miejsce PRZED kontem, które mówi, że fiszki zrobisz ze zdjęcia własnych notatek (najważniejsze w zamówieniu Alka).
   Wjazd, zasłona pierwszej sekundy, kółko przy krawędzi końcowej i rząd przycisków wspólne z oknem samouczka (wyżej). */
.demo-koniec-okno { max-width: 540px; }
.demo-koniec-okno .om-tresc { padding-top: 10px; }
.demo-koniec-zdjecie {
  display: flex; align-items: center; gap: 12px; margin-top: 16px; padding: 12px 14px; border-radius: 18px;
  background: #FFFFFF; color: #17183B; font-size: 0.95rem; font-weight: 700; line-height: 1.35;
}
.demo-koniec-zdjecie-ikona {
  flex: none; width: 40px; height: 40px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
  background: #FFC83D; color: #17183B; font-size: 1.1rem;
}
.demo-koniec-zdjecie-ikona .ico { margin: 0; line-height: 1; }
/* Niskie okno (telefon 360 × 640, laptop 1280 × 650 przy skalowaniu Windows): bez podpisu i z ciaśniejszą głową, żeby
   kafle trybów nie uciekały pod krawędź. Przy 1280 × 650 ilustracja wchodziła na akapit (zrzut makiety), stąd mniejsza
   ilustracja i węższy tytuł. */
@media (max-height: 680px) {
  .samouczek-okno .om-podpis { display: none; }
  .samouczek-tryby { margin-top: 14px; padding-top: 12px; }
}
@media (max-height: 680px) and (min-width: 561px) {
  .samouczek-okno .om-glowa { min-height: 128px; }
  .samouczek-okno .om-ilustracja { width: 136px; height: 136px; }
  .samouczek-okno .om-tytul { max-width: calc(100% - 124px); }
}
/* ---------- 16. SPOŁECZNOŚĆ W STYLU KANWY (2026-10-03) ----------
   Alek: „poprawić wizualną stronę »społeczność«, aby pasowała z aktualnym designem strony kolorystycznie
   i ergonomicznie, czyli głównie kolory”. Kanwa nie ma planszy Społeczności, więc role barw idą za kanwą
   i za aplikacją mobilną, która ma już tablicę w nowym stylu (profil/Tablica.tsx, tablica/PasekObserwowanych.tsx):
   · na ZDJĘCIU (granatowy scrim rgba(23, 24, 59, a) zamiast szarości slate Tailwinda) akcja jest ŻÓŁTA z granatem,
     a stan „włączony” biały; na KARCIE odwrotnie: akcja w akcencie (--oro, w ciemnym żółty), stan „włączony” żółty.
     Tak samo robi kanwa (.na-granacie).
   · „lubię” ma JEDNĄ barwę, czerwień logo (dawniej niebieskie serce na kafelku i w karcie, czerwone na utworze);
     na zdjęciu biała pigułka z granatowym konturem serca, jak Serce w aplikacji.
   · „N nowych słów” i „znasz X%” żółte z granatem (pigułka „nowe” w aplikacji, .mow-kafelek-znasz), poziom CEFR
     jak .mow-cefr, rodzaj materiału w barwie TRYBU (Czytanie niebieski, Słuchanie czerwony, Mówienie zielony);
     liczniki zostają bezbarwne.
   · zieleń tylko dla „znasz / łatwe / postęp”: ramka obserwowanych, „+” w karcie, zakładka galerii, pasek wgrywania
     i licznik moderatora tracą zieleń (licznik w ciemnym miał 1,62 : 1, tytuł obserwowanych 2,70 : 1).
   · cichy tekst (daty, „Usuń”, „Zgłoś”, liczniki znaków, stopka) --tekst-neutralny 5,02 : 1 na karcie zamiast
     --muted-light 2,68 : 1; na --bg-soft (kafel reklamy) --grigio, bo tam neutralny ma tylko 4,31.
   · karty płaskie z obwódką 1,5 px (kafle czytanek bez błękitnego gradientu i lawendowej ramki 2 px), tytuły Outfit 800,
     cele dotyku ≥ 44 px (dawniej 13 x 15 krzyżyk szukania, 26 x 14 „Usuń” przy komentarzu, 28 px kółka kafla utworu).
   Barwy na zdjęciu i plakietki trybów są STAŁE w obu motywach (literały, jak .okno-marki): --marka-niebieski
   i --marka-czerwony jaśnieją w ciemnym motywie i biały napis miałby na nich 3,7 : 1. Reszta idzie przez tokeny.
   Dalsza część tych samych zasad dla telefonu stoi w miejscu, w bloku „3. SPOŁECZNOŚĆ NA TELEFONIE” (reguły z `body`). */

/* ===== 16a. KAFEL ZDJĘCIA (leży na zdjęciu: barwy stałe) ===== */
/* Serce: pełna biała pigułka (nie 92% jak w aplikacji: czerwony licznik nad ciemnym zdjęciem spadałby do 4,07 : 1). */
.community-serce { position: relative; }
/* Pole dotyku 44 px bez zmiany wyglądu (pigułka ma 32 px). */
.community-serce::after { content: ''; position: absolute; inset: -6px; }
/* Serce na okładce kafla (biała pigułka) stoi w sekcji 19. */
.community-tile-overlay {
  background: linear-gradient(0deg, rgba(23, 24, 59, 0.95) 0%, rgba(23, 24, 59, 0.82) 40%, rgba(23, 24, 59, 0.25) 78%, rgba(23, 24, 59, 0) 100%);
}
.community-tile-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 0.95rem; color: #FFFFFF; }
/* Lawenda na scrimie 82% nad bielą (najgorszy przypadek) 6,73 : 1; dawny #CBD5E1 był szarością slate. */
.community-tile-meta { color: var(--lawenda); }
/* Przyciski NA ZDJĘCIU (zdjęcie, zgłoszone i kandydujące): akcja żółta, drugi plan biały. Czerwona pigułka „Zapisz”
   (w ciemnym 2,78 : 1) i czarne „Zapisane” odchodzą; czerwień w kanwie znaczy błąd, trudne albo Słuchanie. */
/* Rozmiary ZWARTE (30 px, jak dawne 28): nakładka zdjęcia działa wyłącznie pod kursorem (na dotyku jest schowana, niżej),
   a kafel zdjęcia bywa niski. Przy 36 px przyciskach i 32 px „Zgłoś” rząd akcji kafla o wysokości 105 px zaczynał się
   19 px od góry, czyli pod sercem i „znasz wszystko” (sięgają 42 px; recenzja 2026-10-03, 9 z 16 kafli przy 1440 x 900).
   Mysz nie potrzebuje 44 px; duże cele mają kafle moderatora na dotyku (niżej). */
.community-tile-overlay .community-btn-zapisz,
.community-tile-overlay .community-btn-przejdz { display: inline-flex; align-items: center; min-height: 30px; padding: 0 13px; font-weight: 800; }
.community-tile-overlay .community-btn-zapisz { background: var(--zolty); color: var(--granat); }
.community-tile-overlay .community-btn-zapisz.zapisane {
  background: rgba(255, 255, 255, 0.18); box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.7); color: #FFFFFF;
}
.community-tile-overlay .community-btn-przejdz { background: #FFFFFF; color: #17183B; }
/* Dolne dopełnienie 8 px zamiast 12: z nim rząd akcji najniższego kafla (105 px) zaczyna się 45 px od góry, pod górnymi
   znaczkami (sięgają 42 px). */
.community-tile:not(:is(.tekst, .rozmowa, .paczka)) .community-tile-overlay { padding-bottom: 8px; }
/* Tytuł i opis, które się nie mieszczą, wygasają pod znaczkami zamiast na nich leżeć. Przycięte były zawsze (na
   najniższych kaflach wychodziły 25 px ponad górną krawędź), ale napis szedł przez serce i licznik pobrań. */
.community-tile:not(:is(.tekst, .rozmowa, .paczka)) .community-tile-overlay {
  -webkit-mask-image: linear-gradient(to bottom, transparent 36px, #000 52px);
  mask-image: linear-gradient(to bottom, transparent 36px, #000 52px);
}
/* Granatowy fokus akcentu znika na granatowym scrimie. */
.community-tile:not(:is(.tekst, .rozmowa, .paczka)) .community-tile-overlay :focus-visible { outline: 3px solid #FFFFFF; outline-offset: 2px; }
/* DOTYK. Nakładka pokazuje się po najechaniu, a na telefonie najechania nie ma: miała opacity 0, ale łapała kliknięcia,
   więc pod kciukiem leżały niewidoczne „Zapisz”, „udostępnij” i „Zgłoś” (zmierzone sondą przy 390 px: hover none,
   pointer-events auto). Tytuł zdjęcia był tam niewidoczny i zostaje niewidoczny (zdjęcie jest treścią), a te same
   akcje są w karcie po dotknięciu. Kafle moderatora (zgłoszone, kandydaci) to narzędzie bez karty, więc tam nakładka
   jest po prostu widoczna. */
@media (hover: none) {
  .community-tile[data-typ="foto"]:not(.naruszenie) .community-tile-overlay { display: none; }
  .community-tile:is(.naruszenie, .kandydat) .community-tile-overlay { opacity: 1; }
  /* Kafel moderatora na telefonie: data zgłoszenia i lista słówek dużą kursywą były wyższe niż kafel, wychodziły ponad
     górną krawędź i zasłaniały całe zdjęcie (recenzja 2026-10-03, „Do weryfikacji” przy 390 px). Zostaje sama akcja
     w pełnym rozmiarze kciuka; resztę pokazuje edytor po dotknięciu kafla (openKandydat). Zgłoszony materiał nie ma
     edytora, więc zostaje mu tytuł w jednej linii i powody w trzech, małym prostym pismem. */
  .community-tile.kandydat :is(.community-tile-tytul, .community-tile-probka) { display: none; }
  .community-tile:is(.naruszenie, .kandydat) .community-tile-overlay :is(.community-btn-zapisz, .community-btn-przejdz) { min-height: 44px; padding: 0 18px; }
  .community-tile.naruszenie .community-tile-tytul { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .community-tile.naruszenie .community-tile-meta {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; font-size: 0.72rem;
  }
}

/* ===== 16b. KAFLE CZYTANKI, UTWORU I ROZMOWY: od 2026-10-05 w sekcji 19 (kafle jak Pinterest) ===== */
/* Tytuł na kaflu zgłoszonego materiału (kafelekNaruszenia, kolejka moderatora). */
.community-tile .paczka-nazwa { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.08rem; letter-spacing: -0.01em; color: var(--testo); }
/* Link autora: 34 px celu (44 na dotyku) bez zmiany układu: margines zjada dopełnienie. */
.cmty-autor-link { padding-block: 6px; margin-block: -6px; }
@media (pointer: coarse) { .cmty-autor-link { padding-block: 11px; margin-block: -11px; } }
/* Dotyk: 44 px celu pod drobnymi napisami („Zgłoś naruszenie”) bez zmiany wyglądu. */
.cmty-zglos { position: relative; }
@media (pointer: coarse) { .cmty-zglos::after { content: ''; position: absolute; inset: -6px 0; } }

/* ===== 16c. PASY NAD TABLICĄ ===== */
/* „Od obserwowanych twórców”: karta zamiast zielonej ramki z zielonym tytułem. */
.cmty-obserwowani { background: var(--card-bg); border: 1.5px solid var(--border); border-radius: 24px; padding: 16px 18px 18px; margin-bottom: 16px; }
.cmty-obs-tytul { color: var(--testo); font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; }
.cmty-obs-tytul .ico { color: var(--oro); }
.cmty-obs-kafelek { background: var(--crema); border: 1.5px solid var(--border-warm-soft); border-radius: 16px; }
.cmty-obs-kafelek:hover { border-color: var(--oro); }
/* Miniatura bez zdjęcia (czytanka, utwór): niebieska jak czytanka w aplikacji, zamiast szarego pola. */
span.cmty-obs-obraz { background: var(--bg-info-soft); color: var(--testo); }
@media (max-width: 560px) { .cmty-obs-kafelek { flex-basis: 168px; } }
/* Polecenie „Odkrywaj”: złota karta jak polecany w aplikacji (dawniej niebieski gradient). */
.cmty-polecany {
  background: var(--bg-gold-soft); border: 1.5px solid color-mix(in srgb, var(--zolty) 55%, transparent);
  border-radius: 24px; padding: 16px 18px;
}
.polecany-ikona { background: var(--zolty); color: var(--granat); }
.polecany-powod { color: var(--grigio); font-weight: 700; }
.polecany-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; color: var(--testo); }
/* Wspólny cel: karta kanwy bez zielonego paska z lewej (wzorzec „karta z kreską”) i bez gradientu Tailwinda. */
.wyz-baner { border: 1.5px solid var(--border); border-radius: 24px; box-shadow: none; padding: 18px 20px; }
.wyz-baner::before { display: none; }
.wyz-gora { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: start; }
.wyz-tytul { min-width: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.1rem; }
/* Termin to zdarzenie, nie „dobrze”: złote tło zamiast zieleni sukcesu. */
.wyz-zegar { background: var(--bg-gold-soft); color: var(--testo); }
.wyz-zamknij { width: 40px; height: 40px; background: var(--bg-soft); color: var(--testo); }
.wyz-liczby b { font-family: var(--font-naglowek); }
/* Pasek postępu w pełnej zieleni logo, jak .community-postep-wypelnienie. */
.wyz-pasek-tlo { background: var(--bg-soft); border: 0; }
.wyz-pasek { background: var(--marka-zielony); }
/* Połysk (::after) sunął też po PUSTYM torze, bo wypełnienie go nie przycinało: w ciemnym motywie jasna plama #7C7D98 na
   torze #212350 (recenzja 2026-10-03; było tak już przed zmianą). */
.wyz-pasek { overflow: hidden; }
@media (max-width: 560px) {
  .wyz-gora { grid-template-columns: minmax(0, 1fr) auto; }
  .wyz-zegar { grid-column: 1; grid-row: 2; justify-self: start; }
}

/* ===== 16d. TABLICA, PUSTE STANY, MODERATOR ===== */
/* Cień zamkniętego panelu kategorii zostawał na ekranie (panel tylko odjeżdża w lewo) i robił szary pas przy lewej
   krawędzi KAŻDEGO widoku Społeczności (zmierzone: tło #F3F5FB ciemniało do rgb(206, 208, 213) przy x = 0). */
.cmty-kategorie { width: min(300px, 86vw); max-width: none; border-right: 1.5px solid var(--border); box-shadow: none; }
.cmty-kategorie.otwarty { box-shadow: 18px 0 50px rgba(23, 24, 59, 0.22); }
.cmty-kategorie-tlo { background: rgba(23, 24, 59, 0.4); }
.cmty-kategorie-zamknij {
  width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--testo); font-size: 1.1rem;
}
.cmty-kategorie-zamknij:hover { background: var(--border); color: var(--testo); }
.cmty-kategorie-zamknij .ico { margin: 0; }
.cmty-kategoria { min-height: 48px; border-radius: 14px; }
/* Wybór = żółty (kanwa), jak własny wiersz rankingu; dawniej napis w akcencie na żółtej poświacie. */
.cmty-kategoria.active { background: var(--bg-highlight); box-shadow: inset 0 0 0 1.5px var(--zolty); color: var(--testo); }
/* Dwie kolumny jak w aplikacji (Tablica.tsx, odstęp 10). Dawne reguły telefonu z tymi wartościami stały w arkuszu
   PRZED bazą i przegrywały kaskadę; przy 360 px wyliczanka auto-fill dawała raz jedną, raz dwie kolumny. */
@media (max-width: 720px) {
  .community-board { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .community-full { padding: 12px 12px 50px; }
}
/* Pusty stan: karta z ilustracją zamiast samego szarego napisu na środku tablicy. */
.community-empty {
  max-width: 520px; margin: 24px auto; padding: 28px 24px; text-align: center;
  background: var(--card-bg); border: 1.5px solid var(--border); border-radius: 28px;
  color: var(--grigio); font-weight: 600;
}
.community-empty::before {
  content: ''; display: block; width: 140px; height: 140px; margin: 0 auto 12px;
  background: url('../../assets/img/ilustracje/fiszki.webp') center / contain no-repeat;
}
.cmty-zaproszenie { border: 1.5px dashed var(--border-warm-dash); border-radius: 28px; }
.cmty-zaproszenie.dragover { background: var(--bg-highlight); border-color: var(--oro); }
.cmty-zaproszenie-ikona {
  width: 60px; height: 60px; margin: 0 auto 14px; border-radius: 20px;
  display: flex; align-items: center; justify-content: center;
  background: var(--oro); color: var(--na-akcencie); font-size: 1.6rem;
}
.cmty-zaproszenie-ikona .ico { margin: 0; }
.cmty-zaproszenie-tytul { font-family: var(--font-naglowek); }
.cmty-zaproszenie-upusc { color: var(--tekst-neutralny); }
/* Etykieta reklamy leży na --bg-soft, gdzie --tekst-neutralny ma tylko 4,31 : 1. */
.community-tile.reklama .reklama-etykieta { color: var(--grigio); font-size: 0.68rem; }
.community-full .app-stopka { color: var(--tekst-neutralny); }
.naruszenie-plakietka { background: #DB2727; }
.naruszenie-zgoda, .pochodzenie-zgoda { color: var(--tekst-neutralny); }
/* Tylko w oknie naruszenia: ta sama lista .naruszenie-poz stoi w „Zgłoś problem” przy fiszkach i quizach (#zglLista),
   a tamto okno nie jest częścią Społeczności. Obwódka 1,5 px także bez wyboru, inaczej lista drgała o piksel przy kliknięciu. */
#naruszenieLista .naruszenie-poz { border-width: 1.5px; }
#naruszenieLista .naruszenie-poz.wybrany { color: var(--testo); border-color: var(--rosso); }
#naruszenieLista .naruszenie-poz.wybrany .ico { color: var(--rosso); }
/* Licznik „Do weryfikacji”: żółty z granatem (dawniej biały na --verde: w ciemnym 1,62 : 1). */
.cmty-licznik { background: var(--zolty); color: var(--granat); animation-name: cmtyLicznikPuls; }
@keyframes cmtyLicznikPuls {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--zolty) 55%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--zolty) 0%, transparent); }
}
/* Ikona notki przydziału wołała --arancio, którego w arkuszu nie ma. */
.cmty-przydzial-notka .ico { color: var(--primary); }

/* ===== 16e. KARTA W POWIĘKSZENIU ===== */
.community-detail-karta.w-siatce { border: 1.5px solid var(--border); border-radius: 24px; box-shadow: 0 24px 48px -28px rgba(23, 24, 59, 0.45); }
/* Wróć: białe kółko z obwódką z kanwy, 44 px (leży na zdjęciu, więc barwy stałe). */
.community-detail-wroc {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  background: #FFFFFF; color: #17183B;
  box-shadow: 0 0 0 1.5px rgba(23, 24, 59, 0.12), 0 4px 12px rgba(23, 24, 59, 0.22);
}
.community-detail-wroc:hover { background: #FFFFFF; }
.community-detail-wroc .ico { margin: 0; }
/* Akcje na zdjęciu 44 px także na komputerze (reguła telefonu z 44 px przegrywała kaskadę: było 40 wszędzie). */
.community-akcja {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  background: rgba(23, 24, 59, 0.72); border: 1.5px solid rgba(255, 255, 255, 0.34); color: #FFFFFF;
}
.community-akcja .ico { margin: 0; }
.community-akcja:hover { background: rgba(23, 24, 59, 0.9); border-color: #FFFFFF; }
/* „+ dodaj słówka” = jedyna akcja główna na scrimie: żółta (dawniej zieleń sukcesu). */
.community-akcja.glowna, .community-akcja.glowna:hover { background: var(--zolty); border-color: var(--zolty); color: var(--granat); }
.community-akcja.glowna:hover { filter: brightness(1.05); border-color: #FFFFFF; }
/* Stan „włączony” na zdjęciu = białe kółko; polubione z czerwonym sercem (4,85 : 1), jak w aplikacji. */
/* Pierścień i cień jak przy „Wróć”: przy pionowym zdjęciu róg kolumny wypada na białym marginesie obok obrazka
   i samo białe kółko znikało (biel na bieli). */
.community-akcja.polubione, .community-akcja.polubione:hover { background: #FFFFFF; border-color: #FFFFFF; color: #DB2727; }
.community-akcja:is(.zapisane-akcja, .aktywna), .community-akcja:is(.zapisane-akcja, .aktywna):hover { background: #FFFFFF; border-color: #FFFFFF; color: #17183B; }
.community-akcja:is(.polubione, .zapisane-akcja, .aktywna) { box-shadow: 0 0 0 1.5px rgba(23, 24, 59, 0.12), 0 4px 12px rgba(23, 24, 59, 0.22); }
/* Czytanka, utwór i rozmowa (.paczka): akcje leżą na tle KARTY, nie na zdjęciu, więc stan „włączony” jest stanem karty
   (zasada wyżej): polubione = obwódka i serce w czerwieni logo, zapisane = żółte z granatem. Białe kółko na białej
   karcie miało 1 : 1 i zostawało gołe serce (recenzja 2026-10-03, rozmowa 4, czytanka 76, utwór 73 przy 390 x 844). */
.community-detail-karta.paczka .community-akcja.polubione,
.community-detail-karta.paczka .community-akcja.polubione:hover {
  background: var(--card-bg); border-color: var(--marka-czerwony); color: var(--marka-czerwony); box-shadow: none;
}
.community-detail-karta.paczka .community-akcja:is(.zapisane-akcja, .aktywna),
.community-detail-karta.paczka .community-akcja:is(.zapisane-akcja, .aktywna):hover {
  background: var(--zolty); border-color: var(--zolty); color: var(--granat); box-shadow: none;
}
.community-detail-akcje-gora :focus-visible, .community-detail-wroc:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 2px; }
/* Na tle karty (czytanka, utwór, rozmowa) biały fokus znikał tak samo jak białe kółko: tam fokus akcentu. */
.community-detail-karta.paczka :is(.community-detail-akcje-gora :focus-visible, .community-detail-wroc:focus-visible) { outline-color: var(--oro); }
.cmty-film-graj::before { background: rgba(23, 24, 59, 0.72); }
/* ROZMOWA Z OKŁADKĄ = KOLUMNA: okładka z pigułkami, pod nią zwiastun i słówka (sekcja 20). Rozmowa z okładką dostaje klasę
   .utwor (renderRozmoweWKarcie), a układ utworu to RZĄD flexa: karta „jak grać” stała obok okładki ściśnięta do 4 px
   i łamała się po literze w słup wysoki na 576 px. Stąd kolumna 658 px przy okładce 365 px, pusty biały pas, pionowa
   kreska przy prawej krawędzi i okładka przesunięta o 2 px względem nalepek (rząd przepełniony o te 4 px; recenzja
   2026-10-03, rozmowa 4 przy 1440 x 900). Było tak od zawsze, tylko pas stał wcześniej nad okładką. Karta „jak grać”
   (tekst i słówka składa renderRozmoweWKarcie także przy okładce) wraca więc pod okładkę na całą szerokość.
   Okładka i nalepki leżą w JEDNEJ komórce siatki: komórka ma wysokość wyższego z nich, a okładka (object-fit: cover)
   rozciąga się do niej. Na wąskim telefonie nalepek jest więcej niż miejsca w kadrze 16:9 i dotąd wystawały 120 px
   POD obrazek lawendową płytą (poświata na białym tle karty); teraz to kadr okładki rośnie, a nalepki zostają na niej.
   Klucz to widoczna karta zdań: utwór ją chowa (renderTekstWKarcie), więc jego wyśrodkowana okładka z przyciskiem
   odtwarzania na środku kolumny zostaje bez zmian.
   Od 2026-10-05 (zwiastun rozmowy) okładka ma kadr 2 : 1 zamiast 16 : 9: pod nią stoi pierwsza wymiana, która ma się
   zmieścić w pierwszym ekranie (zmierzone w kanwie przy 1440 px: przy 16 : 9 odpowiedzi ucznia zaczynały się pod zgięciem).
   Kadr bierze górę obrazka wyżej środka, bo postacie na okładkach z rysownika mają głowy w górnej trzeciej części. */
.community-detail-karta.paczka.utwor .community-detail-obraz:has(> #communityDetailZdania:not(.hidden)) {
  display: grid; grid-template-columns: minmax(0, 760px); justify-content: center; align-content: start; row-gap: 18px;
}
.community-detail-karta.paczka.utwor .community-detail-obraz:has(> #communityDetailZdania:not(.hidden)) > :is(img, .cmty-nalepki) { grid-area: 1 / 1; }
.community-detail-karta.paczka.utwor .community-detail-obraz:has(> #communityDetailZdania:not(.hidden)) > img {
  align-self: stretch; height: 100%; min-height: 0; max-width: none; max-height: none; margin: 0;
  aspect-ratio: 2 / 1; object-position: 50% 35%;
}
.community-detail-karta.paczka.utwor .community-detail-obraz:has(> #communityDetailZdania:not(.hidden)) > .cmty-nalepki {
  position: relative; inset: auto; align-self: end; justify-self: start;
}
.community-detail-karta.paczka.utwor .community-detail-obraz:has(> #communityDetailZdania:not(.hidden)) > #communityDetailZdania {
  grid-area: 2 / 1; width: auto; max-height: none; overflow: visible; padding-right: 0;
}
/* (Przyciski pod tytułem karty: od 2026-10-11 jeden pod drugim na całą szerokość panelu, sekcja 21b. Dawne flex: 1 w rzędzie
   łamało „Obejrzyj i ucz się z tego utworu” w pigułce na dwie linie przy 1440 px.) */
.community-detail-panel h2 { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.35rem; letter-spacing: -0.01em; }
.community-ai-nota { color: var(--tekst-neutralny); font-size: 0.72rem; }
.community-slowo-chip { border-width: 1.5px; }
.community-slowo-chip:not(.juz-mam):not(.community-chip-akcja) { border-color: var(--border); }
.community-slowo-chip.juz-mam { border-width: 1.5px; }
.community-chip-akcja { position: relative; min-height: 36px; }
@media (pointer: coarse) { .community-chip-akcja::after { content: ''; position: absolute; inset: -4px 0; } }
.community-komentarze-naglowek { font-family: var(--font-naglowek); font-weight: 800; font-size: 1rem; }
.community-komentarz-kiedy, .community-komentarze-pusto, .community-komentarz-licznik { color: var(--tekst-neutralny); }
/* „Usuń” / „Zgłoś” przy komentarzu: pigułka 32 px (44 na dotyku) zamiast napisu 26 x 14 px. OPŁYWANA na końcu wiersza
   z nickiem: jako zwykły element w linii pigułka z dopełnieniem nie mieściła się obok daty, spadała w KAŻDYM komentarzu
   do osobnej linii, a jej 44 px celu z ujemnym marginesem leżało na treści komentarza (niewidzialne „Usuń” nad tekstem
   własnego komentarza; recenzja 2026-10-03 przy 390 px). Opływana stoi w rogu, wiersz nie rośnie, a tekst omija ją
   tylko tam, gdzie ona jest. Ujemny górny margines = połowa nadwyżki nad wierszem nicku (18 px). */
.community-komentarz-akcje { float: inline-end; margin: -7px 0 0; margin-inline-start: 6px; }
.community-komentarz-akcje button {
  min-height: 32px; padding: 0 8px; border-radius: 999px; color: var(--tekst-neutralny);
}
.community-komentarz-akcje button:hover { background: var(--bg-error-soft); color: var(--testo); }
@media (pointer: coarse) {
  .community-komentarz-akcje { margin-top: -13px; }
  .community-komentarz-akcje button { min-height: 44px; min-width: 44px; }
}
.community-komentarz-form input { min-height: 44px; padding: 0 16px; background: var(--card-bg); border: 1.5px solid var(--border-2); }
.community-komentarz-form input:focus { border-color: var(--oro); }
.community-komentarz-form button { width: 44px; height: 44px; }
.community-detail-panel .cmty-zglos { min-height: 40px; font-size: 0.78rem; font-weight: 700; color: var(--tekst-neutralny); border-radius: 999px; }
.community-detail-panel .cmty-zglos:hover { background: var(--bg-error-soft); color: var(--testo); }
.community-detail-panel .cmty-zglos:hover .ico { color: var(--rosso); }
/* Usuwanie (moderator): pigułka 44 px; w ciemnym granat na #FF6B6B (6,15 : 1) zamiast białego (2,78). */
.community-detail-usun { min-height: 44px; border-radius: 999px; border-width: 1.5px; }
.community-detail-usun:hover { background: var(--rosso); color: var(--na-akcencie); }

/* ===== 16f. PASEK NARZĘDZI I PANEL KATEGORII ===== */
/* Jedna wysokość paska: 40 px (dawniej 31 filtr, 32 kafelki, 36 szukanie, 40 aparat i nagłówek). */
#communitySearch { height: 40px; padding: 0 40px 0 36px; border: 1.5px solid var(--border); }
#communitySearch::placeholder { color: var(--tekst-neutralny); }
.community-search-ico { left: 14px; color: var(--grigio); opacity: 1; }
.community-search-clear {
  right: 4px; width: 32px; height: 32px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
}
.community-search-clear:hover { background: var(--bg-soft); color: var(--testo); }
.community-search-clear .ico { margin: 0; }
@media (pointer: coarse) { .community-search-clear { right: 2px; width: 40px; height: 40px; } }
/* Aparat i kafelki jak .header-theme obok: białe kółko z pierścieniem 1,5 px, pod kursorem pierścień akcentu. */
.community-aparat, .community-kafelki {
  width: 40px; height: 40px; border: none; border-radius: 50%;
  background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border); color: var(--testo);
}
.community-kafelki { font-size: 0.95rem; }
.community-aparat:hover, .community-kafelki:hover { background: var(--card-bg); color: var(--testo); box-shadow: 0 0 0 1.5px var(--oro); }
.community-kafelki.otwarty { background: var(--bg-highlight); color: var(--testo); box-shadow: 0 0 0 1.5px var(--oro); }
/* Filtr to przełącznik cyklu, nie stan: neutralna pigułka jak sortowanie w aplikacji (dawniej stale „aktywny” obrys). */
.community-chip, .community-chip.active {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px; border: none;
  background: var(--card-bg); box-shadow: 0 0 0 1.5px var(--border); color: var(--testo);
  font-size: 0.82rem; font-weight: 700;
}
.community-chip .ico { color: var(--grigio); }
/* Wielokropek musi stać na napisie: pigułka jest flexem, a text-overflow na niej nie sięga do spana w środku
   (filtr ucinał się na „Popul” bez wielokropka). */
.community-chip { max-width: 100%; }
.community-chip > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Krzyżyk czyszczenia stoi tylko przy wpisanym tekście, więc pusta wyszukiwarka nie trzyma dla niego 40 px. */
#communitySearch:placeholder-shown { padding-right: 12px; }
.community-chip:hover { background: var(--card-bg); color: var(--testo); box-shadow: 0 0 0 1.5px var(--oro); }
/* „Wszystkie języki” włączone = wybór (żółty z granatem, 11,04 : 1). */
#cmtyMixBtn.wlaczony, #cmtyMixBtn.wlaczony:hover { background: var(--zolty); color: var(--granat); box-shadow: none; }
#cmtyMixBtn.wlaczony .ico { color: var(--granat); }
/* Strzałka języka (26 x 26 px) dostaje cel na całą pigułkę z flagą: kliknięcie w flagę otwiera to samo menu. */
.community-topbar .header-lang { position: relative; }
.community-topbar .header-lang-caret::before { content: ''; position: absolute; inset: 0; border-radius: 999px; }
body.tryb-goscia .gosc-cta { min-height: 40px; }
@media (max-width: 768px) {
  /* Telefon: wszystkie kontrolki paska 44 px (zakładki już mają 44). Układ w dwóch rzędach stoi w bloku telefonu. */
  #communitySearch { height: 44px; }
  .community-topbar :is(.community-aparat, .community-kafelki, .header-theme) { width: 44px; height: 44px; }
  .community-topbar :is(.community-chip, .header-lang) { min-height: 44px; height: auto; }
  body.tryb-goscia .gosc-cta { min-height: 44px; }
  /* Zakładka „Fiszki” była pustą pigułką 28 x 44 px (ikona ukryta, napis schowany regułą dla nazw zakładek), a to
     jedyne wyjście z tablicy do nauki. Napis wraca, skrócony wielokropkiem; strzałka menu zostaje schowana. */
  /* Oba rzędy po 44 px (pasek 2 x 44 + 8 + 2 x 10 = 116 px): pigułka zakładek miała 52 px (4 px dopełnienia wokół
     zakładek 44 px), a panel konta 48 px. */
  .community-topbar .mode-tabs { padding: 2px; }
  .community-topbar .mode-tab { min-height: 40px; padding-block: 0; }
  .community-topbar .header-konto { padding-block: 2px; }
  .cmty-nawigacja .mode-tab #modeFiszkiLabel {
    display: inline-block; max-width: 8ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
  }
}

/* ===== 16g. PROFIL, WGRYWANIE, OKNO MODERATORA ===== */
.profil-galeria-wiecej {
  min-height: 44px; border: none; border-radius: 999px;
  background: var(--card-bg); box-shadow: inset 0 0 0 1.5px var(--border-2); color: var(--testo);
}
.profil-galeria-wiecej:hover:not(:disabled) { background: var(--card-bg); box-shadow: inset 0 0 0 1.5px var(--oro); color: var(--testo); }
.profil-zapelnienie { background: rgba(23, 24, 59, 0.5); }
/* „Obserwator” na tokenach (7,18 / 7,48 : 1); ciemne nadpisania tego kruszcu usunięte, tokeny same się odwracają. */
.tw-odznaka.szary { --tw-tlo: var(--bg-soft); --tw-ramka: var(--border-2); --tw-tekst: var(--grigio); }
/* „Wgrywasz zdjęcie na Społeczność” to informacja, nie sukces: błękit zamiast zielonej ramki. */
.cmty-wgraj-info { background: var(--bg-info-soft); border: 0; border-radius: 14px; color: var(--muted-dark); }
.cmty-wgraj-info .ico { color: var(--primary); }
/* Okno wgrywania na telefonie: nagłówek okien .wordmap łamie się tam (flex-wrap), więc długi tytuł „Wgraj zdjęcie na
   Społeczność” spychał krzyżyk pod siebie, na lewą stronę (było tak już przed zmianą). Tytuł łamie się w dwie linie,
   krzyżyk zostaje w prawym rogu. */
#cmtyUploadOverlay .wordmap-header { flex-wrap: nowrap; align-items: flex-start; }
#cmtyUploadOverlay .wordmap-title { min-width: 0; }
#cmtyUploadOverlay .wordmap-close { flex-shrink: 0; }
.community-detail { background: rgba(23, 24, 59, 0.62); }
.community-upload-karta { border-radius: 28px; box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.55); }
.community-detail-close {
  top: 16px; right: 16px; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--testo); font-size: 1.1rem;
}
.community-detail-close:hover { background: var(--border); }
.community-detail-close .ico { margin: 0; }
.community-upload-pole input, .community-upload-pole select, .cmty-dodaj-slowo input { border-width: 1.5px; border-radius: 14px; }
/* #cmtyAutoBtn, nie .btn-auto-nazwa: ta klasa stoi też w „Ćwicz słowa z paczki”, przy Excelu i w przeglądzie zdjęcia. */
.cmty-zmien-plik, #cmtyAutoBtn, .cmty-dodaj-slowo button { border-width: 1.5px; }
.cmty-slowo-usun { width: 32px; height: 32px; }
@media (pointer: coarse) { .cmty-slowo-usun { width: 40px; height: 40px; } }
.akcja-dymek { box-shadow: 0 8px 26px rgba(23, 24, 59, 0.28); }
/* ===== KONIEC STYLU KANWY ===== */

/* ===== KONSOLA ADMINA: UKŁAD Z PANELEM BOCZNYM (2026-09-29) =====
   Dwanaście zakładek w jednym pasku przewijanym w bok zastąpił panel boczny z grupami (Przegląd, Ludzie, Treść,
   Komunikacja, Pieniądze, AI i koszty, System). Styl kanwy: granatowy pasek tytułu (stały w obu motywach, jak ekrany
   marki), Outfit 800 w nagłówkach, pigułki w nawigacji, wybrana zakładka w akcencie (--oro: granat, w ciemnym żółty),
   karty z obwódką 1,5 px. Tabele i liczby zostają gęste: to dalej narzędzie pracy. Na telefonie (do 860 px) panel
   wysuwa się przyciskiem menu z lewej, a zasłona pod nim zamyka go dotknięciem. Sekcja stoi na końcu arkusza, więc
   wygrywa z dawnymi regułami .admin-* przy równej swoistości. */
/* Konsola miała być „całą stroną bez marginesów” (komentarz przy .admin-shell), ale nakładka .wordmap-overlay ma
   20 px wypełnienia, a powłoka 100vw: na komputerze flex ją ścieśniał (ramka po bokach), a na telefonie treść nie
   pozwalała jej zejść poniżej szerokości ekranu i konsola wystawała 20 px w prawo (zmierzone na zrzucie 390 px). */
#adminOverlay.wordmap-overlay { padding: 0; }
.admin-shell { width: 100%; min-width: 0; height: 100vh; height: 100dvh; font-family: var(--font-tekst); position: relative; }
.admin-topbar { background: #17183B; gap: 10px 14px; }
.admin-topbar h2 { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; letter-spacing: 0; color: #FFFFFF; }
.admin-menu-btn {
  display: none; align-items: center; justify-content: center; width: 38px; height: 38px; flex-shrink: 0;
  border: 1.5px solid rgba(255,255,255,0.22); border-radius: 999px; background: rgba(255,255,255,0.08);
  color: #FFFFFF; cursor: pointer; font-size: 1rem;
}
.admin-szukaj {
  display: inline-flex; align-items: center; gap: 8px; min-width: 230px;
  border: 1.5px solid rgba(255,255,255,0.22); border-radius: 999px; background: rgba(255,255,255,0.08);
  color: #F3F5FB; padding: 6px 8px 6px 14px; font-family: var(--font-tekst); font-size: 0.8rem; font-weight: 600; cursor: pointer;
}
.admin-szukaj span { flex: 1; text-align: left; }
.admin-szukaj:hover, .admin-menu-btn:hover { background: rgba(255,255,255,0.16); }
.admin-szukaj kbd, .admin-paleta kbd {
  font-family: var(--font-tekst); font-size: 0.66rem; font-weight: 800; padding: 2px 8px; border-radius: 999px;
  background: rgba(255,255,255,0.16); color: inherit; white-space: nowrap;
}
.admin-szukaj:focus-visible, .admin-menu-btn:focus-visible, .admin-topbar .wordmap-close:focus-visible { outline: 2px solid #FFC83D; outline-offset: 2px; }

.admin-uklad { flex: 1; min-height: 0; display: flex; position: relative; }
.admin-nav {
  width: 240px; flex-shrink: 0; overflow-y: auto; padding: 16px 10px 28px;
  background: var(--bianco); border-right: 1.5px solid var(--border);
  display: flex; flex-direction: column; gap: 14px;
}
.admin-nav-grupa { display: flex; flex-direction: column; gap: 2px; }
.admin-nav-naglowek {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 0.66rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--grigio); padding: 0 12px 4px;
}
.admin-tab {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 38px;
  border: none; background: transparent; padding: 7px 12px; border-radius: 999px;
  font-family: var(--font-tekst); font-size: 0.86rem; font-weight: 700; color: var(--testo);
  cursor: pointer; text-align: left; transition: background 0.15s ease, color 0.15s ease;
}
.admin-tab .ico { width: 18px; text-align: center; color: var(--grigio); flex-shrink: 0; }
.admin-tab:hover { background: var(--bg-soft); }
.admin-tab.active { background: var(--oro); color: var(--na-akcencie); }
.admin-tab.active .ico { color: var(--na-akcencie); }
.admin-tab:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }
.admin-tab-nazwa { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-tab-licznik {
  min-width: 22px; padding: 1px 7px; border-radius: 999px; text-align: center;
  font-size: 0.7rem; font-weight: 800; font-variant-numeric: tabular-nums;
  background: var(--marka-czerwony); color: #FFFFFF;
}
.admin-tab-licznik:empty { display: none; }
.admin-tab-licznik.cichy { background: var(--bg-soft); color: var(--grigio); }
.admin-nav-zaslona { display: none; }

.admin-body { flex: 1; min-width: 0; overflow-y: auto; padding: 20px 24px 40px; }
.admin-glowa { margin: 0 0 16px; }
.admin-glowa-grupa {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 0.68rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--grigio);
}
.admin-glowa h2 { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.55rem; line-height: 1.15; margin: 2px 0 4px; color: var(--testo); }
.admin-glowa p { margin: 0; max-width: 72ch; font-size: 0.88rem; line-height: 1.5; color: var(--grigio); }
.admin-card { border: 1.5px solid var(--border); border-radius: 16px; }
.admin-card h3 { font-family: var(--font-naglowek); letter-spacing: 0.05em; }
/* Karta, do której właśnie przeniosła pozycja skrzynki albo wyszukiwarka: żółta obwódka na chwilę, żeby oko wiedziało,
   gdzie wylądowało. Przy ograniczonym ruchu zostaje sama obwódka (to wskaźnik, nie ozdoba). */
.admin-card.admin-karta-blysk { box-shadow: 0 0 0 3px var(--zolty); transition: box-shadow 0.3s ease; }

/* Skrzynka „Do zrobienia” i wiersze tablicy Społeczności (te same pozycje, inne działanie) */
.adz-lista { display: flex; flex-direction: column; gap: 8px; }
.adz-poz {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 10px 14px;
  border: 1.5px solid var(--border); border-left: 5px solid var(--border); border-radius: 14px;
  background: var(--bianco); color: var(--testo); font-family: var(--font-tekst); cursor: pointer;
}
button.adz-poz:hover { box-shadow: var(--shadow-hover); }
button.adz-poz:focus-visible { outline: 2px solid var(--fokus); outline-offset: 2px; }
.adz-poz.pilne { border-left-color: var(--marka-czerwony); }
.adz-poz.uwaga { border-left-color: var(--zolty); }
.adz-poz.info  { border-left-color: var(--marka-niebieski); }
.adz-poz.statyczna { cursor: default; }
.adz-ile {
  min-width: 46px; text-align: center; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.35rem;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.adz-ile .ico { font-size: 1.15rem; }
.adz-poz.pilne .adz-ile { color: var(--marka-czerwony); }
.adz-tekst { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.adz-tytul { font-weight: 800; font-size: 0.9rem; }
.adz-opis { font-size: 0.78rem; line-height: 1.45; color: var(--grigio); overflow-wrap: anywhere; }
.adz-idz { font-size: 0.76rem; font-weight: 800; color: var(--grigio); white-space: nowrap; }
.adz-pusto { padding: 14px 16px; border-radius: 14px; background: var(--bg-success-soft); color: var(--verde); font-weight: 700; }
.adz-spokoj { margin-top: 10px; font-size: 0.76rem; color: var(--grigio); }
.adz-spokoj:empty { display: none; }

/* Wyszukiwarka poleceń (Ctrl+K) */
.admin-paleta {
  position: absolute; inset: 0; z-index: 40; display: flex; align-items: flex-start; justify-content: center;
  padding: 10vh 16px 16px; background: rgba(14, 15, 38, 0.55);
}
.admin-paleta.hidden { display: none; }
.admin-paleta-okno {
  width: min(640px, 100%); max-height: 76vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--bianco); border: 1.5px solid var(--border); border-radius: 20px;
  box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.5);
}
.admin-paleta-pole { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1.5px solid var(--border); color: var(--grigio); }
.admin-paleta-pole input {
  flex: 1; min-width: 0; border: none; background: transparent; outline: none;
  font-family: var(--font-tekst); font-size: 1rem; font-weight: 600; color: var(--testo);
}
.admin-paleta-pole kbd { background: var(--bg-soft); color: var(--grigio); }
.admin-paleta-lista { overflow-y: auto; padding: 6px; }
.admin-paleta-poz {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; border: none; border-radius: 12px;
  background: transparent; color: var(--testo); text-align: left; cursor: pointer;
  font-family: var(--font-tekst); font-size: 0.9rem; font-weight: 600;
}
.admin-paleta-poz .ico { width: 18px; text-align: center; color: var(--grigio); flex-shrink: 0; }
.admin-paleta-poz .app-nazwa { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-paleta-poz .app-gdzie { margin-left: auto; padding-left: 10px; font-size: 0.74rem; font-weight: 600; color: var(--grigio); white-space: nowrap; }
.admin-paleta-poz.wybrany { background: var(--oro); color: var(--na-akcencie); }
.admin-paleta-poz.wybrany .ico, .admin-paleta-poz.wybrany .app-gdzie { color: var(--na-akcencie); }
.admin-paleta-pusto { padding: 16px; font-size: 0.86rem; color: var(--grigio); }
.admin-paleta-stopka { padding: 8px 16px; border-top: 1.5px solid var(--border); font-size: 0.72rem; color: var(--grigio); }

@media (max-width: 860px) {
  .admin-menu-btn { display: inline-flex; }
  .admin-topbar { padding: 10px 16px; }
  .admin-topbar h2 { font-size: 0.95rem; }
  .admin-topbar .admin-env { display: none; }
  .admin-szukaj { min-width: 0; padding: 8px 12px; }
  .admin-szukaj span, .admin-szukaj kbd { display: none; }
  .admin-topbar .wordmap-close { order: 5; }
  .admin-daterange { order: 10; width: 100%; }
  .admin-nav {
    position: absolute; top: 0; bottom: 0; left: 0; z-index: 20; width: min(280px, 84vw);
    transform: translateX(-105%); transition: transform 0.22s ease; box-shadow: 0 20px 50px -10px rgba(0, 0, 0, 0.45);
  }
  .admin-shell.nav-otwarta .admin-nav { transform: none; }
  .admin-shell.nav-otwarta .admin-nav-zaslona { display: block; position: absolute; inset: 0; z-index: 19; background: rgba(14, 15, 38, 0.45); }
  .admin-body { padding: 14px 16px 32px; }
  .admin-glowa h2 { font-size: 1.3rem; }
  .adz-idz { display: none; }
  .adz-poz { padding: 10px 12px; gap: 10px; }
  .admin-paleta { padding-top: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .admin-nav, .admin-tab, .admin-card.admin-karta-blysk { transition: none; }
}

/* ---------- KONSOLA: CZYTELNOŚĆ LICZB I MOTYWY (2026-10-11) ----------
   Alek: „ma być czytelnie, przejrzyście i rzetelnie”. Zmierzone przed zmianą: podpowiedzi .admin-hint nie miały żadnego
   stylu (zwykły akapit z marginesem 16 px), podsumowania i etykiety stały z kolorem łupkowym #475569 w atrybutach, który
   w ciemnym motywie ginął na granacie (kontrast ok. 2:1), kod rabatowy był wypisany granatem #0F172A na granatowym tle,
   siatka wykresów świeciła jasnym #E2E8F0, a zielona liczba „zysk” #15803D na granacie miała kontrast ok. 3:1. Teraz
   wszystko z tokenów motywu. Reguły pod .admin-shell: ta sama klasa .admin-hint stoi też w panelu moderatora. */
.admin-shell .admin-hint { font-size: 0.8rem; line-height: 1.5; color: var(--grigio); margin: 0 0 10px; }
.admin-card h3 .admin-hint {
  margin: 0 0 0 6px; font-family: var(--font-tekst); font-size: 0.74rem; font-weight: 600;
  text-transform: none; letter-spacing: 0; color: var(--grigio);
}
.admin-card h3 .admin-hint:empty { display: none; }
.admin-podsumowanie { font-size: 0.78rem; font-weight: 800; color: var(--muted-dark); font-variant-numeric: tabular-nums; }
.admin-etykieta { font-size: 0.78rem; font-weight: 800; color: var(--muted-dark); }
.admin-etykieta-pole { display: inline-flex; align-items: center; gap: 8px; }
.admin-blad-linia { font-size: 0.78rem; font-weight: 700; color: var(--rosso); }
.admin-blad-linia:empty { display: none; }
.admin-daterange-strzalka { color: #94A3B8; margin: 0; }
/* Stan danych pod opisem zakładki: okres liczb, godzina pobrania, „Odśwież”. */
.admin-glowa-stan {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin-top: 10px;
  font-size: 0.78rem; color: var(--grigio); font-variant-numeric: tabular-nums;
}
#adminGlowaOkres { font-weight: 800; color: var(--muted-dark); }
#adminGlowaOkres:empty, #adminGlowaKiedy:empty { display: none; }
.admin-glowa-stan .admin-btn[hidden] { display: none; }
/* Kafle liczb: grupy „W okresie” i „Stan na teraz” na Pulpicie, akcent z barw marki w obu motywach. */
.kpi-sekcje { margin-bottom: 14px; }
.kpi-sekcje .kpi-grid { margin-bottom: 10px; }
.kpi-naglowek {
  font-family: var(--font-naglowek); font-weight: 800; font-size: 0.7rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--grigio); margin: 4px 0 6px;
}
.kpi-naglowek span { font-family: var(--font-tekst); font-weight: 600; letter-spacing: 0; text-transform: none; margin-left: 6px; }
.admin-shell .kpi { border: 1.5px solid var(--border); border-left: 4px solid var(--marka-niebieski); border-radius: 12px; }
.admin-shell .kpi.zysk { border-left-color: var(--marka-zielony); }
.admin-shell .kpi.zysk .kpi-value { color: var(--verde); }
.admin-shell .kpi.uwaga { border-left-color: var(--zolty); }
.admin-shell .kpi.zle { border-left-color: var(--marka-czerwony); }
.admin-shell .kpi .kpi-sub { color: var(--grigio); line-height: 1.4; }
#adminAudioPakiet { display: contents; }
/* Wykresy: siatka i podpisy osi w kolorach motywu. */
.admin-shell .wykres-siatka { stroke: var(--border); }
.admin-shell .wykres-os { fill: var(--grigio); }
.admin-shell .chart-legend { color: var(--muted-dark); }
/* Rozbicia (waluta, metoda, plan, źródło). */
.rozbicie { margin-bottom: 14px; }
.rozbicie-tytul { font-size: 0.7rem; font-weight: 800; color: var(--grigio); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; }
.admin-shell .bar-row { grid-template-columns: minmax(92px, max-content) 1fr 54px; }
.admin-shell .bar-nazwa { font-weight: 700; }
.admin-shell .bar-fill { background: var(--marka-niebieski); }
/* Tabele: daty bez łamania, podpis pod nazwą, kod rabatowy w kolorze tekstu, dopisek o uciętej liście. */
.admin-shell .dt td.mono { white-space: nowrap; }
.admin-shell .dt .dt-podpis { font-size: 0.72rem; color: var(--grigio); white-space: normal; }
.admin-shell .dt .dt-kod { color: var(--testo); font-size: 0.82rem; }
.admin-shell .dt-wiecej { margin: 8px 0 0; }
.admin-shell .dt th { color: var(--muted-dark); }
@media (max-width: 860px) {
  .admin-glowa-stan { margin-top: 8px; }
  .admin-shell .kpi .kpi-value { font-size: 1.3rem; }
}

/* ---------- 16. MINI QUIZY: UKŁAD Z KANWY (2026-10-03) ----------
   Kanwa „Mini quizy Lingaria” (Alek: „Ten design wygląda świetnie. DODAJMY TO WIĘC FUNKCJONALNIE NA APLIKACJĘ NA TELEFON
   i na DESKTOP”; pierwotnie: „im mniej zbędnego tekstu tym lepiej, plus może wtedy brak obramowania jak karta …
   osobowość, u nas jest bezosobowo”). Jedno polecenie, postać z dymkiem zamiast karty, kafle z dolną krawędzią, werdykt
   w arkuszu od dołu. Sekcja stoi NA KOŃCU arkusza i wygrywa kolejnością z „10. QUIZ”; reguły w zasięgu #miniExamArea
   i #miniExamQuestion, bo .game-tile, .pf-czas, .bez-audio-btn i .context-word dzielą inne tryby („Gra w pary”,
   Czytanie). Na komputerze kolumna 640 px; układ wierszowy arkusza zależy od SZEROKOŚCI KOLUMNY (zapytanie kontenera),
   nie okna: przy oknie 769–943 px kolumna ma 425–600 px, a przy szynie rankingu 556 px.
   WYJĄTEK OD „wybór = --oro”: wybór w mini quizie jest NIEBIESKI jak na kanwie (P8, decyzja Alka 2026-10-03); wskazanie
   klawiaturą (.klaw-wybor) zostaje w --oro, to dwa różne znaki. */
#miniExamArea {
  max-width: 640px; margin-inline: auto; min-height: 620px;
  display: flex; flex-direction: column; gap: 22px;
  container: quiz / inline-size;
}
#miniExamArea.hidden { display: none !important; }
/* Telefon: obszar quizu sięga dołu okna (pod nagłówkiem strony), żeby arkusz z „Sprawdź” stał na dole ekranu jak na kanwie. */
@media (max-width: 768px) { #miniExamArea { min-height: calc(100dvh - 140px); } }
#miniExamArea .quiz-topbar { gap: 12px; margin: 0; min-height: 44px; }
#miniExamArea .quiz-close, #miniExamArea .quiz-report-btn {
  width: 44px; height: 44px; min-width: 44px; min-height: 44px; padding: 0; flex: none;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 999px;
  color: var(--tekst-neutralny); opacity: 1; filter: none; font-size: 18px;
}
#miniExamArea .quiz-close:hover, #miniExamArea .quiz-report-btn:hover { color: var(--testo); background: var(--bg-soft); }
#miniExamArea .quiz-close svg { display: block; }
#miniExamArea .quiz-report-btn .ico { margin: 0; font-size: 18px; line-height: 1; }
#miniExamArea .quiz-progress-track { height: 14px; background: var(--border); border-radius: 999px; }
#miniExamArea .quiz-progress-fill {
  background: var(--marka-niebieski); box-shadow: inset 0 4px 0 rgba(255, 255, 255, 0.28);
  transition: width 0.25s ease, background-color 0.2s ease;
}
#miniExamArea .quiz-progress-fill.dobrze { background: var(--marka-zielony); }
/* Pigułka combo z kanwy: żółta, granatowa błyskawica i sam mnożnik. Barwy marki stałe w obu motywach; progi x2/x3/x5
   barwią tło zamków i baner, nie pigułkę (gradienty fiolet i złoto progu były spoza palety). */
#miniExamArea .combo-licznik,
#miniExamArea .combo-licznik.combo-t1, #miniExamArea .combo-licznik.combo-t2, #miniExamArea .combo-licznik.combo-t3 {
  gap: 4px; padding: 6px 10px; border: none; box-shadow: none; flex: none;
  background: var(--zolty); color: var(--granat);
  font-family: var(--font-naglowek); font-weight: 800; font-size: 15px; line-height: 1;
}
#miniExamArea .combo-licznik .combo-mnoznik { padding: 0; background: none; font-size: inherit; font-weight: inherit; }
#miniExamArea .combo-licznik .combo-ile-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
#miniExamArea .combo-licznik.combo-t3 .combo-znak { animation: none; }
/* Wiersz znacznika: „CEL DNIA · 2/5”, „PREMIUM”, powtórka celu. Pusty (zwykły Mini test) znika razem z odstępem. */
.quiz-znacznik-wiersz { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.quiz-znacznik-wiersz:not(:has(> :not(.hidden):not(:empty))) { display: none; }
#miniExamArea .quiz-badge:empty { display: none; }
#miniExamArea .quiz-badge, #miniExamArea .quiz-cel-chip, #miniExamArea .quiz-premium-chip {
  display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 0; border: none; background: none;
  font-family: var(--font-tekst); font-size: 12px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--grigio); line-height: 1.3;
}
#miniExamArea .quiz-badge::before {
  content: ''; flex: none; width: 20px; height: 20px; border-radius: 999px;
  background: var(--zolty) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317183B' stroke-width='3'%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
}
#miniExamArea .quiz-cel-chip .ico, #miniExamArea .quiz-premium-chip .ico {
  flex: none; width: 20px; height: 20px; border-radius: 999px; margin: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--zolty); color: var(--granat); font-size: 11px;
}
#miniExamArea .quiz-premium-chip.zajawka { cursor: pointer; min-height: 32px; text-decoration: underline; text-underline-offset: 3px; }
@media (pointer: coarse) { #miniExamArea .quiz-premium-chip.zajawka { min-height: 44px; } }
/* Polecenie: Outfit 800, flaga 24×17 tuż za zdaniem. Przy intruzie, kartkówce i odmianie przez osoby postać stoi obok. */
.quiz-polecenie { display: flex; align-items: center; gap: 12px; }
.quiz-polecenie.pusty { display: none; }
.quiz-polecenie-tekst { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.quiz-polecenie-linia { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
#miniExamArea .quiz-heading {
  margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 28px; line-height: 1.15;
  letter-spacing: -0.01em; color: var(--testo); overflow-wrap: anywhere;
}
#miniExamArea .quiz-heading:empty { display: none; }
#miniExamArea .quiz-heading.jako-znacznik {
  font-family: var(--font-tekst); font-size: 12px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--grigio); line-height: 1.3;
}
.quiz-polecenie-flaga { display: inline-flex; flex: none; width: 24px; height: 17px; border-radius: 4px; overflow: hidden; line-height: 0; }
.quiz-polecenie-flaga svg { width: 24px; height: 17px; display: block; object-fit: cover; }
.quiz-pod-polecenie:empty { display: none; }
.quiz-postac-obok { flex: none; width: var(--postac-obok, 84px); height: var(--postac-obok, 84px); object-fit: contain; }
@container quiz (min-width: 600px) {
  #miniExamArea .quiz-heading:not(.jako-znacznik) { font-size: 30px; }
  .quiz-postac-obok { width: calc(var(--postac-obok, 84px) + 12px); height: calc(var(--postac-obok, 84px) + 12px); }
}
@media (max-width: 768px) and (max-height: 700px) {
  #miniExamArea .quiz-heading:not(.jako-znacznik) { font-size: 24px; }
  #miniExamArea { gap: 14px; }
}

/* Krok: kolumna od sceny do arkusza, który stoi na dole obszaru quizu (margin-top: auto) i klei się do dołu okna. */
#miniExamQuestion { flex: 1; display: flex; flex-direction: column; min-height: 0; }
#miniExamQuestion > .mini-exam-card { flex: 1; display: flex; flex-direction: column; gap: 22px; }
#miniExamQuestion > .mini-exam-card.quiz-krok { text-align: left; }
@media (max-width: 768px) and (max-height: 700px) { #miniExamQuestion > .mini-exam-card { gap: 14px; } }

/* SCENA: postać i dymek. „obok”: postać po lewej, dymek z ogonkiem w lewo, uniesiony o 0,42 wysokości postaci.
   „nad”: dymek na całą szerokość z ogonkiem w dół, pod nim postać albo kadr baristki. */
.quiz-scena { display: flex; align-items: flex-end; gap: 4px; min-width: 0; }
.quiz-scena .quiz-postac { flex: none; width: var(--postac-tel, 136px); height: var(--postac-tel, 136px); object-fit: contain; }
.quiz-scena.obok .quiz-dymek { margin-bottom: calc(var(--postac-tel, 136px) * 0.42); }
.quiz-scena.nad { flex-direction: column-reverse; align-items: stretch; gap: 0; }
.quiz-scena.nad .quiz-postac { align-self: flex-start; margin: 2px 0 0 24px; width: calc(var(--postac-tel, 136px) * 0.9); height: calc(var(--postac-tel, 136px) * 0.9); }
.quiz-dymek {
  position: relative; min-width: 0; display: flex; align-items: center; gap: 12px;
  padding: 16px 20px; background: var(--card-bg); color: var(--testo);
  border: 2px solid var(--border); border-radius: 22px;
}
.quiz-dymek::before {
  content: ''; position: absolute; width: 16px; height: 16px; background: var(--card-bg);
  border: 0 solid var(--border); transform: rotate(45deg);
}
.quiz-scena.obok .quiz-dymek::before { left: -10px; bottom: 18px; border-left-width: 2px; border-bottom-width: 2px; }
.quiz-scena.nad .quiz-dymek::before { left: 70px; bottom: -10px; border-right-width: 2px; border-bottom-width: 2px; }
.quiz-dymek:has(.quiz-glosnik) { padding: 12px 18px 12px 12px; }
.quiz-dymek-slowo { display: block; font-family: var(--font-naglowek); font-weight: 700; font-size: 30px; line-height: 1.1; overflow-wrap: normal; min-width: 0; }
.quiz-dymek-slowo.lamany { overflow-wrap: anywhere; }
.quiz-dymek-slowo.sredni { font-size: 25px; }
.quiz-dymek-slowo.maly { font-size: 21px; line-height: 1.2; }
/* Flaga języka słowa za słowem (quizDymekSlowoHtml, od 2026-10-11 przy „Co to znaczy po polsku?”): słowo kurczy się
   i mierzy jak dotąd (min-width: 0), flaga stoi stale obok, nigdy nie spada do nowej linijki. */
.quiz-dymek-slowo-flaga { display: flex; align-items: center; gap: 10px; min-width: 0; }
.quiz-dymek-flaga { flex-shrink: 0; display: inline-flex; line-height: 0; border-radius: 4px; box-shadow: 0 0 0 1px var(--border); }
.quiz-dymek-kolumna { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.quiz-dymek-zdanie { font-family: var(--font-naglowek); font-weight: 700; font-size: 24px; line-height: 1.35; overflow-wrap: anywhere; }
.quiz-dymek .glos-tlum-nad { margin: 0; max-width: none; min-height: 0; text-align: left; font-family: var(--font-tekst); font-size: 15px; font-weight: 600; color: var(--grigio); }
.quiz-dymek .glos-tlum-nad:empty { display: none; }
.quiz-dymek-emotka { font-size: 28px; line-height: 1; }
/* Emotka nad słowem (quizDymekSlowoHtml): obok słowa i głośnika zjadała 40 px z ~128 na słowo przy 390 px. */
.quiz-dymek-z-emotka { gap: 2px; }
.quiz-dymek-z-emotka .quiz-dymek-emotka { font-size: 22px; }
/* Kadr baristki: okno 170×190 nad całym mowienie.webp 340×340 przesuniętym o -14 / -120 (kanwa „Powtórz na głos”). */
.quiz-postac-kadr { display: block; flex: none; align-self: flex-start; width: 170px; height: 190px; margin-left: 24px; overflow: hidden; }
.quiz-scena .quiz-postac-kadr .quiz-postac { display: block; width: 340px; height: 340px; max-width: none; margin: -120px 0 0 -14px; }
/* Głośnik w dymku: niebieskie koło z białą ikoną (4,9 : 1), duży z dolną krawędzią w pytaniu ze słuchu. Pierścień „czytam”
   zapala klasa speaking na schowanych słupkach (speakText). */
.quiz-glosnik {
  position: relative; flex: none; width: 44px; height: 44px; padding: 0; border: none; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; background: var(--marka-niebieski); color: #FFFFFF;
}
.quiz-glosnik.duzy { width: 64px; height: 64px; margin-bottom: 5px; box-shadow: 0 5px 0 var(--niebieski-ciemny, #204EB8); }
.quiz-glosnik.duzy:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--niebieski-ciemny, #204EB8); }
.quiz-glosnik svg { display: block; }
.quiz-glosnik:focus-visible { outline: 3px solid var(--fokus); outline-offset: 3px; }
.quiz-glosnik-fala { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }
.quiz-glosnik:has(.speaking)::after {
  content: ''; position: absolute; inset: -6px; border-radius: 999px; border: 3px solid var(--marka-niebieski);
  animation: quizGlosnikPuls 1s ease-in-out infinite;
}
@keyframes quizGlosnikPuls { 0%, 100% { opacity: 0.2; transform: scale(0.96); } 50% { opacity: 0.6; transform: scale(1.04); } }
/* Tempo lektora: koło 48 obok głośnika, a nie piksel w rogu kafelka. */
#miniExamQuestion .quiz-tempo {
  position: static; flex: none; width: 48px; height: 48px; padding: 0; border-radius: 999px; cursor: pointer; line-height: 1;
  border: 2px solid var(--border); background: var(--crema); color: var(--testo); box-shadow: none;
  font-family: var(--font-naglowek); font-weight: 800; font-size: 13px; letter-spacing: 0;
}
#miniExamQuestion .quiz-tempo.wolno { border-color: var(--oro); color: var(--testo); }
#miniExamQuestion .quiz-tempo:hover { border-color: var(--border-2); }
/* Linki „Nie wiem”, „Nie mogę teraz …”, „Wróć do pisania”: Figtree 700 15, pole 44, bez podkreślenia (kanwa). */
#miniExamQuestion .quiz-link {
  min-height: 44px; padding: 0 8px; margin: 0; border: none; background: none; cursor: pointer;
  font-family: var(--font-tekst); font-weight: 700; font-size: 15px; color: var(--grigio); text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
#miniExamQuestion .quiz-link:hover { color: var(--testo); text-decoration: underline; text-underline-offset: 3px; }
#miniExamQuestion > .mini-exam-card > .quiz-link, #miniExamQuestion .mini-exam-input-row > .quiz-link,
#miniExamQuestion .quiz-wybor > .quiz-link { align-self: center; }
/* Pole odpowiedzi 64 px, Outfit 700 24, niebieska ramka z pierścieniem przy fokusie (kanwa „Napisz”). Stany werdyktu
   i „sprawdza” powtarzają tu reguły sekcji „QUIZ”, bo ten selektor (z #id) jest od nich mocniejszy. */
#miniExamQuestion .mini-exam-input-row { max-width: none; margin: 0; gap: 10px; align-items: stretch; }
#miniExamQuestion .mini-exam-input-row input:not(.glos-pole) {
  height: 64px; box-sizing: border-box; padding: 0 20px; border: 2px solid var(--border); border-radius: 18px;
  background: var(--card-bg); color: var(--testo); text-align: left;
  font-family: var(--font-naglowek); font-weight: 700; font-size: 24px;
}
#miniExamQuestion .mini-exam-input-row input:not(.glos-pole):focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 4px var(--fokus-pierscien); }
#miniExamQuestion .mini-exam-input-row input.sprawdza:not(.glos-pole) { border-color: color-mix(in srgb, var(--oro) 45%, var(--border)); box-shadow: none; }
#miniExamQuestion .mini-exam-input-row input.correct:not(.glos-pole) { border-color: var(--marka-zielony); background: var(--bg-success-soft); box-shadow: none; }
#miniExamQuestion .mini-exam-input-row input.wrong:not(.glos-pole) { border-color: var(--rosso); background: var(--bg-error-soft); box-shadow: none; }

/* ODPOWIEDŹ GŁOSEM (kanwa „Powiedz po włosku”, „W trakcie mówienia”): dymek ucznia po prawej naprzeciw dymka postaci,
   pod nim trzy kreski w barwach logo, mikrofon 96 na dole kroku. Dymek to wciąż #miniExamInput (glosPokaz pisze value):
   pusty = przerywany kontur z trzema kropkami (placeholder jest spacją, więc :placeholder-shown), pełny = niebieski
   dymek Outfit 700 26. Mikrofon to element marki jak scena Mówienia: zieleń logo w OBU motywach (K23), ikona GRANATOWA
   (biel na #35A64D ma 3,1 : 1), dolna krawędź 6, pierścień 14% w spoczynku, 22% + 10% w nasłuchu (dawniej czerwone koło
   80 px z szarą ramką). Rant czasu (--glos-maks) zostaje, w zieleni tekstu (--verde: ciemna w jasnym motywie, jasna
   w ciemnym), żeby było go widać na zielonym pierścieniu w obu motywach. */
#miniExamQuestion .mini-exam-input-row.glos { flex: 1; display: flex; flex-direction: column; gap: 18px; }
#miniExamQuestion .glos-odczyt {
  align-self: flex-end; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; max-width: 88%; min-width: 0;
}
#miniExamQuestion .mini-exam-input-row .glos-pole,
#miniExamQuestion .mini-exam-input-row .glos-pole.correct,
#miniExamQuestion .mini-exam-input-row .glos-pole.wrong {
  box-sizing: border-box; width: auto; max-width: 100%; min-width: 112px; min-height: 64px; margin: 0; padding: 14px 22px;
  field-sizing: content; border: 2px solid var(--marka-niebieski); border-radius: 22px 22px 6px 22px;
  background: var(--bg-info-soft); color: var(--testo); -webkit-text-fill-color: currentColor; opacity: 1;
  font-family: var(--font-naglowek); font-weight: 700; font-size: 26px; line-height: 1.25; text-align: start;
  box-shadow: none; outline: none; cursor: default; pointer-events: none; resize: none; overflow: hidden;
}
#miniExamQuestion .mini-exam-input-row textarea.glos-pole { font-size: 22px; line-height: 1.35; }
/* „Przeczytaj / Powtórz na głos”: dymek ucznia staje OBOK kadru baristki (ona po lewej, uczeń po prawej, jak w rozmowie),
   a nie pod nim. Pod kadrem było 100 px pustego miejsca po prawej, a mikrofon wypadał przez to pod zgięcie telefonu. Szerokość
   = kolumna minus kadr z marginesem; dłuższy odczyt łamie się w dół, nie wchodzi na postać. Tylko gdy wiersz odpowiedzi
   stoi TUŻ pod sceną: w „Powtórz na głos” między nimi jest „Nie mogę teraz słuchać” i dymek wchodził na ten link. */
#miniExamQuestion .quiz-scena.nad:has(.quiz-postac-kadr) + .mini-exam-input-row.glos .glos-odczyt { margin-top: -112px; max-width: calc(100% - 206px); }
@container quiz (min-width: 600px) {
  #miniExamQuestion .quiz-scena.nad:has(.quiz-postac-kadr) + .mini-exam-input-row.glos .glos-odczyt { margin-top: -132px; max-width: calc(100% - 240px); }
}
#miniExamQuestion .mini-exam-input-row .glos-pole::placeholder { color: transparent; }
#miniExamQuestion .mini-exam-input-row .glos-pole.niepewne { color: var(--grigio); font-weight: 600; }
#miniExamQuestion .mini-exam-input-row .glos-pole.sprawdza { color: var(--grigio); }
#miniExamQuestion .mini-exam-input-row .glos-pole.correct { border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--verde); }
#miniExamQuestion .mini-exam-input-row .glos-pole.wrong { border-color: var(--rosso); background: var(--bg-error-soft); color: var(--czerwien-tekst); }
#miniExamQuestion .mini-exam-input-row .glos-pole:placeholder-shown {
  width: 112px; height: 64px; padding: 0; border: 2px dashed var(--krawedz-kafla);
  background:
    radial-gradient(circle, var(--krawedz-kafla) 3.5px, transparent 4.5px) calc(50% - 14px) 50% / 8px 8px no-repeat,
    radial-gradient(circle, var(--krawedz-kafla) 3.5px, transparent 4.5px) 50% 50% / 8px 8px no-repeat,
    radial-gradient(circle, var(--krawedz-kafla) 3.5px, transparent 4.5px) calc(50% + 14px) 50% / 8px 8px no-repeat;
}
/* Trzy kreski: zieleń, czerwień, niebieski logo; w spoczynku niewidoczne, ale miejsce zostaje (dymek nie skacze). Wysokość
   z pętli głośności (setWaveBars: 6–28 px) przycina się do 14–26, jak na kanwie. */
#miniExamQuestion .glos-fala { margin: 0; padding-right: 8px; visibility: hidden; }
#miniExamQuestion .glos-fala.slucha { visibility: visible; }
#miniExamQuestion .glos-fala .audio-wave { gap: 6px; height: 32px; }
#miniExamQuestion .glos-fala .audio-wave span {
  width: 9px; min-height: 8px; max-height: 32px; border-radius: 6px; opacity: 1; animation: none; transition: height 0.05s linear;
}
/* MIKROFON ŻYJE OD PIERWSZEJ CHWILI (2026-10-04, Alek: „dobrze zbiera i działa, ale nie widać, czy mikrofon już działa,
   tak jakby się zamrażał”). Silnik przeglądarki dostaje strumień do pomiaru głośności dopiero po pierwszym odczycie
   (drugi strumień potrafił wywrócić Web Speech, patrz glosStartPrzegladarka), więc do pierwszego słowa kreski stały
   w spoczynkowych 18/26/14 px. Dopóki pętla nie da klasy `zywa`, kreski oddychają na zmianę; potem rysuje je głośność. */
#miniExamQuestion .glos-fala.slucha:not(.zywa) .audio-wave span { animation: glosOddech 1.1s ease-in-out infinite; transform-origin: center; }
#miniExamQuestion .glos-fala.slucha:not(.zywa) .audio-wave span:nth-child(2) { animation-delay: 0.18s; }
#miniExamQuestion .glos-fala.slucha:not(.zywa) .audio-wave span:nth-child(3) { animation-delay: 0.36s; }
@keyframes glosOddech { 0%, 100% { transform: scaleY(0.55); } 50% { transform: scaleY(1); } }
#miniExamQuestion .glos-fala .audio-wave span:nth-child(1) { height: 18px; background: var(--marka-zielony); }
#miniExamQuestion .glos-fala .audio-wave span:nth-child(2) { height: 26px; background: var(--marka-czerwony); }
#miniExamQuestion .glos-fala .audio-wave span:nth-child(3) { height: 14px; background: var(--marka-niebieski); }
#miniExamQuestion .glos-scena { margin-top: auto; padding-top: 22px; gap: 22px; }
#miniExamQuestion .quiz-mik {
  width: 96px; height: 96px; flex: none; border: none; background: var(--marka-zielony); color: var(--granat);
  box-shadow: 0 0 0 10px color-mix(in srgb, var(--marka-zielony) 14%, transparent), 0 6px 0 var(--zielen-gleboka);
  transition: box-shadow 0.18s ease, transform 0.08s ease, filter 0.18s ease;
}
#miniExamQuestion .quiz-mik .ico { font-size: 38px; }
#miniExamQuestion .quiz-mik:hover:not(:disabled) { background: var(--marka-zielony); filter: brightness(1.05); }
#miniExamQuestion .quiz-mik:active:not(:disabled) {
  transform: translateY(4px); box-shadow: 0 0 0 10px color-mix(in srgb, var(--marka-zielony) 14%, transparent), 0 2px 0 var(--zielen-gleboka);
}
/* W nasłuchu pierścienie rosną z głośnością (`--poziom` 0-1 z pętli glosFalaStart), więc czułość widać też na przycisku;
   bez poziomu (przed pierwszym słowem) pierścień pulsuje sam. */
#miniExamQuestion .quiz-mik.slucha, #miniExamQuestion .quiz-mik.slucha:hover:not(:disabled) {
  --poziom: 0;
  background: var(--marka-zielony); color: var(--granat);
  box-shadow: 0 0 0 calc(10px + var(--poziom) * 10px) color-mix(in srgb, var(--marka-zielony) 24%, transparent),
              0 0 0 calc(22px + var(--poziom) * 18px) color-mix(in srgb, var(--marka-zielony) 11%, transparent), 0 6px 0 var(--zielen-gleboka);
  transition: box-shadow 0.08s linear, transform 0.08s ease, filter 0.18s ease;
}
#miniExamQuestion .quiz-mik.slucha:not(.zywa) { animation: glosPierscien 1.4s ease-in-out infinite; }
@keyframes glosPierscien { 0%, 100% { --poziom: 0; } 50% { --poziom: 0.55; } }
@property --poziom { syntax: '<number>'; inherits: true; initial-value: 0; }
@media (prefers-reduced-motion: reduce) {
  #miniExamQuestion .glos-fala.slucha:not(.zywa) .audio-wave span { animation: glosOddechCichy 1.6s ease-in-out infinite; transform: none; }
  #miniExamQuestion .quiz-mik.slucha:not(.zywa) { animation: none; --poziom: 0.4; }
  @keyframes glosOddechCichy { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }
}
#miniExamQuestion .quiz-mik:focus-visible { outline: 3px solid var(--fokus); outline-offset: 14px; }
/* Linijka stanu w miejscu linków („Słucham…”, „Rozpoznaję…”), linki w jednym wierszu, gdy linijka jest pusta. */
#miniExamQuestion .glos-stan {
  min-height: 44px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-tekst); font-weight: 700; font-size: 15px; color: var(--verde);
}
#miniExamQuestion .glos-stan:empty { display: none; }
#miniExamQuestion .glos-stan:not(:empty) + .glos-linki { display: none; }
#miniExamQuestion .glos-linki { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 28px; }
/* Telefon w przeglądarce ma nad quizem nagłówek strony (~120 px): przy „Przeczytaj na głos” (kadr baristki 190) mikrofon
   wypadał pod zgięcie na 390×844. Krok głosowy dostaje więc ciaśniejsze odstępy i kadr 136×152 (ten z niskiego telefonu). */
@media (max-width: 768px) {
  #miniExamQuestion > .mini-exam-card:has(.mini-exam-input-row.glos) { gap: 18px; }
  #miniExamQuestion .glos-scena { padding-top: 8px; gap: 16px; }
  #miniExamQuestion .mini-exam-card:has(.mini-exam-input-row.glos) .quiz-postac-kadr { width: 136px; height: 152px; }
  #miniExamQuestion .mini-exam-card:has(.mini-exam-input-row.glos) .quiz-postac-kadr .quiz-postac { width: 272px; height: 272px; margin: -96px 0 0 -11px; }
  #miniExamQuestion .quiz-scena.nad:has(.quiz-postac-kadr) + .mini-exam-input-row.glos .glos-odczyt { margin-top: -104px; max-width: calc(100% - 172px); }
}

/* ARKUSZ WERDYKTU: przed odpowiedzią przezroczysty pasek akcji, po odpowiedzi (data-stan) tło stanu, postać wystająca
   40 px nad krawędź, tytuł Outfit 800 28, linijka Figtree 17, pigułka XP i „Dalej”. z-index 1: panel 5/10 i rekord
   (.polmetek, 40) wchodzą NAD arkusz 650 ms po odpowiedzi, a toasty zostają nad nim. */
#miniExamQuestion .quiz-arkusz {
  margin-top: auto; position: sticky; bottom: 16px; z-index: 1;
  display: flex; flex-direction: column; gap: 16px; border-radius: 24px;
}
#miniExamQuestion .quiz-arkusz[data-stan] {
  padding: 20px 24px; background: var(--bg-soft); box-shadow: var(--shadow-hover);
  animation: quizArkuszWjazd 0.28s cubic-bezier(.2, .8, .2, 1);
}
#miniExamQuestion .quiz-arkusz[data-stan="dobrze"] { background: var(--bg-success-soft); }
#miniExamQuestion .quiz-arkusz[data-stan="zle"] { background: var(--bg-error-soft); }
/* Krok bez przycisków przed odpowiedzią (głos: „Nie wiem” stoi pod mikrofonem, prawda/fałsz) i bez komunikatu: arkusz
   znika, a nie zostaje pustym paskiem tła strony na dole telefonu. Druga szansa głosu i werdykt pokazują go z powrotem. */
#miniExamQuestion .quiz-arkusz:not([data-stan]):not(:has(.quiz-akcje > *)):not(:has(.mini-exam-feedback:not(:empty))) { display: none; }
@keyframes quizArkuszWjazd { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.quiz-arkusz-gora { display: flex; align-items: center; gap: 14px; min-width: 0; }
.quiz-arkusz:not([data-stan]) .quiz-arkusz-gora:not(:has(.mini-exam-feedback:not(:empty))) { display: none; }
.quiz-arkusz-postac { flex: none; width: 92px; height: 92px; object-fit: contain; margin: -40px 0 -8px -6px; }
.quiz-arkusz-postac[hidden], .quiz-arkusz-xp[hidden] { display: none; }
.quiz-arkusz-glowa { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.quiz-arkusz-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 28px; line-height: 1.2; color: var(--testo); }
.quiz-arkusz-tytul:empty { display: none; }
.quiz-arkusz[data-stan="dobrze"] .quiz-arkusz-tytul { color: var(--verde); }
.quiz-arkusz[data-stan="zle"] .quiz-arkusz-tytul { color: var(--czerwien-tekst); }
#miniExamQuestion .quiz-arkusz .mini-exam-feedback {
  margin: 0; min-height: 0; text-align: left; font-family: var(--font-tekst); font-size: 17px; font-weight: 600; line-height: 1.5;
}
#miniExamQuestion .quiz-arkusz .mini-exam-feedback:empty { display: none; }
#miniExamQuestion .quiz-arkusz[data-stan] .mini-exam-feedback { color: var(--testo); }
#miniExamQuestion .quiz-arkusz .mini-exam-feedback b, #miniExamQuestion .quiz-arkusz .mini-exam-feedback strong { font-weight: 800; }
#miniExamQuestion .quiz-arkusz .quiz-stan { justify-content: flex-start; }
/* Linijka stanu w arkuszu rośnie z tekstem. Wysokość 1,6em z overflow: hidden pochodzi z wąskiej linijki pod polem
   odpowiedzi (jedna linijka, stała, żeby „Dalej” nie skakało), a w arkuszu kolumna obok postaci ma przy 390 px ~250 px:
   „Dobrze! Twoja odpowiedź też się liczy.” łamało się w dwie linijki i obie wychodziły ucięte z góry i z dołu (zrzut Alka
   2026-10-04). Pusta linijka „źle” (.quiz-stan-znika) dalej zwija się do zera. */
#miniExamQuestion .quiz-arkusz .quiz-stan:not(.quiz-stan-znika) {
  height: auto; min-height: 1.6em; overflow: visible; line-height: 1.3; text-wrap: pretty;
}
#miniExamQuestion .quiz-arkusz .quiz-dodatkowo { text-align: left; font-size: 14px; }
.quiz-arkusz-xp {
  align-self: flex-start; padding: 4px 10px; border-radius: 999px; background: var(--zolty); color: var(--granat);
  font-family: var(--font-naglowek); font-weight: 800; font-size: 14px; line-height: 1.3;
}
/* Pasek akcji: link „Nie wiem” po lewej, główny przycisk = pigułka z kółkiem 46 (kanwa), szary, gdy wyłączony. */
#miniExamQuestion .quiz-akcje { display: flex; align-items: center; gap: 12px; }
#miniExamQuestion .quiz-akcje .quiz-nie-wiem { flex: none; }
#miniExamQuestion .quiz-akcje .btn {
  display: inline-flex; align-items: center; flex: 1; width: auto; max-width: none; min-height: 64px; margin: 0; padding: 0 10px 0 28px; border-radius: 999px;
  font-family: var(--font-naglowek); font-weight: 800; font-size: 19px; text-transform: none; letter-spacing: 0;
  box-shadow: none; transform: none;
}
#miniExamQuestion .quiz-akcje .btn:not(.btn-strzalka) { justify-content: center; padding: 0 24px; }
#miniExamQuestion .quiz-akcje .btn.btn-strzalka::after { width: 46px; height: 46px; }
#miniExamQuestion .quiz-akcje .btn-dalej, #miniExamQuestion .quiz-akcje .quiz-dalej { background: var(--oro); color: var(--na-akcencie); }
#miniExamQuestion .quiz-akcje .btn:hover:not(:disabled) { transform: none; box-shadow: var(--shadow-hover); }
#miniExamQuestion .quiz-akcje .btn:active:not(:disabled) { transform: translateY(2px); box-shadow: none; }
#miniExamQuestion .quiz-sprawdz:disabled:not(.btn-dalej) {
  background: var(--border); color: var(--tekst-neutralny); opacity: 1; cursor: not-allowed;
  --kolko-tlo: var(--krawedz-kafla); --kolko-strzalka: var(--strzalka-szara);
}
@container quiz (min-width: 600px) {
  .quiz-scena .quiz-postac { width: 168px; height: 168px; }
  .quiz-scena.obok .quiz-dymek { margin-bottom: 70px; max-width: 440px; }
  .quiz-scena.nad .quiz-dymek { max-width: 560px; }
  .quiz-scena.nad .quiz-postac { width: 150px; height: 150px; }
  .quiz-dymek-slowo { font-size: 34px; }
  .quiz-dymek-slowo.sredni { font-size: 28px; }
  .quiz-dymek-slowo.maly { font-size: 23px; }
  .quiz-postac-kadr { width: 200px; height: 224px; }
  .quiz-scena .quiz-postac-kadr .quiz-postac { width: 400px; height: 400px; margin: -142px 0 0 -16px; }
  #miniExamQuestion .quiz-akcje .btn { flex: 0 0 auto; min-width: 240px; margin-left: auto; }
  /* Odpowiedzi w bloku 560 px na środku kolumny 640 (pasek akcji i arkusz zostają na całą kolumnę), lista kafli 64. */
  #miniExamQuestion .quiz-kafle, #miniExamQuestion .mini-exam-input-row:not(.glos), #miniExamQuestion .pf-przyciski { width: 100%; max-width: 560px; margin-inline: auto; }
  #miniExamQuestion .quiz-slowa-lista:not(.siatka):not(.dwie) .quiz-kafel { min-height: 64px; }
  #miniExamQuestion .quiz-arkusz[data-stan] { flex-direction: row; align-items: center; gap: 20px; }
  #miniExamQuestion .quiz-arkusz[data-stan] .quiz-arkusz-gora { flex: 1; }
  #miniExamQuestion .quiz-arkusz[data-stan] .quiz-akcje { flex: none; width: auto; min-width: 240px; }
  #miniExamQuestion .quiz-arkusz[data-stan] .quiz-akcje .btn { white-space: nowrap; }
  #miniExamQuestion .quiz-arkusz[data-stan] .quiz-akcje .btn { min-width: 0; width: 100%; margin: 0; }
  .quiz-arkusz-postac { width: 96px; height: 96px; margin: -44px 0 -8px -6px; }
}
/* KAFLE WYBORU (kanwa): ramka 2 + dolna krawędź 4 w --krawedz-kafla, promień 18. Wybrany NIEBIESKI (P8), po werdykcie:
   wybrany dobry zielony z ptaszkiem, zły czerwony przekreślony z X, dobry niewybrany przerywany zielony, reszta wygaszona.
   Ptaszek i X to maska SVG w barwie tokenu, więc działają w obu motywach. */
#miniExamQuestion .quiz-kafle { display: flex; flex-direction: column; gap: 12px; margin: 0; }
#miniExamQuestion .quiz-kafle.dwie, #miniExamQuestion .quiz-kafle.siatka,
#miniExamQuestion .intruz-siatka.quiz-kafle, #miniExamQuestion .odm-opcje.quiz-kafle { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
#miniExamQuestion .rodz-opcje.quiz-kafle { display: grid; grid-template-columns: repeat(var(--kolumn, 4), minmax(0, 1fr)); gap: 10px; }
#miniExamQuestion .quiz-kafel {
  position: relative; display: flex; align-items: center; gap: 10px; min-width: 0; min-height: 58px; margin: 0; padding: 10px 20px;
  border: 2px solid var(--krawedz-kafla); border-bottom-width: 4px; border-radius: 18px; background: var(--card-bg); color: var(--testo);
  font-family: var(--font-tekst); font-weight: 600; font-size: 19px; line-height: 1.25; text-align: left;
  cursor: pointer; opacity: 1; box-shadow: none; transform: none; outline-offset: 3px;
  transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.08s ease;
}
#miniExamQuestion .quiz-kafel-tekst { min-width: 0; overflow-wrap: anywhere; }
#miniExamQuestion .quiz-kafle.nauka .quiz-kafel { font-family: var(--font-naglowek); font-weight: 700; }
#miniExamQuestion .quiz-kafle.siatka .quiz-kafel, #miniExamQuestion .rodz-opcje .quiz-kafel,
#miniExamQuestion .intruz-siatka .quiz-kafel, #miniExamQuestion .odm-opcje .quiz-kafel { justify-content: center; text-align: center; }
#miniExamQuestion .quiz-kafle.siatka .quiz-kafel { min-height: 76px; }
#miniExamQuestion .rodz-opcje .quiz-kafel { min-height: 76px; padding: 8px; font-size: 26px; font-weight: 800; color: var(--testo); }
#miniExamQuestion .intruz-siatka .quiz-kafel { min-height: 120px; border-bottom-width: 5px; border-radius: 22px; font-size: 22px; }
#miniExamQuestion .odm-opcje .quiz-kafel { min-height: 64px; font-size: 21px; }
#miniExamQuestion .quiz-kafel:hover { border-color: var(--border-2); transform: none; }
#miniExamQuestion .quiz-kafel:active { border-bottom-width: 2px; transform: translateY(2px); }
/* Pogrubienie wyboru cieniem tekstu, nie wagą kroju: zmiana wagi poszerzała napis i dłuższa fraza przy zaznaczeniu
   potrafiła przeskoczyć na drugą linijkę (recenzja 2026-10-03). Kanwa ma wybrany kafel pogrubiony. */
#miniExamQuestion .quiz-kafel.wybrana { border-color: var(--primary); background: var(--bg-warn-soft); text-shadow: 0.4px 0 0 currentColor, -0.4px 0 0 currentColor; }
#miniExamQuestion .quiz-kafle.zablokowane .quiz-kafel { cursor: default; transform: none; }
#miniExamQuestion .quiz-kafle.zablokowane .quiz-kafel:not(.poprawna):not(.bledna) {
  border-color: var(--border); border-bottom-width: 2px; background: transparent; color: var(--tekst-neutralny);
}
#miniExamQuestion .quiz-kafel.poprawna { border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--testo); font-weight: 700; }
#miniExamQuestion .quiz-kafle.zablokowane .quiz-kafel.poprawna:not(.wybrana) { border-style: dashed; border-bottom-width: 2px; background: transparent; }
#miniExamQuestion .quiz-kafel.bledna { border-color: var(--rosso); background: var(--bg-error-soft); color: var(--testo); opacity: 1; font-weight: 700; }
#miniExamQuestion .quiz-kafel.bledna .quiz-kafel-tekst { text-decoration: line-through; text-decoration-thickness: 2px; }
#miniExamQuestion .quiz-kafel.poprawna::after, #miniExamQuestion .quiz-kafel.bledna::after {
  content: ''; flex: none; width: 24px; height: 24px; margin-left: auto;
  -webkit-mask: var(--kafel-znak) center / contain no-repeat; mask: var(--kafel-znak) center / contain no-repeat;
}
#miniExamQuestion .quiz-kafel.poprawna::after {
  background: var(--verde);
  --kafel-znak: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
#miniExamQuestion .quiz-kafel.bledna::after {
  background: var(--czerwien-tekst);
  --kafel-znak: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E");
}
#miniExamQuestion .quiz-kafle.siatka .quiz-kafel::after, #miniExamQuestion .rodz-opcje .quiz-kafel::after,
#miniExamQuestion .intruz-siatka .quiz-kafel::after, #miniExamQuestion .odm-opcje .quiz-kafel::after { position: absolute; right: 10px; top: 10px; width: 20px; height: 20px; }
#miniExamQuestion .quiz-kafel .kl { display: none; }
@media (hover: hover) and (pointer: fine) {
  #miniExamQuestion .quiz-kafel .kl {
    display: inline-flex; flex: none; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 6px;
    background: var(--bg-soft); color: var(--grigio); font-family: var(--font-tekst); font-size: 12px; font-weight: 700; line-height: 1;
  }
  #miniExamQuestion .quiz-kafle.siatka .quiz-kafel .kl, #miniExamQuestion .rodz-opcje .quiz-kafel .kl,
  #miniExamQuestion .intruz-siatka .quiz-kafel .kl, #miniExamQuestion .odm-opcje .quiz-kafel .kl { position: absolute; left: 8px; top: 8px; }
  /* Wyśrodkowany tekst nie wchodzi pod cyfrę w rogu ani pod ptaszek werdyktu (recenzja 2026-10-03: „łaj spokój” pod
     cyfrą 4 w siatce słuchania, „la” pod cyfrą 1 w rodzajniku przy wąskim oknie z myszą). Rodzajnik ma 8 px paddingu
     i krótki napis, więc dostaje mniejszą cyfrę tuż w rogu. */
  #miniExamQuestion .quiz-kafle.siatka .quiz-kafel, #miniExamQuestion .intruz-siatka .quiz-kafel,
  #miniExamQuestion .odm-opcje .quiz-kafel { padding-inline: 34px; }
  #miniExamQuestion .rodz-opcje .quiz-kafel .kl { left: 5px; top: 5px; width: 18px; height: 18px; font-size: 11px; border-radius: 5px; }
  #miniExamQuestion .quiz-kafle.zablokowane .quiz-kafel .kl { visibility: hidden; }
}
/* Luki w dymku: rodzajnik i forma czasownika. Pusta = przerywana ramka, zaznaczona = niebieski chip (podgląd wyboru). */
#miniExamQuestion .rodz-haslo { margin: 0; text-align: left; font-size: 30px; font-weight: 700; color: var(--testo); }
#miniExamQuestion .rodz-zdanie { margin: 0; max-width: none; text-align: left; }
#miniExamQuestion .rodz-tlum, #miniExamQuestion .odm-bezok { margin: 0; text-align: left; font-family: var(--font-tekst); font-size: 15px; font-weight: 600; color: var(--grigio); }
#miniExamQuestion .rodz-luka, #miniExamQuestion .odm-luka {
  display: inline-flex; align-items: center; justify-content: center; min-height: 38px; margin: 0 8px 0 0; padding: 0 8px; vertical-align: middle;
  border: 2px dashed var(--krawedz-kafla); border-radius: 10px; color: var(--testo); font-weight: 700; line-height: 1.2;
}
#miniExamQuestion .rodz-zdanie .rodz-luka, #miniExamQuestion .odm-luka { margin: 0 4px; min-width: 64px; }
#miniExamQuestion .rodz-luka.podglad, #miniExamQuestion .odm-luka.podglad { border-style: solid; border-color: var(--primary); background: var(--bg-warn-soft); }
#miniExamQuestion .rodz-luka.odslonieta, #miniExamQuestion .odm-luka.dobra { border-style: solid; border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--testo); }
#miniExamQuestion .odm-luka.zla { border-style: solid; border-color: var(--rosso); background: var(--bg-error-soft); color: var(--testo); }
#miniExamQuestion .odm-bezok { align-self: flex-start; padding: 3px 10px; border-radius: 999px; background: var(--crema); font-size: 14px; font-weight: 700; }
#miniExamQuestion .odm-karta { margin: 0; padding: 0; border: none; border-radius: 0; text-align: left; font-family: var(--font-naglowek); font-size: 23px; font-weight: 700; line-height: 1.5; }
#miniExamQuestion .odm-tlum-nad { margin: 0; padding: 0; border: none; border-radius: 0; background: none; text-align: left; font-family: var(--font-tekst); font-size: 15px; font-weight: 600; color: var(--grigio); }

/* PRAWDA CZY FAŁSZ (kanwa): para w dymku, pasek czasu 6 px w żółci marki pod sceną, dwa duże kafle 128 z kołem 48:
   „Prawda” zielone z granatowym ptaszkiem (biały na zieleni logo ma 3,1 : 1), „Fałsz” czerwone z białym X. */
#miniExamQuestion .pf-slowo { margin: 0; font-size: 28px; font-weight: 700; color: var(--testo); }
#miniExamQuestion .pf-tlum { margin: 0; font-family: var(--font-tekst); font-size: 18px; font-weight: 700; color: var(--testo); }
#miniExamQuestion .pf-czas { height: 6px; margin: 0; background: var(--border); }
#miniExamQuestion .pf-czas-fill { background: var(--zolty); }
#miniExamQuestion .pf-przyciski { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
#miniExamQuestion .pf-btn {
  position: relative; height: 128px; margin: 0; padding: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  border: 2px solid var(--krawedz-kafla); border-bottom-width: 5px; border-radius: 22px; background: var(--card-bg); color: var(--testo);
  font-family: var(--font-naglowek); font-weight: 800; font-size: 20px; cursor: pointer; transform: none; box-shadow: none;
}
#miniExamQuestion .pf-btn:active { border-bottom-width: 2px; transform: translateY(2px); }
#miniExamQuestion .pf-kolo { width: 48px; height: 48px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }
#miniExamQuestion .pf-btn.tak .pf-kolo { background: var(--marka-zielony); color: var(--granat); }
#miniExamQuestion .pf-btn.nie .pf-kolo { background: var(--marka-czerwony); color: #FFFFFF; }
#miniExamQuestion .pf-przyciski.zamrozone .pf-btn { opacity: 0.55; }
#miniExamQuestion .pf-przyciski.zablokowane .pf-btn { opacity: 1; cursor: default; transform: none; border-bottom-width: 2px; color: var(--tekst-neutralny); }
#miniExamQuestion .pf-przyciski.zablokowane .pf-btn .pf-kolo { opacity: 0.4; }
#miniExamQuestion .pf-przyciski.zablokowane .pf-btn.poprawna { border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--testo); }
#miniExamQuestion .pf-przyciski.zablokowane .pf-btn.bledna { border-color: var(--rosso); background: var(--bg-error-soft); color: var(--testo); }
#miniExamQuestion .pf-przyciski.zablokowane .pf-btn.poprawna .pf-kolo, #miniExamQuestion .pf-przyciski.zablokowane .pf-btn.bledna .pf-kolo { opacity: 1; }
#miniExamQuestion .pf-btn .kl { display: none; }
@media (hover: hover) and (pointer: fine) {
  #miniExamQuestion .pf-btn .kl {
    display: inline-flex; position: absolute; left: 10px; top: 10px; align-items: center; justify-content: center; width: 22px; height: 22px;
    border-radius: 6px; background: var(--bg-soft); color: var(--grigio); font-family: var(--font-tekst); font-size: 12px; font-weight: 700;
  }
}
/* ROZSYPANKA LITEROWA (kanwa „Ułóż słowo”): cyfra odliczania w dymku, sloty z dolną kreską (bieżący niebieski, pusty
   --krawedz-kafla), litery 52×56 z dolną krawędzią, zużyta litera zostaje szarym miejscem tej samej wielkości. Cyfra bez
   dawnego padding 38 px z „10. QUIZ”: dymek z cyfrą miał ~160 px wysokości i po odliczaniu scena skakała (recenzja). */
#miniExamQuestion .anagram-karta { text-align: left; }
#miniExamQuestion .anagram-odliczanie { margin: 0; padding: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 48px; line-height: 1; color: var(--testo); }
#miniExamQuestion .anagram-litery { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 0; }
#miniExamQuestion .anagram-odpowiedz { gap: 6px; min-height: 48px; }
#miniExamQuestion .anagram-slot {
  width: 36px; height: 48px; margin: 0; border: none; border-radius: 0; background: none;
  border-bottom: 3px solid var(--krawedz-kafla);
}
#miniExamQuestion .anagram-slot.biezacy { border-bottom-color: var(--primary); }
#miniExamQuestion .anagram-litera.ulozona {
  width: 36px; height: 48px; min-width: 0; padding: 0; margin: 0; border: none; border-radius: 0; background: none;
  border-bottom: 3px solid var(--testo); font-family: var(--font-naglowek); font-weight: 800; font-size: 26px; color: var(--testo);
}
#miniExamQuestion #anagramPula .anagram-litera {
  width: 52px; height: 56px; min-width: 0; padding: 0; margin: 0; border: 2px solid var(--krawedz-kafla); border-bottom-width: 4px;
  border-radius: 14px; background: var(--card-bg); font-family: var(--font-naglowek); font-weight: 800; font-size: 24px; color: var(--testo); transform: none;
}
#miniExamQuestion #anagramPula .anagram-litera:active { border-bottom-width: 2px; transform: translateY(2px); }
#miniExamQuestion #anagramPula .anagram-litera.zuzyta { visibility: visible; border-color: var(--border); background: var(--border); color: transparent; pointer-events: none; }
#miniExamQuestion .anagram-przedrostek { align-self: flex-end; margin: 0 4px 6px 0; font-family: var(--font-naglowek); font-size: 22px; color: var(--grigio); }
#miniExamQuestion .anagram-litery.zablokowane .anagram-litera { cursor: default; }
/* Sloty odpowiedzi zawsze w JEDNYM wierszu, jak na kanwie i w aplikacji: przy dłuższym słowie maleją razem z literą
   (--n = liczba liter, --p = miejsce na przedrostek „il”/„la”; stawia je anagramRysujStan). Zmierzone w recenzji 2026-10-03
   przy 390 px: sztywne 36 px + 6 px mieściły w kolumnie 358 px 8 slotów (z „il”/„la” 7), więc 6 z 18 słów z talii
   (cinquecento, frequentare, il coraggio…) zawijało ostatni slot do drugiego wiersza jak zabłąkaną kreskę. */
#miniExamQuestion .anagram-odpowiedz { flex-wrap: nowrap; }
#miniExamQuestion .anagram-odpowiedz .anagram-slot,
#miniExamQuestion .anagram-odpowiedz .anagram-litera.ulozona { flex: 0 1 36px; width: auto; min-width: 16px; }
#miniExamQuestion .anagram-odpowiedz .anagram-litera.ulozona { font-size: min(26px, calc((100cqi - var(--p, 0px) - 6px * (var(--n, 8) - 1)) / var(--n, 8) * 0.8)); }
#miniExamQuestion .anagram-odpowiedz .anagram-przedrostek { flex: none; }
/* UŁÓŻ ZDANIE (kanwa): dwie linie odpowiedzi po 64 px z kreską, klocki z dolną krawędzią, pula wyśrodkowana. */
#miniExamQuestion .sentence-puzzle-prompt { margin: 0; text-align: left; }
#miniExamQuestion .sentence-puzzle-answer {
  min-height: 128px; margin: 0; padding: 10px 0 0; display: flex; flex-wrap: wrap; align-content: flex-start; align-items: center; justify-content: flex-start; gap: 8px 8px;
  border: none; background: linear-gradient(transparent 62px, var(--border) 62px, var(--border) 64px, transparent 64px) 0 0 / 100% 64px;
}
#miniExamQuestion .sentence-puzzle-pool { justify-content: center; gap: 10px; }
#miniExamQuestion .sentence-tile {
  position: relative; min-height: 48px; padding: 10px 16px; display: inline-flex; align-items: center; gap: 6px; border-radius: 14px;
  border: 2px solid var(--krawedz-kafla); border-bottom-width: 4px; background: var(--card-bg); color: var(--testo);
  font-family: var(--font-tekst); font-weight: 600; font-size: 19px; line-height: 1.2;
}
#miniExamQuestion .sentence-tile:hover { border-color: var(--border-2); }
#miniExamQuestion .sentence-tile .kl { display: none; }
@media (hover: hover) and (pointer: fine) {
  #miniExamQuestion .sentence-puzzle-pool .sentence-tile .kl {
    display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 5px;
    background: var(--bg-soft); color: var(--grigio); font-size: 11px; font-weight: 700;
  }
}
#miniExamQuestion .quiz-zdanie-glosy { text-align: left; }
/* DOPASUJ PARY (kanwa „Połącz pary”): bez postaci; lewa kolumna w języku nauki (Outfit), prawa w języku interfejsu,
   kafle 64 z dolną krawędzią, wybrany niebieski (dawniej bursztyn), trafiony wygaszony. Tylko w quizie: .game-tile
   dzieli „Gra w pary”. */
#miniExamQuestion .game-board { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 14px; align-content: center; flex: 1; }
#miniExamQuestion .game-col { display: flex; flex-direction: column; gap: 12px; }
#miniExamQuestion .game-tile {
  min-height: 64px; padding: 8px 12px; display: flex; align-items: center; justify-content: center; text-align: center;
  border: 2px solid var(--krawedz-kafla); border-bottom-width: 4px; border-radius: 18px; background: var(--card-bg); color: var(--testo);
  font-family: var(--font-tekst); font-weight: 600; font-size: 19px; line-height: 1.2; box-shadow: none; transform: none; overflow-wrap: anywhere;
}
#miniExamQuestion .game-col:first-child .game-tile { font-family: var(--font-naglowek); font-weight: 700; }
#miniExamQuestion .game-tile.selected { border-color: var(--primary); background: var(--bg-warn-soft); }
#miniExamQuestion .game-tile.matched { border-color: var(--border); border-bottom-width: 2px; background: transparent; color: var(--tekst-neutralny); opacity: 1; pointer-events: none; }
#miniExamQuestion .game-tile.wrong { border-color: var(--rosso); background: var(--bg-error-soft); }
/* KARTKÓWKA (kanwa): bez kratki zeszytu i numerów; wiersz „słowo | pole”, pole 50 px z niebieskim fokusem. */
#miniExamQuestion .kartkowka-kartka { margin: 0; padding: 0; max-width: none; border: none; border-radius: 0; background: none; display: flex; flex-direction: column; gap: 8px; }
#miniExamQuestion .kartkowka-wiersz { grid-template-columns: 112px minmax(0, 1fr); align-items: center; gap: 12px; min-height: 0; }
#miniExamQuestion .kartkowka-nr { display: none; }
#miniExamQuestion .kartkowka-obce { font-family: var(--font-tekst); font-weight: 700; font-size: 17px; }
#miniExamQuestion .kartkowka-pole { grid-column: auto; gap: 2px; }
#miniExamQuestion .kartkowka-input {
  height: 50px; box-sizing: border-box; padding: 0 14px; border: 2px solid var(--border); border-radius: 14px; background: var(--card-bg);
  font-family: var(--font-naglowek); font-weight: 700; font-size: max(16px, 19px); color: var(--testo); text-decoration: none;
}
#miniExamQuestion .kartkowka-input:focus { outline: none; border-color: var(--primary); border-style: solid; box-shadow: 0 0 0 4px var(--fokus-pierscien); }
#miniExamQuestion .kartkowka-wiersz.sprawdza .kartkowka-input { border-color: color-mix(in srgb, var(--oro) 45%, var(--border)); border-style: solid; }
#miniExamQuestion .kartkowka-wiersz.dobrze .kartkowka-input { border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--testo); }
#miniExamQuestion .kartkowka-wiersz.zle .kartkowka-input { border-color: var(--rosso); background: var(--bg-error-soft); color: var(--testo); text-decoration: line-through; }
#miniExamQuestion .kartkowka-poprawna { font-family: var(--font-tekst); font-size: 14px; }

/* Niski telefon (375×667, 360×640): mniejsza postać, żeby pole i „Sprawdź” stały nad zgięciem. */
@media (max-width: 768px) and (max-height: 700px) {
  .quiz-scena .quiz-postac { width: calc(var(--postac-tel, 136px) * 0.72); height: calc(var(--postac-tel, 136px) * 0.72); }
  .quiz-scena.obok .quiz-dymek { margin-bottom: calc(var(--postac-tel, 136px) * 0.3); }
  .quiz-postac-kadr { width: 136px; height: 152px; }
  .quiz-scena .quiz-postac-kadr .quiz-postac { width: 272px; height: 272px; margin: -96px 0 0 -11px; }
  .quiz-dymek-slowo { font-size: 26px; }
}
/* Telefon w przeglądarce: arkusz klei się do dołu okna i sięga krawędzi (zaokrąglone tylko górne rogi), pasek akcji
   przed odpowiedzią ma tło strony, żeby przewijana treść nie prześwitywała spod „Sprawdź”. Pigułka „Darmowe Premium”
   (.probne-licznik, fixed, lewy dolny róg) staje nad arkuszem: --quiz-dol ustawia quizArkuszUstaw. */
@media (max-width: 768px) {
  #miniExamQuestion .quiz-arkusz { bottom: 0; }
  #miniExamQuestion .quiz-arkusz:not([data-stan]) { background: var(--crema); padding: 10px 0 calc(10px + env(safe-area-inset-bottom)); border-radius: 0; }
  #miniExamQuestion .quiz-arkusz[data-stan] {
    margin-inline: -20px; border-radius: 28px 28px 0 0; padding: 22px 20px calc(18px + env(safe-area-inset-bottom));
    box-shadow: 0 -10px 30px -18px rgba(23, 24, 59, 0.45);
  }
  body.w-quizie .probne-licznik { bottom: calc(var(--quiz-dol, 150px) + 12px); }
}
@media (prefers-reduced-motion: reduce) {
  #miniExamArea .quiz-progress-fill { transition: none; }
  #miniExamQuestion .quiz-arkusz[data-stan] { animation: none; }
  .quiz-glosnik:has(.speaking)::after { animation: none; opacity: 0.5; }
  #miniExamQuestion .quiz-akcje .btn:active:not(:disabled), .quiz-glosnik.duzy:active { transform: none; }
  #miniExamQuestion .quiz-kafel:active, #miniExamQuestion .pf-btn:active, #miniExamQuestion .quiz-mik:active:not(:disabled) { transform: none; }
  #miniExamQuestion .anagram-odliczanie { animation: none; }
  #miniExamQuestion .quiz-mik { transition: none; }
}

/* ---------- 17. MÓWIENIE I CZYTANIE: ŚRODEK W UKŁADZIE MINI QUIZÓW (2026-10-04) ----------
   Kanwy „Mówienie Lingaria” i „Czytanie Lingaria” (Alek: „Jeśli chodzi o desktop podoba mi się tylko ten środkowy kontener
   w każdym przykładzie (boki lewy i prawy zostaw taki jak jest obecnie)”, potem o Czytaniu: „podoba mi się ten układ na
   telefonie i w desktopie, pozwalam zmieniać”). Zmienia się WYŁĄCZNIE środek: scena rozmowy (mapa rozmów, panel „Rozmowy”
   i panele boczne zostają) i kartka czytanki. Sam CSS na istniejących klasach, bez zmian w JS: kolejność klocków sceny
   ustawia `order`, a .mow-srodek i .mow-linia mają `display: contents`, więc kwestia rozmówcy staje NAD odpowiedziami
   (dymek z baristką, jak w quizie ze słuchu), a linijka stanu zostaje pod mikrofonem i nie zasłania już kwestii (do dziś
   dzieliły jedno miejsce i „Słucham…” chowało zdanie rozmówcy). Odpowiedzi to kafle quizu (siatka: tekst i tłumaczenie
   w pierwszej kolumnie, „+N”, gwiazdka i » w kolejnych), mikrofon zielony 96 z dolną krawędzią jak w quizie głosowym. */
#widokMowienia .mow-scena:not(.wybor) {
  max-width: 680px; width: 100%; margin-inline: auto; box-sizing: border-box;
  justify-content: flex-start; align-items: stretch; text-align: start;
  padding: 22px 28px 28px; min-height: 660px;
  background: var(--card-bg); border: 2px solid var(--border); border-radius: 28px;
}
#widokMowienia .mow-scena:not(.wybor) .mow-srodek,
#widokMowienia .mow-scena:not(.wybor) .mow-linia { display: contents; }
#widokMowienia .mow-scena:not(.wybor) .mow-zaczep { order: 1; }
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie { order: 2; }
#widokMowienia .mow-scena:not(.wybor) .mow-cwiczenie-slot { order: 3; }
#widokMowienia .mow-scena:not(.wybor) .mow-gora { order: 4; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymki { order: 5; }
#widokMowienia .mow-scena:not(.wybor) .mow-mik-obszar { order: 6; }
#widokMowienia .mow-scena:not(.wybor) .mow-swobodna-pasek { order: 7; }
#widokMowienia .mow-scena:not(.wybor) .mow-status { order: 8; }
#widokMowienia .mow-scena:not(.wybor) .mow-status-cichy { order: 9; }
#widokMowienia .mow-scena:not(.wybor) .mow-karta { order: 10; }
#widokMowienia .mow-scena:not(.wybor) .mow-akcje { order: 11; }
#widokMowienia .mow-scena:not(.wybor) .mow-sugestie { order: 12; }
/* Znacznik: „TYTUŁ” wersalikami i pigułki poziomów zostają w nagłówku sceny, tylko w kroju znacznika quizu. */
/* Nagłówek sceny w PRZEPŁYWIE (2026-10-04, zrzut Alka: na poziomie 3 licznik i pigułki poziomów schodziły do drugiego wiersza
   i wchodziły na „TWOJA KOLEJ”, a we wprowadzeniu na granatową kartę): już nie absolute, tylko pierwszy klocek sceny,
   z miejscem po prawej na „Zacznij od nowa”. Zawinięty w dwa wiersze spycha resztę w dół, zamiast na nią wjeżdżać. */
#widokMowienia .mow-scena:not(.wybor) .mow-naglowek { position: static; order: 0; margin: 0 0 20px; margin-inline-end: 170px; }
#widokMowienia .mow-scena:not(.wybor) .mow-od-nowa { top: 20px; right: auto; inset-inline-end: 20px; }
#widokMowienia .mow-naglowek-tytul { font-size: 12.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--grigio); }
/* Polecenie = tytuł strony (Outfit 800), jak polecenie mini quizu. */
#widokMowienia .mow-scena:not(.wybor) .mow-zaczep { max-width: none; width: 100%; margin: 0 0 16px; text-align: start; }
#widokMowienia .mow-scena:not(.wybor) .mow-instrukcja {
  font-family: var(--font-naglowek); font-weight: 800; font-size: clamp(1.5rem, 2.4vw, 1.85rem); line-height: 1.15; color: var(--testo);
}
#widokMowienia .mow-scena:not(.wybor) .mow-swobodna-kryteria { justify-content: flex-start; }
/* Kwestia rozmówcy: dymek z ogonkiem przy postaci rozmówcy.
   POSTAĆ ROZMÓWCY (2026-10-08, Alek o baristce wyciętej z ilustracji Mówienia: „Poprawić postać uciętą i dodatkowo rozróżnić
   postać według płci”): jedna z ośmiu CAŁYCH postaci (assets/img/mowienie/postacie, płótno 2:3, stopy na wspólnej linii),
   pokazana w całości (contain), bez okna, które by ją przycinało. Którą, mówi serwer (mowienie_scen_postac: płeć z głosu
   lektora, stała dla rozmowy) w polu `postac`; mowUstawPostac kładzie ją na scenie jako data-postac, a plik wskazuje jedna
   z ośmiu reguł niżej (dwa identyfikatory w selektorze: wygrywają z regułą tła ::before bez względu na kolejność). Plik wprost
   w regule, nie w zmiennej CSS: arkusz wychodzi plikiem z assets/app/ z adresami przepisanymi na ../../ (zasoby_lib), a url()
   w zmiennej przeglądarki rozwiązują względem różnych adresów. Bez pola (nieznana wartość) postaci nie ma, zamiast losować płeć
   niezgodną z głosem. Do tego dnia stał tu kadr KADR_BARISTKI × 0,66 z mowienie.webp (ucięta ręka z kubkiem i fartuch).
   Postać 104 × 156 stoi stopami przy dolnej krawędzi dymka (głowa wyżej niż dawny kadr, więc dymek ma większy margines nad sobą). */
#widokMowienia #mowScena[data-postac="k1"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/k1.webp"); }
#widokMowienia #mowScena[data-postac="k2"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/k2.webp"); }
#widokMowienia #mowScena[data-postac="k3"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/k3.webp"); }
#widokMowienia #mowScena[data-postac="k4"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/k4.webp"); }
#widokMowienia #mowScena[data-postac="m1"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/m1.webp"); }
#widokMowienia #mowScena[data-postac="m2"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/m2.webp"); }
#widokMowienia #mowScena[data-postac="m3"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/m3.webp"); }
#widokMowienia #mowScena[data-postac="m4"] .mow-pytanie::before { background-image: url("../../assets/img/mowienie/postacie/m4.webp"); }
#widokMowienia .mow-scena:not(.wybor) .mow-linia .mow-pytanie,
#widokMowienia .mow-scena:not(.wybor) .mow-linia.z-statusem .mow-pytanie { opacity: 1; transform: none; visibility: visible; pointer-events: auto; }
#widokMowienia .mow-scena:not(.wybor) .mow-linia.pusto .mow-pytanie { display: none; }
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis)) {
  position: relative; align-items: stretch; align-self: stretch; min-height: 64px; box-sizing: border-box;
  margin: 60px 0 32px 124px; padding: 14px 16px 10px; text-align: start;
  background: var(--card-bg); border: 2px solid var(--border); border-radius: 22px;
  transition: border-color .2s var(--mow-ease), box-shadow .2s var(--mow-ease);
}
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::before {
  content: ''; position: absolute; left: -122px; bottom: -30px; width: 104px; height: 156px; pointer-events: none;
  background: center bottom / contain no-repeat;
}
/* Ciemny motyw: karta sceny ma ten sam granat (#17183B), co kontur postaci, więc kontur, granatowe spodnie i ciemne włosy
   znikały w tle. Cienka jasna obwódka wokół sylwetki oddziela ją od karty. */
:root[data-theme="dark"] #widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::before {
  filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 0.5px rgba(255, 255, 255, 0.85));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) #widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::before {
    filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 0.5px rgba(255, 255, 255, 0.85));
  }
}
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::after {
  content: ''; position: absolute; left: -10px; bottom: 18px; width: 16px; height: 16px; pointer-events: none;
  background: var(--card-bg); border-left: 2px solid var(--border); border-bottom: 2px solid var(--border); transform: rotate(45deg);
  transition: border-color .2s var(--mow-ease);
}
/* Lektor gra: ramka i poświata w błękicie głośnika (kanwa „Mówi rozmówca”). */
#widokMowienia .mow-scena:has(#mowMikObszar.lektor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis)) {
  border-color: var(--marka-niebieski); box-shadow: 0 0 0 4px color-mix(in srgb, var(--marka-niebieski) 18%, transparent);
}
#widokMowienia .mow-scena:has(#mowMikObszar.lektor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::after { border-color: var(--marka-niebieski); }
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie-wiersz { justify-content: flex-start; align-items: flex-start; }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-tekst {
  font-family: var(--font-naglowek); font-weight: 700; font-size: clamp(1.2rem, 2vw, 1.4rem); line-height: 1.3;
}
#widokMowienia .mow-scena:not(.wybor) .mow-bot-narzedzia { justify-content: flex-start; }
/* Wprowadzenie („Bot opis”): granatowa karta z żółtą etykietą (kanwa „Wprowadzenie”), barwy stałe w obu motywach. */
#widokMowienia .mow-scena:not(.wybor) .mow-pytanie:has(.mow-bot-opis) { align-self: stretch; margin: 6px 0 20px; }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis {
  max-width: none; width: 100%; box-sizing: border-box; padding: 18px 20px 14px; border-radius: 26px; border: none;
  background: var(--granat); color: #fff;
}
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .mow-bot-tekst { color: #fff; font-weight: 600; font-size: clamp(1.05rem, 1.8vw, 1.2rem); line-height: 1.45; }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .mow-bot-tlum { color: rgba(255, 255, 255, 0.8); }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .mow-glos { color: rgba(255, 255, 255, 0.75); }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .mow-glos:hover, #widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .mow-glos.wl { color: var(--zolty); }
#widokMowienia .mow-scena:not(.wybor) .mow-opis-etykieta { color: var(--zolty); font-size: 0.75rem; }
/* Ciemny motyw: karta sceny ma ten sam granat, co wprowadzenie, więc wprowadzenie bierze jaśniejszy granat i obwódkę. */
:root[data-theme="dark"] #widokMowienia .mow-scena:not(.wybor) .mow-bot-opis { background: var(--granat-jasny); box-shadow: inset 0 0 0 2px var(--border-2); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) #widokMowienia .mow-scena:not(.wybor) .mow-bot-opis { background: var(--granat-jasny); box-shadow: inset 0 0 0 2px var(--border-2); }
}
/* Znane słówka na granacie: jasne tło zamiast ciemnej zieleni poziomu (na zrzucie zlewało się z kartą). */
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis .znane-slowo { background: rgba(255, 255, 255, 0.16); color: #fff; }
/* WYJAŚNIENIE W JĘZYKU UCZNIA (flaga jezyk_ucznia, 2026-10-06; kanwa „Kreator rozmów Mówienie”, plansza „Kanwa: język wprowadzenia”):
   żółta karta z granatowym napisem i etykietą „Wyjaśnienie” z żarówką, w obu motywach (barwy marki na ekranie Mówienia są stałe).
   Reguły z :root[data-theme] powtórzone, bo ciemny wariant karty wprowadzenia ma wyższą swoistość. */
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui,
:root[data-theme="dark"] #widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui { background: var(--zolty); color: var(--granat); box-shadow: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) #widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui { background: var(--zolty); color: var(--granat); box-shadow: none; }
}
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui .mow-bot-tekst,
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui .mow-opis-etykieta { color: var(--granat); }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui .mow-glos { color: rgba(23, 24, 59, 0.7); }
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui .mow-glos:hover,
#widokMowienia .mow-scena:not(.wybor) .mow-bot-opis.ui .mow-glos.wl { color: var(--granat); }
.mow-opis-etykieta .ico { margin: 0 4px 0 0; }
/* Odczyt na żywo: dymek ucznia po prawej (niebieski), jak w quizie głosowym. */
#widokMowienia .mow-scena:not(.wybor) .mow-gora:not(:empty) {
  align-self: flex-end; max-width: 86%; margin: 0 0 14px; padding: 10px 16px; justify-content: flex-start; text-align: start;
  background: color-mix(in srgb, var(--marka-niebieski) 10%, var(--card-bg)); border: 2px solid var(--marka-niebieski);
  border-radius: 22px 22px 6px 22px; color: var(--testo);
  font-family: var(--font-naglowek); font-weight: 700; font-size: 1.15rem;
  --mow-gora-tlo: color-mix(in srgb, var(--marka-niebieski) 10%, var(--card-bg));
}
/* Sufit wysokości liczy LINIJKI TEKSTU (trzy, przy karcie ćwiczenia jedna), a dymek ma 10 px wypełnienia i 2 px obwódki z każdej strony.
   Przy box-sizing: border-box wspólna reguła .mow-gora (max-height 4.8em, przy karcie 1.6em) odejmowała je od tekstu: pod kartą oceny
   zostawało ok. 5 px na linijkę i „Oggi ho dormito…” wychodziło ucięte od góry (zrzut Alka 2026-10-05). */
#widokMowienia .mow-scena:not(.wybor) .mow-gora:not(:empty) { max-height: calc(4.8em + 24px); }
#widokMowienia .mow-scena:not(.wybor) .mow-srodek.z-cwiczeniem .mow-gora:not(:empty) { max-height: calc(1.6em + 24px); }
/* Taśma przewijania (.przewija) w dymku: maska wygaszała cały dymek razem z obwódką i tłem, więc lewy brzeg znikał w białej mgle.
   W dymku wygasa sam tekst: zasłona w kolorze tła dymku nad jego lewym (przy jednej linijce) albo górnym (przy trzech) brzegiem. */
#widokMowienia .mow-scena:not(.wybor) .mow-gora.przewija:not(:empty) { -webkit-mask-image: none; mask-image: none; position: relative; }
/* Taśma przy karcie ćwiczenia pokazuje NAJNOWSZE słowa (prawy koniec), jak we wspólnej regule .mow-srodek.z-cwiczeniem .mow-gora.przewija; reguła dymka
   wyżej (justify-content: flex-start) wygrywała z nią swoistością i na zrzucie Alka stał początek wypowiedzi z uciętym końcem. */
#widokMowienia .mow-scena:not(.wybor) .mow-srodek.z-cwiczeniem .mow-gora.przewija:not(:empty) { justify-content: flex-end; }
#widokMowienia .mow-scena:not(.wybor) .mow-gora.przewija:not(:empty)::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1.4em; z-index: 1; pointer-events: none;
  border-radius: 20px 20px 0 0; background: linear-gradient(to bottom, var(--mow-gora-tlo), transparent);
}
#widokMowienia .mow-scena:not(.wybor) .mow-srodek.z-cwiczeniem .mow-gora.przewija:not(:empty)::before {
  inset: 0 auto 0 0; width: 22%; height: auto; border-radius: 20px 0 0 20px;
  background: linear-gradient(to right, var(--mow-gora-tlo), transparent);
}
/* Odpowiedzi = kafle quizu. */
#widokMowienia .mow-scena:not(.wybor) .mow-dymki {
  flex-direction: column; align-items: stretch; justify-content: flex-start; flex-wrap: nowrap;
  width: 100%; min-height: 0; gap: 12px; padding: 0; margin-bottom: 20px;
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; column-gap: 0; row-gap: 2px; align-items: center;
  width: 100%; max-width: none; box-sizing: border-box; min-height: 58px; padding: 12px 12px 12px 18px; text-align: start;
  background: var(--card-bg); border: 2px solid var(--border); border-radius: 18px; box-shadow: 0 4px 0 var(--border);
  font-family: var(--font-naglowek); font-weight: 700; font-size: 1.15rem; line-height: 1.3; color: var(--testo);
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > * { grid-column: 1; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek:hover { background: var(--card-bg); border-color: var(--marka-niebieski); }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.uzyty { box-shadow: 0 4px 0 var(--border); }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek-pl,
#widokMowienia .mow-scena:not(.wybor) .mow-duch-dalej { font-family: var(--font-tekst); font-weight: 500; font-size: 0.92rem; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.po-naszemu .mow-dymek-tekst { font-family: var(--font-tekst); font-weight: 600; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek-cel { font-family: var(--font-naglowek); }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-plus,
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-gwiazda,
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-pomin { position: static; grid-row: 1 / span 3; align-self: center; margin-left: 8px; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-plus {
  grid-column: 2; padding: 3px 9px; font-size: 0.82rem; font-weight: 800; box-shadow: none;
  background: color-mix(in srgb, var(--marka-zielony) 16%, var(--card-bg)); color: var(--verde);
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-gwiazda { grid-column: 3; font-size: 1.2rem; filter: none; }
#widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-pomin {
  grid-column: 4; width: 34px; height: 34px; font-size: 0.95rem; border: none; box-shadow: none; background: var(--bg-soft); color: var(--muted-dark);
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.trafiony {
  background: color-mix(in srgb, var(--marka-zielony) 14%, var(--card-bg)); border-color: var(--marka-zielony);
  box-shadow: 0 4px 0 color-mix(in srgb, var(--marka-zielony) 70%, var(--granat));
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.pominiety {
  background: color-mix(in srgb, var(--zolty) 22%, var(--card-bg)); border-color: var(--zolty); box-shadow: 0 4px 0 color-mix(in srgb, var(--zolty) 70%, var(--granat));
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.duch {
  background: transparent; border-style: dashed; box-shadow: none; color: var(--muted-light);
  font-family: var(--font-tekst); font-weight: 700; font-size: 1rem;
}
#widokMowienia .mow-scena:not(.wybor) .mow-dymek.duch:hover { border-color: var(--marka-niebieski); color: var(--muted-dark); }
/* Mikrofon: zielony 96 z granatową ikoną i dolną krawędzią (quiz głosowy); --moc (głośność) rozdmuchuje pierścień. */
#widokMowienia .mow-scena:not(.wybor) .mow-mik-obszar { align-self: center; width: 128px; height: 128px; margin-top: auto; }
#widokMowienia .mow-scena:not(.wybor) .mow-mik {
  inset: 16px; background: var(--marka-zielony); color: var(--granat);
  box-shadow: 0 6px 0 color-mix(in srgb, var(--marka-zielony) 70%, var(--granat)), 0 0 0 10px color-mix(in srgb, var(--marka-zielony) 14%, transparent);
}
#widokMowienia .mow-scena:not(.wybor) .mow-mik:hover:not(:disabled) { background: color-mix(in srgb, var(--marka-zielony) 88%, #fff); }
#widokMowienia .mow-scena:not(.wybor) .mow-mik.slucha, #widokMowienia .mow-scena:not(.wybor) .mow-mik.slucha:hover {
  background: var(--marka-zielony); color: var(--granat);
  box-shadow: 0 6px 0 color-mix(in srgb, var(--marka-zielony) 70%, var(--granat)),
              0 0 0 calc(10px + var(--moc, 0) * 10px) color-mix(in srgb, var(--marka-zielony) 22%, transparent),
              0 0 0 calc(22px + var(--moc, 0) * 14px) color-mix(in srgb, var(--marka-zielony) 10%, transparent);
}
#widokMowienia .mow-scena:not(.wybor) .mow-mik:disabled { background: var(--bg-soft); color: var(--muted-light); box-shadow: none; }
#widokMowienia .mow-scena:not(.wybor) .mow-mik .ico { font-size: 2rem; }
#widokMowienia .mow-scena:not(.wybor) .mow-fala { color: var(--marka-zielony); }
#widokMowienia .mow-scena:not(.wybor) .mow-odliczanie { inset: 6px; width: calc(100% - 12px); height: calc(100% - 12px); }
#widokMowienia .mow-scena:not(.wybor) .mow-lektor, #widokMowienia .mow-scena:not(.wybor) .mow-dalej { inset: 16px; }
/* Linijka stanu pod mikrofonem: pochwała w kroju nagłówków jak „Świetnie!” quizu. */
#widokMowienia .mow-scena:not(.wybor) .mow-status { align-self: center; margin-top: 14px; text-align: center; }
#widokMowienia .mow-scena:not(.wybor) .mow-linia:not(.z-statusem) .mow-status:empty { display: none; }
#widokMowienia .mow-scena:not(.wybor) .mow-status.ok { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.5rem; color: var(--verde); }
#widokMowienia .mow-scena:not(.wybor) .mow-status-cichy, #widokMowienia .mow-scena:not(.wybor) .mow-swobodna-pasek { align-self: center; text-align: center; }
/* Karty pod rozmówcą (poprawka, fragment, „co źle”, ocena): karty quizu, „co źle” na czerwonym tle jak arkusz „Prawie!”. */
/* Swoistość: reguła slotu z paddingiem 0 wygrywała z kartą i tekst kart stał na ramce (krytyk 2026-10-04), więc karty ją omijają. */
#widokMowienia .mow-scena:not(.wybor) .mow-cwiczenie-slot .mow-cwiczenie:not(.mow-poprawka-karta) { padding: 0; margin-bottom: 16px; }
#widokMowienia .mow-scena:not(.wybor) .mow-poprawka-karta {
  max-width: none; width: 100%; box-sizing: border-box; align-items: flex-start; text-align: start; padding: 16px 48px 14px 20px; margin: 0 0 16px;
  border: 2px solid var(--border); border-radius: 22px; box-shadow: 0 4px 0 var(--border);
}
#widokMowienia .mow-scena:not(.wybor) .mow-pomylka-karta {
  background: color-mix(in srgb, var(--marka-czerwony) 9%, var(--card-bg)); border-color: transparent; box-shadow: none;
}
#widokMowienia .mow-scena:not(.wybor) .mow-cwiczenie-zdanie { font-family: var(--font-naglowek); font-weight: 700; font-size: clamp(1.25rem, 2.2vw, 1.5rem); line-height: 1.4; }
#widokMowienia .mow-scena:not(.wybor) .mow-fragment-slowo { color: var(--testo); background: color-mix(in srgb, var(--zolty) 30%, transparent); border-radius: 8px; padding: 0 6px; }
#widokMowienia .mow-scena:not(.wybor) .mow-pomylka-dalej { text-align: start; }

/* ---- Czytanie: kartka jak biała karta quizu, panel próby jak arkusz z polem i pigułkami ----
   Kartka w kratkę z czerwonym marginesem schodzi (kanwa „Komputer: próba w kartce”): biała karta z ramką 2 i rogami 28,
   zdania płyną dalej akapitem. Panel próby pod zdaniem dostaje niebieską ramkę, pole w ramce i duże przyciski: zielony
   mikrofon, „nie wiem” w obrysie, ptaszek „Sprawdź” w granacie z żółtym kółkiem (w ciemnym motywie żółty). */
#widokTekstow .kartka {
  background-image: none; background-color: var(--card-bg);
  border: 2px solid var(--border); border-radius: 28px; box-shadow: none; padding: 30px 32px;
}
#widokTekstow .kartka::before { display: none; }
#widokTekstow .kartka-akapit { padding-left: 0; line-height: 1.8; }
[dir="rtl"] #widokTekstow .kartka-akapit { padding-right: 0; }
#widokTekstow .kartka-akapit + .kartka-akapit { margin-top: 18px; }
#widokTekstow .kartka-postep { height: 12px; border-radius: 999px; background: var(--border); overflow: hidden; }
#widokTekstow .kartka-postep-fill { background: var(--marka-niebieski); border-radius: 999px; box-shadow: inset 0 4px 0 rgba(255, 255, 255, 0.25); }
#widokTekstow .kartka-segment.aktywny {
  margin: 16px 0; padding: 14px 16px; border-radius: 22px; box-shadow: none;
  background: color-mix(in srgb, var(--marka-niebieski) 7%, var(--card-bg)); border: 2px solid var(--marka-niebieski);
}
/* Dół z zapasem: .kartka-proba > * ma overflow: hidden (animacja rozwijania), a ucinało dolną krawędź i spód okrągłych przycisków. */
#widokTekstow .kartka-proba-wnetrze { gap: 10px; padding-top: 10px; padding-bottom: 10px; }
/* Bieżące zdanie czyta się jak słowo w dymku quizu: Outfit 700, pełna barwa tekstu (dotąd przygaszone). */
#widokTekstow .kartka-segment.aktywny .kartka-zrodlo { color: var(--testo); font-family: var(--font-naglowek); font-weight: 700; font-size: 1.15rem; line-height: 1.4; }
#widokTekstow .proba-linia { display: flex; flex-direction: column; align-items: stretch; gap: 10px; line-height: 1.45; }
#widokTekstow .proba-pole {
  display: block; min-height: 52px; box-sizing: border-box; padding: 13px 16px; border-radius: 16px;
  background: var(--card-bg); border: 2px solid var(--marka-niebieski); font-size: 1.05rem;
}
#widokTekstow .proba-ikony { display: flex; align-items: center; gap: 10px; white-space: normal; }
#widokTekstow .proba-ikona {
  width: 52px; height: 52px; margin: 0; border-radius: 999px; font-size: 1.25rem;
  display: inline-flex; align-items: center; justify-content: center;
}
#widokTekstow .proba-ikona.mik { order: 1; background: var(--marka-zielony); border: none; color: var(--granat); box-shadow: 0 4px 0 color-mix(in srgb, var(--marka-zielony) 70%, var(--granat)); }
#widokTekstow .proba-ikona.mik:hover { border: none; color: var(--granat); }
#widokTekstow .proba-ikona.nie { order: 2; background: var(--card-bg); border: 2px solid var(--border); color: var(--testo); box-shadow: 0 4px 0 var(--border); }
#widokTekstow .proba-ikona.ok { order: 3; margin-inline-start: auto; width: 64px; background: var(--oro); border: none; color: var(--na-akcencie); box-shadow: 0 4px 0 color-mix(in srgb, var(--oro) 70%, #000); }
#widokTekstow .proba-ikona.ok:hover, #widokTekstow .proba-ikona.nie:hover, #widokTekstow .proba-ikona.mik:hover { transform: translateY(-1px); }
#widokTekstow .proba-czesci { font-size: 0.85rem; }
@media (prefers-reduced-motion: reduce) {
  #widokTekstow .proba-ikona:hover { transform: none; }
}
/* Wąskie okno (telefon w przeglądarce): mniejsza postać obok kwestii i miejsce na zawinięty nagłówek sceny. Do 2026-10-08 postaci
   tu nie było wcale (wycinek baristki zjadał 128 px szerokości); cała postać 60 × 90 zostawia dymkowi przy 390 px ekranu ~250 px,
   tyle, ile ma dymek obok postaci w aplikacji. */
@media (max-width: 600px) {
  #widokMowienia .mow-scena:not(.wybor) { padding: 20px 16px 20px; border-radius: 22px; }
  #widokMowienia .mow-scena:not(.wybor) .mow-naglowek { margin-inline-end: 0; margin-top: 46px; }
  /* Flaga „Zgłoś problem”: w górnym wierszu po lewej, naprzeciw „Zacznij od nowa” (pod nim siadała na tytule sceny). */
  #widokMowienia .mow-scena:not(.wybor) .mow-zglos { top: 18px; inset-inline-end: auto; inset-inline-start: 12px; }
  #widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis)) { margin: 12px 0 24px 68px; }
  #widokMowienia .mow-scena:not(.wybor) .mow-pytanie:not(:empty):not(:has(.mow-bot-opis))::before { left: -70px; bottom: -20px; width: 60px; height: 90px; }
  #widokMowienia .mow-scena:not(.wybor) .mow-dymek { padding: 10px 10px 10px 14px; font-size: 1.05rem; }
  #widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-pomin { width: 30px; height: 30px; }
  #widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-plus,
  #widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-gwiazda,
  #widokMowienia .mow-scena:not(.wybor) .mow-dymek > .mow-pomin { margin-left: 6px; }
  #widokTekstow .kartka { padding: 20px 16px; border-radius: 22px; }
}

/* ---------- 18. SPOŁECZNOŚĆ: MOZAIKA UPORZĄDKOWANA (2026-10-04) ----------
   Kanwa „Społeczność Lingaria”, wersja B (Alek: „jakby to co jest obecnie na localhoście ale lepiej”, potem „Fajnie do
   roboty, pozwalam działać”; odstępy: „mniejsze o 30%”, „jeszcze bardziej”). Mozaika zostaje, zmienia się:
   · pigułki RODZAJÓW nad mozaiką (#cmtyRodzaje, renderRodzaje) z kropką w barwie trybu i licznikiem; wybrana w barwie
     akcentu (--oro: granat, w ciemnym żółty), jak każdy wybór w stylu kanwy;
   · pigułka KOLEJNOŚCI ze strzałką listy (Popularne / Najnowsze / Odkrywaj), aparat jako żółte kółko W polu szukania;
   · kafel ZDJĘCIA: obraz w całości, a tytuł, autor, liczba słówek, „nowe”, serce, komentarze i pobrania w stopce POD nim
     (dawniej tylko na najechaniu); akcje (Zapisz, link, Zgłoś) dalej na obrazku na najechaniu;
   · odstępy mozaiki 6 px zamiast 18 (u Alka na kanwie z 16 przez 11 do 6), kafel na najechaniu podnosi się o 3 px,
     bez powiększenia, które przy ciasnej mozaice wchodziło na sąsiadów;
   · kafel utworu bez rzędu trzech kółek (serce stoi na okładce, link i QR w karcie). */
.community-topbar .cmty-rodzaje {
  flex: 1 0 100%; order: 99; display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
  padding: 2px 0 2px; margin-top: 2px;
}
.community-topbar .cmty-rodzaje::-webkit-scrollbar { display: none; }
.cmty-rodzaj {
  flex: none; display: inline-flex; align-items: center; gap: 7px; height: 40px; padding: 0 14px; border-radius: 999px;
  border: 2px solid var(--border); background: var(--card-bg); color: var(--testo); cursor: pointer;
  font: inherit; font-weight: 800; font-size: 0.86rem; white-space: nowrap;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.cmty-rodzaj:hover { border-color: var(--border-2); background: var(--bg-soft); }
.cmty-rodzaj.active, .cmty-rodzaj.active:hover { background: var(--oro); border-color: var(--oro); color: var(--na-akcencie); }
.cmty-rodzaj:focus-visible { outline: 3px solid var(--oro); outline-offset: 2px; }
.cmty-rodzaj .ico { margin: 0; font-size: 0.85rem; }
.cmty-rodzaj-kropka { width: 9px; height: 9px; border-radius: 50%; flex: none; box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.6); }
.cmty-rodzaj-ile { font-weight: 700; opacity: 0.62; font-variant-numeric: tabular-nums; }
#communitySortBtn .cmty-sort-strzalka { margin: 0 -2px 0 2px; font-size: 0.8rem; opacity: 0.7; }
/* Aparat w polu szukania: żółte kółko przy prawej krawędzi pola, krzyżyk czyszczenia przesunięty przed nie. */
.community-topbar .community-search-wrap { max-width: 520px; }
.community-topbar .community-search-wrap #communitySearch { padding-right: 88px; }
.community-topbar .community-search-wrap .community-aparat {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%); width: 36px; height: 36px; min-width: 0;
  border: none; border-radius: 50%; background: var(--zolty); color: var(--granat); box-shadow: none;
}
.community-topbar .community-search-wrap .community-aparat:hover { background: #F2B21C; color: var(--granat); box-shadow: none; }
.community-topbar .community-search-wrap .community-aparat .ico { margin: 0; }
.community-topbar .community-search-wrap .community-search-clear { right: 46px; }
body.tryb-goscia .community-topbar .community-search-wrap #communitySearch { padding-right: 40px; }
body.tryb-goscia .community-topbar .community-search-wrap .community-search-clear { right: 8px; }

/* Mozaika: ciasne odstępy (siatka liczy wysokości z rowGap, więc spany same się zgadzają). */
/* Krok siatki 2 px zamiast 8: przy 8 px zaokrąglenie wysokości kafla do kroku dokładało pod nim do 13 px pustki
   i pionowe przerwy wychodziły ~20 px mimo gap 6. Dlatego wiersze idą BEZ odstępu (row-gap 0), a odstęp między kaflami
   (column-gap) dolicza się do wysokości kafla w dopasujWysokoscKafelka*, przeliczCloseup: przerwa wychodzi 6-7 px. */
#communityBoard.community-board { column-gap: 6px; row-gap: 0; grid-auto-rows: 2px; }
#communityBoard .community-tile:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(23, 24, 59, 0.22); }
#communityBoard .community-tile.otwarty:hover { transform: none; }

/* Kafle tablicy (stopka zdjęcia, pigułka „Zapisz / Zgłoś” czytanki i rozmowy, nota o YouTube pod utworem) są od
   2026-10-05 przebudowane w sekcji 19 (kafle jak Pinterest); dawne reguły tych kafli zniknęły razem z ich znacznikami.
   Gość nie widzi „znasz X%”: liczy się względem talii, której nie ma. */
body.tryb-goscia #communityBoard .community-tile .cmty-pokrycie { display: none; }

@media (prefers-reduced-motion: reduce) {
  #communityBoard .community-tile:hover { transform: none; }
}

/* ---------- 19. SPOŁECZNOŚĆ: KAFLE JAK PINTEREST (2026-10-05) ----------
   Kanwa „Społeczność jak Pinterest” (Alek: „u nas za dużo pojawia się na raz i za dużo wolnej przestrzeni widać nad
   każdym postem … ukryć część tagów, a wyświetlać je dopiero po najechaniu”; po projekcie: „Świetnie, rób”). Kafel bez
   ramki i tła: zaokrąglona OKŁADKA z treścią, pod nią tytuł (2 linijki), jedna linijka i „⋯”. Nakładka na okładce
   (rodzaj, Zapisz, plakietki, autor, liczniki, serce) tylko na najechaniu i przy fokusie; na dotyku jej nie ma.
   Kafel nie podnosi się na najechaniu: okładka ciemnieje pod nakładką, jak u Pinteresta. Barwy na okładce stałe
   (leżą na zdjęciu albo na granatowym zaciemnieniu), reszta przez tokeny. Kafle moderatora (kandydat, naruszenie)
   i reklamy zostają po staremu: nie mają klasy .pin. */
#communityBoard.community-board { column-gap: 10px; }
#communityBoard .community-tile.pin.pin {
  background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible; display: block;
}
#communityBoard .community-tile.pin.pin:hover { transform: none; box-shadow: none; }
#communityBoard .community-tile.pin.menu-otwarte { z-index: 30; }
#communityBoard .community-tile.pin.otwarty { outline: none; }
#communityBoard .community-tile.pin.otwarty .pin-ok { outline: 3px solid var(--oro); outline-offset: 2px; }

/* Okładka. */
#communityBoard .pin-ok { position: relative; display: block; overflow: hidden; border-radius: 16px; background: var(--bg-soft); }
#communityBoard .pin-ok > img { display: block; width: 100%; height: auto; }
#communityBoard .pin-ok-utwor { aspect-ratio: 1 / 1; background: #17183B; }
#communityBoard .pin-ok-utwor > img, #communityBoard .pin-ok-rozmowa.z-obrazem > img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
#communityBoard .pin-play {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 46px; height: 46px; border-radius: 50%; background: #FFFFFF; color: #17183B;
  display: grid; place-items: center; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
}
#communityBoard .pin-play .ico { margin: 0 0 0 2px; font-size: 1rem; }
#communityBoard .pin-zrodlo {
  position: absolute; left: 10px; bottom: 9px; padding: 2px 7px; border-radius: 999px;
  background: rgba(23, 24, 59, 0.72); color: #FFFFFF; font-size: 0.66rem; font-weight: 800; letter-spacing: 0.02em;
}
#communityBoard .pin-ok-rozmowa { background: #35A64D; }
#communityBoard .pin-ok-rozmowa.z-obrazem { aspect-ratio: 4 / 3; }
#communityBoard .pin-ok-rozmowa:not(.z-obrazem) { padding: 10px 10px 2px; }
#communityBoard .pin-ok-rozmowa .pin-ilustracja { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: contain; }
/* Znak „SI” (sekcja 19a) w lewym dolnym rogu okładki, tam gdzie „YouTube” na kadrze utworu. z-index 3 = NAD nakładką
   (z-index 2), inaczej pod kursorem nakładka przykrywa znak i dymka nie dałoby się wywołać; wiersz autora w nakładce
   odsuwa się wtedy w prawo, żeby znak nie wszedł na awatar. */
#communityBoard .pin-znak-ai { position: absolute; left: 10px; bottom: 9px; z-index: 3; }
#communityBoard .pin-ok:has(> .pin-znak-ai) .pin-nak-wiersz { padding-left: 30px; }
/* Czytanka: początek tekstu na kartce, kursywą jak zajawka w Czytaniu. */
#communityBoard .pin-ok-tekst {
  min-height: 160px; box-sizing: border-box; padding: 12px 14px 16px;
  background: var(--card-bg); border: 1.5px solid var(--border);
}
#communityBoard .pin-cudz {
  display: block; height: 20px; font-family: var(--font-naglowek); font-weight: 800; font-size: 2.1rem; line-height: 1;
  color: var(--marka-niebieski);
}
#communityBoard .pin-wyc {
  margin: 4px 0 0; font-style: italic; font-size: 0.8rem; line-height: 1.5; color: var(--testo);
  display: -webkit-box; -webkit-line-clamp: 8; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}

/* Nakładka: najechanie i fokus z klawiatury (Tab po przyciskach nakładki też ją pokazuje). */
#communityBoard .pin-nak {
  position: absolute; inset: 0; z-index: 2; box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: space-between; gap: 8px; padding: 10px;
  background: rgba(23, 24, 59, 0.7); color: #FFFFFF;
  opacity: 0; pointer-events: none; transition: opacity 0.15s ease;
}
@media (hover: hover) {
  #communityBoard .community-tile.pin:is(:hover, :focus-within) .pin-nak { opacity: 1; pointer-events: auto; }
}
@media (hover: none) {
  #communityBoard .pin-nak { display: none; }
}
#communityBoard .pin-nak-gora { display: flex; justify-content: space-between; align-items: flex-start; gap: 6px; }
#communityBoard .pin-typ {
  padding: 4px 9px; border-radius: 999px; font-size: 0.66rem; font-weight: 800; letter-spacing: 0.04em;
  text-transform: uppercase; white-space: nowrap;
}
#communityBoard .pin-typ.tekst { background: #2463E9; color: #FFFFFF; }
#communityBoard .pin-typ.utwor { background: #DB2727; color: #FFFFFF; }
#communityBoard .pin-typ.rozmowa { background: #35A64D; color: #17183B; }
#communityBoard .pin-akcje { margin: 0; }
#communityBoard .pin-nak .community-btn-zapisz {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 13px; border-radius: 999px;
  background: #FFC83D; color: #17183B; font-size: 0.78rem; font-weight: 800; box-shadow: none;
}
#communityBoard .pin-nak .community-btn-zapisz:hover { background: #FFD566; filter: none; }
#communityBoard .pin-nak .community-btn-zapisz.zapisane {
  background: rgba(255, 255, 255, 0.18); box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.75); color: #FFFFFF;
}
#communityBoard .pin-nak-dol { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
#communityBoard .pin-chipy { display: flex; flex-wrap: wrap; gap: 4px; }
#communityBoard .pin-chip {
  display: inline-flex; align-items: center; gap: 3px; padding: 3px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.94); color: #17183B; font-size: 0.66rem; font-weight: 800; white-space: nowrap;
}
#communityBoard .pin-chip .ico { margin: 0; font-size: 0.7rem; }
#communityBoard .pin-nak-wiersz { display: flex; align-items: center; gap: 8px; min-width: 0; }
#communityBoard .pin-autor { flex: 1; min-width: 0; display: flex; color: #FFFFFF; font-size: 0.74rem; font-weight: 700; }
#communityBoard .pin-autor .cmty-autor-link { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: #FFFFFF; }
#communityBoard .pin-autor .cmty-autor-nick { color: #FFFFFF; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#communityBoard .pin-autor .cmty-autor-foto { width: 20px; height: 20px; flex: none; box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.85); }
#communityBoard .pin-licznik { display: inline-flex; align-items: center; gap: 3px; flex: none; font-size: 0.74rem; font-weight: 800; color: #FFFFFF; }
#communityBoard .pin-licznik .ico { margin: 0; font-size: 0.8rem; }
#communityBoard .pin-nak .community-serce {
  flex: none; min-height: 32px; padding: 5px 10px 5px 8px; background: #FFFFFF; box-shadow: none;
}
#communityBoard .pin-nak .community-serce:hover { background: #FFFFFF; }
#communityBoard .pin-nak .community-serce svg { width: 18px; height: 18px; }
#communityBoard .pin-nak .community-serce path { stroke: #17183B; }
#communityBoard .pin-nak .community-serce-ile { color: #17183B; font-size: 0.72rem; font-weight: 800; }
#communityBoard .pin-nak .community-serce-ile:empty { display: none; }
#communityBoard .pin-nak .community-serce.lubie path { fill: #DB2727; stroke: #DB2727; }
#communityBoard .pin-nak .community-serce.lubie .community-serce-ile { color: #DB2727; }
#communityBoard .pin-nak :focus-visible { outline: 3px solid #FFFFFF; outline-offset: 2px; }

/* Podpis pod okładką: tytuł, jedna linijka i „⋯”. */
#communityBoard .community-tile.pin .pin-pod {
  position: relative; display: flex; flex-direction: row; align-items: flex-start; gap: 4px; padding: 8px 2px 4px;
}
#communityBoard .pin-pod-tekst { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
#communityBoard .pin-tytul {
  font-weight: 700; font-size: 0.84rem; line-height: 1.3; color: var(--testo);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}
#communityBoard .pin-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0;
  font-size: 0.74rem; line-height: 1.3; color: var(--tekst-neutralny); font-variant-numeric: tabular-nums;
}
#communityBoard .pin-flaga svg { display: block; border-radius: 3px; }
#communityBoard .pin-poziom { font-weight: 800; color: var(--testo); }
#communityBoard .pin-znasz { display: inline-flex; align-items: center; gap: 5px; }
#communityBoard .pin-pierscien { width: 14px; height: 14px; flex: none; }
#communityBoard .pin-pierscien circle { fill: none; stroke: var(--border); stroke-width: 2.5; }
#communityBoard .pin-pierscien .pin-pierscien-luk { stroke: var(--marka-niebieski); stroke-linecap: round; }
#communityBoard .pin-nowe { font-weight: 700; color: var(--verde); }
#communityBoard .pin-nowe.znane { color: var(--tekst-neutralny); }
#communityBoard .pin-tylko-gosc { display: none; }
body.tryb-goscia #communityBoard .pin-tylko-gosc { display: inline; }
body.tryb-goscia #communityBoard .pin-nowe,
body.tryb-goscia #communityBoard .pin-nak .community-serce { display: none; }
#communityBoard .community-tile.pin .edycja-znak { margin: 0; }
#communityBoard .pin-wiecej {
  flex: none; width: 32px; height: 32px; margin: -4px -4px 0 0; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--testo); display: grid; place-items: center; cursor: pointer;
}
#communityBoard .pin-wiecej:hover, #communityBoard .menu-otwarte .pin-wiecej { background: var(--pigulka-cicha); }
#communityBoard .pin-wiecej:focus-visible { outline: 3px solid var(--oro); outline-offset: 1px; }
#communityBoard .pin-wiecej .ico { margin: 0; font-size: 1rem; }
@media (pointer: coarse) { #communityBoard .pin-wiecej { width: 40px; height: 40px; margin: -8px -8px 0 0; } }
#communityBoard .pin-menu {
  display: none; position: absolute; right: -2px; top: calc(100% - 2px); z-index: 5; min-width: 200px;
  flex-direction: column; padding: 6px; border-radius: 14px;
  background: var(--card-bg); border: 1.5px solid var(--border); box-shadow: 0 14px 34px -10px rgba(23, 24, 59, 0.4);
}
#communityBoard .menu-otwarte .pin-menu { display: flex; }
#communityBoard .pin-menu :is(.pin-menu-poz, .cmty-zglos) {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; margin: 0; padding: 0 10px;
  border: 0; border-radius: 10px; background: transparent; color: var(--testo);
  font: inherit; font-size: 0.84rem; font-weight: 700; text-align: left; text-decoration: none; cursor: pointer; white-space: nowrap;
}
#communityBoard .pin-menu :is(.pin-menu-poz, .cmty-zglos):hover { background: var(--bg-soft); }
#communityBoard .pin-menu .cmty-zglos { color: var(--rosso); }
#communityBoard .pin-menu .ico { margin: 0; font-size: 0.95rem; }
@media (max-width: 720px) {
  #communityBoard.community-board { column-gap: 8px; }
  #communityBoard .pin-ok-tekst { min-height: 130px; padding: 10px 12px 14px; }
}
@media (prefers-reduced-motion: reduce) {
  #communityBoard .pin-nak { transition: none; }
}

/* ---------- 19a. ZNAK „SI” NA OBRAZIE Z GENERATORA (2026-10-08) ----------
   Alek: „na stronie społeczności może zamiast »Obraz AI« pisać »SI« żeby oznaczenie było mniej nachalne, może być jeszcze
   mniejsze”. JS: sekcja ZNAK „SI” NA OBRAZIE Z GENERATORA (znakSiHtml). Dawna pigułka „obraz z AI” (0,66 rem, ~60 × 18 px)
   to dziś dwie litery w znaczku ~22 × 16 px, a pełne zdanie w dymku nad znakiem. Barwy stałe w obu motywach, bo znak leży
   na obrazku: biel na granacie 0,62 ma kontrast co najmniej 5 : 1 nawet nad białym fragmentem obrazka (przy 0,55 wychodziło
   3,9 : 1, za mało na tak małe litery); dymek pełnym granatem (biel na #17183B ~17 : 1). Okładki mają overflow: hidden, więc
   dymek ma sufit szerokości: kafel tablicy na telefonie 375 px ma ~170 px okładki, przy 320 px ~144 px. Pole dotyku
   (::before) większe niż sam znak, bo 22 × 16 px to za mało pod palec. Miejsce znaku ustala kontekst: .pin-znak-ai
   (tablica, sekcja 19), .mow-znak-ai (mapa Mówienia i okno twórcy), .cmty-nalepki (karta rozmowy, sekcja 20). */
.znak-si {
  position: relative; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  padding: 3px 5px; border-radius: 6px; background: rgba(23, 24, 59, 0.62); color: #FFFFFF;
  font-size: 0.625rem; font-weight: 800; line-height: 1; letter-spacing: 0.06em; cursor: help;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.znak-si[hidden] { display: none; }
.znak-si::before { content: ''; position: absolute; inset: -8px -6px; }
.znak-si:focus { outline: none; }
.znak-si:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 2px; }
.znak-si-dymek {
  position: absolute; left: 0; bottom: calc(100% + 6px); z-index: 1; box-sizing: border-box;
  width: max-content; max-width: min(180px, calc(50vw - 36px)); padding: 6px 9px; border-radius: 10px;
  background: #17183B; color: #FFFFFF; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
  font-size: 0.72rem; font-weight: 600; line-height: 1.35; letter-spacing: 0; text-align: left; white-space: normal;
  opacity: 0; visibility: hidden; transform: translateY(2px); pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0s linear 0.12s;
}
.znak-si.pokaz .znak-si-dymek,
.znak-si:focus-visible .znak-si-dymek { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
@media (hover: hover) {
  .znak-si:hover .znak-si-dymek { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
}
/* Escape (znakSiKlawisz) chowa dymek, choć kursor albo fokus dalej stoi na znaku; ta reguła musi stać za tymi wyżej. */
.znak-si.schowany .znak-si-dymek { opacity: 0; visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  .znak-si-dymek { transition: none; }
}

/* ---------- 20. SPOŁECZNOŚĆ: ZWIASTUN ROZMOWY W KARCIE (2026-10-05) ----------
   Kanwa „Zawartość rozmowy Mówienia”, wariant A (Alek: „Możesz wdrażać”), JS: sekcja ZWIASTUN ROZMOWY W KARCIE. Pod okładką
   pierwsza wymiana do kliknięcia (dymek rozmówcy w lawendzie, odpowiedzi ucznia jak kafle quizu: biel, zielona obwódka Mówienia
   i dolna krawędź), pod nią słówka ze znakiem „znasz” / „nowe”, w panelu liczby i dwa przyciski. Kolory przez tokeny, więc
   ciemny motyw idzie sam; pasek „inna odpowiedź, inna rozmowa” stoi na --oro (granat w jasnym, żółty w ciemnym), bo stały
   granat znikał na granatowej karcie ciemnego motywu. */
#communityDetailZdania:has(> .cmty-zw-slowka) { max-height: none; overflow: visible; gap: 26px; padding-right: 0; }
.cmty-zw-glowa { display: flex; align-items: center; justify-content: space-between; gap: 8px 14px; flex-wrap: wrap; margin-bottom: 12px; }
.cmty-zw-glowa h3 { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.2rem; letter-spacing: -0.01em; color: var(--testo); }
.cmty-zw-glowa > span { font-size: 0.82rem; color: var(--grigio); }
.cmty-zwiastun { display: flex; flex-direction: column; gap: 12px; }
.cmty-zwiastun .cmty-zw-glowa { margin-bottom: 0; }
.cmty-zw-rzad { display: flex; align-items: flex-start; gap: 12px; }
.cmty-zw-ty { justify-content: flex-end; }
.cmty-zw-awatar {
  flex: none; width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center;
  background: var(--marka-zielony); color: #17183B; font-size: 1.1rem;
}
.cmty-zw-awatar .ico { margin: 0; }
.cmty-zw-awatar.ty { background: var(--zolty); }
.cmty-zw-kolumna { display: flex; flex-direction: column; gap: 6px; min-width: 0; max-width: 580px; }
.cmty-zw-ty .cmty-zw-kolumna { width: min(100%, 470px); }
.cmty-zw-kto { font-size: 0.78rem; font-weight: 700; color: var(--grigio); }
.cmty-zw-ty .cmty-zw-kto { text-align: right; }
.cmty-zw-dymek {
  display: flex; align-items: center; gap: 12px; padding: 12px 12px 12px 16px;
  background: var(--bg-soft); border-radius: 6px 20px 20px 20px;
}
.cmty-zw-tekst { flex: 1; min-width: 0; font-size: 1.05rem; font-weight: 600; line-height: 1.4; color: var(--testo); }
.cmty-zw-glos {
  flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  border: 1.5px solid var(--border); background: var(--card-bg); color: var(--primary); font-size: 1rem;
}
.cmty-zw-glos .ico { margin: 0; }
.cmty-zw-glos:hover { border-color: var(--primary); }
.cmty-zw-pl { padding-left: 16px; font-size: 0.85rem; line-height: 1.4; color: var(--grigio); }
.cmty-zw-odp {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; min-height: 44px;
  padding: 10px 16px 11px; text-align: left; font: inherit; color: var(--testo); cursor: pointer;
  background: var(--card-bg); border: 2px solid var(--marka-zielony); border-radius: 20px 20px 6px 20px;
  box-shadow: 0 3px 0 color-mix(in srgb, var(--marka-zielony) 45%, var(--card-bg));
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.2s ease, opacity 0.2s ease;
}
.cmty-zw-odp:hover { transform: translateY(-1px); box-shadow: 0 4px 0 color-mix(in srgb, var(--marka-zielony) 45%, var(--card-bg)); }
.cmty-zw-odp:active { transform: translateY(2px); box-shadow: 0 1px 0 color-mix(in srgb, var(--marka-zielony) 45%, var(--card-bg)); }
.cmty-zw-odp.wybrana { background: var(--bg-success-soft); border-color: var(--verde); box-shadow: 0 3px 0 var(--verde); }
.cmty-zw-odp.zgaszona { opacity: 0.45; }
.cmty-zw-odp.zgaszona:hover { opacity: 0.8; }
.cmty-zw-odp-t { font-size: 0.98rem; font-weight: 700; line-height: 1.35; }
.cmty-zw-odp-pl { font-size: 0.8rem; line-height: 1.35; color: var(--grigio); }
:is(.cmty-zw-odp, .cmty-zw-glos, .cmty-zw-dalej button, .cmty-zw-oko):focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
.cmty-zw-zacheta, .cmty-zw-dalej { display: flex; align-items: center; gap: 12px; border-radius: 16px; font-size: 0.9rem; line-height: 1.4; }
.cmty-zw-zacheta { padding: 12px 16px; border: 2px dashed var(--border-2); color: var(--grigio); }
.cmty-zw-zacheta .ico { margin: 0; flex: none; color: var(--primary); font-size: 1.15rem; }
.cmty-zw-dalej { padding: 10px 10px 10px 16px; background: var(--oro); color: var(--na-akcencie); }
.cmty-zw-dalej > span { flex: 1; min-width: 0; }
.cmty-zw-dalej .ico { margin: 0; flex: none; color: var(--przycisk-kolko); font-size: 1.15rem; }
.cmty-zw-dalej button {
  flex: none; min-height: 40px; padding: 0 16px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--card-bg); color: var(--testo); font: inherit; font-size: 0.85rem; font-weight: 700;
}
.cmty-zw-rzad.wjazd, .cmty-zw-dalej.wjazd { animation: cmtyZwWjazd 0.35s ease-out both; }
@keyframes cmtyZwWjazd { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
/* Słówka: kafle z tłumaczeniem i znakiem; podświetlone = padły w klikniętej odpowiedzi. */
.cmty-zw-znasz { display: flex; align-items: center; gap: 10px; font-size: 0.82rem; line-height: 1.3; color: var(--testo); }
.cmty-zw-znasz span { color: var(--grigio); }
.cmty-zw-znasz b { color: var(--testo); }
.cmty-zw-znasz svg { flex: none; }
.cmty-zw-znasz circle { fill: none; stroke-width: 6; }
.cmty-zw-znasz .tlo { stroke: var(--bg-highlight); }
.cmty-zw-znasz .pasek { stroke: var(--zolty); stroke-linecap: round; }
.cmty-zw-siatka { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 6px; }
.cmty-zw-slowo {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 12px; min-width: 0;
  border: 1.5px solid var(--border); border-radius: 14px; background: var(--card-bg);
  transition: background 0.25s ease, border-color 0.25s ease;
}
.cmty-zw-slowo.uzyte { background: var(--bg-highlight); border-color: var(--zolty); }
.cmty-zw-slowo-teksty { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* Słówko się zawija, nie ucina: przy 390 px „un chilogrammo” wychodziło jako „un chilog…”, a to jest treść, nie ozdoba.
   Na telefonie znak idzie POD słówko (media niżej): obok niego zostawało ~90 px i słowo łamało się w środku („chilogram mo”). */
.cmty-zw-slowo .t { font-size: 0.92rem; font-weight: 700; line-height: 1.3; color: var(--testo); overflow-wrap: break-word; }
.cmty-zw-slowo .pl { font-size: 0.78rem; line-height: 1.3; color: var(--grigio); overflow-wrap: break-word; }
.cmty-zw-znak { flex: none; font-size: 0.7rem; font-weight: 700; padding: 3px 8px; border-radius: 999px; }
.cmty-zw-znak.znasz { color: var(--verde); background: var(--bg-success-soft); }
.cmty-zw-znak.nowe { color: var(--primary); background: var(--bg-warn-soft); }
/* „+120 słówek” na miejscu ostatniego słówka siatki (2026-10-08, Alek: „zamiast kafelka »Il nome« zrób »+117 słówek«”). Ten sam
   kształt co kafel słówka, ale przerywana ramka i miękkie tło, bo to nie słówko, tylko wejście do paletki ze wszystkimi; „Zobacz
   wszystkie” w kolorze odnośnika, ramka w akcencie na najechaniu. */
.cmty-zw-wiecej { display: flex; min-width: 0; }
.cmty-zw-wiecej button {
  flex: 1; min-width: 0; min-height: 44px; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; gap: 1px;
  padding: 8px 10px 8px 12px; text-align: left; font: inherit; cursor: pointer;
  border: 1.5px dashed var(--border-2); border-radius: 14px; background: var(--bg-soft); color: var(--testo);
  transition: border-color 0.2s ease;
}
.cmty-zw-wiecej button:hover { border-color: var(--oro); }
.cmty-zw-wiecej button:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
.cmty-zw-wiecej .t { font-size: 0.92rem; font-weight: 800; line-height: 1.3; color: var(--testo); }
.cmty-zw-wiecej .pl { font-size: 0.78rem; font-weight: 700; line-height: 1.3; color: var(--primary); }
/* Pigułki na okładce: leżą na obrazku, więc barwy stałe w obu motywach. */
.cmty-zw-pigulka {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 999px;
  font-size: 0.75rem; font-weight: 700; line-height: 1.2;
}
.cmty-zw-pigulka .ico { margin: 0; font-size: 0.8rem; }
.cmty-zw-pigulka.poziom { background: #FFC83D; color: #17183B; }
/* Znak „SI” obok pigułki poziomu (dawna pigułka „obraz z AI”, wygląd w sekcji 19a). Warstwa pigułek nie łapie kliknięć,
   znak tak: dymek wychodzi po najechaniu i po stuknięciu. */
.cmty-nalepki .znak-si { pointer-events: auto; }
/* Opis z okiem: tłumaczenie po naszemu pod spodem, schowane do kliknięcia (jak oko instrukcji na scenie). */
.cmty-zw-oko {
  display: inline-grid; place-items: center; width: 32px; height: 32px; margin-left: 4px; vertical-align: middle; cursor: pointer;
  border: 1.5px solid var(--border); border-radius: 50%; background: var(--card-bg); color: var(--grigio);
}
.cmty-zw-oko .ico { margin: 0; font-size: 0.85rem; }
.cmty-zw-oko[aria-expanded="true"] { color: var(--testo); border-color: var(--testo); }
.cmty-zw-opis-pl:not([hidden]) { display: block; margin-top: 6px; font-size: 0.85rem; color: var(--grigio); }
/* Panel: kafle liczb i dwa przyciski jeden pod drugim (dawny wiersz słówek ma sufit 210 px z przewijaniem). flex 0 0 auto, bo
   wiersz słówek dawał się ściskać (flex 0 1 auto, min-height 0), a jego zawartość wylewała się wtedy NA komentarze: zrzut Alka
   z 2026-10-05, kafle liczb na nagłówku „Komentarze”, „Zagraj” na pustej liście, drugi przycisk pod polem komentarza. */
/* margin-bottom 0 od 2026-10-11: przyciski stoją dziś w osobnym wierszu (#communityDetailAkcje, sekcja 21b), a odstęp od kafli
   daje sam .cmty-zw-liczby (14 px, jak wtedy, gdy kafle i przyciski były w jednym wierszu); 18 px wierszowi dawało 32 px przerwy. */
#communityDetailSlowa:has(> .cmty-zw-liczby) { display: block; flex: 0 0 auto; max-height: none; overflow: visible; padding-right: 0; margin-bottom: 0; }
/* Liczba nowych pozycji na „Weź słówka do fiszek” (dawniej „Zrób fiszki z rozmowy”; od 2026-10-11 wspólny przycisk
   .cmty-akcja-slowka, sekcja 21b): błękit „nowe”, jak znak przy słówku. */
.cmty-akcja-slowka .cmty-zw-ile {
  margin-left: 6px; padding: 2px 8px; border-radius: 999px; background: var(--bg-warn-soft); color: var(--primary);
  font-size: 0.72rem; font-weight: 800; white-space: nowrap;
}
/* Z liczbą plus jest zbędny (liczba mówi, co się doda), a w panelu 300 px przy 1280 px okna napis łamał się na dwie linie. */
.cmty-akcja-slowka:has(.cmty-zw-ile) > .ico { display: none; }
.cmty-akcja-slowka > span:not(.cmty-zw-ile) { white-space: nowrap; }
.cmty-zw-grali { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 12px; font-size: 0.82rem; color: var(--grigio); }
.cmty-zw-grali .ico { margin: 0; color: var(--verde); }
/* PANEL JEDZIE Z PRZEWIJANIEM (cmtyPasekWysokosc w JS): lewa kolumna rozmowy ma przy 1440 px ~1700 px, a panel z „Zagraj”
   i komentarzami znikał po pierwszym przewinięciu. Sticky potrzebuje przodka bez kontenera przewijania, a karta miała
   overflow: hidden; clip przycina tak samo (z zaokrągleniem), ale nie zakłada przewijania. Pod paskiem Społeczności, gdy
   pasek stoi; przy samej górze, gdy schował się przy zjeździe w dół. Karta w pionie (wąska) zostaje bez tego. */
.community-detail-karta.w-siatce:not(.pion):has(.cmty-zw-slowka) { overflow: clip; }
.community-detail-karta.w-siatce:not(.pion):has(.cmty-zw-slowka) > .community-detail-panel {
  position: sticky; align-self: flex-start;
  top: calc(var(--cmty-pasek-h, 0px) + 12px);
  max-height: calc(100vh - var(--cmty-pasek-h, 0px) - 28px);
  transition: top 0.26s cubic-bezier(.22, 1, .36, 1), max-height 0.26s cubic-bezier(.22, 1, .36, 1);
}
body.cmty-pasek-schowany .community-detail-karta.w-siatce:not(.pion):has(.cmty-zw-slowka) > .community-detail-panel {
  top: 16px; max-height: calc(100vh - 32px);
}
.cmty-zw-liczby { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; margin-bottom: 14px; }
.cmty-zw-liczba { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border-radius: 16px; background: var(--bg-soft); min-width: 0; }
.cmty-zw-liczba b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.6rem; line-height: 1; color: var(--testo); }
.cmty-zw-liczba span { font-size: 0.75rem; line-height: 1.25; color: var(--grigio); }
.cmty-zw-liczba.zdania { background: var(--bg-success-soft); }
.cmty-zw-liczba.zdania :is(b, span) { color: var(--verde); }
/* (Przyciski karty rozmowy jeden pod drugim: od 2026-10-11 wspólna reguła .cmty-akcje w sekcji 21b dla czterech typów.) */
@media (max-width: 640px) {
  .cmty-zw-tekst { font-size: 0.98rem; }
  .cmty-zw-awatar { width: 34px; height: 34px; font-size: 0.95rem; }
  .cmty-zw-ty .cmty-zw-kolumna { width: 100%; }
  .cmty-zw-siatka { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .cmty-zw-slowo { flex-direction: column; align-items: flex-start; gap: 5px; }
  .cmty-zw-slowo-teksty { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .cmty-zw-odp, .cmty-zw-slowo, .cmty-zw-wiecej button { transition: none; }
  .cmty-zw-odp:is(:hover, :active) { transform: none; }
  .cmty-zw-rzad.wjazd, .cmty-zw-dalej.wjazd { animation: none; }
  .community-detail-karta.w-siatce > .community-detail-panel { transition: none; }
}

/* ---------- 21. KOMENTARZE W KARCIE (2026-10-05) ----------
   Alek przy karcie rozmowy: „wymyśl coś lepszego z komentarzami”. Było: szary nagłówek „Komentarze (0)”, to samo zdanie
   z pauzą pod każdym materiałem, gołe pole i licznik „0/100” pod nim zawsze. Jest: liczba w pigułce, pusta lista jako
   zaproszenie (pod rozmową: „zagraj i napisz, jak poszło”), pole w jednej pigułce z awatarem piszącego i strzałką, która
   ożywa dopiero z tekstem, licznik dopiero od 70 znaków, a pod rozmową przy nicku ukończony poziom (pole `poziom` z serwera).
   Dotyczy każdej karty (zdjęcie, czytanka, utwór, rozmowa): to jeden blok w panelu. */
.community-komentarze-sekcja { gap: 10px; padding-top: 16px; border-top: 1.5px solid var(--border); }
.community-komentarze-naglowek { display: flex; align-items: center; gap: 8px; margin: 0; }
.community-komentarze-naglowek > span:first-child { color: var(--testo); font-weight: 800; }
.community-komentarze-ile:empty { display: none; }
.community-komentarze-ile {
  display: inline-grid; place-items: center; min-width: 24px; height: 24px; padding: 0 7px; border-radius: 999px;
  background: var(--bg-soft); font-family: var(--font-tekst); font-size: 0.78rem; font-weight: 800; color: var(--testo);
}
.community-komentarze-naglowek .community-komentarze-ile { color: var(--testo); font-weight: 800; }
.community-komentarze-lista { margin: 0; }
.community-komentarze-pusto {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-radius: 16px;
  background: var(--bg-soft); color: var(--grigio); font-size: 0.85rem; line-height: 1.4;
}
.community-komentarze-pusto .ico { margin: 0; flex: none; font-size: 1.3rem; color: var(--primary); }
.community-komentarz { gap: 10px; padding: 10px 0; }
.community-komentarz-poziom {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 2px 8px; border-radius: 999px;
  background: var(--bg-highlight); color: var(--testo); font-size: 0.68rem; font-weight: 700; vertical-align: 1px;
}
.community-komentarz-poziom .ico { margin: 0; font-size: 0.7rem; }
.community-komentarz-form {
  align-items: center; gap: 6px; padding: 4px; border: 1.5px solid var(--border-2); border-radius: 999px; background: var(--card-bg);
}
.community-komentarz-form:focus-within { border-color: var(--oro); }
.community-komentarz-ja { flex: none; width: 34px; height: 34px; display: grid; place-items: center; }
.community-komentarz-ja :is(img, span) {
  width: 34px; height: 34px; margin: 0; border-radius: 50%; object-fit: cover;
  display: grid; place-items: center; font-size: 0.85rem; font-weight: 800; color: #FFFFFF;
}
.community-komentarz-ja:empty { display: none; }
.community-komentarz-form input { flex: 1; min-width: 0; min-height: 36px; padding: 0 6px; border: 0; background: transparent; }
.community-komentarz-form input:focus { border: 0; outline: none; }
.community-komentarz-form button { width: 40px; height: 40px; }
.community-komentarz-form button:disabled { background: var(--bg-soft); color: var(--muted-light); cursor: default; filter: none; }
.community-komentarz-licznik { margin-top: -4px; }
@media (pointer: coarse) { .community-komentarz-form button { width: 44px; height: 44px; } }

/* ---------- 21a. PRZYCISKI KARTY UTWORU I CZYTANKI NIE ZNIKAJĄ (2026-10-11) ----------
   Przy „Dodaj do Słuchania” (Alek ze zrzutem karty „Marco Mengoni - Due Vite”: pod opisem od razu komentarze i „Zgłoś
   naruszenie”) wyszło, że CAŁY rząd przycisków karty utworu miał wysokość 0: #communityDetailSlowa dziedziczy po liście
   słówek zdjęcia flex 0 1 auto i min-height 0 („przy ciasnej karcie oddaje miejsce jako pierwsza”), a panel ma max-height
   74vh i overflow hidden. Zmierzone w podglądzie przy 1024 × 768: tytuł 80 px, meta 35, opis z twórcami 128, komentarze
   min. 190, „Zgłoś” 40, więc na „Weź słówka”, „Dodaj do Słuchania” i „Odtwórz film tutaj” zostawało 0 px. Przyciski to nie
   lista chipów do przewijania: rząd się nie kurczy, a gdy panel się nie mieści, przewija się CAŁY panel (komentarze
   i „Zgłoś” dalej osiągalne). Karta rozmowy (kafle .cmty-zw-liczby) ma własną regułę w sekcji 20 i panel sticky.
   Od 2026-10-11 rząd stoi we WŁASNYM wierszu panelu (#communityDetailAkcje, sekcja 21b) dla czterech typów, więc reguła mówi
   o nim, a nie o wierszu słówek; przy zdjęciu nad rzędem zostaje lista chipów, która dalej oddaje miejsce jako pierwsza. */
.community-detail-karta.w-siatce:not(.pion) > .community-detail-panel:has(> #communityDetailAkcje > .cmty-akcje):not(:has(.cmty-zw-liczby)) {
  overflow-y: auto;
}

/* ---------- 21b. JEDEN RZĄD AKCJI W KAŻDEJ KARCIE (2026-10-11) ----------
   Alek: „Ujednolić przyciski w Społeczności, bo na razie, niezależnie od tego, czy wejdę w scenariusz do dodania do Mówienia,
   czy film do Słuchania, czy czytankę, czy ze zdjęcia fiszki, każda ma inne przyciski, a wszystkie mają na celu to samo”. JS:
   sekcja JEDEN WZÓR DODAWANIA ZE SPOŁECZNOŚCI. Zdjęcie, czytanka, utwór i rozmowa mają rząd w tym samym wierszu panelu
   (#communityDetailAkcje: pod treścią karty, nad komentarzami) i w układzie, który karta rozmowy dostała z kanwy „Zawartość
   rozmowy Mówienia”: przyciski jeden pod drugim na całą szerokość panelu, główny „Dodaj do …” (z kółkiem) pierwszy, szare
   pod nim. Dawniej czytanka i utwór kładły je w zawijany rząd szerokości napisów, a zdjęcie nie miało ich wcale. Wiersz się
   nie kurczy (flex 0 0 auto): to przyciski, nie lista do przewijania (sekcja 21a). */
#communityDetailAkcje { flex: 0 0 auto; margin-bottom: 14px; }
#communityDetailAkcje:empty { display: none; }
.cmty-akcje { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
.cmty-akcje .btn { width: 100%; min-height: 44px; margin: 0; }
#communityDetailAkcje > .cmty-lekcja { margin-top: 10px; }

/* ---------- 22. PROFIL GRACZA I PASSA W STYLU KANWY (2026-10-06) ----------
   Projekt „Profil i passa Lingaria” (https://claude.ai/artifact/ByypKHbCXrrRc9fX61nBQC). Alek: „Zaprojektuj lepszy wygląd bocznej karty
   od rankingu w stylu aplikacji. Zaprojektuj też lepszy design dla daystreak”, po projekcie: „podoba mi się … zajmij się teraz
   wdrożeniem tego, co zaprojektowałeś”. Głowa profilu to granatowy blok marki (barwy stałe w obu motywach, jak ekrany marki), karty pod
   nią stoją na tokenach motywu. Okno passy to okno marki na żółtym (barwy stałe: tokeny przestawione w .ps-okno), dymek passy pod
   licznikiem na tokenach motywu. Układ profilu liczy się od szerokości PANELU (container query), bo panel ma 46vw. */
.profil-tresc { container-type: inline-size; }
.pp-glowa { display: flex; flex-direction: column; gap: 18px; padding: 14px 22px 20px; border-radius: 28px; background: var(--granat); color: #FFFFFF; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .pp-glowa { box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.08); } }
:root[data-theme="dark"] .pp-glowa { box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.08); }
.pp-glowa-gora { display: flex; justify-content: flex-end; align-items: center; min-height: 30px; }
.pp-twoj { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--zolty); }
.pp-ja { display: flex; align-items: center; gap: 18px; min-width: 0; }
.pp-awatar { flex: none; }
.pp-awatar .leaderboard-avatar-img, .pp-awatar .leaderboard-avatar-fallback {
  width: 92px; height: 92px; border-radius: 999px; object-fit: cover; box-shadow: 0 0 0 4px var(--zolty);
  display: flex; align-items: center; justify-content: center; font-family: var(--font-naglowek); font-weight: 800; font-size: 2.3rem; color: #FFFFFF;
}
.pp-awatar .profil-zapelnienie { border-radius: 999px; }
.pp-ja-teksty { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pp-imie { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pp-imie h2 { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.75rem; line-height: 1.1; color: #FFFFFF; overflow-wrap: anywhere; }
.pp-imie .rank-row-flag { flex: none; line-height: 0; }
.pp-nick { font-size: 0.92rem; color: #B9BCD6; }
.pp-pigulki { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; }
.pp-pigulka { display: inline-flex; align-items: center; min-height: 30px; padding: 0 12px; border-radius: 999px; background: rgba(255, 255, 255, 0.1);
  font-size: 0.8rem; font-weight: 600; color: #DADCF0; }
.pp-glowa .tw-odznaka { --tw-tlo: rgba(255, 255, 255, 0.1); --tw-ramka: transparent; --tw-tekst: #FFFFFF; min-height: 30px; }
.pp-obserwuj { align-self: flex-start; display: inline-flex; align-items: center; gap: 8px; min-height: 48px; padding: 0 22px; border: 0; border-radius: 999px;
  background: var(--zolty); color: var(--granat); font: inherit; font-size: 0.95rem; font-weight: 800; cursor: pointer; transition: transform 0.15s ease; }
.pp-obserwuj:hover { transform: translateY(-1px); }
.pp-obserwuj.obserwujesz { background: rgba(255, 255, 255, 0.12); color: #FFFFFF; }
.pp-obserwuj .ico { margin: 0; }
.pp-obserwuj:focus-visible, .pp-glowa .profil-liczba:focus-visible { outline: 3px solid var(--zolty); outline-offset: 2px; }
.pp-kafle { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.pp-kafel { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 14px 16px; border-radius: 20px;
  background: rgba(255, 255, 255, 0.08); box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.12); }
.pp-kafel-linga { background: var(--zolty); color: var(--granat); box-shadow: none; }
.pp-kafel-gora { display: flex; align-items: center; justify-content: space-between; gap: 6px; min-height: 26px; }
.pp-kafel-gora .ico { margin: 0; font-size: 1.25rem; line-height: 1; }
.pp-ikona-xp { color: #8EB0FF; }
.pp-trend { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; background: rgba(23, 24, 59, 0.12); font-size: 0.85rem; }
.pp-trend .ico { margin: 0; font-size: 0.95rem; }
.pp-kafel-liczba { margin-top: 6px; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.9rem; line-height: 1.05;
  font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pp-kafel-liczba small { font-size: 1rem; }
.pp-kafel-podpis { font-size: 0.8rem; font-weight: 700; color: #DADCF0; }
.pp-kafel-linga .pp-kafel-podpis { color: var(--granat); }
.pp-kafel-passa .profil-passa-ogien { display: inline-block; width: 22px; height: 26px; line-height: 0; }
.pp-kafel-passa.stan-zabity { opacity: 0.75; }
.pp-postep { display: flex; flex-direction: column; gap: 8px; }
.pp-postep-wiersz { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 0.88rem; }
.pp-postep-wiersz b { font-weight: 700; }
.pp-postep-wiersz span { color: #B9BCD6; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pp-postep-tor { height: 12px; border-radius: 999px; background: rgba(255, 255, 255, 0.14); overflow: hidden; }
.pp-postep-tor > div { height: 100%; border-radius: 999px; background: var(--zolty); transition: width 0.6s cubic-bezier(.22, 1, .36, 1); }
.pp-postep-jasny .pp-postep-wiersz span { color: var(--grigio); }
.pp-postep-jasny .pp-postep-tor { height: 10px; background: var(--bg-soft); }
.pp-postep-jasny .pp-postep-tor > div { background: var(--marka-niebieski); }
.pp-glowa .profil-liczby { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; padding-top: 14px; border-top: 1.5px solid rgba(255, 255, 255, 0.12); }
.pp-glowa .profil-liczba { min-width: 0; padding: 6px 2px; border: 0; border-radius: 14px; background: none; color: #FFFFFF; font: inherit; text-align: center; }
.pp-glowa .profil-liczba.klik { cursor: pointer; }
.pp-glowa .profil-liczba.klik:hover { background: rgba(255, 255, 255, 0.08); }
.pp-glowa .profil-liczba b { display: block; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.3rem; line-height: 1.2; }
.pp-glowa .profil-liczba span { display: block; font-size: 0.78rem; color: #B9BCD6; overflow-wrap: anywhere; }
/* Karty pod głową: dwie kolumny w szerokim panelu, jedna w wąskim. */
.pp-siatka { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 14px; align-items: start; }
.pp-szeroka { grid-column: 1 / -1; }
.pp-karta { display: flex; flex-direction: column; gap: 14px; min-width: 0; padding: 20px 22px; border-radius: 24px;
  background: var(--card-bg); border: 1.5px solid var(--border); color: var(--testo); }
.pp-karta-glowa { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.pp-h { margin: 0; display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.2rem; line-height: 1.2; color: var(--testo); }
.pp-maly { font-size: 0.82rem; color: var(--grigio); }
.pp-licznik { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; height: 26px; padding: 0 8px; border-radius: 999px;
  background: var(--bg-soft); font-family: var(--font-body, inherit); font-size: 0.8rem; font-weight: 800; }
.pp-suma { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.pp-suma b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.75rem; line-height: 1.1; }
.pp-suma span { font-size: 0.85rem; color: var(--grigio); }
.pp-przelacznik { display: inline-flex; flex-wrap: wrap; gap: 4px; padding: 4px; border-radius: 999px; background: var(--bg-soft); }
.pp-przelacznik button { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 14px; border: 0; border-radius: 999px;
  background: transparent; color: var(--grigio); font: inherit; font-size: 0.86rem; font-weight: 700; cursor: pointer; }
.pp-przelacznik button .ico { margin: 0; }
.pp-przelacznik button b { font-weight: 800; }
.pp-przelacznik button.aktywna { background: var(--zolty); color: var(--granat); font-weight: 800; }
.pp-przelacznik button:focus-visible { outline: 3px solid var(--oro); outline-offset: 1px; }
/* Wykres XP (buildXpChartSvg): słupki na tokenach, żeby ciemny motyw nie dostał białych pasów. */
.pp-wyk-linia { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 4; }
.pp-wyk-linia.zero { stroke: var(--border-2); stroke-width: 1.5; stroke-dasharray: none; }
.pp-wyk-os { fill: var(--grigio); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.pp-wyk-dzien { fill: var(--testo); font-size: 11px; font-weight: 700; }
.pp-wyk-wartosc { fill: var(--grigio); font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.pp-slupek { fill: color-mix(in srgb, var(--marka-niebieski) 45%, var(--card-bg)); }
.pp-slupek.max, .pp-slupek.oni { fill: var(--marka-niebieski); }
.pp-slupek.dzis, .pp-slupek.ja { fill: var(--zolty); }
.pp-slupek.minus { fill: var(--marka-czerwony); }
.pp-slupek.zero { fill: var(--border); }
.pp-wyk-legenda { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 4px; font-size: 0.82rem; font-weight: 700; color: var(--grigio); }
.pp-wyk-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.pp-kropka { display: inline-block; width: 10px; height: 10px; border-radius: 3px; }
.pp-kropka.oni { background: var(--marka-niebieski); }
.pp-kropka.ja { background: var(--zolty); }
/* Słówka: barwy poziomów z logo, kafel poziomu na tle tej barwy rozmytej w kolorze karty (działa w obu motywach). */
.pp-poz-latwe { --pp-poz: var(--marka-zielony); }
.pp-poz-srednie { --pp-poz: var(--marka-niebieski); }
.pp-poz-trudne { --pp-poz: var(--marka-czerwony); }
.pp-poz-nowe { --pp-poz: #9EA3BE; }
.pp-duza { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pp-duza b { font-family: var(--font-naglowek); font-weight: 800; font-size: 2.3rem; line-height: 1; }
.pp-duza span { font-size: 0.88rem; color: var(--grigio); }
.pp-pasek { display: flex; gap: 2px; height: 14px; border-radius: 999px; overflow: hidden; background: var(--bg-soft); }
.pp-pasek span { display: block; height: 100%; background: var(--pp-poz); }
.pp-poziomy { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.pp-poziom { display: flex; flex-direction: column; padding: 10px 12px; border-radius: 14px; background: color-mix(in srgb, var(--pp-poz) 15%, var(--card-bg)); }
.pp-poziom b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.25rem; color: var(--testo); }
.pp-poziom span { display: inline-flex; align-items: center; gap: 6px; font-size: 0.8rem; font-weight: 600; color: var(--testo); }
.pp-poziom span::before { content: ''; width: 8px; height: 8px; flex: none; border-radius: 999px; background: var(--pp-poz); }
.pp-tematy { display: flex; flex-direction: column; gap: 12px; }
.pp-temat { display: flex; flex-direction: column; gap: 5px; }
.pp-temat-wiersz { display: flex; justify-content: space-between; gap: 8px; font-size: 0.9rem; }
.pp-temat-wiersz span { min-width: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pp-temat-wiersz b { font-weight: 800; font-variant-numeric: tabular-nums; }
.pp-temat-tor { height: 8px; border-radius: 999px; background: color-mix(in srgb, var(--marka-niebieski) 14%, var(--card-bg)); overflow: hidden; }
.pp-temat-tor span { display: block; height: 100%; border-radius: 999px; background: color-mix(in srgb, var(--marka-niebieski) 62%, var(--card-bg)); }
.pp-temat-tor span.pierwszy { background: var(--marka-niebieski); }
.pp-trudne { display: flex; flex-direction: column; }
.pp-trudne-poz { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1.5px solid var(--bg-soft); }
.pp-trudne-poz:first-child { padding-top: 0; border-top: 0; }
.pp-flaga { flex: none; line-height: 0; }
.pp-flaga svg { border-radius: 2px; }
.pp-trudne-slowo { flex: 1; min-width: 0; font-size: 0.98rem; line-height: 1.4; overflow-wrap: anywhere; }
.pp-trudne-slowo b { font-weight: 800; }
.pp-trudne-slowo span { color: var(--grigio); }
.pp-trudne-tor { flex: none; width: 84px; height: 6px; border-radius: 999px; background: var(--bg-error-soft); overflow: hidden; }
.pp-trudne-tor span { display: block; height: 100%; border-radius: 999px; background: var(--marka-czerwony); }
.pp-trudne-ile { flex: none; min-width: 84px; text-align: right; font-size: 0.82rem; font-weight: 800; color: var(--rosso); }
.pp-pusto { margin: 0; font-size: 0.88rem; color: var(--grigio); }
.pp-rekordy { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px; }
.pp-rekord { display: flex; flex-direction: column; gap: 3px; padding: 14px; border-radius: 18px; background: color-mix(in srgb, var(--pp-rek) 16%, var(--card-bg)); }
.pp-rekord-passa { --pp-rek: var(--zolty); --pp-rek-ikona: var(--marka-czerwony); }
.pp-rekord-combo { --pp-rek: var(--marka-niebieski); --pp-rek-ikona: var(--marka-niebieski); }
.pp-rekord-celnosc { --pp-rek: var(--marka-zielony); --pp-rek-ikona: var(--marka-zielony); }
.pp-rekord-dni { --pp-rek: #9EA3BE; --pp-rek-ikona: var(--testo); }
.pp-rekord-ikona .ico { margin: 0; font-size: 1.2rem; color: var(--pp-rek-ikona); }
.pp-rekord b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.35rem; line-height: 1.15; }
.pp-rekord > span:last-child { font-size: 0.8rem; font-weight: 600; color: var(--testo); }
.pp-jezyki { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 0.88rem; }
.pp-jezyki > span:first-child { font-weight: 600; color: var(--grigio); }
.pp-jezyk { display: inline-flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 14px; border-radius: 999px; border: 1.5px solid var(--border); font-weight: 700; }
.pp-jezyk svg { border-radius: 2px; }
/* Galeria twórcy: kafle jak na tablicy Społeczności (okładka, tytuł, jedna linijka), liczby na okładce. */
.pp-gal { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 14px; }
.pp-gal-kafel { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 0; border: 0; background: none; color: var(--testo); font: inherit; text-align: left; cursor: pointer; }
.pp-gal-okladka { position: relative; display: block; aspect-ratio: 1 / 1; border-radius: 18px; overflow: hidden; background: var(--bg-soft); }
.pp-gal-okladka img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.2s ease; }
.pp-gal-kafel:hover .pp-gal-okladka img { transform: scale(1.04); }
.pp-gal-kafel:focus-visible { outline: 3px solid var(--oro); outline-offset: 3px; border-radius: 18px; }
.pp-gal-flaga { position: absolute; left: 8px; top: 8px; z-index: 1; line-height: 0; border-radius: 3px; overflow: hidden; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); }
.pp-gal-liczby { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; display: flex; justify-content: space-evenly; gap: 2px; padding: 18px 6px 7px;
  background: linear-gradient(180deg, rgba(23, 24, 59, 0) 0%, rgba(23, 24, 59, 0.72) 62%); color: #FFFFFF; font-size: 0.72rem; font-weight: 800; pointer-events: none; }
.pp-gal-liczby > span { display: inline-flex; align-items: center; gap: 4px; }
.pp-gal-liczby .ico { margin: 0; font-size: 0.75rem; }
.pp-gal-liczby > span.pusto { opacity: 0.5; }
.pp-gal-film { background: #111111; }
.pp-gal-play { position: absolute; left: 50%; top: 44%; z-index: 1; display: flex; align-items: center; justify-content: center; width: 46px; height: 46px;
  border-radius: 999px; background: #FFFFFF; color: var(--marka-czerwony); transform: translate(-50%, -50%); }
.pp-gal-play .ico { margin: 0 0 0 2px; }
.pp-gal-zrodlo { position: absolute; left: 8px; top: 8px; z-index: 1; padding: 3px 8px; border-radius: 999px; background: rgba(23, 24, 59, 0.6); color: #FFFFFF; font-size: 0.68rem; font-weight: 800; }
.pp-gal-kartka { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 10px; padding: 16px 16px 34px;
  background: color-mix(in srgb, var(--marka-niebieski) 12%, var(--card-bg)); }
.pp-gal-cudzyslow { font-family: var(--font-naglowek); font-weight: 800; font-size: 3rem; line-height: 0.6; color: var(--marka-niebieski); }
.pp-gal-poziom { display: inline-flex; align-items: center; min-height: 28px; padding: 0 12px; border-radius: 999px; background: var(--card-bg); font-size: 0.8rem; font-weight: 800; }
.pp-gal-tytul { font-size: 0.9rem; font-weight: 800; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pp-gal-meta { display: inline-flex; align-items: center; gap: 6px; font-size: 0.78rem; color: var(--grigio); }
.pp-gal-meta svg { border-radius: 2px; }
/* Twórca w Społeczności */
.pp-wskaznik { align-self: flex-start; padding: 4px 12px; border-radius: 999px; background: var(--bg-soft); font-size: 0.85rem; font-weight: 800; }
.pp-wskaznik.dobry { color: var(--verde); }
.pp-wskaznik.sredni { color: #9A6407; }
.pp-wskaznik.slaby { color: var(--rosso); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .pp-wskaznik.sredni { color: #E5B23C; } }
:root[data-theme="dark"] .pp-wskaznik.sredni { color: #E5B23C; }
.pp-tw-kafle { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.pp-tw-kafel { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 12px 14px; border-radius: 16px; border: 1.5px solid var(--border); }
.pp-tw-kafel b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.35rem; }
.pp-tw-kafel span { font-size: 0.8rem; line-height: 1.35; color: var(--grigio); }
.pp-tw-status { margin: 0; font-size: 0.88rem; line-height: 1.55; color: var(--grigio); }
.pp-karta .tw-blokada { margin-top: 0; }
@media (prefers-reduced-motion: reduce) {
  .pp-gal-kafel:hover .pp-gal-okladka img, .pp-obserwuj:hover { transform: none; }
  .pp-postep-tor > div { transition: none; }
}
@container (max-width: 560px) {
  .pp-siatka { grid-template-columns: minmax(0, 1fr); }
  .pp-ja { flex-direction: column; text-align: center; }
  .pp-imie, .pp-pigulki { justify-content: center; }
  .pp-obserwuj { align-self: stretch; justify-content: center; }
  .pp-kafle { gap: 8px; }
  .pp-kafel { padding: 12px 10px; }
  .pp-kafel-liczba { font-size: 1.25rem; }
  .pp-glowa .profil-liczba b { font-size: 1.1rem; }
  .pp-glowa .profil-liczba span { font-size: 0.7rem; }
  .pp-karta { padding: 18px; }
  .pp-trudne-tor { display: none; }
  .pp-trudne-ile { min-width: 0; }
  .pp-tw-kafle { gap: 8px; }
  .pp-tw-kafel { padding: 10px 12px; }
}

/* PASSA: dymek pod licznikiem (na tokenach motywu) */
.ps-dymek-glowa { display: flex; align-items: center; gap: 12px; }
.ps-dymek-ogien { display: flex; align-items: center; justify-content: center; flex: none; width: 50px; height: 50px; border-radius: 16px;
  background: color-mix(in srgb, var(--zolty) 24%, var(--card-bg)); }
.ps-ogien-host { display: inline-block; width: 28px; height: 33px; line-height: 0; }
.ps-dymek-teksty { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ps-dymek-teksty b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.4rem; line-height: 1.1; }
.ps-stan { font-size: 0.8rem; font-weight: 700; }
.ps-stan.tak { color: var(--verde); }
.ps-stan.nie { color: var(--rosso); }
.ps-zamr-chip { display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 5px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--marka-niebieski) 16%, var(--card-bg)); color: var(--marka-niebieski); font-size: 0.8rem; font-weight: 800; }
.ps-zamr-chip .ico { margin: 0; }
.ps-sekcja { margin-top: 14px; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; color: var(--grigio); }
.ps-tydzien { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); margin-top: 6px; }
.ps-tydz-dzien { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.ps-tydz-dzien > span { font-size: 0.72rem; font-weight: 700; color: var(--grigio); }
.ps-rekord { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.ps-rekord-wiersz { display: flex; justify-content: space-between; gap: 8px; font-size: 0.82rem; }
.ps-rekord-wiersz span { color: var(--grigio); white-space: nowrap; }
.ps-rekord-tor { height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.ps-rekord-tor > div { height: 100%; border-radius: 999px; background: var(--zolty); }
.ps-dymek-stopka { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 14px; padding-top: 12px;
  border-top: 1.5px solid var(--bg-soft); font-size: 0.8rem; color: var(--grigio); }
.ps-link { display: inline-flex; align-items: center; gap: 2px; flex: none; padding: 0; border: 0; background: none; color: var(--marka-niebieski);
  font: inherit; font-size: 0.82rem; font-weight: 800; cursor: pointer; }
.ps-link .ico { margin: 0; }
/* Dzień w kalendarzu: kółko na pasku ciągłości passy. */
.ps-dzien { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 42px; }
.ps-kolko { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; box-sizing: border-box;
  border-radius: 999px; background: var(--card-bg); color: var(--grigio); font-size: 0.8rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.ps-kolko .ico { margin: 0; font-size: 0.95rem; line-height: 1; }
.ps-nauka .ps-kolko { background: var(--zolty); }
.ps-zamrozenie .ps-kolko { background: color-mix(in srgb, var(--marka-niebieski) 22%, var(--card-bg)); color: var(--marka-niebieski); }
.ps-pusty .ps-kolko { border: 1.5px solid var(--border); }
.ps-przyszly .ps-kolko { border: 1.5px dashed var(--border-2); background: transparent; }
.ps-dzien.dzis .ps-kolko { box-shadow: 0 0 0 2.5px var(--card-bg), 0 0 0 5px var(--testo); }
.ps-pusty.dzis .ps-kolko { border-style: dashed; }
.ps-plomyk { display: block; width: 16px; height: 18px; }
.ps-pas { position: absolute; top: 9px; bottom: 9px; left: 50%; right: 50%; background: color-mix(in srgb, var(--zolty) 45%, var(--card-bg)); }
.ps-pas.lewo { left: 0; }
.ps-pas.prawo { right: 0; }
/* PASSA: okno marki na żółtym. Tokeny przestawione na jasne, bo okno marki ma barwy stałe w obu motywach (białe karty na żółtym). */
.ps-okno { max-width: 460px; --card-bg: #FFFFFF; --testo: #17183B; --grigio: #4A4B6B; --border: #E3E4EF; --border-2: #C9CCE0; --bg-soft: #EEF0F7; }
.ps-glowa { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0 24px 4px; text-align: center; }
.ps-okno #streakBigFlame { width: 92px; height: 108px; margin: -16px auto 0; font-size: 3.4rem; line-height: 0; }
.ps-okno #streakBigCount.ps-liczba { font-family: var(--font-naglowek); font-weight: 800; font-size: 4.6rem; line-height: 0.95; letter-spacing: -0.03em;
  color: var(--granat); font-variant-numeric: tabular-nums; }
.ps-liczba-podpis { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.2rem; color: var(--granat); }
.ps-stan-pigulka { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; margin-top: 10px; padding: 0 16px; border-radius: 999px;
  background: #FFFFFF; color: var(--granat); font-size: 0.9rem; font-weight: 700; }
.ps-stan-pigulka .ico { margin: 0; }
.ps-stan-pigulka.tak .ico { color: #1F7A35; }
.ps-stan-pigulka.nie .ico { color: var(--marka-czerwony); }
.ps-tresc { display: flex; flex-direction: column; gap: 14px; }
.ps-kafle { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.ps-kafel { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 12px; border-radius: 18px; background: #FFFFFF; color: var(--granat); }
.ps-kafel .ico { margin: 0 0 4px; font-size: 1.05rem; line-height: 1; }
.ps-kafel b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.3rem; line-height: 1.15; }
.ps-kafel span { font-size: 0.78rem; font-weight: 600; color: #4A4B6B; }
.ps-kafel.zamrozenia .ico, .ps-kafel.zamrozenia b { color: var(--marka-niebieski); }
.ps-kafel.teraz { background: var(--granat); color: #FFFFFF; }
.ps-kafel.teraz span { color: #D4D5F0; }
.ps-kafel.teraz .ico { color: var(--zolty); }
.ps-kal { padding: 16px; border-radius: 22px; background: #FFFFFF; color: var(--granat); }
.ps-kal-tytul { margin: 0 0 10px; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; }
.ps-kal-dni { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); margin-bottom: 4px; text-align: center; font-size: 0.72rem; font-weight: 700; color: var(--grigio); }
.ps-kal-siatka { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); row-gap: 4px; }
.ps-legenda { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 14px; margin-top: 10px; font-size: 0.74rem; font-weight: 600; color: var(--grigio); }
.ps-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.ps-leg { display: inline-block; width: 12px; height: 12px; box-sizing: border-box; border-radius: 999px; }
.ps-leg.nauka { background: var(--zolty); }
.ps-leg.zamrozenie { background: color-mix(in srgb, var(--marka-niebieski) 22%, var(--card-bg)); }
.ps-leg.pusty { border: 1.5px solid var(--border); }
.ps-leg.pas { width: 20px; height: 8px; background: color-mix(in srgb, var(--zolty) 45%, var(--card-bg)); }
.ps-kal-podsumowanie { margin-top: 8px; text-align: center; font-size: 0.86rem; font-weight: 800; }
.ps-zasady { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border-radius: 20px; background: rgba(255, 255, 255, 0.55);
  color: var(--granat); font-size: 0.9rem; line-height: 1.5; }
.ps-zasady > div { display: flex; align-items: flex-start; gap: 12px; }
.ps-zasady .ico { flex: none; margin: 3px 0 0; }
.ps-zasady strong { font-weight: 800; }
.ps-okno .om-akcje { margin-top: 4px; }
@media (max-width: 420px) {
  .ps-kafle { gap: 6px; }
  .ps-kafel { padding: 10px; }
  .ps-kafel b { font-size: 1.1rem; }
  .ps-kolko { width: 32px; height: 32px; }
}

/* ---------- 23. „DOBRANE DO CIEBIE” W ODKRYWAJ (2026-10-07) ----------
   Kanwa „Odkrywaj i dłuższe rozmowy”, plansze „Odkrywaj na komputerze” i „na telefonie”: biała karta z nagłówkiem, opisem celów
   i dwoma małymi przyciskami, pod nią cztery karty trybów (okładka w barwie trybu, pigułka trybu, powód z żarówką, tytuł, meta,
   granatowa pigułka z żółtym kółkiem). Na telefonie karty przesuwa się w bok (scroll-snap), na szerokim ekranie stoją w rzędzie.
   Barwy trybów stałe w obu motywach (jak okładki): Mówienie zielone, Zdjęcie żółte, Czytanie niebieskie, Słuchanie czerwone. */
/* flex-wrap: nowrap - dawna belka ma na telefonie wrap, a w kolumnie z zawijaniem szerokość „linii” liczy się z treści:
   opis i rząd kart wychodziły poza kartę (zmierzone na 375 px: rząd kart 476 px w karcie 345 px). */
.cmty-polecany.odk {
  display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 16px;
  background: var(--card-bg); border: 1.5px solid var(--border); border-radius: 24px; padding: 20px 20px 22px;
}
.odk-glowa { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 20px; }
.odk-glowa-tekst { flex: 1 1 420px; min-width: 0; }
.odk-naglowek { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.45rem; line-height: 1.15; color: var(--testo); }
.odk-opis { margin: 4px 0 0; font-size: 0.9rem; color: var(--grigio); }
.odk-opis b { color: var(--testo); font-weight: 800; }
.odk-przyciski { display: flex; flex-wrap: wrap; gap: 8px; }
.odk-maly {
  display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 16px; margin: 0; border-radius: 999px;
  border: 1.5px solid var(--border); background: var(--card-bg); color: var(--testo);
  font: inherit; font-size: 0.84rem; font-weight: 700; cursor: pointer;
}
.odk-maly:hover { border-color: var(--oro); }
.odk-maly .ico { margin: 0; }
.odk-karty { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; min-width: 0; }
.odk-karta {
  display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  border: 1.5px solid var(--border); border-radius: 20px; background: var(--card-bg);
}
.odk-okladka {
  position: relative; display: block; width: 100%; height: 150px; padding: 0; margin: 0; border: 0; overflow: hidden; cursor: pointer;
  background: var(--k); --k: var(--marka-niebieski);
}
.odk-okladka.odk-zielony, .odk-kropka.odk-zielony { --k: var(--marka-zielony, #35A64D); }
.odk-okladka.odk-zolty, .odk-kropka.odk-zolty { --k: var(--zolty); }
.odk-okladka.odk-niebieski, .odk-kropka.odk-niebieski { --k: var(--marka-niebieski); }
.odk-okladka.odk-czerwony, .odk-kropka.odk-czerwony { --k: var(--marka-czerwony); }
.odk-foto { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .35s ease; }
.odk-ilustracja { position: absolute; right: 8px; bottom: 0; height: 140px; width: auto; transition: transform .35s ease; }
.odk-okladka:hover .odk-foto, .odk-okladka:hover .odk-ilustracja { transform: scale(1.04); }
.odk-cytat {
  position: absolute; left: 14px; top: 44px; right: 104px; text-align: left;
  font-style: italic; font-size: 0.8rem; line-height: 1.45; color: #FFFFFF;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.odk-tryb {
  position: absolute; left: 10px; top: 10px; display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 12px; border-radius: 999px; background: #FFFFFF; color: var(--granat);
  font-weight: 800; font-size: 0.75rem;
}
.odk-kropka { width: 8px; height: 8px; border-radius: 50%; background: var(--k); }
.odk-najlepiej {
  position: absolute; right: 10px; top: 10px; display: inline-flex; align-items: center; height: 28px; padding: 0 12px;
  border-radius: 999px; background: var(--granat); color: var(--zolty); font-weight: 800; font-size: 0.75rem;
}
.odk-tresc { flex: 1; display: flex; flex-direction: column; gap: 6px; padding: 12px 14px 14px; min-width: 0; }
.odk-powod { margin: 0; display: flex; align-items: flex-start; gap: 6px; font-size: 0.78rem; font-weight: 700; color: var(--grigio); }
.odk-powod .ico { margin: 2px 0 0; color: var(--marka-niebieski); }
.odk-tytul { margin: 0; font-family: var(--font-naglowek); font-weight: 700; font-size: 1.05rem; line-height: 1.25; }
.odk-tytul button {
  padding: 0; margin: 0; border: 0; background: none; font: inherit; color: var(--testo); text-align: left; cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.odk-tytul button:hover { text-decoration: underline; }
.odk-meta { margin: 0; font-size: 0.8rem; color: var(--grigio); }
.odk-akcja {
  margin: auto 0 0; align-self: flex-start; display: inline-flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 0 5px 0 16px; border: 0; border-radius: 999px; background: var(--oro); color: var(--na-akcencie, #FFFFFF);
  font: inherit; font-weight: 800; font-size: 0.86rem; cursor: pointer;
}
.odk-tresc .odk-akcja { margin-top: 8px; }
/* Kółko ze strzałką jak w .btn-strzalka: te same tokeny motywu (w jasnym żółte kółko na granacie, w ciemnym granatowe na żółtym). */
.odk-kolko {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--przycisk-kolko) var(--przycisk-kolko-strzalka) center / 18px 18px no-repeat;
}
[dir="rtl"] .odk-kolko, [dir="rtl"] .mow-kafelek-odblokuj-kolko, [dir="rtl"] .cmty-zw-premium-kolko { transform: scaleX(-1); }
@media (max-width: 1100px) { .odk-karty { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .cmty-polecany.odk { padding: 16px 0 18px; border-radius: 20px; }
  .odk-glowa { padding: 0 16px; }
  .odk-naglowek { font-size: 1.25rem; }
  .odk-karty { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 12px; padding: 0 16px 4px; scrollbar-width: none; }
  .odk-karty::-webkit-scrollbar { display: none; }
  .odk-karta { flex: 0 0 82%; scroll-snap-align: start; }
}
@media (prefers-reduced-motion: reduce) { .odk-foto, .odk-ilustracja { transition: none; } }

/* ---------- 24. DŁUŻSZA ROZMOWA NA KONCIE DARMOWYM (2026-10-07) ----------
   Ta sama kanwa, plansze „Karta rozmowy, konto darmowe” i „Kafel na tablicy i na mapie Mówienia”. Kafel mapy: przygaszona okładka,
   granatowe kółko z żółtą kłódką, pogrubiona liczba kwestii i żółte „Odblokuj z Premium” w miejscu pigułek poziomów. Kafel tablicy:
   granatowa pigułka „Premium” z kłódką na okładce, widoczna zawsze. Karta: kafel kwestii na żółtym tle i granatowy blok Premium
   zamiast „Zagraj”. */
.mow-kafelek.premium-kwestii .mow-kafelek-foto img { filter: saturate(.35); }
.mow-kafelek { position: relative; }
.mow-kafelek-zamek {
  position: absolute; left: 14px; top: 14px; z-index: 2; width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; background: var(--granat); color: var(--zolty);
}
.mow-kafelek-zamek .ico { margin: 0; }
.mow-kafelek-kwestii-premium { font-weight: 800; color: var(--testo); }
.mow-kafelek-odblokuj {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 5px 0 14px; margin: 0; border: 0;
  border-radius: 999px; background: var(--zolty); color: var(--granat); font: inherit; font-weight: 800; font-size: 0.8rem; cursor: pointer;
  white-space: nowrap;
}
.mow-kafelek.premium-kwestii .mow-kafelek-glowa > .ico { color: var(--granat); }
/* Żółta pigułka marki ma w obu motywach granatowe kółko z żółtą strzałką (jak .na-granacie .btn-strzalka). */
.mow-kafelek-odblokuj-kolko, .cmty-zw-premium-kolko {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--granat) var(--strzalka-zolta) center / 18px 18px no-repeat;
}
.tekst-wiersz.premium-kwestii .tekst-poziom { background: var(--granat); color: var(--zolty); }
.pin-premium {
  position: absolute; left: 10px; top: 10px; z-index: 3; display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 11px; border-radius: 999px; background: var(--granat); color: var(--zolty);
  font-weight: 800; font-size: 0.75rem; pointer-events: none;
}
.pin-premium .ico { margin: 0; font-size: 0.8rem; }
.pin-kwestii-premium { font-weight: 800; color: var(--testo); }
.cmty-zw-pigulka.premium { background: var(--granat); color: var(--zolty); display: inline-flex; align-items: center; gap: 6px; }
.cmty-zw-pigulka.premium .ico { margin: 0; }
.cmty-zw-liczba.premium { background: color-mix(in srgb, var(--zolty) 18%, var(--card-bg)); border-color: var(--zolty); }
.cmty-zw-liczba.premium b { display: inline-flex; align-items: center; gap: 6px; }
.cmty-zw-liczba.premium b .ico { margin: 0; font-size: 0.85rem; }
.cmty-zw-premium {
  display: flex; align-items: center; gap: 14px; padding: 18px 20px; border-radius: 22px;
  background: var(--granat); color: #FFFFFF;
}
.cmty-zw-premium-tresc { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.cmty-zw-premium-pigulka {
  align-self: flex-start; height: 24px; padding: 0 10px; border-radius: 999px; display: inline-flex; align-items: center;
  background: var(--zolty); color: var(--granat); font-weight: 800; font-size: 0.72rem;
}
.cmty-zw-premium h3 { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.2rem; line-height: 1.2; color: #FFFFFF; }
.cmty-zw-premium p { margin: 0; font-size: 0.88rem; line-height: 1.5; color: #D9DCEC; }
.cmty-zw-premium-akcje { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 6px; }
.cmty-zw-premium-btn {
  display: inline-flex; align-items: center; gap: 10px; min-height: 46px; padding: 0 5px 0 18px; margin: 0; border: 0;
  border-radius: 999px; background: var(--zolty); color: var(--granat); font: inherit; font-weight: 800; font-size: 0.88rem; cursor: pointer;
}
.cmty-zw-premium-link {
  padding: 0; margin: 0; border: 0; background: none; color: #FFFFFF; font: inherit; font-weight: 700; font-size: 0.88rem;
  text-decoration: underline; cursor: pointer; min-height: 44px;
}
.cmty-zw-premium-img { flex: none; width: 96px; height: auto; align-self: flex-end; }
/* Wąski panel karty (karta w siatce tablicy ma przy 1280 px ~190 px na blok): obrazek schodzi, tekst dostaje całą szerokość. */
/* Od 2026-10-11 blok stoi we wspólnym rzędzie akcji (.cmty-akcje, sekcja 21b) na miejscu „Dodaj do Mówienia”. */
.cmty-akcje:has(> .cmty-zw-premium) { container-type: inline-size; }
@container (max-width: 380px) { .cmty-zw-premium-img { display: none; } }

/* ---------- 25. PRÓBKI PREMIUM (2026-10-11) ----------
   Kontrakt próbek (Alek: „jednak nie chcę darmowego Premium na 60 minut”): dłuższa rozmowa z wolną próbką albo ta, na którą próbka poszła,
   ma zamiast kłódki żółty chip „Próbka Premium” (żółty jak Chip premium w aplikacji: to prezent, nie zamek). Kafel mapy: chip w stopce przed
   liczbą kwestii; kafel tablicy: pigułka w rogu okładki tam, gdzie stała granatowa „Premium”; karta: pigułka na okładce. Barwy stałe w obu
   motywach (leżą na obrazku albo są znakiem marki). Plansza „Tak działa Premium” to wariant ściany (sekcja 12): „Zobacz Premium” jako żółta
   pigułka na granacie, a pierwsza sekunda głucha jak plansze-nagrody (.zamrozona, planszaZamroz). */
.mow-kafelek-probka, .pin-premium.pin-probka, .cmty-zw-pigulka.probka {
  display: inline-flex; align-items: center; gap: 6px; background: #FFC83D; color: #17183B; font-weight: 800;
}
.mow-kafelek-probka { min-height: 26px; padding: 0 10px; border-radius: 999px; font-size: 0.74rem; white-space: nowrap; }
.mow-kafelek-probka .ico, .cmty-zw-pigulka.probka .ico { margin: 0; font-size: 0.8rem; }
.sciana-cta { margin: 6px 0 4px; }
.sciana-cta .sciana-do-planow { width: 100%; max-width: 360px; }
#premiumScianaOverlay .sciana-okno.zamrozona :is(.wordmap-close, #scianaPozniej, .sciana-do-planow) { pointer-events: none; }
#premiumScianaOverlay .sciana-okno.zamrozona .sciana-do-planow { position: relative; overflow: hidden; }
#premiumScianaOverlay .sciana-okno.zamrozona .sciana-do-planow::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: color-mix(in srgb, #17183B 58%, transparent);
  transform-origin: right center; animation: planszaOdmrazanie var(--zamrozenie-ms, 1s) linear forwards;
}
#premiumScianaOverlay .sciana-okno.zamrozona :is(.wordmap-close, #scianaPozniej) { opacity: 0.55; }

/* =====================================================================
   23. MOWA SWOBODNA (2026-10-08, kanwa „Swobodne mówienie”; JS: sekcja MOWA SWOBODNA, HTML: #mowWolna)
   Układ z aplikacji: polecenie jak tytuł strony, baristka z kadru quizu z dymkiem (kolor = werdykt), dymek ucznia po
   prawej, karta poprawki jak „co źle” w rozmowach, żółta karta powtórki z flagą, mikrofon granatowy z żółtą obwódką,
   w nasłuchu zielony. Kolory z tokenów motywu, barwy marki (--granat, --zolty, --marka-*) stałe w obu motywach.
   ===================================================================== */
.mow-mapa-podtytul-wiersz { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 14px; margin: 4px 0 12px; }
.mow-mapa-podtytul-wiersz .mow-mapa-podtytul { margin: 0; }
.mws-wejscie {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px 0 12px; border-radius: 999px;
  border: 1.5px solid var(--border); background: var(--card-bg); color: var(--testo); font: inherit; font-weight: 700; font-size: 0.9rem; cursor: pointer;
}
.mws-wejscie .ico { margin: 0; font-size: 1rem; color: var(--marka-zielony); }
.mws-wejscie:hover { border-color: var(--marka-zielony); }
.mws [hidden] { display: none !important; }   /* atrybut hidden przegrywał z display:flex klasy (pułapka z Mówienia) */
.mws {
  max-width: 560px; margin: 0 auto; padding: 4px 4px 0; display: flex; flex-direction: column;
  min-height: min(780px, calc(100dvh - 140px)); color: var(--testo);
}
.mws .ico { margin: 0; }
.mws button:focus-visible, .mws-wejscie:focus-visible, .mws input:focus-visible { outline: 3px solid var(--fokus); outline-offset: 2px; }
.mws-glowa { display: flex; align-items: center; gap: 10px; }
.mws-glowa-tekst { flex: 1; min-width: 0; }
.mws-tytul { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.2rem; line-height: 1.1; }
.mws-jezyk { margin-top: 2px; font-size: 0.85rem; font-weight: 600; color: var(--grigio); }
.mws-kolko {
  width: 44px; height: 44px; flex-shrink: 0; padding: 0; border-radius: 50%; border: 1.5px solid var(--border);
  background: var(--card-bg); color: var(--testo); display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem; cursor: pointer;
}
.mws-kolko[aria-expanded="true"] { background: var(--przycisk); border-color: var(--przycisk); color: var(--na-przycisku); }
.mws-flaga {
  height: 44px; padding: 0 15px 0 13px; border-radius: 999px; border: 1.5px solid var(--border); background: var(--card-bg); color: var(--testo);
  display: inline-flex; align-items: center; gap: 7px; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.05rem; cursor: pointer;
}
.mws-flaga .ico { font-size: 1rem; }
.mws-flaga.ma { background: var(--zolty); border-color: var(--zolty); color: var(--granat); }
.mws-flaga[aria-expanded="true"] { background: var(--granat); border-color: var(--granat); color: var(--zolty); }
.mws-flaga.mrug { animation: mwsMrug .6s ease-out; }
@keyframes mwsMrug { 40% { transform: scale(1.18); } }

.mws-scena { flex: 1; display: flex; flex-direction: column; gap: 14px; padding: 20px 0 8px; }
.mws.z-panelem .mws-scena { display: none; }
.mws.z-panelem .mws-dol { opacity: .35; pointer-events: none; }
.mws-polecenie {
  margin: 0 4px; display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; font-family: var(--font-naglowek); font-weight: 800;
  font-size: 1.7rem; line-height: 1.12; letter-spacing: -.01em; color: var(--testo);
}
.mws-polecenie-flaga { display: inline-flex; line-height: 0; }
/* Postać rozmówcy (2026-10-08, Alek: „tak jak w mówieniu, wybieraj losowo postać”): jedna z ośmiu CAŁYCH postaci Mówienia
   (płótno 2:3, stopy na wspólnej linii), losowana w mwsOtworz; do tego wieczoru stał tu kadr baristki z mowienie.webp
   (KADR_BARISTKI × 0,62, ucięta ręka z kubkiem). W ciemnym motywie jasna obwódka jak na scenie rozmów: kontur postaci
   ma granat tła karty. */
.mws-rozmowca { display: flex; align-items: flex-end; gap: 4px; }
.mws-postac { width: 88px; height: 132px; flex-shrink: 0; }
.mws-postac img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: center bottom; }
:root[data-theme="dark"] .mws-postac img { filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 0.5px rgba(255, 255, 255, 0.85)); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .mws-postac img { filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 0.5px rgba(255, 255, 255, 0.85)); }
}
.mws-dymek {
  position: relative; flex: 1; min-width: 0; margin-bottom: 38px; display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 16px 10px 10px; border-radius: 22px; background: var(--card-bg); border: 2px solid var(--border); transition: box-shadow .2s;
}
.mws-dymek::before {
  content: ''; position: absolute; left: -10px; bottom: 18px; width: 16px; height: 16px; background: inherit;
  border-left: 2px solid; border-bottom: 2px solid; border-color: inherit; transform: rotate(45deg);
}
.mws-dymek.bez-glosnika { padding-left: 18px; }
/* Pytanie rozmówcy (dopytanie): komentarz werdyktu drobniej nad pytaniem, oczko z tłumaczeniem po prawej (mwsPokazPytanie). */
.mws-dymek.z-pytaniem { padding-right: 8px; }
.mws-dymek-kom { margin: 0 0 2px; font-size: 0.95rem; font-weight: 700; color: var(--grigio); }
.mws-dymek.zielony .mws-dymek-kom { color: var(--verde); }
.mws-oko-dymku { align-self: flex-start; }
/* Zachęta w miejscu postaci, dopóki postać nie ma nic do powiedzenia (Alek: „zamiast niego można napisać »Powiedz dowolne
   zdanie w języku nauki i sprawdź się« drobną czcionką”). */
.mws-zacheta { margin: 0 4px; font-size: 0.95rem; line-height: 1.45; color: var(--grigio); }
.mws-uczen-bylo { opacity: .7; }
.mws-dymek.zielony { background: var(--bg-success-soft); border-color: var(--marka-zielony); }
.mws-dymek.zolty { background: var(--bg-gold-soft); border-color: var(--zolty); }
.mws-dymek.mowi { box-shadow: 0 0 0 4px color-mix(in srgb, var(--marka-niebieski) 18%, transparent); }
.mws-glosnik {
  width: 44px; height: 44px; flex-shrink: 0; padding: 0; border-radius: 50%; border: 0; background: var(--bg-warn-soft);
  color: var(--marka-niebieski); display: inline-flex; align-items: center; justify-content: center; font-size: 1.15rem; cursor: pointer;
}
.mws-dymek.zielony .mws-glosnik, .mws-dymek.zolty .mws-glosnik, .mws-glosnik.bialy { background: var(--card-bg); }
.mws-dymek.mowi .mws-glosnik { background: var(--marka-niebieski); color: #FFFFFF; }
.mws-dymek-tresc { flex: 1; min-width: 0; padding-top: 7px; }
.mws-dymek-tekst { margin: 0; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.25rem; line-height: 1.22; color: var(--testo); overflow-wrap: anywhere; }
.mws-dymek-pod { margin: 4px 0 0; font-size: 0.95rem; font-style: italic; color: var(--grigio); }
.mws-tresc { display: flex; flex-direction: column; gap: 14px; }
.mws-tresc:empty { display: none; }
/* Dymek ucznia: niebieski jak w rozmowach, przerywana ramka w trakcie mówienia, zielony po zaliczeniu. */
.mws-uczen {
  align-self: flex-end; max-width: 88%; padding: 12px 18px; border-radius: 22px 22px 6px 22px; border: 2px solid var(--marka-niebieski);
  background: var(--bg-warn-soft); font-family: var(--font-naglowek); font-weight: 700; font-size: 1.18rem; line-height: 1.32;
  color: var(--testo); overflow-wrap: anywhere;
}
.mws-uczen.na-zywo { border-style: dashed; }
/* Krzyżyk „zacznij od nowa” był w dymku na żywo (34 px, trudny do trafienia w trakcie mówienia); od 2026-10-09 to „Od nowa”
   w lewym miejscu dolnego paska (#mwsOdNowa), dalej też Escape. */
.mws-uczen.trafiony { border-color: var(--marka-zielony); background: var(--bg-success-soft); color: var(--verde); }
/* Oczko w zielonym dymku: tłumaczenie wypowiedzi na język interfejsu pod zdaniem (mwsPokazSens). */
.mws-uczen.z-okiem { padding-right: 8px; }
.mws-uczen-wiersz { display: flex; align-items: flex-start; gap: 6px; }
.mws-uczen-wiersz > span { flex: 1; min-width: 0; padding-top: 3px; }
.mws-oko {
  width: 36px; height: 36px; flex-shrink: 0; margin: -4px 0 -4px 0; padding: 0; border: 0; border-radius: 50%; background: transparent;
  color: inherit; display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem; cursor: pointer; opacity: .75;
}
.mws-oko:hover, .mws-oko[aria-pressed="true"] { opacity: 1; background: color-mix(in srgb, var(--marka-zielony) 14%, transparent); }
.mws-uczen-sens { margin: 6px 0 2px; font-family: var(--font-tekst); font-weight: 600; font-size: 0.97rem; line-height: 1.4; color: var(--grigio); }
/* Zielony dymek do kliknięcia i jego edycja („nie to chciałem powiedzieć”, mwsZmianaStart): pole w języku interfejsu, pod nim
   zdanie w języku nauki od modelu. Kolory z motywu (dymek jest jasny albo ciemny), nie granat z żółtej karty „Powtórka”. */
.mws-uczen.klikalny { cursor: pointer; }
.mws-uczen.klikalny:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--marka-zielony) 16%, transparent); }
.mws-uczen.zmienia { width: 88%; box-sizing: border-box; display: flex; flex-direction: column; gap: 8px; color: var(--testo); }
.mws-zmiana-tytul { font-family: var(--font-tekst); font-size: 0.86rem; font-weight: 800; color: var(--verde); }
.mws-zmiana-pole {
  display: block; width: 100%; box-sizing: border-box; min-height: 64px; padding: 10px 12px; border: 2px solid var(--marka-zielony);
  border-radius: 14px; background: var(--card-bg); color: var(--testo); font-family: var(--font-tekst); font-weight: 600; font-size: 1rem;
  line-height: 1.4; resize: vertical; outline: none;
}
.mws-zmiana-pole:focus { box-shadow: 0 0 0 4px color-mix(in srgb, var(--marka-zielony) 22%, transparent); }
.mws-zmiana-nauka { margin: 0; min-height: 1.4em; font-family: var(--font-naglowek); font-weight: 700; font-size: 1.12rem; line-height: 1.35; color: var(--verde); }
.mws-zmiana-blad { font-family: var(--font-tekst); font-weight: 700; font-size: 0.95rem; color: var(--rosso); }
.mws-zmiana-akcje { display: flex; flex-wrap: wrap; gap: 8px; }
.mws-uczen.zmienia .mws-obrys { color: var(--testo); border-color: color-mix(in srgb, var(--testo) 28%, transparent); font-family: var(--font-tekst); }
.mws-uczen.zmienia .mws-obrys:hover { background: color-mix(in srgb, var(--card-bg) 60%, transparent); }
.mws-kropki { display: inline-flex; gap: 5px; padding: 6px 0; }
.mws-kropki i { width: 8px; height: 8px; border-radius: 50%; background: var(--marka-niebieski); opacity: .4; animation: mwsKropka 1s ease-in-out infinite; }
.mws-kropki i:nth-child(2) { animation-delay: .15s; }
.mws-kropki i:nth-child(3) { animation-delay: .3s; }
/* Karta poprawki: tło jak karta „co źle” w rozmowach; postać z fiszkami w nagłówku zdjęta 2026-10-08 (Alek: „wywal tą miniaturową babeczkę przy POPRAWNIE”). */
.mws-karta { border-radius: 24px; padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.mws-karta-popraw { background: var(--bg-error-soft); }
.mws-karta-glowa { display: flex; align-items: center; gap: 8px; }
.mws-etykieta { font-size: 0.8rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--grigio); }
.mws-licznik-zdan { padding: 2px 8px; border-radius: 999px; background: var(--card-bg); font-size: 0.78rem; font-weight: 800; color: var(--testo); }
.mws-odstep { flex: 1; }
.mws-zdanie { margin: 0; font-family: var(--font-naglowek); font-weight: 700; font-size: 1.42rem; line-height: 1.45; color: var(--testo); overflow-wrap: anywhere; }
.mws-pk {
  font-weight: 800; color: var(--verde); background: var(--bg-success-soft); border-radius: 7px; padding: 0 4px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.mws-brak, .mws-pk.mws-brak {
  font-weight: 800; color: var(--marka-czerwony); background: none; padding: 0; text-decoration-line: underline; text-decoration-style: dotted;
  text-decoration-color: var(--marka-czerwony); text-decoration-thickness: 3px; text-underline-offset: 6px; text-decoration-skip-ink: none;
}
/* Zdanie ucznia z poprawkami (mwPoprawkaWZdaniu): słowo źle powiedziane skreślone na czerwono, brakujące wstawione na zielono,
   jak poprawione słowa (.mws-pk). Zamiana to para obok siebie: najpierw skreślone, potem wstawione. */
.mws-zle {
  font-weight: 800; color: var(--rosso); text-decoration-line: line-through; text-decoration-color: var(--rosso);
  text-decoration-thickness: 3px; text-decoration-skip-ink: none; background: color-mix(in srgb, var(--card-bg) 70%, transparent);
  border-radius: 7px; padding: 0 4px; -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.mws-dodane {
  font-weight: 800; color: var(--verde); background: var(--bg-success-soft); text-decoration: none; border-radius: 7px; padding: 0 4px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.mws-oko-karty { color: var(--grigio); }
.mws-oko-karty[aria-pressed="true"] { color: var(--testo); }
/* Tłumaczenie poprawnego zdania pod nim (oczko karty, mwsPokazSensKarty). */
.mws-karta-sens { margin: -2px 0 0; font-size: 1rem; line-height: 1.45; font-weight: 600; color: var(--grigio); }
.mws-kosz { color: var(--grigio); }
.mws-kosz:hover { color: var(--rosso); }
/* Karta powtórki spod flagi: żółty ekran marki (stały w obu motywach), sens w białym dymku. */
.mws-karta-pamiec { background: var(--zolty); color: var(--granat); }
.mws-wiecej {
  width: 40px; height: 40px; flex-shrink: 0; padding: 0; border: 0; border-radius: 50%; background: rgba(255, 255, 255, .55); color: var(--granat);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.15rem; cursor: pointer;
}
.mws-wiecej:hover, .mws-wiecej[aria-expanded="true"] { background: #FFFFFF; }
/* Pole edycji zdania (mwsEdytujSens): ten sam biały dymek, co .mws-sens, tylko do pisania. */
.mws-sens-pole { display: block; width: 100%; box-sizing: border-box; border: 2px solid var(--granat); resize: vertical; min-height: 90px; outline: none; }
.mws-sens-pole:focus { box-shadow: 0 0 0 4px rgba(23, 24, 59, .18); }
.mws-sens-blad { margin: 0; padding: 8px 12px; border-radius: 12px; background: #FFFFFF; color: #B91C1C; font-weight: 700; font-size: 0.95rem; }
.mws-pigulka-flagi {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 7px; padding: 6px 13px 6px 11px; border-radius: 999px;
  background: var(--granat); color: var(--zolty); font-weight: 800; font-size: 0.9rem;
}
.mws-sens {
  margin: 0; padding: 16px 18px; border-radius: 20px 20px 20px 6px; background: #FFFFFF; color: var(--granat);
  font-family: var(--font-naglowek); font-weight: 700; font-size: 1.35rem; line-height: 1.35;
}
.mws-karta-akcje { display: flex; flex-wrap: wrap; gap: 8px; }
.mws-obrys {
  min-height: 44px; padding: 0 15px 0 12px; border-radius: 999px; border: 1.5px solid rgba(23, 24, 59, .28); background: transparent;
  color: var(--granat); display: inline-flex; align-items: center; gap: 7px; font: inherit; font-weight: 700; font-size: 0.92rem; cursor: pointer;
}
.mws-obrys:hover { background: rgba(255, 255, 255, .45); }

.mws-dol { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 0 18px; }
/* DOLNY PASEK (kanwa „jeden dolny pasek, trzy stałe miejsca”): trzy równe kolumny, mikrofon w środkowej. Boki trzymają szerokość
   także puste, więc mikrofon nigdy nie zmienia miejsca. Przycisk boczny = koło 60 px z ikoną i podpis pod nim (cały jest celem). */
/* Środek bocznego koła na wysokości środka mikrofonu: obszar mikrofonu ma 132 px, koło 60 px, więc 36 px od góry. */
.mws-dok { width: 100%; max-width: 420px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; justify-items: center; }
.mws-dok-bok { display: flex; justify-content: center; min-width: 0; padding-top: 36px; }
.mws-dok-btn {
  min-width: 76px; padding: 0; border: 0; background: transparent; color: var(--testo); font: inherit; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
}
.mws-dok-btn[hidden], .mws-dok-zegar[hidden] { display: none; }
.mws-dok-kolko {
  width: 60px; height: 60px; border-radius: 50%; border: 1.5px solid var(--border); background: var(--card-bg); box-shadow: var(--shadow);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.35rem; transition: transform .1s, border-color .15s;
}
.mws-dok-btn:hover .mws-dok-kolko { border-color: var(--border-2); }
.mws-dok-btn:active .mws-dok-kolko { transform: scale(.94); }
.mws-dok-btn:focus-visible { outline: none; }
.mws-dok-btn:focus-visible .mws-dok-kolko { outline: 3px solid var(--marka-niebieski); outline-offset: 3px; }
.mws-dok-napis { font-weight: 700; font-size: 0.88rem; line-height: 1.2; text-align: center; }
.mws-dok-btn.turla .ico { animation: mwsTurla .6s cubic-bezier(.3, .7, .4, 1); }
.mws-dok-btn.czeka .ico { animation: mwsTurla .9s linear infinite; }
@keyframes mwsTurla { 50% { transform: rotate(200deg) scale(1.2); } 100% { transform: rotate(360deg); } }
.mws-dok-zegar { display: flex; flex-direction: column; align-items: center; gap: 1px; min-height: 60px; justify-content: center; }
.mws-dok-zegar b { font-family: var(--font-naglowek); font-weight: 800; font-size: 1.25rem; color: var(--testo); font-variant-numeric: tabular-nums; }
.mws-dok-zegar span { font-size: 0.8rem; font-weight: 600; color: var(--grigio); }
/* „Dopowiedz” przy wyniku wypowiedzi (pod zielonym dymkiem albo na karcie poprawki), bo dotyczy tego jednego zdania. */
.mws-dopowiedz {
  min-height: 40px; padding: 0 14px 0 10px; border-radius: 999px; border: 1.5px dashed var(--marka-zielony); background: var(--card-bg);
  color: var(--verde); display: inline-flex; align-items: center; gap: 6px; font: inherit; font-weight: 700; font-size: 0.9rem; cursor: pointer;
}
.mws-dopowiedz:hover { border-style: solid; }
.mws-uczen-blok { align-self: flex-end; max-width: 88%; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.mws-uczen-blok > .mws-uczen { max-width: 100%; }
.mws-karta-popraw .mws-dopowiedz { align-self: flex-start; border-color: color-mix(in srgb, var(--testo) 35%, transparent); color: var(--testo); }
.mws-mik-obszar { position: relative; width: 132px; height: 132px; display: flex; align-items: center; justify-content: center; }
.mws-mik {
  position: relative; width: 88px; height: 88px; padding: 0; border-radius: 50%; border: 0; background: var(--przycisk); color: var(--na-przycisku);
  display: inline-flex; align-items: center; justify-content: center; font-size: 2rem; cursor: pointer;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--zolty) 50%, transparent); transition: transform .1s, background .15s, box-shadow .15s;
}
.mws-mik:active { transform: scale(.95); }
.mws .mws-mik:focus-visible { outline-offset: 8px; }
.mws-mik-stop, .mws-mik-krec, .mws-mik-ok { display: none; }
.mws-mik-stop { width: 26px; height: 26px; border-radius: 6px; background: var(--granat); }
.mws-mik-krec { width: 34px; height: 34px; border-radius: 50%; border: 3.5px solid color-mix(in srgb, var(--marka-zielony) 25%, transparent); border-top-color: var(--marka-zielony); animation: mwsKrec .8s linear infinite; }
@keyframes mwsKrec { to { transform: rotate(360deg); } }
.mws-mik-obszar.slucha .mws-mik {
  background: var(--marka-zielony); color: var(--granat);
  box-shadow: 0 0 0 10px color-mix(in srgb, var(--marka-zielony) 22%, transparent), 0 0 0 22px color-mix(in srgb, var(--marka-zielony) 10%, transparent);
}
.mws-mik-obszar.slucha.odlicza .mws-mik { box-shadow: 0 0 0 10px color-mix(in srgb, var(--marka-zielony) 22%, transparent); }
.mws-mik-obszar.slucha .mws-mik-ikona { display: none; }
.mws-mik-obszar.slucha .mws-mik-stop { display: block; }
.mws-mik-obszar.wlacza .mws-mik { background: var(--bg-success-soft); color: var(--verde); box-shadow: 0 0 0 2px var(--marka-zielony); }
.mws-mik-obszar.mysli .mws-mik { background: var(--bg-soft); color: var(--grigio); box-shadow: none; cursor: default; }
.mws-mik-obszar.mysli .mws-mik-ikona { display: none; }
.mws-mik-obszar.mysli .mws-mik-krec { display: block; }
.mws-mik-obszar.dobrze .mws-mik { background: var(--marka-zielony); color: var(--granat); box-shadow: none; animation: mwsWyskok .5s cubic-bezier(.2, 1.6, .4, 1); }
.mws-mik-obszar.dobrze .mws-mik-ikona { display: none; }
.mws-mik-obszar.dobrze .mws-mik-ok { display: inline-flex; }
@keyframes mwsWyskok { 0% { transform: scale(.8); } 55% { transform: scale(1.16); } 100% { transform: scale(1); } }
.mws-mik-obszar.wylaczony .mws-mik { opacity: .5; }
.mws-krag { position: absolute; inset: 22px; border-radius: 50%; border: 3px solid var(--marka-zielony); pointer-events: none; opacity: 0; }
.mws-mik-obszar.dobrze .mws-krag { animation: mwsKrag .65s ease-out; }
@keyframes mwsKrag { from { opacity: .9; transform: scale(1); } to { opacity: 0; transform: scale(1.9); } }
.mws-pierscien { position: absolute; inset: 0; width: 132px; height: 132px; transform: rotate(-90deg); pointer-events: none; display: none; }
.mws-mik-obszar.odlicza .mws-pierscien { display: block; }
.mws-pierscien circle { fill: none; stroke-width: 4; }
.mws-pierscien .tor { stroke: var(--border); }
.mws-pierscien .postep { stroke: var(--marka-zielony); stroke-linecap: round; stroke-dasharray: 389.6; stroke-dashoffset: 389.6; }
.mws-mik-obszar.odlicza .mws-pierscien .postep { animation: mwsOdlicz 2s linear forwards; }
@keyframes mwsOdlicz { to { stroke-dashoffset: 0; } }
/* Lektorka mówi: mikrofon chowa się, w jego kole skaczą trzy kropki w barwach logo (jak .mow-lektor w rozmowach). */
.mws-lektor {
  display: none; position: absolute; width: 88px; height: 88px; padding: 0; border-radius: 50%; border: 2px solid var(--border);
  background: var(--card-bg); align-items: center; justify-content: center; gap: 8px; cursor: pointer;
}
.mws-lektor span { width: 14px; height: 14px; border-radius: 50%; background: var(--marka-zielony); animation: mwsKropka .8s ease-in-out infinite; }
.mws-lektor span:nth-child(2) { background: var(--marka-czerwony); animation-delay: .18s; }
.mws-lektor span:nth-child(3) { background: var(--marka-niebieski); animation-delay: .36s; }
@keyframes mwsKropka { 0%, 100% { transform: translateY(0); opacity: .55; } 50% { transform: translateY(-6px); opacity: 1; } }
.mws-mik-obszar.lektor .mws-mik { visibility: hidden; }
.mws-mik-obszar.lektor .mws-lektor { display: inline-flex; }
@media (prefers-reduced-motion: reduce) { .mws-lektor span, .mws-kropki i { animation: none; opacity: 1; } }
.mws-status { margin: 2px 0 0; min-height: 22px; max-width: 460px; text-align: center; color: var(--grigio); font-size: 0.93rem; font-weight: 600; }
.mws-status.slucha { color: var(--verde); }
.mws-status.blad { color: var(--marka-czerwony); }
.mws-pole { margin-top: 8px; width: 100%; display: flex; gap: 8px; }
.mws-pole input {
  flex: 1; min-width: 0; height: 46px; padding: 0 14px; border-radius: 14px; border: 1.5px dashed var(--border-warm-dash);
  background: var(--card-bg); color: var(--testo); font: inherit; font-size: 1rem;
}
.mws-pole button { height: 46px; padding: 0 18px; border-radius: 999px; border: 0; background: var(--przycisk); color: var(--na-przycisku); font: inherit; font-weight: 800; cursor: pointer; }
.mws-pole button:disabled { opacity: .45; cursor: default; }
/* Panele flagi i ustawień: karta pod nagłówkiem, scena chowa się na ich czas (klasa .z-panelem). */
.mws-panel { margin: 14px 0 0; padding: 18px 16px 10px; border-radius: 26px; background: var(--card-bg); border: 1.5px solid var(--border); box-shadow: 0 12px 30px rgba(23, 24, 59, .12); }
.mws-panel h2 { margin: 0 0 12px; font-family: var(--font-naglowek); font-weight: 800; font-size: 1.35rem; color: var(--testo); }
.mws-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.mws-lista li { display: flex; align-items: center; gap: 10px; padding: 12px 12px 12px 14px; border-radius: 18px; background: var(--bg-soft); }
.mws-lista-tresc { flex: 1; min-width: 0; }
.mws-lista-zdanie { font-size: 1.02rem; line-height: 1.5; font-weight: 600; color: var(--testo); overflow-wrap: anywhere; }
.mws-lista-zdanie .mws-pk { color: inherit; background: none; padding: 0; text-decoration: underline; text-decoration-color: var(--zolty); text-decoration-thickness: 3px; text-underline-offset: 4px; }
.mws-lista-sens { margin-top: 2px; font-size: 0.88rem; color: var(--grigio); }
.mws-lista-mik {
  width: 44px; height: 44px; flex-shrink: 0; padding: 0; border-radius: 50%; border: 0; background: var(--przycisk); color: var(--na-przycisku);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem; cursor: pointer;
}
.mws-lista-mik:disabled { opacity: .45; cursor: default; }
.mws-lista-usun {
  width: 44px; height: 44px; flex-shrink: 0; padding: 0; border-radius: 50%; border: 0; background: transparent; color: var(--grigio);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1rem; cursor: pointer;
}
.mws-lista-usun:hover:not(:disabled) { color: var(--rosso); background: var(--bg-error-soft); }
.mws-lista-usun:disabled { opacity: .45; cursor: default; }
/* Zakładki panelu flagi: „Do utrwalenia” i „Umiesz”, w miejscu dawnego nagłówka listy. */
.mws-zakladki { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0 0 12px; }
.mws-zakladka {
  min-height: 44px; padding: 0 2px; border: 0; background: transparent; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-naglowek); font-weight: 800; font-size: 1.25rem; color: var(--grigio); box-shadow: inset 0 -3px 0 transparent;
}
.mws-zakladka[aria-selected="true"] { color: var(--testo); box-shadow: inset 0 -3px 0 var(--zolty); }
.mws-zakladka-n { min-width: 24px; padding: 1px 7px; border-radius: 999px; background: var(--bg-soft); font-family: inherit; font-size: 0.82rem; color: var(--testo); }
.mws-pusto { margin: 0 0 8px; color: var(--grigio); }
.mws-panel-stopka { display: flex; justify-content: center; margin-top: 6px; }
.mws-wyczysc { min-height: 44px; padding: 0 14px; border: 0; background: transparent; color: var(--marka-czerwony); font: inherit; font-weight: 700; font-size: 0.93rem; cursor: pointer; }
.mws-wiersz { padding: 12px 0; border-top: 1px solid var(--border-warm-soft); }
.mws-wiersz:first-of-type { border-top: 0; }
.mws-wiersz.obok { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.mws-ust-etykieta { display: flex; align-items: center; gap: 8px; font-size: 0.97rem; font-weight: 700; color: var(--testo); }
.mws-segment { display: grid; grid-template-columns: repeat(var(--mws-n, 3), minmax(0, 1fr)); gap: 4px; margin-top: 8px; padding: 4px; border-radius: 20px; background: var(--bg-soft); }
.mws-segment button {
  min-height: 44px; padding: 6px 4px; border-radius: 16px; border: 0; background: transparent; color: var(--testo); font: inherit; font-weight: 700;
  font-size: 0.93rem; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; cursor: pointer;
}
.mws-segment small { font-weight: 600; font-size: 0.78rem; color: var(--grigio); }
.mws-segment button[aria-pressed="true"] { background: var(--przycisk); color: var(--na-przycisku); }
.mws-segment button[aria-pressed="true"] small { color: inherit; opacity: .85; }
.mws-przelacznik {
  width: 52px; height: 32px; flex-shrink: 0; padding: 0 4px; border-radius: 999px; border: 1.5px solid var(--border); background: var(--bg-soft);
  display: inline-flex; align-items: center; justify-content: flex-start; cursor: pointer;
}
.mws-przelacznik span { width: 22px; height: 22px; border-radius: 50%; background: var(--tekst-neutralny); }
.mws-przelacznik[aria-checked="true"] { justify-content: flex-end; background: var(--przycisk); border-color: var(--przycisk); }
.mws-przelacznik[aria-checked="true"] span { background: var(--na-przycisku); }
@media (max-width: 420px) {
  .mws-postac { width: 72px; height: 108px; }
  .mws-polecenie { font-size: 1.5rem; }
  .mws-zdanie { font-size: 1.28rem; }
  .mws-sens { font-size: 1.2rem; }
}
