/**
 * Lukuro Reviews - Styles
 *
 * Arkusz cytuje WYLACZNIE nazwy `lukuro-*` - tak samo jak znaczniki, odkad warstwa
 * dual-class zeszla w `v2.31.0` (plan REV-STD-001). Do tego wydania renderer wypisywal
 * obok kazdej klasy jej stara nazwe z prefiksem pierwszego klienta; byl to zaczep dla
 * custom CSS konsumenta, nigdy dla tego pliku.
 *
 * KONTRAKT ZNACZNIKOW (2026-08-24). Ten arkusz NIE maluje przyciskow ani pol formularza -
 * robi to motyw, przez klasy `bricks-button` i `woocommerce-Input ... input-text`, ktore
 * wypisuje renderer. Reguly ponizej, ktore duplikuja wyglad kontrolki motywu, stoja
 * w `:where()`, czyli maja specyficznosc ZERO: witryna z Advanced Themerem wygrywa z nimi
 * bez `!important` i bez zaleznosci od kolejnosci enqueue, a witryna bez AT dostaje z nich
 * poprawny wyglad. Ten sam wzorzec niesie `trainings-account.css` po SZKOL-010.
 *
 * Zmierzone na instancji mitoterapii 2026-08-24 i wazne przy kazdej kolejnej powierzchni:
 * kontrolki na `/moje-konto/odzyskiwanie-hasla/` czerpia czesc wygladu (padding 14,16/28,12,
 * stopien 18,94 px, promien pola 13,33 px) z reguly `html .login-card .woocommerce-Button`,
 * czyli z KLASY GLOBALNEJ TEJ WITRYNY, ktora Bricks emituje wylacznie na tamtej stronie.
 * Tych wartosci nie da sie odziedziczyc na endpoincie wirtualnym i nie wolno ich cytowac -
 * dlatego fallback ponizej odtwarza je ze SKALI AT, nie z wartosci tamtej witryny.
 */

@layer lukuro.modules {

/* Lokalne tokeny opinii wskazuja na globalna warstwe semantyczna (lukuro-tokens.css).
   Dark mode NIE jest jeszcze dowieziony: sloty to umozliwiaja, ale drugiego zestawu
   wartosci ani przelacznika w tej wersji nie ma. */
:root {
    /* Kolor marki w dwoch rolach: `primary` jako TLO przyciskow i granica,
       `primary-text` jako TRESC (hover odnosnikow, link oceny) - jeden token
       nie obsluzy obu, bo kolor dobrany pod tlo daje jako tekst 1.58:1. */
    --lukuro-reviews-primary: var(--lukuro-color-primary, #111);
    --lukuro-reviews-primary-text: var(--lukuro-color-primary-text, #111);
    --lukuro-reviews-primary-hover: var(--at-primary-l-1, #059669);

    /* Gwiazdki: 3.80:1 wobec tla i 3.40:1 wobec gwiazdki pustej. Ocena niesie
       informacje (ile wypelnionych), wiec podlega SC 1.4.11 i nie moze opierac
       rozroznienia na samym odcieniu. Bazowy zolty dawal 1.06:1 wobec pustej. */
    --lukuro-reviews-star-color: var(--lukuro-color-star, #b8952a);
    --lukuro-reviews-star-empty: var(--lukuro-color-star-empty, rgba(0, 0, 0, .05));

    --lukuro-reviews-border: var(--lukuro-color-hairline, #e0e0e0);
    --lukuro-reviews-text: var(--lukuro-color-text, #222);
    --lukuro-reviews-text-muted: var(--lukuro-color-text-muted, #666);
    --lukuro-reviews-btn-default: var(--lukuro-color-text-muted, #666);
    --lukuro-reviews-success: var(--lukuro-color-success, #11b76b);

    /* Rola TEKSTOWA sukcesu, osobna od wypelnienia (2026-08-26). Slot wyzej opisuje kolor
       PLASZCZYZNY - u konsumenta zwykle zielen palety motywu - i jako pismo schodzi ponizej
       progu: na mitoterapii dawal 1,85:1 przy wymaganych 4,5:1, mimo ze liczba w komentarzu
       nizej mowila 7,20:1. Ta liczba dotyczyla FALLBACKU pakietu, ktory dziala wylacznie
       tam, gdzie konsument slotu nie podpial - czyli nigdzie u nas. Fallback tutaj to zielen
       Bricksa przyciemniona do 62% (ten sam ton, 6,08:1 na bieli, 5,39:1 na tincie 12%). */
    --lukuro-reviews-success-text: var(--lukuro-color-success-text, #0a7041);

    /* Oba stany sa uzywane jako `color:`, wiec licza sie pod role tekstowa: 6.86:1 (blad)
       i 6.08:1 (sukces) na bieli. UWAGA - te liczby opisuja FALLBACKI pakietu i obowiazuja
       tylko tam, gdzie konsument nie podpial slotu. Podpiety slot moze byc dowolnie jasny:
       bazowe kolory stanow AT i palety Bricksa nadaja sie na wypelnienia, nie na tekst
       (`--bricks-text-success` daje 2.62:1). Dlatego sukces ma osobna zmienna tekstowa
       wyzej, a blad jej nie potrzebuje, bo slot `--lukuro-color-danger` u konsumentow
       prowadzi do czerwieni pisma, nie do wypelnienia. */
    --lukuro-reviews-error: var(--lukuro-color-danger, #991b1b);

    /* Powierzchnie i krawedzie sekcji ida na kolor marki, a nie na neutralna szarosc.
       Powod nie jest estetyczny: witryna konsumenta i tak musiala to nadrobic wlasnym
       CSS-em (mitoterapia - 5 regul w Bricksie na `--at-space--*` i `--at-primary-t-6`),
       a te reguly Bricks emituje WYLACZNIE na stronach ze swoim elementem, wiec panel
       konta zostawal bez nich. Teraz niesie je arkusz modulu i dziala wszedzie.

       Tinta jest NIEPRZEZROCZYSTA (`color-mix` z powierzchnia, nie z `transparent`),
       zeby zagniezdzone odpowiedzi nie kumulowaly alfy i poziom czwarty nie robil sie
       ciemniejszy od pierwszego.

       Kontrast policzony na palecie mitoterapii (primary `#0ba1bf` na bieli -> tinta
       `rgb(231,246,249)`), bo to jedyna instalacja, na ktorej te wartosci daja sie zmierzyc:
         - tekst bazowy na tincie      7.66:1 (bylo 6.38:1 na `surface-alt` w 100%)  AAA
         - tekst stonowany na tincie   5.57:1 (bylo 4.30:1, czyli PONIZEJ AA 4.5:1)  AA
       Zmiana wiec kontrast POPRAWIA, a jedna pozycje wyciaga z niezdania. */
    --lukuro-reviews-surface: var(--lukuro-color-surface, #fff);

    /* Tlo dymka odpowiedzi. Idzie na NEUTRALNA SZAROSC, nie na kolor marki (decyzja usera
       2026-08-24: "tlo odpowiedzi jasniejsze i w szarosc bardziej a nie w primary"). Wczesniej
       bylo to 4% marki, czyli `#f5fbfc` na palecie mitoterapii - delikatne, ale wciaz turkusowe,
       przez co dymek czytal sie jako element firmowy zamiast jako tlo cudzej wypowiedzi.

       Mieszanka idzie z KOLOREM TEKSTU, a nie z ustalonym szarym: dzieki temu dziala w obie
       strony motywu. Na jasnym daje `#fbfbfb`, na ciemnym rozjasnia powierzchnie zamiast ja
       przyciemniac - gdyby stala tu wartosc `#fbfbfb`, w trybie ciemnym dymek bylby biala plama.

       Tinta zostaje NIEPRZEZROCZYSTA (`color-mix` z powierzchnia, nie z `transparent`), zeby
       zagniezdzone odpowiedzi nie kumulowaly alfy i poziom czwarty nie robil sie ciemniejszy
       od pierwszego.

       2%, a nie 3%: przy 3% wychodzi `#f8f8f8`, czyli tlo CIEMNIEJSZE niz poprzednie `#f5fbfc`
       (jasnosc wzgledna 0,9409 wobec 0,9544), a user prosil o jasniejsze. 2% daje `#fbfbfb`
       i jasnosc 0,9626, czyli realnie wyzej niz punkt wyjscia.

       Kontrast ZMIERZONY na instancji po zmianie (nie policzony z zalozen): tlo dymka wychodzi
       `#fbfcfc` przy jasnosci wzglednej 0,9685 wobec 0,9544 poprzedniej tinty, czyli realnie
       jasniej. Tekst bazowy na dymku **14,93:1** (AAA), tekst stonowany **5,99:1** (AA).
       Sam dymek wobec bialej karty daje 1,03:1 - to celowo malo, bo dymek ma odcinac sie
       ksztaltem i wcieciem, a nie kontrastem plaszczyzn.
       Token niesie JEDNA role - tlo dymka - i nic wiecej go nie uzywa. */
    --lukuro-reviews-tint: color-mix(in srgb, var(--lukuro-reviews-text, #222) 2%, var(--lukuro-reviews-surface, #fff));
    /* Tlo POL DO PISANIA - formularza opinii, odpowiedzi i odpowiedzi zagniezdzonej. Trzy
       powierzchnie, jedna rola, wiec jedna wartosc: marka sprowadzona do 3% (decyzja usera
       2026-08-26; wczesniej 6% - za ciezko jak na plaszczyzne, ktora ma wylacznie powiedziec
       "tu sie pisze"). To NIE jest `--lukuro-trainings-tint` - tamta zyje w module szkolen
       i liczy sie z `surface-alt`, ta z koloru marki. */
    --lukuro-reviews-tint-soft: color-mix(in srgb, var(--lukuro-reviews-primary, #0ba1bf) 3%, var(--lukuro-color-surface, #fff));
    /* Tlo CALEJ SEKCJI, gdy stoi jako karta (`lukuro-reviews--framed`, opcja, patrz koniec
       pliku). Sekcja jest POJEMNIKIEM, wiec bierze czysta powierzchnie, a nie tinte
       (decyzja usera 2026-08-26).

       Byla po drodze wersja z tinta (tekst 5%, zmierzone `#f5f6f7`, biala karta na tym 1,080:1)
       i zostala odrzucona z tego samego powodu, dla ktorego BIALY jest pojemnik modulu
       w szkoleniach: odcien niosa juz karty W SRODKU, wiec drugi odcien pod nimi robi z ekranu
       trzy warstwy tla zamiast jednej. Granice sekcji niesie ramka i wypelnienie, nie plaszczyzna.

       Token zostaje mimo tego, ze dzis oddaje sama powierzchnie: to jest SLOT tla sekcji.
       Konsument, ktory chce ja podbarwic, ma jedno miejsce do przestawienia i nie musi
       przepisywac reguly z `@media`.

       Nazwa NIE zawiera slowa "tint" wlasnie dlatego - token o nazwie `-tint-*` trzymajacy
       czysta biel klamalby przy pierwszym czytaniu, a arkusz ma juz dwa prawdziwe tinty
       (`-tint` dymka i `-tint-soft` pol do pisania) i nie potrzebuje trzeciego pozornego. */
    --lukuro-reviews-section-bg: var(--lukuro-reviews-surface, #fff);
    --lukuro-reviews-border-brand: color-mix(in srgb, var(--lukuro-reviews-primary, #0ba1bf) 10%, transparent);
    --lukuro-reviews-rule: color-mix(in srgb, var(--lukuro-reviews-primary, #0ba1bf) 20%, transparent);

    /* Awatar ma DWA rozmiary w calej sekcji i sa one tokenem, bo geometria lacznika watku
       liczy sie z nich: pion lacznika stoi w osi awatara RODZICA. */
    --lukuro-reviews-avatar: 32px;
    --lukuro-reviews-avatar-lg: 44px;

    /* Lacznik watku (wzorzec dyskusji). `elbow` to poziomy zasieg luku, czyli odleglosc
       od osi awatara rodzica do lewej krawedzi awatara odpowiedzi; z niej wylicza sie
       TAKZE wciecie kazdego poziomu, wiec obie rzeczy zmieniaja sie jedna wartoscia. */
    --lukuro-reviews-elbow: 22px;

    /* Odstep w watku. Ta sama wartosc musi byc marginesem kontenera odpowiedzi, odstepem
       miedzy rodzenstwem I wzniosem luku - inaczej miedzy koncem pionu a poczatkiem luku
       zostaje przerwa dokladnie tej roznicy. Jedna zmienna zamyka to raz na zawsze. */
    --lukuro-reviews-thread-gap: var(--at-space--xs, 0.875rem);

    /* Odstep miedzy awatarem a dymkiem. Osobny token, bo wchodzi do arytmetyki lacznika:
       os pionu zagniezdzonego liczy sie jako "odstep + polowa awatara" wstecz od krawedzi
       `-main`. Zmierzone, gdy byly to dwie niezalezne wartosci: na waskim ekranie odstep
       schodzil o polowe, a pion zostawal na pelnej i mijal awatar o 6,4 px. */
    --lukuro-reviews-avatar-gap: var(--at-space--xs, 0.875rem);

    /* Promien luku jest MNIEJSZY od jego zasiegu i to jest cala roznica miedzy linia, ktora
       plynie, a cwiartka kola. Przy promieniu rownym zasiegowi luk nie ma ani prostego
       odcinka pionowego, ani poziomego - wyglada jak naroznik, nie jak linia prowadzaca
       do awatara. Te wartosci zostawiaja 16 px pionu i 8 px dobiegu do awatara. */
    --lukuro-reviews-connector-radius: 14px;
    /* Linia ma 1 px i barwe RAMKI KARTY OPINII (decyzja usera 2026-08-24). Odwolanie do tokenu,
       a nie powtorzona wartosc: gdyby ramka kiedys drgnela, lacznik poszedlby za nia zamiast
       zostac sam. Wczesniej lacznik jechal na 22% barwy marki i czytal sie jako element
       firmowy - wyrazniejszy niz ramka, ktora otacza cala karte. Na 10% schodzi w szarosc
       i staje sie tym, czym ma byc: cienkim wloknem struktury pod trescia. */
    --lukuro-reviews-connector: var(--lukuro-reviews-border-brand);
    --lukuro-reviews-connector-w: 1px;

    --lukuro-reviews-radius: 12px;
    --lukuro-reviews-radius-s: 8px;
    /* Promien SEKCJI jako karty. Musi byc WIEKSZY od promienia kart opinii - ramka o tym samym
       promieniu wokol kart o tym samym promieniu czyta sie jak podwojna obwodka, a nie jak
       jedno w drugim. */
    --lukuro-reviews-radius-l: 16px;
    /* Cien sekcji stojacej jako karta - CELOWO na granicy widocznosci (wymaganie usera
       2026-08-26, po korekcie "bardziej delikatny"). Wartosc rowna tej, ktora niesie modul
       szkolen (`--lukuro-trainings-shadow`), bo obie powierzchnie stoja jedna pod druga na
       tym samym ekranie panelu konta i roznica byla by widoczna jako niedopatrzenie.
       Wlasny token, a NIE cytowanie tamtego: moduly sa niezalezne, opinie dzialaja bez szkolen
       i odwrotnie, wiec zapozyczona zmienna zniknelaby przy opt-oucie tamtego modulu. */
    --lukuro-reviews-shadow: 0 1px 1px rgba(0, 0, 0, .02), 0 3px 8px rgba(0, 0, 0, .02);
    --lukuro-reviews-transition: all 0.2s ease;
}

/* Container */

/**
 * `display: block` i `width: 100%` NIE sa kosmetyka - to jedyne, co trzyma sekcje w kolumnie.
 *
 * Konsument osadza sekcje w rozmaitych opakowaniach i czesc z nich jest kontenerem flex.
 * Zmierzone na panelu szkolen: modul stawia sekcje w golym `<section>`, a Bricks stylizuje
 * goly `section` jako `display: flex; align-items: center`. Korzen stawal sie wtedy
 * KURCZACYM SIE elementem flex, wiec jego szerokosc byla funkcja wlasnej TRESCI, nie ukladu:
 * ta sama sekcja mierzyla 519,5 / 777,4 / 925,8 px na trzech powierzchniach i stala 129,7 px
 * (a na widoku szkolenia 258,7 px) w prawo od kazdego innego bloku strony.
 *
 * `display: block` odbiera tez status elementu flex DZIECIOM korzenia. Wczesniej naglowek
 * i formularz kurczyly sie do szerokosci wlasnej tresci (262,5 px i 277 px przy sekcji
 * 777,4 px), przez co kreska pod naglowkiem konczyla sie na 34% szerokosci sekcji, a lista
 * pod spodem byla wyrazne szersza. To sa objawy 1, 2 i 3 z audytu - wszystkie z tej przyczyny.
 *
 * `max-width` NIE nalezy tutaj. Szerokosc kolumny zna konsument, nie modul; sztywne 800 px
 * dokladalo czwarta szerokosc do trzech, ktore strona juz miala.
 */
.lukuro-reviews {
    display: block;
    width: 100%;
    font-family: inherit;
    color: var(--lukuro-reviews-text);
}

/* Header */

/* Naglowek NIE ma kreski pod soba (decyzja usera 2026-08-24) i to jest wartosc domyslna
   pakietu, a nie zdjecie ustawione u konsumenta. Kreska byla pierwotnie objawem nr 2 audytu:
   naglowek jako kurczacy sie element flex konczyl ja na 34% szerokosci sekcji (262,5 px wobec
   777,4 px). Naprawa szerokosci z `ffa8d4d` sprawila, ze kreska szla juz przez cala kolumne -
   i wtedy okazalo sie, ze jest po prostu zbedna: sekcje od tresci nad nia odcina odstep, a same
   opinie sa kartami z wlasnymi krawedziami.

   `width: 100%` zostaje jako asekuracja na wypadek opakowania, ktore mimo wszystko ustawi
   korzen na flex - bez niej naglowek kurczylby sie do szerokosci tytulu i licznik odjechalby
   od prawej krawedzi kolumny. */
.lukuro-reviews-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    width: 100%;
    gap: var(--at-space--xs, 0.875rem);
    margin-bottom: var(--at-space--s, 1.25rem);
}

/* Tytul sekcji ma DOMYSLNIE barwe i grubosc naglowkow (decyzja usera 2026-08-24). Wczesniej
   bral `--lukuro-reviews-text`, czyli kolor tekstu ciaglego, i czytal sie jak akapit ustawiony
   wiekszym stopniem, a nie jak naglowek sekcji.

   `--at-primary-d-5` nie jest tu wyborem estetycznym, tylko odwzorowaniem KONTRAKTU MOTYWU:
   `bricks-base.css` ma globalna regule `h1, h2, h3, h4, h5, h6, .h1 ... { color:
   var(--at-primary-d-5) }`, wiec to jest barwa, ktora motyw daje kazdemu naglowkowi. Tytul
   sekcji jest `h3`, wiec bez wlasnej deklaracji dostalby ja sam - modul deklaruje ja jawnie
   tylko po to, zeby pakiet BEZ Advanced Themera nie zostal z kolorem tekstu ciaglego.

   Wczesniej stal tu `--at-neutral-d-5` i to byl blad: ten token daje `rgb(30, 35, 35)`, podczas
   gdy naglowki motywu renderuja sie `rgb(2, 41, 49)` - zmierzone na powierzchni lekcji, czyli
   tam, gdzie nie stoi ani jedna regula custom CSS witryny. Zmylila mnie regula buildera
   u konsumenta, ktora dla tej sekcji uzywa tokenu neutralnego; ale ona opisuje wybor jednej
   witryny, a nie to, czym motyw rysuje naglowki.

   Grubosc jest literalem: AT nie ma tokenu wagi, a `--mito-heading--weight` to zmienna
   konkretnej witryny, na ktorej framework stac nie moze. `500` to wartosc, ktora ten token
   oddaje, i ta sama, ktora maja naglowki motywu (zmierzone). */
.lukuro-reviews-title {
    font-size: var(--at-text--l, 1.25rem);
    font-weight: 500;
    margin: 0;
    color: var(--at-primary-d-5, var(--lukuro-reviews-text, #222));
}

/**
 * RYTM PODSUMOWANIA IDZIE SASIEDZTWEM, a nie marginesem konkretnego elementu (decyzja usera
 * 2026-08-26). W podsumowaniu moga stac trzy rzeczy i KAZDA jest warunkowa: tytul, zajawka
 * (`lede`) i statystyka (`show_summary`). Margines przypisany do jednej z nich rozjezdza sie
 * przy kazdej kombinacji, ktorej akurat nie sprawdzono.
 *
 * Zmierzone dwa razy, oba razy blednie, zanim regula trafila tutaj:
 *   - margines na TYTULE, gdy nie bylo statystyki: wisial i odstep do formularza skladal sie
 *     z dwoch zrodel - 8 px stad plus `--at-space--s` z naglowka, razem 28,00 px zamiast 20,00;
 *   - ten sam margines po dolozeniu zajawki: trafial miedzy tytul a zajawke, a zajawka
 *     przyklejala sie do gwiazdek na 0,00 px.
 *
 * `> :not(:last-child)` zamyka wszystkie kombinacje jedna regula: cokolwiek stoi w podsumowaniu,
 * dostaje odstep do NASTEPNEGO elementu, a ostatni nie dostaje nic - wiec odstep do tego, co
 * jest pod naglowkiem, niesie wylacznie `margin-bottom` naglowka. Jedno zrodlo, jak mialo byc.
 *
 * Warunek stoi w arkuszu, a nie w rendererze, i to jest wlasciwy podzial: renderer wypisuje
 * albo nie wypisuje kazdej z trzech rzeczy, ale to arkusz wie, co ich sasiedztwo znaczy
 * dla odstepow.
 */
.lukuro-reviews-summary > * {
    margin-block: 0;
}

.lukuro-reviews-summary > :not(:last-child) {
    margin-bottom: 0.5rem;
}

/* Zajawka sekcji. Marginesu WLASNEGO nie ma - rytm podsumowania niesie regula sasiedztwa wyzej.

   Stopien `--at-text--s` i kolor stonowany: to jest podpis pod tytulem, a nie tresc sekcji.
   `max-width` w jednostce `ch` liczy sie z SZEROKOSCI ZNAKU tego pisma, wiec wiersz zostaje
   czytelny takze wtedy, gdy konsument przestawi skale - inaczej niz `px`, ktore trzymaloby
   szerokosc kolumny, ale nie liczbe znakow w wierszu. */
.lukuro-reviews-lede {
    max-width: 65ch;
    color: var(--lukuro-reviews-text-muted);
    font-size: var(--at-text--s, 0.875rem);
    line-height: 1.5;
}

.lukuro-reviews-stats {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.lukuro-reviews-average {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Srednia ocena i licznik ida na skale AT (decyzja usera 2026-08-24) - byly ostatnimi
   wartosciami w naglowku sekcji na wlasnej skali arkusza (2rem i 0.875rem).

   WAGA JEST LITERALEM, a nie `var(--mito-heading--weight)`, mimo ze user podal wlasnie ten
   token. Powod jest kontraktowy: `--mito-*` to zmienna KONKRETNEJ witryny, a arkusz frameworka
   nie moze stac na czyms, czego u nastepnego konsumenta nie bedzie - to samo ustalenie, ktore
   zakazuje cytowania klas globalnych witryny. AT nie ma wlasnego tokenu wagi (sprawdzone na
   instancji: jest tylko `--at-mark-font-weight`, pusty), wiec zostaje liczba. `500` to
   dokladnie ta wartosc, ktora `--mito-heading--weight` oddaje na tej witrynie - efekt jest
   identyczny, zaleznosci nie ma.

   Kolor bierze `--at-neutral-d-5` z fallbackiem na wlasny token tekstu sekcji, zeby pakiet bez
   AT nie zostal z golym `inherit`. */
.lukuro-reviews-average-number {
    font-size: var(--at-text--l, 1.25rem);
    font-weight: 500;
    color: var(--at-neutral-d-5, var(--lukuro-reviews-text, #222));
}

.lukuro-reviews-stars {
    display: flex;
    gap: 2px;
}

.lukuro-reviews-stars .star {
    font-size: 1.25rem;
    color: var(--lukuro-reviews-star-empty);
}

.lukuro-reviews-stars .star.filled {
    color: var(--lukuro-reviews-star-color);
}

.lukuro-reviews-count {
    color: var(--lukuro-reviews-text-muted);
    font-size: var(--at-text--s, 0.8125rem);
}

/**
 * Przycisk glowny. Wyglad nalezy do motywu (`bricks-button` + wariant `primary`); ponizsze
 * reguly sa WYLACZNIE fallbackiem dla witryny bez Advanced Themera, dlatego stoja
 * w `:where()`. Jeden selektor obsluguje wszystkie trzy role: otwarcie formularza, wysylke
 * opinii i wysylke odpowiedzi - kazda z nich nosi `lukuro-reviews__cta`.
 */
:where(.lukuro-reviews__cta) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 10px 20px;
    border: none;
    border-radius: 999px;
    background: var(--lukuro-reviews-primary);
    color: var(--lukuro-color-on-primary, #fff);
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    transition: opacity 0.15s ease;
}

:where(.lukuro-reviews__cta:hover) {
    color: var(--lukuro-color-on-primary, #fff);
    opacity: 0.88;
}

/* Stan wylaczenia zostaje regula o specyficznosci NIEZEROWEJ: motyw go nie zna, wiec nie ma
   z czym przegrywac, a przy `:where()` przegralby z wlasnym stanem bazowym wyzej. */
.lukuro-reviews button:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Przegladarka bez JavaScriptu: formularz odslania regula w `<noscript>`, a to zdanie
   mowi, ze samo wyslanie i tak wymaga skryptu. Bez niego formularz przeladowywalby strone
   i milczal. */
.lukuro-reviews-noscript {
    margin: 0 0 1rem;
    color: var(--lukuro-reviews-text-muted);
}

/* Form */

/* Neutralna szarosc `surface-subtle` (`#f1f2f3` na mitoterapii) nie miala zwiazku z marka
   i pod lekcja, gdzie formularz stoi otworem jako PIERWSZY element sekcji, ustawiala
   pierwsze wrazenie calego ekranu. Ta sama tinta co dymek odpowiedzi, tylko slabsza,
   zeby pole do pisania nie konkurowalo z trescia rozmowy. */
/* Odstep pod formularzem idzie `--at-space--l` (decyzja usera 2026-08-26), czyli o szczebel
   wyzej niz odstep nad nim. To NIE jest asymetria przez nieuwage: nad formularzem stoi jego
   wlasny tytul, z ktorym tworzy jedna calosc, a pod nim zaczyna sie CUDZA tresc - lista opinii.
   Granica miedzy "tu piszesz" a "tu czytasz" ma byc wyrazniejsza niz odstep wewnatrz pierwszej
   z tych dwoch rzeczy. Zmierzone u tego konsumenta: 39,16 px zamiast 28,12 px. */
.lukuro-reviews-form-wrapper {
    width: 100%;
    background: var(--lukuro-reviews-tint-soft);
    border: 1px solid var(--lukuro-reviews-border-brand);
    padding: var(--at-space--s, 1.25rem);
    border-radius: var(--lukuro-reviews-radius);
    margin-bottom: var(--at-space--l, 2.5rem);
}

.lukuro-review-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.lukuro-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

@media (max-width: 640px) {
    .lukuro-form-row {
        grid-template-columns: 1fr;
    }
}

/* Opakowanie pola w konwencji WooCommerce. `form-row` samo z siebie nie niesie na tej
   witrynie nic poza `margin-block: 0` z `bricks-base.css` (zmierzone), wiec nie gryzie sie
   z siatka `.lukuro-form-row` - ta zostaje tam, gdzie byla, jako kontener dwoch pol. */
.lukuro-reviews .lukuro-form-field {
    display: block;
    margin: 0;
    padding: 0;
}

/**
 * Pole formularza. Wartosci ida na skale AT, wiec na witrynie z AT pole ma te same wymiary
 * co pola WooCommerce w Moim koncie - bez kopiowania czegokolwiek z tamtej witryny.
 * Fallback w `:where()`, zeby regula motywu wygrywala bez walki o wage.
 */
:where(.lukuro-reviews .input-text) {
    width: 100%;
    padding: var(--at-space--xs, 0.875rem);
    border: 1px solid color-mix(in srgb, var(--lukuro-reviews-primary, #0ba1bf) 20%, transparent);
    border-radius: var(--at-radius--s, 0.833rem);
    background: var(--lukuro-reviews-surface);
    color: inherit;
    font-family: inherit;
    font-size: var(--at-text--m, 1rem);
}

:where(.lukuro-reviews .input-text:focus) {
    outline: 2px solid var(--lukuro-reviews-primary);
    outline-offset: 1px;
}

/**
 * KOMPOZYTOR: POLE ROSNIE Z TRESCIA (decyzja usera 2026-08-26)
 *
 * Pole opinii zaczyna sie na jednym wierszu i dociaga sie do wysokosci wpisanego tekstu -
 * wysokosc ustawia `reviews.js`, tutaj stoja tylko granice. Puste pole kosztowalo wczesniej
 * 126,2 px (`rows="4"`), a caly formularz pod lekcja 227,2 px, i platila za to KAZDA
 * czytelniczka, takze ta, ktora nic nie pisze.
 *
 * `min-height` rowne progowi dotykowemu (SC 2.5.5): pole jest kontrolka, wiec 44 px nalezy mu
 * sie niezaleznie od tresci. NIE JEST to jednak wysokosc startowa - te niesie `rows="2"`
 * w rendererze i to ona jest realna dolna granica, bo `initComposer()` wraca po skasowaniu
 * tekstu dokladnie do wysokosci z `rows`. Dwie wartosci, dwie role: 44 px to prog dotykowy,
 * dwa wiersze to obietnica "tu sie pisze zdanie, nie haslo".
 *
 * `max-height` jest po to, zeby dluga opinia nie wypchnela listy poza ekran - powyzej pulapu
 * pole dostaje WLASNY suwak, wiec tekst nie znika, tylko przewija sie w miejscu.
 *
 * `resize: vertical` naprawia przy okazji blad: pole mialo `resize: both` (wartosc domyslna
 * przegladarki dla `textarea`), wiec dalo sie je wyciagnac takze W BOK, poza kolumne czytania,
 * i strona dostawala poziomy pasek przewijania.
 *
 * Pion zostaje, ale NIE JEST wyjsciem ponad pulap i nie nalezy tak go opisywac - `max-height`
 * clampuje takze wysokosc ustawiona uchwytem (zmierzone: przeciagniecie na 600 px daje wysokosc
 * wyliczona 200 px). Uchwyt sluzy wiec do ZMNIEJSZENIA pola albo dociagniecia go do pulapu
 * recznie; powyzej pulapu tekst przewija sie w miejscu i to jest jedyna droga.
 */
.lukuro-reviews .lukuro-form-grow {
    min-height: 44px;
    max-height: 200px;
    resize: vertical;
    overflow-y: auto;
}

/**
 * RZAD AKCJI ODSLANIA SIE DOPIERO, GDY JEST PO CO.
 *
 * Wylacznie w trybie STALE OTWARTYM (`data-always-open`, czyli dyskusja pod lekcja). Tam
 * formularz stoi caly czas i jego przycisk czekal na nikogo; w trybie z przyciskiem
 * "Napisz opinie" formularz jest juz SKUTKIEM decyzji, wiec rzad akcji zostaje widoczny -
 * inaczej "Anuluj" znikalby przy kazdym klikniecu poza pole i nie byloby czym sie wycofac.
 *
 * Warunek jest podwojny i oba czlony sa potrzebne. `:focus-within` obsluguje klawiature:
 * przycisk pojawia sie, ZANIM tab do niego dojdzie, wiec nie wypada z kolejnosci fokusu.
 * Klasa `--dirty` (od `reviews.js`) trzyma go widocznym, gdy w polu cos juz jest, a fokus
 * poszedl gdzie indziej - inaczej napisane pytanie zostawaloby bez widocznej drogi wyslania.
 */
.lukuro-reviews-form-wrapper[data-always-open] .lukuro-form-actions {
    display: none;
}

.lukuro-reviews-form-wrapper[data-always-open] .lukuro-review-form:focus-within .lukuro-form-actions,
.lukuro-reviews-form-wrapper[data-always-open] .lukuro-review-form--dirty .lukuro-form-actions {
    display: flex;
}

/* Rating select */
.lukuro-form-rating label:first-child {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: 500;
}

.lukuro-rating-select {
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-end;
    gap: 0.25rem;
}

.lukuro-rating-select input {
    display: none;
}

/* Gwiazdki wejscia oceny sa MNIEJSZE niz byly (2rem), ale NIE schodza do rozmiaru gwiazdek
   wyswietlanych (1,25rem w naglowku, 1rem przy opinii). Powod jest dostepnosciowy, nie
   estetyczny: to jedyne gwiazdki, ktore sie KLIKA, wiec podlegaja SC 2.5.8 Target Size
   (Minimum) z WCAG 2.2 - cel nie moze byc mniejszy niz 24x24 px. 1,5rem daje dokladnie 24 px
   i to jest podloga, ponizej ktorej ten element schodzic nie moze.

   `i { font-size: 1em }` jest potrzebne, odkad w etykiecie stoi ikona zestawu zamiast golego
   znaku `★`: bez tego ikona jechalaby na wlasnym rozmiarze, a nie na rozmiarze etykiety. */
.lukuro-rating-select label {
    font-size: 1.5rem;
    line-height: 1;
    color: var(--lukuro-reviews-star-empty);
    cursor: pointer;
    transition: color 0.1s;
}

.lukuro-rating-select label :is(i, svg) {
    font-size: 1em;
    line-height: 1;
}

.lukuro-rating-select input:checked ~ label,
.lukuro-rating-select label:hover,
.lukuro-rating-select label:hover ~ label {
    color: var(--lukuro-reviews-star-color);
}

/* ROZMIAR przyciskow sekcji niesie modul, WYGLAD dalej nalezy do motywu (barwa, promien, stany,
   typografia rodziny). Decyzja usera 2026-08-24: "Napisz opinie" i przyciski formularzy maja
   byc domyslnie mniejsze - to akcje w obrebie sekcji, a nie glowne wezwanie strony, a przy
   domyslnym rozmiarze przycisku motywu (zmierzone: 15 px pisma, wypelnienie 12/24 px, wysokosc
   44 px) przyciagaly wzrok mocniej niz sama tresc opinii.

   Dlaczego regula ma specyficznosc, skoro reszta wygladu przycisku stoi w `:where()`: motyw nie
   ma wariantu mniejszego przycisku (sprawdzone na instancji - `.bricks-button.sm|md|lg|xl` nie
   istnieje w jego arkuszu), wiec nie da sie tego zalatwic klasa motywu w rendererze. Selektor
   jest DWUKLASOWY, zeby wygrywal z `.bricks-button` niezaleznie od kolejnosci arkuszy, ale
   pozostal do nadpisania rownie prosta regula po stronie konsumenta.

   Zmieniamy WYLACZNIE stopien pisma i wypelnienie. Wysokosc wychodzi z nich ~34 px, czyli nadal
   powyzej progu 24 px z SC 2.5.8.

   PROG DOTYKOWY SCHODZI Z 44 NA 36 px i to jest swiadomy kompromis, nie przeoczenie. 44 px to
   `min-height` z `:where(.lukuro-reviews__cta)` wyzej, czyli poziom SC 2.5.5 Target Size
   (Enhanced) - wymaganie AAA. 36 px zostaje wyraznie powyzej progu AA (SC 2.5.8 Target Size
   (Minimum), 24 px), wiec zgodnosc na poziomie AA jest zachowana, a AAA dla tych czterech
   przyciskow - nie. Pozostale kontrolki sekcji tego progu nie ruszaja.
   */
.lukuro-reviews .lukuro-reviews-add-btn,
.lukuro-reviews .lukuro-form-cancel,
.lukuro-reviews .lukuro-form-submit,
.lukuro-reviews .lukuro-comment-submit {
    font-size: var(--at-text--s, 0.8125rem);
    padding: calc(var(--at-space--xs, 0.875rem) / 2) var(--at-space--xs, 0.875rem);
    min-height: 36px;
}

/* Form actions */
.lukuro-form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
}

/* Przycisk drugorzedny ("Anuluj", "Zaladuj wiecej") nosi samo `bricks-button`, czyli
   neutralny wariant przycisku motywu. Fallback jak wyzej: `:where()`, specyficznosc zero. */
:where(.lukuro-form-cancel),
:where(.lukuro-load-more) {
    background: transparent;
    border: 1px solid var(--lukuro-reviews-rule);
    padding: 10px 20px;
    border-radius: 999px;
    color: inherit;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
}

/* Reviews list */
.lukuro-reviews-list {
    display: flex;
    flex-direction: column;
    gap: var(--at-space--s, 1.25rem);
}

.lukuro-reviews-empty {
    text-align: center;
    color: var(--lukuro-reviews-text-muted);
    padding: 2rem;
}

/* Single review */

/**
 * Karta zostaje BIALA z ramka w kolorze marki - to nie jest wybor z niczego, tylko
 * odwzorowanie tego, co witryna konsumenta juz sobie ustawila na powierzchni produktowej
 * i co user zatwierdzil jako wzorzec ("na szkoleniach musi byc tak samo"). Dzieki temu
 * przebudowa nie zmienia wygladu 94 opinii stojacych na zywym sklepie.
 *
 * UKLAD IDZIE SIATKA (decyzja usera 2026-08-26): awatar w kolumnie 1, CALA reszta w kolumnie 2 -
 * autor, data, plakietki, ocena, tresc, rzad akcji, odpowiedzi i formularz. Do tej pory kolumna
 * awatara obowiazywala WYLACZNIE w rzedzie naglowka, wiec pod nim tresc i przyciski wracaly na
 * lewa krawedz karty i opinia czytala sie inaczej niz odpowiedz na nia.
 *
 * DLACZEGO SIATKA, A NIE FLEX Z OPAKOWANIEM. Odpowiedz robi to flexem, bo ma opakowanie
 * `-main` - potrzebuje go do lacznika. Karta opinii linii nie emituje, wiec opakowania nie
 * potrzebuje, a dolozenie go zepchneloby `-replies` i `-reply-form` o poziom nizej i zlamalo
 * CZTERY sciezki `:scope >` w `reviews.js`. Siatka daje ten sam uklad, zostawiajac oba wezly
 * bezposrednimi dziecmi karty.
 *
 * KOLUMNA 2 NIESIE TAKZE WCIECIE POZIOMU 1 - patrz `.lukuro-review-replies` nizej.
 *
 * `min-width: 0` na dzieciach kolumny 2 jest warunkiem koniecznym, nie kosmetyka: sciezka `1fr`
 * ma domyslnie rozmiar `min-content`, wiec dlugi wyraz albo szeroka tabela w tresci opinii
 * rozepchnelyby karte poza kolumne czytania.
 *
 * Dzieci wyliczone SA JAWNIE, zamiast `> :not(.lukuro-review-avatar)`: wezel dolozony kiedys
 * do karty ma wtedy wpasc w oko przy pierwszym renderze, a nie po cichu wskoczyc do kolumny 2.
 *
 * `row-gap` zostaje ZEROWY. Rytm pionowy niosa istniejace `margin-bottom` naglowka i tresci -
 * takze te z custom CSS konsumenta, ktory siega po te same wezly (zmierzone u pierwszej
 * witryny 2026-09-04: `margin-bottom` na naglowku i tresci opinii, w DWOCH zywych
 * szablonach `bricks_template`). `row-gap` zdublowalby je.
 */
.lukuro-review-item {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--lukuro-reviews-avatar-gap);
    align-items: start;
    padding: var(--at-space--s, 1.25rem);
    background: var(--lukuro-reviews-surface);
    border: 1px solid var(--lukuro-reviews-border-brand);
    border-radius: var(--lukuro-reviews-radius);
}

.lukuro-review-avatar {
    grid-column: 1;
    grid-row: 1;
}

.lukuro-review-item > .lukuro-review-header,
.lukuro-review-item > .lukuro-review-variant,
.lukuro-review-item > .lukuro-review-content,
.lukuro-review-item > .lukuro-review-photos,
.lukuro-review-item > .lukuro-review-actions,
.lukuro-review-item > .lukuro-review-replies,
.lukuro-review-item > .lukuro-reply-form {
    grid-column: 2;
    min-width: 0;
}

/* `center`, a nie `flex-start`: awatar wyszedl z tego rzedu do wlasnej kolumny siatki, wiec
   nie ma juz czego wyrownywac do gory - zostaly same etykiety i ocena, ktore czytaja sie
   w jednej linii bazowej. */
.lukuro-review-header {
    display: flex;
    align-items: center;
    gap: var(--at-space--xs, 0.875rem);
    margin-bottom: var(--at-space--xs, 0.875rem);
    flex-wrap: wrap;
}

/* Ocena dosuwa sie do prawej krawedzi karty. Bez tego stala tuz za plakietkami, w polowie
   szerokosci, i czytala sie jak kolejna plakietka zamiast jak podsumowanie wpisu. */
.lukuro-review-rating {
    margin-inline-start: auto;
}

.lukuro-review-avatar img {
    width: var(--lukuro-reviews-avatar-lg, 44px);
    height: var(--lukuro-reviews-avatar-lg, 44px);
    border-radius: 50%;
    object-fit: cover;
}

.lukuro-review-meta {
    flex: 1;
    min-width: 120px;
}

.lukuro-review-author {
    display: block;
    font-size: var(--at-text--m, 1rem);
    font-weight: 500;
    line-height: 1.2;
}

.lukuro-review-date {
    font-size: var(--at-text--xs, 0.75rem);
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-review-rating {
    display: flex;
    gap: 2px;
}

.lukuro-review-rating .star {
    color: var(--lukuro-reviews-star-empty);
    font-size: 1rem;
}

.lukuro-review-rating .star.filled {
    color: var(--lukuro-reviews-star-color);
}

.lukuro-review-content {
    font-size: var(--at-text--m, 1rem);
    margin-bottom: var(--at-space--xs, 0.875rem);
    line-height: 1.5;
}

.lukuro-review-content p:last-child {
    margin-bottom: 0;
}

/* Verified badge */
.lukuro-verified-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--at-text--xs, 0.75rem);
    color: var(--lukuro-reviews-success-text);
    background: color-mix(in srgb, var(--lukuro-reviews-success, #11b76b) 12%, transparent);
    padding: 0.125rem 0.625rem;
    border-radius: 999px;
}

.lukuro-verified-badge :is(i, svg) {
    font-size: 0.875rem;
}

/* Plakietka strony witryny - odpowiedz prowadzacej, obslugi sklepu itd.
   Kolor marki, a nie zielen "zweryfikowanego zakupu": to inny rodzaj informacji,
   wiec nie moze wygladac jak ta sama plakietka w innym miejscu. */
.lukuro-staff-badge {
    display: inline-flex;
    align-items: center;
    font-size: var(--at-text--xs, 0.75rem);
    line-height: 1.2;
    color: var(--lukuro-reviews-primary);
    background: color-mix(in srgb, var(--lukuro-reviews-primary, #111) 10%, transparent);
    padding: 0.125rem 0.625rem;
    border-radius: 999px;
    white-space: nowrap;
}

.lukuro-comment-meta .lukuro-staff-badge {
    margin-inline-end: 0.25rem;
}

/* Actions */

/**
 * Caly rzad akcji - glosy z ikonami, "Skomentuj", "Odpowiedz", "Komentarze (N)" i godzina -
 * jedzie na `--at-text--xs` (decyzja usera 2026-08-24). To jest warstwa POMOCNICZA pod
 * wypowiedzia i ma sie tak czytac; wczesniej szla na 0,875 rem i 1 rem, czyli momentami
 * mocniej niz sama tresc odpowiedzi.
 *
 * Stopien nadaje kontener, a kontrolki dziedzicza (`font-size: inherit`, ikony `1em`) -
 * inaczej kazda z osmiu rol wymagalaby wlasnej wartosci i rozjechalyby sie przy pierwszej
 * zmianie skali.
 *
 * HOVER: wylacznie zmiana koloru na barwe marki, ZERO podkreslenia (decyzja usera). Kciuki
 * traca tez tlo na hoverze - podswietlenie prostokatem robilo z nich przyciski, a maja byc
 * kontrolkami tekstowymi. Stany `active` glosow zostaja, bo niosa informacje, a nie wskazanie.
 */
.lukuro-review-actions,
.lukuro-comment-actions {
    font-size: var(--at-text--xs, 0.75rem);
}

.lukuro-review-actions button,
.lukuro-comment-actions button,
.lukuro-review-actions .lukuro-comment-date,
.lukuro-comment-actions .lukuro-comment-date {
    font-size: inherit;
}

.lukuro-review-actions button :is(i, svg),
.lukuro-comment-actions button :is(i, svg) {
    font-size: 1em;
}

.lukuro-review-actions {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.lukuro-vote-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    background: transparent;
    border: none;
    color: var(--lukuro-reviews-btn-default);
    cursor: pointer;
    padding: 0.375rem 0.5rem;
    border-radius: var(--lukuro-reviews-radius-s);
    transition: var(--lukuro-reviews-transition);
}

.lukuro-vote-btn:hover {
    color: var(--lukuro-reviews-primary);
}

.lukuro-vote-btn.active.lukuro-vote-like {
    color: var(--lukuro-reviews-success-text);
    background: color-mix(in srgb, var(--lukuro-reviews-success, #11b76b) 12%, transparent);
}

.lukuro-vote-btn.active.lukuro-vote-dislike {
    color: var(--lukuro-reviews-error);
    background: color-mix(in srgb, var(--lukuro-reviews-error, #ef4444) 12%, transparent);
}

.lukuro-vote-btn.loading {
    opacity: 0.6;
    pointer-events: none;
}

.lukuro-toggle-replies,
.lukuro-reply-btn {
    background: transparent;
    border: none;
    color: var(--lukuro-reviews-btn-default);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.lukuro-toggle-replies:hover,
.lukuro-reply-btn:hover,
.lukuro-comment-reply-btn:hover {
    color: var(--lukuro-reviews-primary);
}

/* IKONY RZEDU AKCJI STOJA NA 0,7 (decyzja usera 2026-08-24). Kciuki, dymek "Komentarze" i strzalka
   "Odpowiedz" sa etykietami czynnosci, nie trescia - przy pelnym kryciu ciagnely wzrok mocniej niz
   liczby i podpisy obok nich. Na `:hover` wracaja na 1 i razem z podpisem zapalaja sie na barwe
   marki, wiec caly przycisk reaguje jako jedna calosc, a nie sam tekst.

   Selektor obejmuje `i` ORAZ `svg`: domyslny zestaw ikon modulu to znaczniki `<i class="fas ...">`,
   ale konsument moze podac przez `icons` wlasny zestaw i wtedy w przycisku stoi `<svg>`.
   `fill: currentColor` sprawia, ze taki `svg` zapala sie razem z tekstem bez osobnej reguly.

   Ikona dziedziczy `color` z przycisku, wiec barwy nie trzeba tu powtarzac - wystarczy krycie. */
.lukuro-vote-btn :is(i, svg),
.lukuro-toggle-replies :is(i, svg),
.lukuro-reply-btn :is(i, svg),
.lukuro-comment-reply-btn :is(i, svg) {
    opacity: 0.7;
    fill: currentColor;
    transition: opacity 0.15s ease;
}

.lukuro-vote-btn:hover :is(i, svg),
.lukuro-toggle-replies:hover :is(i, svg),
.lukuro-reply-btn:hover :is(i, svg),
.lukuro-comment-reply-btn:hover :is(i, svg) {
    opacity: 1;
}

/* ROZMIAR IKON Z WLASNEGO ZESTAWU. Caly modul wymiaruje ikony pismem otoczenia (`font-size`
   na `.star`, na etykiecie wejscia oceny, na przycisku akcji) - i to dziala, dopoki ikona jest
   glifem fontu. Ikona z zestawu SVG wchodzi jako inline `<svg>` z wymiarami z pliku, zwykle
   24x24 px, i `font-size` jej nie dotyczy: bez tej reguly gwiazdka w naglowku sekcji urosla
   by z 1,25rem do 24 px, a kciuk w rzedzie akcji z 1em do tego samego.

   Regula sciaga je z powrotem do rozmiaru pisma, w ktorym stoja. Barwy nie powtarza - ikony
   zestawu niosa `currentColor` w `fill`/`stroke`, wiec dziedzicza ja z otoczenia. */
.lukuro-reviews .star svg,
.lukuro-rating-select label svg,
.lukuro-verified-badge svg,
.lukuro-review-actions button svg,
.lukuro-comment-actions button svg {
    width: 1em;
    height: 1em;
}

/* Replies */

/**
 * LACZNIK WATKU. Model (wersja trzecia i ostateczna, decyzja usera 2026-08-26):
 *
 *   Linia nie zaczyna sie przy opinii ANI przy odpowiedzi na nia. Pierwszy odcinek rysuje
 *   odpowiedz poziomu 1, ktora sama ma odpowiedzi - jako ZEJSCIE spod wlasnego awatara.
 *   Gdy linia juz sie zaczela, biegnie ciagiem przez cala podrozmowe, takze w dol, w kolejne
 *   poziomy. Przerwa jest zawsze bledem poza jednym miejscem: gornym koncem przy pierwszej
 *   odpowiedzi w grupie.
 *
 * Krotko: POZIOM 0 I POZIOM 1 SA WOLNE OD LINII, linia zaczyna sie tam, gdzie z poziomu 1
 * wychodzi poziom 2.
 *
 * TRZY ODCINKI, wszystkie zaczepione o boks, ktory sam ich potrzebuje:
 *
 *   LUK (`::before`, kazda odpowiedz OD POZIOMU 2) - podejmuje linie z gory, plynnie wygina
 *   sie w prawo i konczy na lewej krawedzi WLASNEGO awatara, w polowie jego wysokosci.
 *
 *   PRZEDLUZENIE (`::after`, odpowiedz OD POZIOMU 2, po ktorej idzie rodzenstwo) - od wlasnego
 *   luku w dol, do wlasnego dolu, gdzie podejmuje je luk nastepnej odpowiedzi. OSTATNIA go
 *   nie rysuje, wiec linia konczy sie na jej luku.
 *
 *   ZEJSCIE (`-say::before`, kazda odpowiedz majaca wlasne odpowiedzi, TAKZE poziom 1) - spod
 *   wlasnego awatara do poczatku wlasnej podrozmowy. Przy poziomie 1 jest to GORNY KONIEC
 *   calej linii; glebiej - jej kontynuacja.
 *
 * DLACZEGO POZIOM 1 STRACIL LUK. Model z 2026-08-24 mowil "linia nie dotyka wypowiedzi
 * nadrzednej" i formalnie byl prawdziwy: luk urywal sie o `thread-gap` nad kontenerem i pod
 * opinia zostawalo czyste tlo. WYGLADALO to jednak dokladnie odwrotnie, bo os luku poziomu 1
 * liczyla sie jako `wciecie kontenera - elbow`, czyli wypadala w SRODKU AWATARA OPINII.
 * Zbieznosc osi byla arytmetyka wciecia, nie wypowiedzia o hierarchii - ale user czytal
 * WYNIK, nie arytmetyke, i zglosil to jako "linie wychodza z pierwszego komentarza".
 *
 * WNIOSEK NA PRZYSZLOSC, oplacony trzema iteracjami: o odbiorze tej linii decyduje POLOZENIE
 * OSI, a nie to, czy odcinek formalnie dotyka cudzego boksu. "Nie dotyka" nie znaczy
 * "nie wychodzi z".
 *
 * Regule wykonuje selektor `.lukuro-review-replies > .lukuro-comment-item::before/::after`
 * nizej, przy samych odcinkach.
 *
 * TRZY MODELE ODRZUCONE PO DRODZE, zeby nie wracaly:
 *   1. `border-left` na kontenerze odpowiedzi - kreska rownolegla do watku, nie wskazywala
 *      niczego ("wyglada to jak border-left, a nie jak linia hierarchii").
 *   2. Pion do konca poddrzewa plus zaslona w kolorze powierzchni na jego ogonie - pion i luk
 *      dzielily 30,1 px tej samej osi, wiec przy 1 px rozjezdzaly sie w podwojna kreske,
 *      a zaslona konczyla sie uskokiem ("linia sklada sie z 2 borderow i jeden z nich wychodzi").
 *   3. Pion spod DOLNEJ KRAWEDZI AWATARA RODZICA do poczatku pierwszej odpowiedzi, rysowany
 *      przez opakowanie `-say`. Geometrycznie czysty - zmierzone 0,0 px rozjazdu, zero
 *      nakladania sie, zero przerw - ale zly model. Jego dlugosc byla funkcja DLUGOSCI TEKSTU
 *      RODZICA, a nie struktury watku: na powierzchni produktowej zmierzone 93,5 px przy
 *      krotkiej opinii i 186,3 px przy szescioliniowej, czyli 76% i 86% calej linii bieglo
 *      wzdluz cudzej wypowiedzi. Zniklo z nim opakowanie `review-say` w karcie opinii i klasa
 *      stanu `lukuro-review-item--thread-open`: istnialy WYLACZNIE po to, zeby ten pion mial
 *      gdzie sie zaczepic i czym sie warunkowac. Opakowanie `-say` przy ODPOWIEDZI zostaje -
 *      ma tam inne zadanie, patrz "ZEJSCIE DO WLASNEJ PODROZMOWY" nizej.
 *
 * DLACZEGO LUK RYSUJE TAKZE PIERWSZA ODPOWIEDZ W GRUPIE, a nie dopiero druga - OBOWIAZUJE
 * OD POZIOMU 2. Kuszace jest oddac pierwszej odpowiedzi sam pion "od wlasnego awatara w dol"
 * i zaczac luki od drugiej; wtedy linia laczylaby dokladnie rodzenstwo i nic ponadto. Rozbija
 * sie to o dane: grupa JEDNOELEMENTOWA nie ma czego laczyc i zostalaby zupelnie bez linii.
 * W bazie tego sklepu 5 z 7 grup odpowiedzi ma dokladnie jedno dziecko. Luk przy kazdej
 * odpowiedzi trzyma jedna regule dla wszystkich: kazda odpowiedz jest ODBIORCA luku, zadna nie
 * jest zrodlem linii, a rodzenstwo wyglada tak samo niezaleznie od licznosci grupy.
 *
 * Na POZIOMIE 1 ten akapit nie obowiazuje i to nie jest wyjatek do reguly, tylko sama regula
 * (2026-08-26): tam grupa jednoelementowa ma po prostu nie miec linii.
 *
 * GEOMETRIA STOI NA DWOCH WZORACH, po jednym na kazda role:
 *
 *   wciecie poziomu 1   = szerokosc awatara opinii + odstep  (kolumna 2 siatki karty)
 *   wciecie poziomu n+1 = polowa awatara rodzica + `--lukuro-reviews-elbow`   (n >= 1)
 *   os lacznika         = wciecie - `--lukuro-reviews-elbow`  (czyli `-elbow` od krawedzi pozycji)
 *
 * Poziom 1 wypadl ze wzoru z `elbow` razem z lukiem, ktory ten czlon obslugiwal - patrz
 * `.lukuro-review-replies`. Dla poziomow 2+ `--lukuro-reviews-elbow` pozostaje JEDYNA
 * wartoscia do zmiany: przestawia naraz zasieg luku i wciecie kazdego poziomu, a lacznik
 * nie ma jak rozjechac sie z awatarem.
 */
/* Odstep miedzy rodzenstwem idzie SASIEDZTWEM, a nie `gap` we flexie - i to nie jest kwestia
   gustu. Kontener odpowiedzi pod opinia nosi inline `display`, ktory ustawia `reviews.js`
   (`none` / `block`), wiec arkusz nie ma jak zrobic z niego kontenera flex: zmierzone, regula
   `display: flex` przegrywa z atrybutem `style` i `gap` przestaje cokolwiek znaczyc. Skutek
   byl widoczny - rodzenstwo stykalo sie bez odstepu, a luk nastepnej odpowiedzi wznosil sie
   w obszar juz zajety przez przedluzenie poprzedniej i linia sie podwajala. Margines dziala
   w obu ukladach, wiec oba kontenery zachowuja sie tak samo. */
.lukuro-review-replies,
.lukuro-nested-replies {
    margin-top: var(--lukuro-reviews-thread-gap);
}

.lukuro-comment-item + .lukuro-comment-item {
    margin-top: var(--lukuro-reviews-thread-gap);
}

/* WCIECIE POZIOMU 1 PRZENIOSLO SIE DO SIATKI KARTY (decyzja usera 2026-08-26) i dlatego ta
   regula jest pusta zamiast nie istniec - bez niej nastepna osoba doda tu `padding-left`
   po raz drugi.

   Kontener stoi w kolumnie 2 karty, wiec zaczyna sie na `avatar-lg + avatar-gap` od jej lewej
   krawedzi: 58 px na desktopie, 41 px na waskim ekranie. Awatar odpowiedzi trafia przez to
   dokladnie pod pierwsza litere opinii - tak, jak we wzorcu dyskusji, na ktory powolal sie
   user.

   Czlon `elbow` ZNIKNAL z tego wzoru i to jest poprawne, a nie przeoczone. `elbow` istnieje
   po to, zeby luk lacznika mial zasieg - a na tym poziomie luku juz nie ma (patrz regula
   gaszaca nizej). Poziomy 2+ zostaja na starym wzorze `avatar/2 + elbow`, bo tam luk zostaje
   i jego os musi dalej trafiac w srodek awatara rodzica.

   Poprzednia wartosc: `avatar-lg / 2 + elbow`, czyli 44 px i 33 px. Zostawienie jej dawaloby
   blok odpowiedzi zaczynajacy sie 14 px NA LEWO od tekstu opinii - do tej pory maskowala to
   linia wychodzaca z awatara opinii, ktorej wlasnie sie pozbywamy. */
.lukuro-review-replies {
    padding-left: 0;
}

/**
 * DYMEK OBEJMUJE SAM TEKST WYPOWIEDZI (decyzja usera 2026-08-24, nadrzedna wobec wczesniejszej
 * z tego samego dnia, ktora kazala mu obejmowac awatar - user obejrzal efekt i zmienil zdanie).
 *
 * Tlo niesie WYLACZNIE `-body`, czyli autor i tresc. Awatar stoi poza dymkiem, po lewej;
 * glosy, "Odpowiedz" i data stoja pod dymkiem, tez poza nim i bez tla. Pozycja sama tla nie ma.
 *
 * CO NIESIE HIERARCHIE, SKORO NIE NIESIE JEJ KOLOR. Tlo dymka jest IDENTYCZNE na kazdej
 * glebokosci - poprzednia wersja odwracala poziomy 2-4 na biala karte z ramka i to wlasnie
 * user odrzucil ("naprzemiennosc tla dla kolejnych poziomow trzeba zrobic inaczej"). Glebokosc
 * niosa trzy rzeczy, wszystkie geometryczne:
 *   1. wciecie kontenera odpowiedzi - stala wartosc na poziom,
 *   2. kreska pionowa przy krawedzi wciecia - czyni wciecie policzalnym przy czterech
 *      poziomach i wiaze odpowiedzi jednego watku, gdy tekst sie zawija,
 *   3. dymek PRZYLEGAJACY do wlasnej tresci - krotka odpowiedz jest waska, wiec kolejne
 *      poziomy nie ukladaja sie w slup blokow tej samej szerokosci, w ktorym schodkowanie
 *      przestaje byc widoczne.
 * Poziom 2 rozni sie od poziomu 1 WYLACZNIE pozycja pozioma: nie kolorem, nie ramka, nie
 * promieniem, nie rozmiarem awatara.
 *
 * Tinta zostaje NIEPRZEZROCZYSTA. Przy jednym tle na wszystkich poziomach kumulacja alfy
 * i tak by nie zachodzila, ale dymek stoi raz na bialej karcie opinii, a raz na tincie
 * formularza - przezroczysty zmienialby wtedy kolor razem z podlozem.
 */
.lukuro-comment-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--lukuro-reviews-avatar-gap);
}

/* Luk lacznika: pion z gory, plynne wygiecie w prawo, koniec przy awatarze tej odpowiedzi.
   Wysokosc = przerwa nad pozycja + polowa awatara, wiec dolna krawedz trafia w os awatara.
   Rysuje go KAZDA odpowiedz, takze pierwsza - u niej luk jest GORNYM KONCEM calej linii:
   urywa sie na granicy odstepu nad kontenerem i nie siega wypowiedzi nadrzednej. */
.lukuro-comment-item::before {
    content: "";
    position: absolute;
    left: calc(-1 * var(--lukuro-reviews-elbow, 22px));
    top: calc(-1 * var(--lukuro-reviews-thread-gap));
    width: var(--lukuro-reviews-elbow, 22px);
    height: calc(var(--lukuro-reviews-thread-gap) + var(--lukuro-reviews-avatar, 32px) / 2);
    border-left: var(--lukuro-reviews-connector-w, 1px) solid var(--lukuro-reviews-connector);
    border-bottom: var(--lukuro-reviews-connector-w, 1px) solid var(--lukuro-reviews-connector);
    border-bottom-left-radius: var(--lukuro-reviews-connector-radius, 14px);
    pointer-events: none;
}

/* Przedluzenie pionu do nastepnego rodzenstwa: pion biegnie dalej w dol, a luk ODGALEZIA sie
   od niego w bok, do awatara. Startuje na `avatar / 2 - promien`, czyli DOKLADNIE tam, gdzie
   luk schodzi z osi i zaczyna sie wyginac.

   Ten `- promien` nie jest kosmetyka. Luk to pudelko z `border-left`, `border-bottom` i dolnym
   lewym zaokragleniem: jego pionowa krawedz konczy sie o promien WYZEJ niz dol pudelka, bo od
   tego miejsca krawedz odchodzi w prawo. Kiedy przedluzenie ruszalo z `avatar / 2`, na osi
   zostawal pusty odcinek dokladnie tej dlugosci (14 px) i przy zaokragleniu bylo widac przerwe -
   zglosil ja user, a automatyczny audyt przebiegu jej NIE zlapal, bo liczyl luk jako pelna
   wysokosc pudelka zamiast do miejsca odejscia z osi. Miernik zostal poprawiony razem z regula.

   Nakladania nadal nie ma: luk trzyma os na `[gora, avatar / 2 - promien]`, przedluzenie
   przejmuje ja od tego samego punktu. Stykaja sie w punkcie, nie na odcinku.

   PRZEDLUZENIE RYSUJE KAZDA ODPOWIEDZ, PO KTOREJ IDZIE RODZENSTWO - takze ta, ktora ma wlasne
   zagniezdzenia. Byla po drodze wersja, w ktorej odpowiedz z podrozmowa przedluzenia nie
   rysowala: `bottom: 0` obejmuje cale poddrzewo, wiec pion biegl wzdluz calej podrozmowy
   (zmierzone 388,6 px) rownolegle do pionu TEJ podrozmowy, co czytalo sie jak dwie szyny.
   Cena okazala sie za wysoka: linia rwala sie miedzy rodzenstwem rozdzielonym podrozmowa,
   a user odrzucil to wprost ("nadal linie sa przerywane"). Ciaglosc jest wazniejsza niz
   dlugosc odcinka - i tak samo robi to wzorzec, na ktory user sie powolywal.

   Wniosek na przyszlosc: przerwa w tej linii jest ZAWSZE bledem, poza jednym miejscem -
   jej gornym koncem przy pierwszej odpowiedzi. */
.lukuro-comment-item:not(:last-child)::after {
    content: "";
    position: absolute;
    left: calc(-1 * var(--lukuro-reviews-elbow, 22px));
    top: calc(var(--lukuro-reviews-avatar, 32px) / 2 - var(--lukuro-reviews-connector-radius, 14px));
    bottom: 0;
    border-left: var(--lukuro-reviews-connector-w, 1px) solid var(--lukuro-reviews-connector);
    pointer-events: none;
}

/**
 * POZIOM 1 NIE ODBIERA LINII (decyzja usera 2026-08-26, trzecia i ostateczna wersja modelu).
 *
 * Model z 2026-08-24 mowil "linia nie dotyka komentarza najwyzszego poziomu" i formalnie byl
 * prawdziwy, ale WYGLADAL dokladnie odwrotnie: os luku poziomu 1 liczyla sie jako
 * `wciecie kontenera - elbow`, czyli wypadala w SRODKU AWATARA OPINII. User zglosil to jako
 * "linie wychodza z pierwszego komentarza" i mial racje - o odbiorze decyduje polozenie osi,
 * a nie to, czy odcinek formalnie dotyka cudzego boksu.
 *
 * REGULA MODELU, ktora z tego wychodzi i ktora zastepuje poprzednia:
 *
 *   Linia nie zaczyna sie przy opinii ANI przy odpowiedzi na nia. Pierwszy odcinek rysuje
 *   odpowiedz poziomu 1, ktora sama ma odpowiedzi - jako ZEJSCIE spod wlasnego awatara.
 *   Gdy linia juz sie zaczela, biegnie ciagiem przez cala podrozmowe, takze w dol, w kolejne
 *   poziomy. Przerwa jest zawsze bledem poza jednym miejscem: gornym koncem przy pierwszej
 *   odpowiedzi w grupie.
 *
 * Akapit "DLACZEGO LUK RYSUJE TAKZE PIERWSZA ODPOWIEDZ" (5 z 7 grup ma jedno dziecko) zostaje
 * w mocy OD POZIOMU 2. Na poziomie 1 grupa jednoelementowa ma po prostu nie miec linii i to
 * jest tresc decyzji, a nie jej skutek uboczny.
 *
 * SELEKTOR JEST STRUKTURALNY, nie po `data-depth`, i to ma dwa powody. Pierwszy: poziom 1 to
 * z definicji bezposrednie dziecko `.lukuro-review-replies` na OBU drogach renderu - PHP
 * wypisuje je w tym kontenerze, a `reviews.js` wstawia tam odpowiedz z AJAX-a
 * (`repliesContainer.insertAdjacentHTML`). Drugi: panel watku omija ten selektor sam z siebie,
 * bo jego cialem jest `.lukuro-nested-replies`, a nie `-review-replies`.
 *
 * Specyficznosc (0,2,1) wygrywa z regula bazowa (0,1,1), wiec kolejnosc w pliku nie ma tu
 * znaczenia - ale regula stoi zaraz za luk i przedluzeniem, zeby czytalo sie je razem.
 *
 * ZEJSCIA (`-say::before`) TA REGULA NIE DOTYKA i to jest istota zmiany: zejscie staje sie
 * POCZATKIEM linii zamiast jej kontynuacja. Rusza spod awatara odpowiedzi poziomu 1, dochodzi
 * do dolu jej `-say`, a tam przejmuje je luk pierwszej odpowiedzi poziomu 2. Punkty styku
 * wypadaja w tym samym miejscu, bo luk wznosi sie dokladnie o `--lukuro-reviews-thread-gap`,
 * czyli o gorny margines kontenera zagniezdzen.
 */
.lukuro-review-replies > .lukuro-comment-item::before,
.lukuro-review-replies > .lukuro-comment-item::after {
    content: none;
}

/* ZEJSCIE DO WLASNEJ PODROZMOWY. Odpowiedz, ktora sama ma odpowiedzi, prowadzi linie od swojego
   awatara w dol, do miejsca, gdzie zaczyna sie jej podrozmowa. Bez tego odcinka watek rwal sie
   na kazdym zagniezdzeniu: linia poziomu 1 biegla ciagiem, ale linia poziomu 2 zaczynala sie
   w powietrzu pod dymkiem rodzica - zmierzone 66 px pustki miedzy dolem awatara odpowiedzi
   a poczatkiem linii jej podrozmowy.

   REGULA MODELU, ktora to porzadkuje: linia nie zaczyna sie przy KOMENTARZU najwyzszego poziomu
   (karta opinii nie emituje niczego), ale gdy juz sie zaczela, biegnie ciagiem przez cala
   dyskusje - takze w dol, w kolejne poziomy. Dlatego `-say` istnieje przy odpowiedzi, a nie
   istnieje przy karcie opinii.

   Rysuje to `-say`, bo jest JEDYNYM boksem o wlasciwym zakresie: zaczyna sie na wysokosci
   awatara i konczy tam, gdzie zaczynaja sie odpowiedzi zagniezdzone. Ani `-main` (siega do dolu
   calego poddrzewa), ani `-body` (konczy sie przed rzedem akcji) tego zakresu nie maja, a CSS
   nie rozepnie odcinka miedzy krawedziami dwoch roznych boksow.

   Pion rusza POD awatarem (`top: avatar`), a nie w jego osi pionowej: `-say::before` maluje sie
   po awatarze, wiec linia zaczynajaca sie w polowie wysokosci przecinalaby zdjecie.

   Styk z dolem jest dokladny, nie przybliżony: pion konczy sie na dole `-say`, a luk pierwszej
   odpowiedzi zagniezdzonej wznosi sie o `--lukuro-reviews-thread-gap` nad swoja pozycje, czyli
   dokladnie o margines gorny kontenera zagniezdzen. Oba punkty wypadaja w tym samym miejscu.

   `:has()` jest warunkiem koniecznym: bez niego kazda wypowiedz BEZ odpowiedzi dostawalaby
   kikut linii pod awatarem. */
.lukuro-comment-say {
    position: relative;
}

/* ZEJSCIE OBOWIAZUJE TAKZE W PANELU. Byl tu przez chwile warunek
   `:not(.lukuro-comment-item--panel)`, wylaczajacy je dla naglowka panelu, z uzasadnieniem,
   ze wypowiedz otwarta w panelu jest naglowkiem, a nie wezlem watku. Arytmetyka za tym stala
   prawdziwa - cialo panelu mialo wtedy os lacznika 13 px na lewo od srodka awatara naglowka,
   wiec zejscie konczyloby sie kikutem obok linii, ktorej nie dotyka - ale wniosek byl zly:
   zamiast poprawic os, wylaczyl linie. Zmierzony skutek: 89,4 px przerwy miedzy awatarem
   naglowka a pierwsza odpowiedzia; zglosil to user. Os poprawiona jest w bloku mobilnym
   (`padding-left` ciala panelu), a zejscie wraca tutaj do wszystkich wypowiedzi bez wyjatku.

   Reguly na przyszlosc, obie oplacone zgloszeniem: przerwa w tej linii jest ZAWSZE bledem
   (jedyny wyjatek to jej gorny koniec przy pierwszej odpowiedzi), a gdy odcinek linii nie ma
   gdzie trafic, blad siedzi w OSI, nie w odcinku.

   `:not(.lukuro-nested-replies--collapsed)` pilnuje rzeczy, ktorej `:has()` samo nie powie:
   pyta ono o ISTNIENIE wezla, a nie o jego widocznosc. Na waskim ekranie podrozmowa jest
   zwinieta (jej tresc pokazuje panel), wiec bez tego warunku kazda wypowiedz z odpowiedziami
   rysowala zejscie DONIKAD - zmierzone 104 px pionu pod awatarem, konczacego sie w pustce.
   Klase trzyma `reviews.js` w jednym miejscu (`setContainer()`), obok inline `display`, ktory
   i tak jest jego wlasnoscia. Cialo panelu warunku nie lamie: stoi na `block`, wiec naglowek
   panelu zejscie rysuje. */
.lukuro-comment-item:has(> .lukuro-comment-main > .lukuro-nested-replies:not(.lukuro-nested-replies--collapsed)) > .lukuro-comment-main > .lukuro-comment-say::before {
    content: "";
    position: absolute;
    left: calc(-1 * (var(--lukuro-reviews-avatar-gap) + var(--lukuro-reviews-avatar, 32px) / 2));
    top: var(--lukuro-reviews-avatar, 32px);
    bottom: 0;
    border-left: var(--lukuro-reviews-connector-w, 1px) solid var(--lukuro-reviews-connector);
    pointer-events: none;
}

.lukuro-comment-main {
    flex: 1;
    min-width: 0;
}

/* `fit-content` z `max-width: 100%` daje dymkowi szerokosc wlasnej tresci, ale nie pozwala
   mu wyjsc poza kolumne. `overflow-wrap: anywhere` lamie jedno dlugie slowo (adres, sklejka
   bez spacji), ktore inaczej rozepchneloby dymek ponad kolumne i dolozylo stronie
   przewijania poziomego - ten sam blad, ktory audyt zmierzyl na korzeniu sekcji.

   WYPELNIENIE JEST JEDNO NA OBU SZEROKOSCIACH: `--at-space--xs` (decyzja usera 2026-08-26).
   Do tej pory desktop mial `--at-space--s`, a blok progowy schodzil na `xs` - dymek odpowiedzi
   jest jednak zwykle krotki, wiec szersze wypelnienie robilo z dwoch slow kafel. Prog przestal
   przez to przelaczac te wartosc, a dwie reguly z bloku mobilnego znikly jako duplikaty.

   ZMIANA TEJ WARTOSCI POCIAGA ZA SOBA `padding-inline-start` rzedu akcji nizej i to nie jest
   powtorzenie, tylko zaleznosc: rzad ma stac w jednej linii z TEKSTEM wypowiedzi, a nie
   z krawedzia dymka. Rozjazd tych dwoch wartosci wiesza kciuki pol znaku obok pierwszej litery. */
.lukuro-comment-body {
    width: fit-content;
    max-width: 100%;
    padding: var(--at-space--xs, 0.875rem);
    background: var(--lukuro-reviews-tint);
    border-radius: var(--lukuro-reviews-radius);
    overflow-wrap: anywhere;
}

.lukuro-comment-avatar {
    flex-shrink: 0;
}

.lukuro-comment-avatar img {
    width: var(--lukuro-reviews-avatar, 32px);
    height: var(--lukuro-reviews-avatar, 32px);
    border-radius: 50%;
    object-fit: cover;
}

.lukuro-comment-meta {
    display: flex;
    gap: 0.5rem;
    align-items: baseline;
    margin-bottom: 0.25rem;
}

.lukuro-comment-author {
    font-weight: 500;
    font-size: var(--at-text--m, 1rem);
}

/* Data zeszla z dymka do rzedu akcji (decyzja usera 2026-08-24) i czyta sie tam jako ostatnia
   pozycja rzedu, nie jako czesc wypowiedzi. */
.lukuro-comment-date {
    font-size: var(--at-text--xs, 0.75rem);
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-comment-content {
    font-size: var(--at-text--m, 1rem);
    line-height: 1.5;
}

/* Rzad akcji stoi POD dymkiem i poza nim, bez tla. Wciecie rowne wypelnieniu dymka ustawia
   go w jednej linii z tekstem wypowiedzi, a nie z krawedzia dymka - inaczej kciuki wisialyby
   pol znaku w lewo od pierwszej litery. Odjete 0,25rem to wlasne wypelnienie przyciskow rzedu.

   WARTOSC IDZIE ZA `--at-space--xs`, bo tyle wynosi wypelnienie dymka - i musi za nim isc na
   OBU szerokosciach. Do 2026-08-26 stalo tu `--at-space--s` i prog przestawial obie wartosci
   naraz; po zrownaniu wypelnienia dymka prog nie ma tu juz czego przelaczac.

   `flex-wrap` nie jest ostroznoscia na wyrost: zmierzone przy oknie 390 px na poziomie
   zagniezdzenia 2 - przycisk "Odpowiedz" konczyl sie na 380 px przy kolumnie 375 px, czyli
   wystawal poza ekran i dokladal stronie przewijania poziomego. */
.lukuro-comment-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--at-space--xs, 0.75rem);
    margin-top: 0.25rem;
    padding-inline-start: calc(var(--at-space--xs, 0.875rem) - 0.25rem);
}

.lukuro-comment-actions .lukuro-vote-btn {
    padding: 0.25rem;
}

.lukuro-comment-reply-btn {
    background: transparent;
    border: none;
    color: var(--lukuro-reviews-btn-default);
    cursor: pointer;
    padding: 0.25rem;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

/* Nested replies */

/* Awatar ma DWA rozmiary w calej sekcji (44 px przy opinii, 32 px przy odpowiedzi), a nie
   cztery malejace z poziomem. Kurczenie sie awatara nie nioslo informacji o glebokosci -
   ta idzie wcieciem i lacznikiem - a przy 24 px zdjecie przestawalo byc rozpoznawalne.

   MARGINES UJEMNY nie jest chwytem, tylko ta sama arytmetyka co wyzej. Kontener zagniezdzen
   siedzi w `-main`, czyli juz za awatarem rodzica i odstepem (46,16 px zmierzone), a os
   lacznika ma stac w osi TEGO awatara. Zeby odleglosc od osi do krawedzi pozycji byla znowu
   rowna `--lukuro-reviews-elbow`, kontener cofa sie o roznice:
       22 - 14,16 - 16 = -8,16 px.
   Netto poziom kosztuje wiec 38 px, a nie 46 - i lacznik trafia w awatar co do piksela. */
.lukuro-nested-replies {
    margin-left: calc(var(--lukuro-reviews-elbow, 22px) - var(--lukuro-reviews-avatar-gap) - var(--lukuro-reviews-avatar, 32px) / 2);
}

/* Reply forms */
.lukuro-nested-reply-form {
    margin-top: var(--at-space--xs, 0.875rem);
    padding: var(--at-space--xs, 0.875rem);
    background: var(--lukuro-reviews-tint-soft);
    border: 1px solid var(--lukuro-reviews-border-brand);
    border-radius: var(--lukuro-reviews-radius-s);
}

.lukuro-nested-reply-form .lukuro-comment-form {
    gap: 0.5rem;
}

.lukuro-nested-reply-form textarea {
    min-height: 60px;
}

.lukuro-reply-form {
    margin-top: var(--at-space--xs, 0.875rem);
    padding: var(--at-space--xs, 0.875rem);
    background: var(--lukuro-reviews-tint-soft);
    border: 1px solid var(--lukuro-reviews-border-brand);
    border-radius: var(--lukuro-reviews-radius-s);
}

.lukuro-comment-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* Wyglad niesie `lukuro-reviews__cta` wyzej; tutaj zostaje samo ustawienie w ukladzie. */
.lukuro-comment-form .lukuro-comment-submit {
    align-self: flex-end;
}

/* Pagination */
.lukuro-reviews-pagination {
    text-align: center;
    margin-top: 1.5rem;
}

:where(.lukuro-load-more:hover) {
    border-color: var(--lukuro-reviews-primary);
    color: var(--lukuro-reviews-primary-text);
}

/* Messages */
.lukuro-reviews-message {
    padding: 1rem;
    border-radius: var(--lukuro-reviews-radius-s);
    margin-bottom: 1rem;
}

.lukuro-reviews-message.success {
    background: var(--lukuro-color-success-bg, #d1fae5);
    color: var(--lukuro-color-success-text, #065f46);
}

.lukuro-reviews-message.error {
    background: var(--lukuro-color-danger-bg, #fee2e2);
    color: var(--lukuro-color-danger-text, #991b1b);
}

/* Loading state */
.lukuro-reviews.loading {
    opacity: 0.6;
    pointer-events: none;
}

/* Honeypot */
.lukuro-hp-field {
    position: absolute;
    left: -9999px;
    opacity: 0;
    height: 0;
    overflow: hidden;
}

/* Responsive */
@media (max-width: 640px) {
    /* Autor i tresc schodza na waskim ekranie o szczebel: `--at-text--m` na desktopie,
       `--at-text--s` tutaj (decyzja usera 2026-08-24). Prog jest TEN SAM, ktory sekcja ma juz
       dla geometrii - nie dokladamy drugiego breakpointu, zeby stopnie pisma i wciecia nie
       zaczely sie przelaczac w dwoch roznych miejscach.

       Dotyczy TAK SAMO karty opinii i dymka odpowiedzi. Byla po drodze wersja, w ktorej dymek
       zostawal o szczebel nizej od opinii na obu szerokosciach - roznica stopnia miala niesc
       hierarchie razem z wcieciem i lacznikiem. User to odrzucil i ma racje: hierarchie niesie
       tu geometria, a wypowiedz czyta sie tak samo niezaleznie od tego, czy jest opinia, czy
       odpowiedzia na nia. Stopien pisma przestal byc nosnikiem glebokosci. */
    .lukuro-review-author,
    .lukuro-review-content,
    .lukuro-comment-author,
    .lukuro-comment-content {
        font-size: var(--at-text--s, 0.8125rem);
    }

    .lukuro-reviews-header {
        flex-direction: column;
        align-items: flex-start;
    }

    /* `.lukuro-review-header { flex-wrap: wrap }` stalo tu do 2026-08-26 i bylo duplikatem -
       regula bazowa ma zawijanie na kazdej szerokosci. Skasowane, a nie zakomentowane: regula
       powtarzajaca wartosc domyslna sugeruje, ze cos tu przelaczamy progiem, i przy nastepnej
       zmianie ukladu ktos bedzie jej szukal jako przyczyny. */

    .lukuro-review-actions {
        gap: 0.5rem;
    }
}

/**
 * Waski ekran. Wciecie schodzi do wartosci, ktora jeszcze niesie hierarchie, ale juz nie zjada
 * kolumny - i schodzi PRZEZ TOKENY, nie przez przepisanie regul: cala geometria lacznika stoi
 * na `--lukuro-reviews-avatar`, `-avatar-lg` i `-elbow`, wiec wystarczy podac tu inne wartosci,
 * a luki dalej trafiaja w awatary co do piksela.
 *
 * AWATAR NIE ZNIKA JUZ NA GLEBSZYCH POZIOMACH. Wczesniej chowal sie od drugiego poziomu w dol,
 * zeby odzyskac 45 px na poziom - teraz lacznik do niego PROWADZI, wiec bez niego linia
 * konczylaby sie w powietrzu. Zamiast tego kurczy sie razem z odstepem i zasiegiem luku:
 * przy tych wartosciach poziom zagniezdzenia kosztuje 29 px zamiast 46, wiec chowanie
 * awatara przestalo byc potrzebne.
 */
@media (max-width: 640px) {
    .lukuro-reviews {
        --lukuro-reviews-avatar: 26px;
        --lukuro-reviews-avatar-lg: 34px;
        --lukuro-reviews-elbow: 16px;
        --lukuro-reviews-connector-radius: 10px;
        --lukuro-reviews-thread-gap: calc(var(--at-space--xs, 0.875rem) / 2);
        --lukuro-reviews-avatar-gap: calc(var(--at-space--xs, 0.875rem) / 2);
    }

    /* Wypelnienie dymka i wciecie rzedu akcji staly tu do 2026-08-26 i schodzily o szczebel
       skali (`--at-space--s` na desktopie, `--at-space--xs` tutaj). Obie reguly ZNIKLY, bo user
       zrownal wypelnienie dymka na obu szerokosciach - stad `--at-space--xs` stoi juz w regule
       bazowej i te dwie byly jej doslownym powtorzeniem.

       Skasowane, a nie zakomentowane: regula powtarzajaca wartosc bazowa sugeruje, ze prog cos
       tu przelacza, i przy nastepnej zmianie wypelnienia ktos bedzie jej szukal jako przyczyny
       rozjazdu, ktorego nie ma.

       Odstep miedzy awatarem a dymkiem oraz `thread-gap` schodza tu o polowe osobno, wyzej. */
}

/**
 * PANEL WATKU NA WASKIM EKRANIE
 *
 * Wciecie jest dobrym nosnikiem glebokosci na szerokim ekranie i zlym na waskim: kosztuje
 * 29,0 px na poziom (stala, arytmetyka tokenow wyzej), wiec przy kolumnie 340,4 px tresc
 * poziomu 4 schodzi do 124,3 px, czyli SZESNASTU znakow w wierszu. Od poziomu 2 glebokosc
 * schodzi wiec panelem, w ktorym kazdy poziom dostaje pelna kolumne (277,4 px przy oknie
 * 390 px, niezaleznie od glebokosci).
 *
 * LICZBY POPRAWIONE 2026-08-24 po pomiarze niezaleznym. Wczesniejsza wersja mowila
 * "kolumna 306 px, poziom 4 = 90 px, TRZYNASCIE znakow" i byla nieprawdziwa z dwoch
 * niezaleznych powodow naraz: kolumna pod lekcja nie jest wezsza od produktowej (obie
 * 340,4 px), a pismo dymka to 15 px, nie 13 px (sredni znak 7,43 px, nie 6,71 px).
 * Rozstrzygniecie sie nie zmienia - 16 znakow w wierszu to nadal trzy slowa - ale liczba
 * zdazyla pojechac stad do czterech innych miejsc. Zrodlo pomiaru:
 * `tracking/audits/2026-08-24-opinie-panel-offcanvas-mobile.md`, sekcja "Weryfikacja niezalezna".
 *
 * PANELEM STAJE SIE POZYCJA, KTORA JUZ STOI W WATKU - `reviews.js` daje jej klase stanu
 * i nic nie przenosi w drzewie. Poddrzewo pozycji jest gotowym panelem, bo renderer trzyma
 * te trzy boksy rodzenstwem w jednym `-main`:
 *
 *   `-thread-chrome`      belka nawigacyjna (skrypt wstawia ja jako pierwsze dziecko)
 *   `-avatar` + `-say`    naglowek: wypowiedz, ktorej odpowiedzi czytamy
 *   `-nested-replies`     cialo, przewijane
 *   `-nested-reply-form`  stopka: formularz odpowiedzi do niej
 *
 * UKLAD IDZIE SIATKA, a nie flexem, i to jest jedyny powod, dla ktorego pozycja zmienia tu
 * `display`: belka ma isc przez CALA szerokosc, a awatar i `-main` stac obok siebie pod nia.
 * Flex w rzedzie ustawilby wszystkie troje w jednej linii, a flex w kolumnie zerwalby awatar
 * z dymkiem.
 *
 * DLACZEGO CIALO I STOPKA MAJA UJEMNY MARGINES. Oba siedza w `-main`, czyli za awatarem
 * i jego odstepem, a w panelu maja siegac lewej krawedzi. Cofaja sie wiec o dokladnie te
 * dwie wartosci i odzyskuja 33 px - czyli to, po co panel w ogole powstal. `padding-left`
 * rowny `--lukuro-reviews-elbow` oddaje z powrotem tyle, ile potrzebuja luki lacznika
 * (rysowane na `left: -elbow`), zeby nie wypadly poza krawedz.
 *
 * WYPOWIEDZ NADRZEDNA NIE EMITUJE W PANELU LACZNIKA. Jest tam NAGLOWKIEM, a nie wezlem
 * watku - dokladnie jak karta opinii, ktora tez linii nie zaczyna. Gdyby zejscie zostalo,
 * bieglaby w osi awatara, czyli 13 px w prawo od osi luku pierwszej odpowiedzi, i konczylo
 * sie kikutem obok linii, ktorej nie dotyka.
 *
 * Pomiary i osiem rozstrzygniec: repo pierwszego konsumenta,
 * `tracking/audits/2026-08-24-opinie-panel-offcanvas-mobile.md`.
 */

/* Kontrolka wejscia stoi w znacznikach ZAWSZE, gdy sa odpowiedzi, ale odslania sie dopiero
   pod atrybutem, ktory ustawia `reviews.js`. Bez JS i przy filtrze `lukuro_reviews_thread_panel`
   na `false` nie ma wiec na stronie przycisku, ktory nic nie robi - a watek renderuje sie
   inline, jak dotad. Na desktopie kontrolka nie pokazuje sie nigdy. */
.lukuro-thread-open {
    display: none;
}

.lukuro-thread-chrome[hidden] {
    display: none;
}

@media (max-width: 640px) {
    [data-thread-panel="on"] .lukuro-thread-open {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        background: transparent;
        border: none;
        padding: 0.25rem;
        cursor: pointer;
        color: var(--lukuro-reviews-btn-default);
        font-size: inherit;
        font-family: inherit;
    }

    [data-thread-panel="on"] .lukuro-thread-open:hover {
        color: var(--lukuro-reviews-primary);
    }

    /* Sama pozycja jako okno. `z-index` ponad pasek administracyjny WordPressa (99999),
       bo panel jest oknem modalnym i przyciecie go paskiem zabraloby mu belke nawigacyjna. */
    .lukuro-comment-item.lukuro-comment-item--panel {
        position: fixed;
        inset: 0;
        z-index: 100000;
        display: grid;
        grid-template-columns: auto 1fr;
        grid-template-rows: auto 1fr;
        align-items: start;
        padding-inline: var(--at-space--xs, 0.875rem);
        background: var(--lukuro-reviews-surface, #fff);
        overflow: hidden;
    }

    /* Panel glebszy jest POTOMKIEM plytszego, wiec dziedziczy po nim `visibility: hidden`
       i musi ja odwrocic u siebie. `:not()` zamiast polegania na kolejnosci regul: panel
       zgaszony nosi OBIE klasy naraz (zostaje panelem, tylko niewidocznym), wiec bez tego
       warunku o wyniku decydowalaby kolejnosc w pliku, a nie zapisana intencja. */
    .lukuro-comment-item.lukuro-comment-item--panel:not(.lukuro-comment-item--panel-behind) {
        visibility: visible;
    }

    /* Panel plytszy GASNIE, gdy wchodzimy glebiej. `visibility` jest jedyna wlasciwoscia,
       ktora dziedziczy sie w dol, ale daje sie odwrocic na potomku (regula wyzej) - a panel
       glebszy JEST potomkiem plytszego. `display: none` ani `inert` nie umieja tego, bo
       zabralyby ze soba takze jego. Skutek uboczny jest pozadany: poddrzewo `visibility:
       hidden` wypada z drzewa dostepnosci, wiec czytnik ekranu widzi jedno okno naraz. */
    .lukuro-comment-item.lukuro-comment-item--panel-behind {
        visibility: hidden;
    }

    .lukuro-comment-item--panel > .lukuro-thread-chrome {
        grid-column: 1 / -1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--at-space--xs, 0.875rem);
        margin-inline: calc(-1 * var(--at-space--xs, 0.875rem));
        padding-inline: var(--at-space--xs, 0.875rem);
        min-height: 44px;
        border-bottom: 1px solid var(--lukuro-reviews-border-brand);
        background: var(--lukuro-reviews-surface, #fff);
    }

    /* Belka jest jedyna nawigacja panelu, wiec jej przyciski NIE podlegaja kompromisowi
       36 px przyjetemu dla przyciskow sekcji - stoja na pelnym progu dotykowym. */
    .lukuro-thread-back,
    .lukuro-thread-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        padding: 0;
        background: transparent;
        border: none;
        cursor: pointer;
        color: var(--lukuro-reviews-btn-default);
    }

    .lukuro-thread-back:hover,
    .lukuro-thread-close:hover {
        color: var(--lukuro-reviews-primary);
    }

    /* Strzalka wstecz gasnie na pierwszym poziomie zamiast znikac - inaczej tytul przeskakiwalby
       w bok przy kazdym zejsciu i powrocie. `visibility: hidden` zabiera ja takze klawiaturze
       i czytnikowi, wiec nie ma tam przycisku bez zadania. */
    .lukuro-thread-chrome .lukuro-thread-back {
        visibility: hidden;
    }

    .lukuro-thread-chrome--has-back .lukuro-thread-back {
        visibility: visible;
    }

    .lukuro-thread-title {
        flex: 1;
        text-align: center;
        font-size: var(--at-text--m, 1rem);
        font-weight: 500;
        color: var(--lukuro-reviews-text);
    }

    .lukuro-comment-item--panel > .lukuro-comment-avatar {
        grid-column: 1;
        grid-row: 2;
        align-self: start;
        margin-top: var(--at-space--xs, 0.875rem);
    }

    .lukuro-comment-item--panel > .lukuro-comment-main {
        grid-column: 2;
        grid-row: 2;
        display: flex;
        flex-direction: column;
        min-height: 0;
        height: 100%;
    }

    .lukuro-comment-item--panel > .lukuro-comment-main > .lukuro-comment-say {
        flex: 0 0 auto;
        margin-top: var(--at-space--xs, 0.875rem);
    }

    /* Cialo panelu. `min-height: 0` jest warunkiem koniecznym przewijania w kolumnie flex -
       bez niego element rosnie z trescia zamiast dostac reszte wysokosci i `overflow` nigdy
       sie nie uruchamia. `overscroll-behavior` zatrzymuje przewijanie na koncu listy zamiast
       przekazywac je tlu.

       `padding-left` NIESIE OS LACZNIKA i jest to jego glowne zadanie, a nie odstep. Luk kazdej
       odpowiedzi rysuje sie na `left: -elbow` wzgledem pozycji, wiec os wypada `elbow` na lewo
       od tresci kontenera. Zeby watek nie rwal sie miedzy naglowkiem panelu a jego cialem, ta
       os musi trafic w SRODEK awatara naglowka - stad `avatar / 2` w tej sumie. Ta sama
       arytmetyka rzadzi kontenerami poza panelem (`.lukuro-nested-replies`, margines ujemny);
       tutaj wychodzi paddingiem, bo `overflow-y: auto` wymusza `overflow-x: auto`, a luk
       wystawiony poza kontener zostalby przyciety.

       WCZESNIEJSZA WERSJA MIALA TU SAMO `elbow` i odzyskiwala tym 13 px szerokosci czytania.
       Cena: os ciala stawala 13 px na lewo od srodka awatara naglowka, wiec zejscie z naglowka
       do watku nie mialo gdzie trafic i zostalo wylaczone - a linia rwala sie na 89,4 px miedzy
       pierwszym awatarem a kolejnym. Zglosil to user; arkusz mial juz wtedy wpisany wniosek
       z poprzedniego takiego zgloszenia ("przerwa w tej linii jest ZAWSZE bledem"). Decyzja
       usera 2026-08-24: ciaglosc linii jest wazniejsza niz te 13 px. Tresc w panelu schodzi
       przez to z 290,5 px na 277,4 px przy oknie 390 px - nadal 37 znakow w wierszu i nadal
       +95,1 px wobec tego samego poziomu czytanego inline. */
    .lukuro-comment-item--panel > .lukuro-comment-main > .lukuro-nested-replies {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin-left: calc(-1 * (var(--lukuro-reviews-avatar, 32px) + var(--lukuro-reviews-avatar-gap)));
        padding-left: calc(var(--lukuro-reviews-avatar, 32px) / 2 + var(--lukuro-reviews-elbow, 22px));
        padding-bottom: var(--at-space--xs, 0.875rem);
    }

    .lukuro-comment-item--panel > .lukuro-comment-main > .lukuro-nested-reply-form {
        flex: 0 0 auto;
        margin-left: calc(-1 * (var(--lukuro-reviews-avatar, 32px) + var(--lukuro-reviews-avatar-gap)));
        margin-bottom: var(--at-space--xs, 0.875rem);
    }

    /* Wypowiedz nadrzedna jest w panelu naglowkiem, a nie wezlem watku, wiec nie emituje
       zadnego z trzech odcinkow lacznika. Luk i przedluzenie gasna tutaj; zejscie ma wlasny
       warunek przy regule, ktora je rysuje (`:not(.lukuro-comment-item--panel)`) - nadpisanie
       go stad nie dzialalo, bo tamten selektor niesie `:has()` i ma piec klas. */
    .lukuro-comment-item--panel::before,
    .lukuro-comment-item--panel::after {
        content: none;
    }

    /* Kontrolka wejscia w naglowku panelu nie ma co powiedziec - czytelniczka JEST juz w tym
       watku, a klikniecie otwieraloby ten sam wezel drugi raz. Kontrolki przy odpowiedziach
       w ciele panelu zostaja: one prowadza glebiej. */
    .lukuro-comment-item--panel > .lukuro-comment-main > .lukuro-comment-say .lukuro-thread-open {
        display: none;
    }
}

/**
 * SEKCJA JAKO KARTA - OPCJA, WYLACZNIE NA DESKTOPIE (decyzja usera 2026-08-26)
 *
 * Wlacza sie klasa `lukuro-reviews--framed` OBOK `lukuro-reviews`, nigdy zamiast niej: zdjecie
 * klasy bazowej zabiera skryptowi kontener (patrz docblok `render_section()`). Klase dokladaja
 * dwie drogi renderu w dwoch miejscach - element Bricksa przez kontrolke `section_card`,
 * pozostali przez argument `framed` / filtr `lukuro_reviews_framed`. Domyslnie WYLACZONE:
 * ta sama metoda obsluguje cztery powierzchnie o roznym otoczeniu, a decyzja "czy ta sekcja
 * jest karta" nalezy do ukladu strony, nie do modulu.
 *
 * PROG. `min-width: 641px` NIE JEST drugim breakpointem, tylko dopelnieniem tego, ktory sekcja
 * ma juz dla geometrii lacznika i stopni pisma (`max-width: 640px`). Na waskim ekranie
 * wypelnienie zjada szerokosc kartom opinii, a tej szerokosci brakuje tam najbardziej.
 *
 * Reguly stoja w bloku PROGOWYM, a nie w bazowym z zerowaniem w `max-width: 640px`: przy
 * zerowaniu kazda przyszla wlasciwosc ramki wymaga pamietania o drugim miejscu, a zapomniana
 * zostaje na mobile w postaci, ktorej nikt nie chcial.
 *
 * Pasmo ulamkowe 640,0-641,0 px (realne przy niecalkowitym DPR) zostaje BEZ ramki i to jest
 * stan poprawny - ramka jest dekoracja, jej brak niczego nie psuje. Zapisane po to, zeby ktos
 * nie "naprawil" tego przez `min-width: 640px`: wtedy przez pelen piksel obowiazywalyby OBA
 * bloki naraz.
 *
 * TRZY PULAPKI, kazda cicho psuje cos, co juz dziala:
 *
 *   1. `box-sizing: border-box` JEST WARUNKIEM KONIECZNYM. Korzen niesie `width: 100%`
 *      (naprawa z audytu 2026-08-24, ma wlasny docblok wyzej). Wypelnienie doliczone do 100%
 *      wypycha sekcje poza kolumne - dokladnie ten objaw, ktory tamta naprawa usuwala.
 *   2. ZADNEGO `overflow`, `transform`, `filter`, `contain` ani `will-change` na korzeniu.
 *      Kazde z nich robi z niego blok zawierajacy dla potomkow `position: fixed`, a panel watku
 *      JEST takim potomkiem - zamknalby sie wewnatrz sekcji zamiast zajac ekran. Dzis nie zderza
 *      sie nigdy (ramka to desktop, panel to mobile), ale wystarczy jedna zmiana progu.
 *   3. Promien zewnetrzny WIEKSZY od promienia kart - stad osobny `--lukuro-reviews-radius-l`.
 *
 * Obwodka bierze ten sam token co karty i po zdjeciu tinty (2026-08-26) jest JEDYNYM nosnikiem
 * granicy sekcji - plaszczyzna jest ta sama po obu jej stronach. Nie da sie jej wiec zdjac
 * "na proba", jak zakladala poprzednia wersja tego akapitu: sekcja przestalaby istniec wizualnie.
 * Gdyby ramka zewnetrzna i ramki kart czytaly sie jako jedna podwojna kreska, droga jest
 * odwrotna - podbic `--lukuro-reviews-section-bg`, zeby granice niosla plaszczyzna, i dopiero
 * wtedy rozwazac zdjecie kreski.
 */
@media (min-width: 641px) {
    .lukuro-reviews--framed {
        box-sizing: border-box;
        padding: var(--at-space--m, 1.75rem);
        border: 1px solid var(--lukuro-reviews-border-brand);
        border-radius: var(--lukuro-reviews-radius-l, 16px);
        background: var(--lukuro-reviews-section-bg);
    }

    /**
     * Cien TYLKO w Moim koncie (wymaganie usera 2026-08-26) - stad `.woocommerce-account`
     * na korzeniu strony jako warunek, a nie sam modyfikator `--framed`.
     *
     * Powod jest merytoryczny, nie ostroznosciowy: `--framed` wlacza takze kontrolka elementu
     * Bricksa, wiec ta sama klasa siedzi na stronie produktu, w ukladzie, ktorego modul nie zna
     * i ktoremu nie ma prawa dokladac uniesienia. W panelu konta sekcja stoi w rzedzie z kartami
     * modulu szkolen i to ONE ustalaja tam jezyk powierzchni - dlatego tutaj cien nalezy sie,
     * a piec pikseli dalej juz nie.
     *
     * Regula stoi w tym samym bloku progowym, co sama oprawa: cien bez ramki i wypelnienia
     * (ponizej 641 px) wisialby pod trescia bez powierzchni, ktora mialby unosic.
     */
    .woocommerce-account .lukuro-reviews--framed {
        box-shadow: var(--lukuro-reviews-shadow);
    }
}

/* ===========================================
   FW-REV-002: podsumowanie w kolumnach, rozklad, zdjecia, filtry, dwie kolumny, modal

   Wszystko ponizej wlacza sie klasa albo wezlem, ktore renderer wypisuje WYLACZNIE przy
   kontrolce innej niz domyslna (D6) - konsument, ktory nic nie wlaczy, nie dostaje ani jednej
   nowej reguly, ktora by go dotyczyla. Kolory tylko przez zmienne sekcji, a te stoja na slotach
   `--lukuro-color-*` (D12); `--at-*` wylacznie dla odstepow i stopni pisma.
   =========================================== */

.lukuro-reviews-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Nadtytul "Zweryfikowane zakupy" (D19) - mikroetykieta nad tytulem sekcji. */
.lukuro-reviews-eyebrow {
    font-size: var(--at-text--2xs, 0.6875rem);
    letter-spacing: var(--lk-tracking--wide, 0.16em);
    text-transform: uppercase;
    color: var(--lukuro-reviews-text-muted);
}

/* Podsumowanie. W `inline` stoja tu tylko wlaczone rozklad i pasek (jeden pod drugim);
   w `columns` - trzy kolumny od progu tabletu, ponizej pion: srednia, rozklad, pasek (D16). */
.lukuro-reviews-overview {
    display: grid;
    gap: var(--at-space--m, 1.5rem);
    margin-bottom: var(--at-space--m, 1.5rem);
}

@media (min-width: 768px) {
    .lukuro-reviews--columns .lukuro-reviews-overview {
        grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr) minmax(0, 1.2fr);
        align-items: start;
        padding-block: var(--at-space--m, 1.5rem);
        border-block: 1px solid var(--lukuro-reviews-border);
    }

    .lukuro-reviews--columns .lukuro-reviews-overview > * + * {
        padding-inline-start: var(--at-space--m, 1.5rem);
        border-inline-start: 1px solid var(--lukuro-reviews-border);
    }
}

.lukuro-reviews-score > * {
    margin: 0;
}

.lukuro-reviews-score__value {
    display: flex;
    align-items: baseline;
    gap: 0.4em;
    line-height: 1;
}

.lukuro-reviews-score__number {
    font-size: var(--at-heading--l, 2.5rem);
    font-weight: 400;
    color: var(--at-primary-d-5, var(--lukuro-reviews-text));
}

.lukuro-reviews-score__scale,
.lukuro-reviews-score__total {
    font-size: var(--at-text--s, 0.875rem);
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-reviews-score .lukuro-reviews-stars {
    margin-block: 0.6em 0.4em;
}

.lukuro-reviews-score .lukuro-reviews-stars .star {
    font-size: 1rem;
}

/* Rozklad ocen: etykieta "5 ★", pasek, liczba. */
.lukuro-reviews-distribution {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.45rem;
}

.lukuro-reviews-distribution__row {
    display: grid;
    grid-template-columns: 2.4em minmax(0, 1fr) 2.5em;
    align-items: center;
    gap: 0.75em;
    font-size: var(--at-text--s, 0.875rem);
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-reviews-distribution__label {
    display: inline-flex;
    align-items: center;
    gap: 0.3em;
}

.lukuro-reviews-distribution__label .star {
    font-size: 0.75em;
    color: var(--lukuro-reviews-star-color);
}

.lukuro-reviews-distribution__bar {
    position: relative;
    height: 4px;
    overflow: hidden;
    border-radius: 2px;
    background: var(--lukuro-reviews-border);
}

.lukuro-reviews-distribution__fill {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--lukuro-share, 0%);
    background: var(--lukuro-reviews-star-color);
}

.lukuro-reviews-distribution__count {
    text-align: end;
    font-variant-numeric: tabular-nums;
}

/* Pasek zdjec od klientek i kafle zdjec w kartach. */
.lukuro-reviews-photostrip__tiles,
.lukuro-review-photos {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.5rem;
}

.lukuro-review-photos {
    grid-template-columns: repeat(auto-fill, minmax(64px, 88px));
    margin-bottom: var(--at-space--xs, 0.875rem);
}

.lukuro-reviews .lukuro-reviews-photo {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1;
    padding: 0;
    overflow: hidden;
    border: 0;
    border-radius: var(--lukuro-reviews-radius-s);
    background: var(--lukuro-reviews-tint);
    cursor: zoom-in;
}

.lukuro-reviews-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.lukuro-reviews-photo:focus-visible,
.lukuro-reviews-filter:focus-visible,
.lukuro-reviews-photostrip__link:focus-visible,
.lukuro-reviews-modal button:focus-visible {
    outline: 2px solid var(--lukuro-reviews-primary);
    outline-offset: 2px;
}

.lukuro-reviews-photo--more {
    cursor: pointer;
}

.lukuro-reviews-photo__more {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: var(--at-text--l, 1.25rem);
    color: var(--lukuro-reviews-surface);
    background: color-mix(in srgb, var(--lukuro-reviews-text) 55%, transparent);
}

.lukuro-reviews .lukuro-reviews-photostrip__link {
    margin-top: 0.75rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--at-text--xs, 0.8125rem);
    color: var(--lukuro-reviews-primary-text);
    text-decoration: underline;
    text-underline-offset: 0.25em;
    cursor: pointer;
}

/* Filtry: przelaczniki (D12). Dlugie nazwy skracane, pelna w `title`.
   Aktywny = para tekst / powierzchnia sekcji, a nie `primary` / `on-primary`: kontrolka
   "Kolor glowny" elementu przestawia `primary`, ale slotu `on-primary` nie rusza, wiec u lulumi
   (jasny slot `primary`, ciemny `on-primary`) z ciemnym primary z kontrolki dawalo to ciemny
   tekst na ciemnym tle (zmierzone na stronie T). Tekst i powierzchnia maja kontrast zawsze. */
.lukuro-reviews-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: var(--at-space--s, 1.25rem);
}

.lukuro-reviews .lukuro-reviews-filter {
    max-width: 100%;
    min-height: 40px;
    padding: 0.4em 1.1em;
    border: 1px solid var(--lukuro-reviews-border);
    border-radius: 999px;
    background: var(--lukuro-reviews-surface);
    color: var(--lukuro-reviews-text);
    font: inherit;
    font-size: var(--at-text--xs, 0.8125rem);
    cursor: pointer;
}

.lukuro-reviews-filter__text {
    display: block;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lukuro-reviews .lukuro-reviews-filter[aria-pressed="true"] {
    border-color: var(--lukuro-reviews-text);
    background: var(--lukuro-reviews-text);
    color: var(--lukuro-reviews-surface);
}

.lukuro-reviews-list[aria-busy="true"] {
    opacity: 0.5;
}

/* Plakietka wariantu zamowienia (D11). */
.lukuro-review-variant {
    margin: 0 0 var(--at-space--2xs, 0.5rem);
    font-size: var(--at-text--xs, 0.8125rem);
    color: var(--lukuro-reviews-text-muted);
}

/* Dwie kolumny kart od progu tabletu (D16); kontrakt `review-replies` / `reply-form` bez zmian. */
@media (min-width: 768px) {
    .lukuro-reviews-list--cols-2 {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-items: start;
    }

    .lukuro-reviews-list--cols-2 > .lukuro-reviews-empty {
        grid-column: 1 / -1;
    }
}

.lukuro-reviews-pagination[hidden] {
    display: none;
}

/* Pole zdjec w formularzu (D2, D4). */
.lukuro-form-photos {
    display: grid;
    gap: 0.5rem;
    margin-bottom: var(--at-space--s, 1.25rem);
    font-size: var(--at-text--s, 0.875rem);
}

/* Etykiety nowych pol maja kolor tekstu sekcji jawnie: motyw witryny potrafi stylizowac `label`
   globalnie (u lulumi szary 2,61:1 - zmierzone axe na stronie T). */
.lukuro-form-photos__label,
.lukuro-form-photos__consent label,
.lukuro-form-variant label {
    color: var(--lukuro-reviews-text);
}

.lukuro-form-photos__hint {
    margin: 0;
    color: var(--lukuro-reviews-text-muted);
    font-size: var(--at-text--xs, 0.8125rem);
}

.lukuro-form-photos__preview {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.lukuro-form-photos__preview:empty {
    display: none;
}

.lukuro-form-photos__preview li {
    width: 64px;
    height: 64px;
    overflow: hidden;
    border-radius: var(--lukuro-reviews-radius-s);
    background: var(--lukuro-reviews-tint);
    font-size: 0.6875rem;
    word-break: break-all;
}

.lukuro-form-photos__preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.lukuro-form-photos__consent {
    display: flex;
    gap: 0.6em;
    align-items: flex-start;
    margin: 0;
    font-size: var(--at-text--xs, 0.8125rem);
    line-height: 1.5;
}

.lukuro-form-photos__consent[hidden] {
    display: none;
}

.lukuro-form-photos__consent input {
    margin-top: 0.3em;
    flex: none;
}

.lukuro-form-variant label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: var(--at-text--s, 0.875rem);
}

/* Modal zdjec (D14). */
.lukuro-reviews-modal {
    width: min(960px, calc(100vw - 2rem));
    max-height: calc(100dvh - 2rem);
    padding: var(--at-space--s, 1.25rem);
    border: 0;
    border-radius: var(--lukuro-reviews-radius);
    background: var(--lukuro-reviews-surface);
    color: var(--lukuro-reviews-text);
}

.lukuro-reviews-modal::backdrop {
    background: color-mix(in srgb, var(--lukuro-reviews-text) 60%, transparent);
}

.lukuro-reviews-modal__bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: var(--at-space--s, 1.25rem);
}

.lukuro-reviews-modal__title {
    margin: 0 auto 0 0;
    font-size: var(--at-text--l, 1.25rem);
    font-weight: 500;
}

.lukuro-reviews-modal button {
    font: inherit;
    cursor: pointer;
}

.lukuro-reviews-modal__close,
.lukuro-reviews-modal__nav {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--lukuro-reviews-border);
    border-radius: 50%;
    background: var(--lukuro-reviews-surface);
    color: var(--lukuro-reviews-text);
    font-size: 1.5rem;
    line-height: 1;
}

.lukuro-reviews-modal__back {
    padding: 0.4em 0.9em;
    border: 1px solid var(--lukuro-reviews-border);
    border-radius: 999px;
    background: none;
    color: var(--lukuro-reviews-text);
    font-size: var(--at-text--xs, 0.8125rem);
}

.lukuro-reviews-modal__grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 0.5rem;
}

.lukuro-reviews-modal__tile {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    padding: 0;
    border: 0;
    border-radius: var(--lukuro-reviews-radius-s);
    overflow: hidden;
    background: var(--lukuro-reviews-tint);
}

.lukuro-reviews-modal__tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.lukuro-reviews-modal__single {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.75rem;
}

.lukuro-reviews-modal__figure {
    margin: 0;
    display: grid;
    gap: 0.75rem;
}

.lukuro-reviews-modal__img {
    width: 100%;
    height: auto;
    max-height: 65dvh;
    object-fit: contain;
    border-radius: var(--lukuro-reviews-radius-s);
    background: var(--lukuro-reviews-tint);
}

/* Kolor, wyrownanie i kroj jawnie: motyw witryny stylizuje `figcaption` (u lulumi szary,
   wysrodkowany), a to jest opis zdjecia od klientki, nie podpis ilustracji artykulu. */
.lukuro-reviews-modal__caption {
    color: var(--lukuro-reviews-text);
    text-align: start;
    font-style: normal;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.75rem;
    font-size: var(--at-text--s, 0.875rem);
}

.lukuro-reviews-modal__author {
    font-weight: 500;
}

.lukuro-reviews-modal__stars {
    display: inline-flex;
    gap: 2px;
    font-size: 0.8rem;
}

.lukuro-reviews-modal__stars .star {
    color: var(--lukuro-reviews-star-empty);
}

.lukuro-reviews-modal__stars .star.filled {
    color: var(--lukuro-reviews-star-color);
}

.lukuro-reviews-modal__variant,
.lukuro-reviews-modal__position {
    color: var(--lukuro-reviews-text-muted);
    font-size: var(--at-text--xs, 0.8125rem);
}

.lukuro-reviews-modal__excerpt {
    flex-basis: 100%;
}

.lukuro-reviews-modal__more {
    margin-top: var(--at-space--s, 1.25rem);
}

@media (max-width: 640px) {
    .lukuro-reviews-modal__single {
        grid-template-columns: 1fr 1fr;
    }

    .lukuro-reviews-modal__figure {
        grid-column: 1 / -1;
        grid-row: 1;
    }

    .lukuro-reviews-modal__nav--next {
        justify-self: end;
    }
}

/* ===========================================
   Lukuro Rating Element
   Mimics WooCommerce Product Rating styling
   =========================================== */

.lukuro-rating {
    display: flex;
    align-items: center;
    gap: var(--at-space--xs, 0.5rem);
}

/* Star rating - uses WooCommerce font for consistency */
.lukuro-rating__stars {
    font-family: WooCommerce;
    font-size: 0.875em;
    font-weight: 400;
    height: 1em;
    line-height: 1;
    overflow: hidden;
    position: relative;
    width: 5.4em;
}

.lukuro-rating__stars::before {
    content: "SSSSS";
    color: color-mix(in srgb, var(--at-primary-d-2, #076e82) 20%, transparent);
    position: absolute;
    left: 0;
    top: 0;
    white-space: nowrap;
}

.lukuro-rating__stars span {
    overflow: hidden;
    position: absolute;
    left: 0;
    top: 0;
    padding-top: 1.5em;
}

.lukuro-rating__stars span::before {
    content: "SSSSS";
    color: var(--accent, #f6db20);
    position: absolute;
    left: 0;
    top: 0;
    white-space: nowrap;
}

/* Link styling */
.lukuro-rating__link {
    color: var(--link, var(--lukuro-color-primary-text, #111));
    font-size: var(--at-text--xs, 0.8125rem);
    text-decoration: none;
    transition: color 0.2s ease;
}

.lukuro-rating__link:hover {
    color: var(--link-hover, var(--at-primary-d-2, #076678));
    text-decoration: underline;
}

/* Empty state - no reviews */
.lukuro-rating--empty .lukuro-rating__stars::before {
    color: var(--at-black-t-5, rgba(0, 0, 0, 0.15));
}

.lukuro-rating--empty .lukuro-rating__link {
    font-weight: 500;
}

/* Custom icon-based stars (overrides WooCommerce font-based stars) */
.lukuro-rating__stars--custom {
    font-family: inherit;
    width: auto;
    height: auto;
    display: inline-flex;
    gap: 2px;
    align-items: center;
}

.lukuro-rating__stars--custom::before {
    display: none;
}

.lukuro-rating__stars--custom span {
    position: static;
    overflow: visible;
    padding-top: 0;
    display: inline-flex;
    align-items: center;
}

.lukuro-rating__stars--custom span::before {
    display: none;
}

.lukuro-rating__stars--custom .star i {
    font-size: 1em;
    line-height: 1;
}

/* Ikona z wlasnego zestawu wchodzi jako inline `<svg>` z wymiarami z pliku (zwykle 24x24 px),
   a nie jako glif fontu - bez tego gwiazdki jechalyby wlasnym rozmiarem zamiast rozmiarem
   kontrolki "Rozmiar gwiazdek". */
.lukuro-rating__stars--custom .star svg {
    width: 1em;
    height: 1em;
    display: block;
}

/* Barwa siedzi na `span.star`, nie na samej ikonie: glif fontu dziedziczy ja przez `color`,
   a SVG zestawu przez `currentColor` w `fill`/`stroke`. Jedna regula obsluguje wiec oba
   zrodla ikon - i tylko dzieki temu kontrolki koloru gwiazdek dzialaja takze w tym trybie. */
.lukuro-rating__stars--custom .star.filled,
.lukuro-rating__stars--custom .star.half {
    color: var(--accent, #f6db20);
}

.lukuro-rating__stars--custom .star.empty {
    color: color-mix(in srgb, var(--at-primary-d-2, #076e82) 20%, transparent);
}

/* Licznik opinii bez odnosnika: ten sam rozmiar i barwa co link, bez podkreslenia i hovera. */
.lukuro-rating__count {
    color: var(--lukuro-color-primary-text, #111);
    font-size: var(--at-text--xs, 0.8125rem);
}

/**
 * OKNO FORMULARZA (FW-REV-010, DK9)
 *
 * Okno to prymityw panelu (`modal-center`), portalowany do `<body>` z klasami `lukuro-reviews
 * lukuro-reviews--panel` (DK12) - dzieki nim reguly pol i gwiazdek wyzej dzialaja w oknie.
 * Opakowanie formularza w oknie nie jest karta: tlo, obwodke i odstepy niesie dialog.
 * Stan "Dziękujemy" i formularz przelacza klasa `lukuro-reviews--thanks` na oknie, nie atrybut
 * `hidden` (ten przegrywa z `display` spoza warstw - `docs/panel.md`).
 */
.lukuro-reviews-form-wrapper--modal {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    margin: 0;
}

.lukuro-reviews--panel:not(.lukuro-reviews--thanks) .lukuro-reviews-thanks,
.lukuro-reviews--panel.lukuro-reviews--thanks .lukuro-reviews-form-wrapper {
    display: none;
}

.lukuro-reviews-thanks {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1em;
    padding: 2em 0;
    text-align: center;
}

.lukuro-reviews-thanks__title {
    margin: 0;
}

.lukuro-reviews-thanks__title:focus {
    outline: none;
}

.lukuro-reviews-thanks__title:focus-visible {
    outline: 2px solid var(--lukuro-reviews-primary);
    outline-offset: 2px;
}

.lukuro-reviews-thanks__text {
    margin: 0;
    color: var(--lukuro-reviews-text-muted);
}

/* ===========================================
   FW-REV-007 / FW-REV-008 (D14): sortowanie, linia liczby, pusty stan, brak wynikow,
   stopka wariantu z kropka. Wezly powstaja wylacznie przy wlaczonej kontrolce, wiec reguly
   nie dotykaja sekcji bez konfiguracji. Kolor przez lokalne tokeny opinii (sloty
   `--lukuro-color-*`), skora konsumenta (np. lulumi `xroika`) nadpisuje rozmiary i odstepy.
   Jednostki `em`, nie `rem` (lulumi: `html { font-size: 62.5% }` dawalby 8 px tekstu); odstepy
   przeliczone na wlasny rozmiar pisma wezla, tak by przy 16 px wyszly te same piksele.
   =========================================== */

.lukuro-reviews-sort {
    display: flex;
    align-items: center;
    gap: 0.77em;
    margin-top: 1.23em;
    font-size: 0.8125em;
    color: var(--lukuro-reviews-text-muted);
}

/* K2.4 (axe, kryt. 3): `@layer bricks { label { color: var(--bricks-text-light) } }` Bricksa trafia
   etykiete wprost i bije dziedziczenie z `.lukuro-reviews-sort` (lulumi: szary 9e9e9e, 2,67:1). */
.lukuro-reviews-sort__label {
    display: inline;
    margin: 0;
    color: inherit;
    font-weight: inherit;
}

.lukuro-reviews-sort__select {
    min-height: 40px;
    width: auto;
    min-width: 15.08em;
    padding: 0 0.923em;
    border: 1px solid var(--lukuro-reviews-border);
    background-color: transparent;
    color: var(--lukuro-reviews-text);
    font: inherit;
    cursor: pointer;
}

.lukuro-reviews-sort[aria-busy="true"] {
    opacity: 0.6;
}

.lukuro-reviews-count-line {
    min-height: 1.5em;
    margin: 1em 0 0;
    font-size: 0.75em;
    line-height: 1.5;
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-reviews-empty--state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5em;
}

.lukuro-reviews-empty__title {
    margin: 0;
    font-size: 1.625em;
    line-height: 1.15;
    color: var(--lukuro-reviews-text);
}

.lukuro-reviews-empty__text {
    max-width: 27.5em;
    margin: 0;
}

.lukuro-reviews-empty__button {
    margin-top: 1em;
}

.lukuro-reviews-no-results {
    padding: 2.86em 0;
    text-align: center;
    font-size: 0.875em;
    color: var(--lukuro-reviews-text-muted);
}

.lukuro-reviews-list--cols-2 > .lukuro-reviews-no-results {
    grid-column: 1 / -1;
}

.lukuro-reviews-no-results__reset {
    padding: 0;
    border: 0;
    background: none;
    color: var(--lukuro-reviews-text);
    font: inherit;
    text-decoration: underline;
    text-underline-offset: 4px;
    cursor: pointer;
}

.lukuro-review-variant--dot {
    display: flex;
    align-items: center;
    gap: 0.375em;
}

.lukuro-review-variant__dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--lukuro-review-variant-dot, currentColor);
    box-shadow: inset 0 0 0 1px var(--lukuro-reviews-border);
}

.lukuro-review-variant__dot--image {
    width: 10px;
    height: 10px;
    background: var(--lukuro-review-variant-dot-image) center / cover no-repeat;
}

/* FW-REV-009 (D15): grupa filtrow tylko z pigulkami wyboru czeka ukryta na pierwsza pigulke. */
.lukuro-reviews-filters[hidden] {
    display: none;
}

/* FW-REV-011 (D16): "Zobacz opinie" w oknie zdjec i wyroznienie opinii po skoku (czas z `data-photo-jump`). */
.lukuro-reviews-modal__jump {
    padding: 0;
    border: 0;
    background: none;
    color: var(--lukuro-reviews-text);
    font: inherit;
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 4px;
    cursor: pointer;
}

.lukuro-reviews[data-photo-jump] .lukuro-review-item {
    transition: box-shadow 0.3s ease;
}

.lukuro-review-item.is-highlighted {
    box-shadow: 0 0 0 2px var(--lukuro-color-primary, #111);
}

.lukuro-review-item.is-highlighted:focus {
    outline: none;
}

@media (prefers-reduced-motion: reduce) {
    .lukuro-reviews[data-photo-jump] .lukuro-review-item {
        transition: none;
    }
}

} /* @layer lukuro.modules */

/* lukuro-state: [hidden] w modalu galerii opinii - elementy przelaczane atrybutem przez JS, ukrycie musi
   wygrac z display kafli i przyciskow tego arkusza. Poza warstwa z !important, docs/css-warstwy.md, tabela state. */
.lukuro-reviews-modal [hidden] {
    display: none !important;
}
