/* ==========================================================================
   Opinie z Profilu Firmy w Google
   --------------------------------------------------------------------------
   Plik dzieli się na dwie warstwy i ta granica jest najważniejszą rzeczą,
   jaką trzeba o nim wiedzieć:

   1. KARTA (.opinia) to cytat z cudzej platformy, więc jest złożona materiałem
      tamtej platformy — biel, Roboto, bursztyn, okrągły monogram, niebieskie
      linki, data względna, znak „G" w rogu. Czytelniczka ma rozpoznać źródło,
      zanim doczyta stopkę; opinie są wyłącznie z Google i z niczego innego.

   2. WSZYSTKO DOOKOŁA (tor, strzałki, podsumowanie, przyciski, blok
      informacyjny, hub) zostaje nasze — granat, pergamin, miedź, Poppins,
      ostre narożniki.

   Identyfikacja Google nie wychodzi poza kartę i nie wolno jej wypuścić:
   serwis wyglądający na produkt Google to sugerowanie aprobaty podmiotu
   trzeciego, czyli art. 7 pkt 4 u.p.n.p.r. — czarna lista, bez testu przesłanek.

   Wszystkie karty są w HTML-u od pierwszej odpowiedzi serwera — tak, jak
   potrzebują tego crawlery, które nie wykonują JavaScriptu. Tor przewija
   Swiper, ale wyłącznie przesuwając gotowe węzły.

   UWAGA na kolejność wczytywania: `.swiper { overflow: hidden }` z globalnego
   bundla działa, zanim jakikolwiek skrypt się wykona. Bez fallbacku niżej
   (`.opinie__rail:not(.swiper-initialized)`) strona bez JS-u pokazuje jedną
   kartę z ośmiu i nie da się dojechać do reszty.
   ========================================================================== */

/*
 * Wartości są wpisane wprost, nie przez var(--zn-*).
 *
 * Tamte tokeny są zadeklarowane w homepage.css, a ta sekcja pojawia się na
 * ~24 szablonach, z których większość homepage.css nie ładuje — tak samo jak
 * `pages.css` czytał kiedyś var(--z-gold) z warunkowego test-layout.css
 * i przez to renderował ten sam eyebrow w dwóch różnych kolorach.
 * Wartości poniżej są co do znaku te same co w homepage.css:241-255.
 */
.reviews--google,
.opinie-page {
    --op-paper:       #f5ede0;                   /* --zn-paper */
    --op-card:        #fbf6ec;                   /* --zn-paper-card */
    --op-card-edge:   rgba(168, 94, 44, 0.22);   /* --zn-line */
    --op-ink:         #2a1f14;                   /* --zn-ink-deep */
    --op-ink-mid:     #4f3f29;                   /* --zn-ink-mid */
    --op-ink-soft:    #826845;                   /* --zn-ink-soft */
    --op-copper:      #a85e2c;                   /* --zn-copper */
    --op-copper-hi:   #c4753a;                   /* --zn-copper-hi */
    --op-copper-deep: #6e3a18;                   /* --zn-copper-deep */

    /* Pergaminowa biel sekcji na navy — ten sam odcień, co .reviews w pages.css. */
    --op-paper-dim:   #d8c9ae;

    /*
     * Miedź rozdzielona: dekoracyjna (obwódki, focus) i tekstowa.
     * #c4753a na pergaminie daje 3,25:1 — za mało na 12–14 px tekstu.
     */
    --op-accent-ink:  #8f4f22;

    /*
     * Gwiazdki — bursztyn Google, jeden odcień w całym serwisie: i na karcie,
     * i w podsumowaniu oceny nad torem. To ta sama ocena z tego samego profilu,
     * więc nie ma powodu, żeby glify różniły się kolorem między jednym a drugim.
     *
     * --op-star-edge to włosowy obrys gwiazdki wypełnionej. Bursztyn na bieli
     * daje 1,7:1 (u samego Google zresztą też), więc bez obrysu kształt byłby
     * poniżej progu 3:1 dla grafiki niosącej informację. Ciemniejsze złoto
     * podnosi go do 3,25:1, pozostając wizualnie niezauważalne przy 15 px.
     */
    --op-star:        #fbbc04;
    --op-star-edge:   #b8860b;

    --op-gap:   1.5rem;
    --op-slide: min(21rem, 78vw);
}

/* --------------------------------------------------------------------------
   Podsumowanie oceny

   Liczby pochodzą z profilu Google, nigdy z bazy — średnia policzona
   z opublikowanego podzbioru byłaby „konsolidacją ocen według nieujawnionych
   kryteriów" z wytycznych omnibusowych. Brzmienie zdania jest ograniczeniem
   prawnym i nie wolno go tu skracać; wolno je tylko inaczej złożyć.
   -------------------------------------------------------------------------- */

.opinie__summary {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    width: max-content;
    max-width: min(100%, 38rem);
    margin: -0.75rem auto clamp(2.25rem, 4.5vw, 3.25rem);
    padding: 1rem 1.5rem;
    /* Kreski zamiast ramki — ten sam język, co hairline'y eyebrow sekcji. */
    border-top: 1px solid rgba(196, 117, 58, 0.32);
    border-bottom: 1px solid rgba(196, 117, 58, 0.32);
    text-align: center;
}

.opinie__summary-stars {
    display: inline-flex;
    gap: 0.3rem;
}

.opinie__summary-stars .opinia__star {
    width: 1.3rem;
    height: 1.3rem;
}

/*
 * `color` kontenera rysuje gwiazdkę PUSTĄ — reguła bazowa niżej używa
 * currentColor, żeby jeden glif obsłużył trzy tła: białą kartę, granat sekcji
 * i pergamin hubu. Wypełniona gwiazdka ma na granacie 10,6:1 sama z siebie,
 * więc ciemny obrys jest tam zbędny i tylko brudziłby kształt.
 */
.reviews--google .opinie__summary-stars {
    color: rgba(235, 223, 200, 0.45);
}

.reviews--google .opinie__summary-stars .opinia__star.is-on {
    stroke: none;
}

.opinie-page .opinie__summary-stars {
    color: rgba(168, 94, 44, 0.35);
}

.opinie__summary-text {
    font-size: 0.82rem;
    line-height: 1.55;
    letter-spacing: 0.01em;
    color: var(--op-paper-dim);
    text-wrap: pretty;
}

/* Wariant na jasnym hubie — te same kreski, inny atrament. */
.opinie__summary--hero {
    align-items: flex-start;
    margin-left: 0;
    margin-right: auto;
    padding-inline: 0;
    text-align: left;
}

.opinie-page .opinie__summary-text {
    color: var(--op-ink-mid);
}

/* --------------------------------------------------------------------------
   Tor kart

   Strzałki mają własne kolumny grida, a nie pozycję absolutną nad torem —
   nakładka przykrywałaby treść karty dokładnie tam, gdzie zaczyna się cytat.
   -------------------------------------------------------------------------- */

.opinie__slider {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.9rem;
    margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem);
}

/* minmax(0, 1fr), nie 1fr: przy slidesPerView:'auto' szerokość slajdów potrafi
   napędzić minimalną szerokość kolumny i tor rośnie w nieskończoność. */

.opinie__rail {
    grid-column: 2;
    /*
     * `.swiper` tnie do padding-boxa, więc padding jest tu jedynym miejscem
     * na cień karty (pion) i na obwódkę focusa linku w skrajnej karcie (poziom).
     * Swiper odejmuje padding kontenera w updateSize(), więc matematyka
     * slajdów pozostaje poprawna.
     */
    padding: 0.85rem 6px 1.5rem;
    margin-inline: -6px;
    text-align: left;
}

/*
 * Swiper dokłada `swiper-horizontal` z `touch-action: pan-y`, co odbiera gest
 * przybliżania dwoma palcami — a to jedyny sposób powiększenia tekstu dla
 * części osób słabowidzących. `pinch-zoom` oddaje go przeglądarce, nie oddając
 * przy tym gestu poziomego, którym slider żyje.
 */
.opinie__rail.swiper-horizontal {
    touch-action: pan-y pinch-zoom;
}

.opinie__rail:focus-visible {
    outline: 2px solid var(--op-copper-hi);
    outline-offset: 4px;
}

/* Szerokość karty — jedno źródło prawdy dla obu trybów.
   Zapis przez .opinie__track wygrywa z `.swiper-slide{width:100%}` z bundla
   niezależnie od kolejności wczytywania arkuszy. */
.opinie__track > .opinie__slide {
    display: flex;
    width: var(--op-slide);
    height: auto;
}

/* Bez tego `margin-top: auto` na stopce karty nie ma czego dociskać i wiersz
   z etykietą pochodzenia przestaje się równać między kartami. */
.opinie__track > .opinie__slide > .opinia {
    width: 100%;
}

/* Gdy wszystkie karty się mieszczą, Swiper przestaje przesuwać — wtedy rząd
   wyrównany do lewej wygląda na przypadkowo urwany w sekcji, w której nagłówek,
   lede, podsumowanie i przyciski są wyśrodkowane.
   Klasa `is-locked` na .opinie__slider, nie `swiper-locked` na kontenerze:
   Swiper 11 nadaje tę drugą wyłącznie przyciskom nawigacji, paginacji
   i scrollbarowi — na .swiper nie trafia nigdy. Klasę dokłada opinie.js. */
.opinie__slider.is-locked .opinie__track {
    justify-content: center;
}

/* --------------------------------------------------------------------------
   Fallback bez JavaScriptu

   Dopóki Swiper nie doda `swiper-initialized` (albo gdy nie doda go nigdy),
   tor jest zwykłym przepełnionym kontenerem: przewija się palcem, gładzikiem,
   Shift+kółkiem i paskiem. Wszystkie karty pozostają osiągalne.
   -------------------------------------------------------------------------- */

.opinie__rail:not(.swiper-initialized) {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(235, 223, 200, 0.5) rgba(235, 223, 200, 0.08);
}

.opinie__rail:not(.swiper-initialized) .opinie__track {
    gap: var(--op-gap);
}

.opinie__rail:not(.swiper-initialized)::-webkit-scrollbar {
    height: 8px;
}

.opinie__rail:not(.swiper-initialized)::-webkit-scrollbar-track {
    background: rgba(235, 223, 200, 0.08);
}

.opinie__rail:not(.swiper-initialized)::-webkit-scrollbar-thumb {
    background: rgba(235, 223, 200, 0.5);
}

/* --------------------------------------------------------------------------
   Strzałki

   Geometria przejęta z .zb-blog__nav (slider bloga) — 52 px koło z hairline'em.
   Odsłania je skrypt i tylko wtedy, gdy tor faktycznie się nie mieści.

   Na ekranach dotykowych ZOSTAJĄ. Wcześniej znikały przy (pointer: coarse),
   a że pasek przewijania na telefonie jest niewidoczny w spoczynku i nie ma
   kropek paginacji, sekcja nie dawała wtedy żadnego sygnału, że jest co przewijać.
   -------------------------------------------------------------------------- */

.opinie__arrow {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    padding: 0;
    border: 1px solid rgba(235, 223, 200, 0.28);
    border-radius: 50%;
    background: transparent;
    color: #ebdfc8;
    cursor: pointer;
    transition: border-color 0.35s ease, color 0.35s ease, background 0.35s ease, transform 0.35s ease;
}

/* [hidden] przegrywa z display: grid, więc trzeba je przywrócić jawnie. */
.opinie__arrow[hidden] {
    display: none;
}

.opinie__arrow--prev { grid-column: 1; }
.opinie__arrow--next { grid-column: 3; }

.opinie__arrow:hover,
.opinie__arrow:focus-visible {
    border-color: var(--op-copper-hi);
    color: var(--op-copper-hi);
    background: rgba(196, 117, 58, 0.1);
    outline: none;
}

.opinie__arrow:focus-visible {
    outline: 2px solid var(--op-copper-hi);
    outline-offset: 3px;
}

.opinie__arrow:active {
    transform: scale(0.96);
}

@media (max-width: 860px) {
    /* Strzałki pod torem: przy 52 px kole po bokach zostaje na kartę tak mało
       miejsca, że przestaje być widać następną. */
    .opinie__slider {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
            'rail rail'
            'prev next';
        row-gap: 1.35rem;
        column-gap: 0.75rem;
    }

    .opinie__rail { grid-area: rail; }

    .opinie__arrow--prev {
        grid-area: prev;
        justify-self: end;
    }

    .opinie__arrow--next {
        grid-area: next;
        justify-self: start;
    }
}

/*
 * Wszystkie karty się mieszczą → strzałek nie ma → tor bierze całą szerokość.
 * Bez tego zostają puste kolumny `auto` (szerokość 0), ale odstępy między
 * torami grida liczą się dalej i tor dostaje ~14 px martwego wcięcia z każdej
 * strony. Klasę dokłada opinie.js razem z chowaniem strzałek.
 * Specyficzność (0,2,0) i (0,3,0) wygrywa też wewnątrz media query wyżej.
 */
.opinie__slider.is-locked {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
}

.opinie__slider.is-locked .opinie__rail {
    grid-area: auto;
}

/* --------------------------------------------------------------------------
   Karta opinii — powierzchnia Google

   Karta jest CYTATEM z cudzej platformy, tak jak osadzony post, i dlatego jest
   złożona materiałem tamtej platformy: biel, Roboto, bursztynowe gwiazdki,
   okrągły kolorowy monogram (to dokładnie awatar zastępczy Google), niebieskie
   linki, data względna, zaokrąglenie 8 px. Czytelniczka ma rozpoznać źródło,
   zanim doczyta stopkę — opinie są wyłącznie z Google i z niczego innego.

   GRANICA JEST NA KRAWĘDZI KARTY I JEST CELOWA. Wszystko dookoła — tło sekcji,
   eyebrow, nagłówek, lede, przyciski, blok informacyjny — zostaje nasze:
   granat, Poppins, miedź. Gdyby identyfikacja Google wyszła poza kartę, serwis
   zacząłby wyglądać na produkt Google — a sugerowanie aprobaty podmiotu
   trzeciego to art. 7 pkt 4 u.p.n.p.r., czarna lista bez testu przesłanek.
   Ta sama reguła zakazuje zestawiania znaku „G" z gwiazdkami w jeden znaczek.
   -------------------------------------------------------------------------- */

.opinia {
    /* Tokeny powierzchni Google — obowiązują wyłącznie wewnątrz karty. */
    --g-surface:   #fff;
    --g-surface-2: #f8f9fa;
    --g-line:      #dadce0;
    --g-ink:       #202124;
    --g-ink-soft:  #5f6368;
    --g-blue:      #1a73e8;

    display: flex;
    flex-direction: column;
    padding: 1.15rem 1.15rem 1rem;
    background: var(--g-surface);
    color: var(--g-ink);
    border: 1px solid var(--g-line);
    border-radius: 8px;
    box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);
    font-family: 'Roboto', Arial, system-ui, sans-serif;
    text-align: left;
}

.opinia__head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.opinia__ident {
    min-width: 0;
}

.opinia__author {
    margin: 0;
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.35;
    color: var(--g-ink);
}

.opinia__meta-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15rem 0.5rem;
    margin: 0.2rem 0 0;
    font-size: 0.8125rem;
    color: var(--g-ink-soft);
}

.opinia__date {
    font-variant-numeric: tabular-nums;
}

/*
 * Znak źródła w rogu karty — dokładnie tam, gdzie stawia go widżet Google.
 * Nie wolno go modyfikować, obwodzić ani zestawiać z gwiazdkami; markup
 * i uzasadnienie prawne są przy zoriana_google_mark() w functions.php.
 */
.opinia__google-mark {
    flex: none;
    align-self: flex-start;
    margin-left: auto;
}

/* --------------------------------------------------------------------------
   Gwiazdki

   Jeden glif w całym serwisie, w bursztynie Google. Kontekst ustawia tylko
   `color`, którym rysowany jest obrys gwiazdki PUSTEJ — dzięki temu ta sama
   reguła obsługuje kartę (biel), podsumowanie na granacie i podsumowanie
   na pergaminowym hubie.
   -------------------------------------------------------------------------- */

.opinia__stars {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    line-height: 1;
    color: var(--g-line);
}

.opinia__star {
    width: 0.95rem;
    height: 0.95rem;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.3;
    stroke-linejoin: round;
}

.opinia__star.is-on {
    fill: var(--op-star);
    /*
     * Bursztyn Google na bieli daje 1,7:1 — u samego Google zresztą też.
     * My dokładamy włosowy obrys w ciemniejszym złocie (3,25:1 wobec bieli),
     * żeby kształt był rozróżnialny (SC 1.4.11). Przy 15 px jest praktycznie
     * niewidoczny. Gdybyś chciał wierność co do piksela — skasuj dwie linie niżej.
     */
    stroke: var(--op-star-edge);
    stroke-width: 0.9;
}

/* --------------------------------------------------------------------------
   Monogram

   Wypełnione kolorowe kółko z inicjałem — to jest awatar zastępczy Google
   i jeden z najsilniejszych sygnałów rozpoznawczych tego widżetu. Kolor
   przydziela Monogram::color() deterministycznie z podpisu autorki, więc ta
   sama osoba ma zawsze ten sam.
   -------------------------------------------------------------------------- */

.opinia__monogram {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 0;
    border-radius: 50%;
    background: var(--opinia-monogram, #5f6368);
    color: #fff;
    font-family: inherit;
    font-size: 1rem;
    font-style: normal;
    font-weight: 500;
    letter-spacing: 0;
    user-select: none;
}

/* --------------------------------------------------------------------------
   Treść opinii
   -------------------------------------------------------------------------- */

.opinia__body {
    margin: 1rem 0 0;
    padding: 0;
    border: 0;
    /* Storefront ustawia blockquote{font-style:italic} — bez tego resetu cała
       treść opinii renderuje się pochyłym Roboto. */
    font-style: normal;
    font-size: 0.9375rem;
    line-height: 1.55;
    color: var(--g-ink);
}

.opinia__body p {
    margin: 0 0 0.65rem;
}

.opinia__body p:last-child {
    margin-bottom: 0;
}

/* Skrót jest wyłącznie wizualny — pełny tekst zostaje w HTML-u, więc
   crawlery i czytniki ekranu dostają całość. Zmieniając liczbę linii,
   zmień też próg pokazywania linku „Więcej" w opinia-card.php. */
.opinia--excerpt .opinia__body {
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Odpowiedź autorki serwisu zostaje w HTML-u także w wycinku — chowa ją CSS,
   więc crawlery, które nie wykonują skryptów, nadal ją czytają.
   UWAGA: display:none wycina ją za to z drzewa dostępności, więc czytnik ekranu
   dostaje odpowiedź dopiero w trybie pełnym na /opinie/. To NIE jest ten sam
   przypadek co line-clamp wyżej, który treść w drzewie zostawia. */
.opinia--excerpt .opinia__reply {
    display: none;
}

.opinia__more {
    margin: 0.5rem 0 0;
    font-size: 0.8125rem;
}

/*
 * Linki w Google Blue, bez stałego podkreślenia — tak jak w widżecie.
 * Wolno je zostawić bez podkreślenia, bo #1a73e8 wobec #202124 daje 3,57:1,
 * czyli powyżej progu rozróżnialności linku od otaczającego tekstu; sygnał
 * niekolorystyczny dokłada podkreślenie na hover i focus.
 */
.opinia__more a,
.opinia__origin,
.opinia__service a {
    color: var(--g-blue);
    font-weight: 500;
    text-decoration: none;
}

.opinia__more a:hover,
.opinia__more a:focus-visible,
.opinia__origin:hover,
.opinia__origin:focus-visible,
.opinia__service a:hover,
.opinia__service a:focus-visible {
    text-decoration: underline;
    text-decoration-thickness: 0.08em;
    text-underline-offset: 0.18em;
}

.opinia a:focus-visible {
    outline: 2px solid var(--g-blue);
    outline-offset: 2px;
    border-radius: 2px;
}

/* Zagnieżdżenie odpowiedzi niesie wcięcie i szarą płaszczyznę, nie pasek przy
   krawędzi — gruba kolorowa listwa z jednej strony to najbardziej opatrzony
   ozdobnik, a Google używa tu dokładnie płaskiego bloku. */
.opinia__reply {
    margin: 0.9rem 0 0 0.6rem;
    padding: 0.75rem 0.9rem;
    background: var(--g-surface-2);
    border: 0;
    border-radius: 8px;
    font-size: 0.875rem;
    color: var(--g-ink);
}

.opinia__reply-label {
    margin: 0 0 0.2rem;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--g-ink-soft);
}

.opinia__reply p {
    margin: 0 0 0.45rem;
}

.opinia__reply p:last-child {
    margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   Stopka karty — dwa poziomy

   Poziom pierwszy realizuje art. 6 ust. 4 pkt 7 u.p.n.p.r. i musi zostać
   na karcie w komplecie. Poziom drugi to odnośniki, i to one wymagają
   powiększonego celu dotykowego (SC 2.5.8).

   Zapis zdaniem, nie wersalikami: to jest komunikat wewnątrz zacytowanego
   artefaktu, więc mówi jego głosem, a nie naszym.
   -------------------------------------------------------------------------- */

/*
 * margin-top: auto dociska stopkę do dna karty, dzięki czemu wiersz z etykietą
 * pochodzenia stoi w jednej linii we wszystkich kartach toru. Minimalnego
 * odstępu od cytatu NIE wolno robić przez `.opinia__body + .opinia__foot` —
 * taka reguła ma wyższą specyficzność, zbiłaby `auto` i stopki by się rozjechały.
 * Odstęp daje padding, który działa niezależnie od tego, ile zostało miejsca.
 */
.opinia__foot {
    margin-top: auto;
    padding-top: 0.9rem;
    border-top: 1px solid var(--g-line);
}

.opinia__provenance {
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--g-ink-soft);
}

/* Flagi jako tekst z kropką rozdzielającą — pigułki z obwódką dokładały
   karcie czwarty kształt przy kontraście 1,04:1 wobec jej tła. */
.opinia__flag::before {
    content: '·';
    margin: 0 0.35em;
}

.opinia__foot-links {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 1rem;
    margin: 0.1rem 0 -0.3rem;
    font-size: 0.8125rem;
}

/* ≥24 px wysokości celu przy zachowanej linii bazowej tekstu (SC 2.5.8).
   Wcześniej link miał 16,8 px przy 9,6 px odstępu do sąsiada — i to akurat
   na odnośniku, którym czytelniczka weryfikuje źródło opinii. */
.opinia__origin,
.opinia__service a {
    display: inline-block;
    padding-block: 0.35rem;
}

/* --------------------------------------------------------------------------
   Przyciski

   Anatomia .zn-arcana__cta ze strony głównej: prostokąt, wersaliki, hairline,
   miedziana kreska pod spodem. Wcześniej pigułka w #a85f2b stała na stronie
   głównej obok CTA w #d97742 — dwa różne pomarańcze w jednym widoku.
   -------------------------------------------------------------------------- */

.opinie__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    justify-content: center;
    margin: 0 0 1.75rem;
}

.opinie-page .opinie__actions {
    justify-content: flex-start;
}

.opinie__cta {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    padding: 0.85rem 1.6rem;
    border: 1px solid var(--op-copper);
    border-radius: 0;
    background: var(--op-card);
    color: var(--op-copper-deep);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    text-decoration: none;
    box-shadow: 0 2px 0 0 var(--op-copper);
    transition: background 0.35s ease, color 0.35s ease, box-shadow 0.35s ease, transform 0.35s ease;
}

.opinie__cta:hover,
.opinie__cta:focus-visible {
    background: var(--op-copper);
    color: var(--op-card);
    box-shadow: 0 2px 0 0 var(--op-copper-deep);
    transform: translateY(-2px);
}

/* Wariant poboczny — na granacie sekcji, więc obwódka w miedzi rozjaśnionej
   (--op-copper na #14142a daje 2,9:1, czyli poniżej progu dla obwódki). */
.opinie__cta--ghost {
    background: transparent;
    border-color: var(--op-copper-hi);
    color: #ebdfc8;
    box-shadow: none;
}

.opinie__cta--ghost:hover,
.opinie__cta--ghost:focus-visible {
    background: rgba(196, 117, 58, 0.14);
    color: #f7ecd8;
    box-shadow: none;
}

/* Na jasnym hubie wariant poboczny wraca na atrament pergaminowy. */
.opinie-page .opinie__cta--ghost {
    border-color: var(--op-copper);
    color: var(--op-copper-deep);
}

.opinie-page .opinie__cta--ghost:hover,
.opinie-page .opinie__cta--ghost:focus-visible {
    background: rgba(168, 94, 44, 0.1);
    color: var(--op-copper-deep);
}

/* --------------------------------------------------------------------------
   Blok informacyjny (art. 6 ust. 4 pkt 7 u.p.n.p.r.)
   Renderowany server-side w tej samej sekcji co opinie — nigdy w modalu.
   -------------------------------------------------------------------------- */

.opinie__disclosure {
    max-width: 46rem;
    margin: 0 auto;
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--op-paper-dim);
}

.opinie-page .opinie__disclosure {
    margin: 0 0 clamp(2rem, 4vw, 3rem);
    color: var(--op-ink-soft);
}

.opinie__disclosure a {
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 0.06em;
    text-underline-offset: 0.16em;
}

/* --------------------------------------------------------------------------
   Strona /opinie/
   -------------------------------------------------------------------------- */

.opinie-page {
    background: var(--op-paper);
    color: var(--op-ink);
    padding: clamp(72px, 10vw, 140px) 0 clamp(80px, 11vw, 150px);
}

.opinie-page__header {
    max-width: 46rem;
    margin-bottom: clamp(2rem, 4.5vw, 3rem);
}

.opinie-page__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 1.1rem;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 4px;
    text-transform: uppercase;
    color: var(--op-copper);
}

.opinie-page__eyebrow::after {
    content: '';
    width: 36px;
    height: 1px;
    background: linear-gradient(90deg, rgba(196, 117, 58, 0.55), transparent);
}

.opinie-page__title {
    margin: 0 0 1rem;
    font-family: 'Poppins', system-ui, sans-serif;
    font-size: var(--text-display, clamp(2rem, 1.06rem + 3.94vw, 3.75rem));
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.015em;
    color: var(--op-ink);
    text-wrap: balance;
}

.opinie-page__lead {
    margin: 0 0 1.25rem;
    max-width: 42rem;
    font-size: 1.02rem;
    line-height: 1.7;
    color: var(--op-ink-mid);
    text-wrap: pretty;
}

/*
 * Nawigacja grup przykleja się do góry. Przy 177 kartach to jedyna rzecz,
 * która daje poczucie miejsca w dokumencie. 7rem to ta sama liczba, co
 * scroll-margin-top niżej — czyli wysokość sticky headera motywu.
 */
.opinie-page__nav {
    position: sticky;
    top: 7rem;
    z-index: 3;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem);
    padding: 0.75rem 0;
    background: var(--op-paper);
    border-bottom: 1px solid var(--op-card-edge);
}

.opinie-page__nav a {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    min-height: 2.25rem;
    padding: 0.4rem 0.9rem;
    border: 1px solid var(--op-card-edge);
    border-radius: 0;
    background: var(--op-card);
    color: var(--op-ink);
    font-size: 0.85rem;
    text-decoration: none;
    transition: border-color 0.25s ease, color 0.25s ease;
}

.opinie-page__nav a:hover,
.opinie-page__nav a:focus-visible {
    border-color: var(--op-copper);
    /* --op-accent-ink, nie --op-copper-hi: to jest tekst 13,6 px na pergaminie. */
    color: var(--op-accent-ink);
}

.opinie-page__nav-count {
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--op-ink-soft);
}

.opinie-page__group {
    margin-bottom: clamp(2.5rem, 5vw, 3.75rem);
}

/* Gołe h2 było jedyną rzeczą oddzielającą sześćdziesiąt kart od kolejnych
   czterdziestu — kreska daje temu podziałowi wagę. */
.opinie-page__group-title {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin: 0 0 1.35rem;
    font-family: 'Poppins', system-ui, sans-serif;
    font-size: clamp(1.25rem, 0.9rem + 1.2vw, 1.6rem);
    font-weight: 600;
    line-height: 1.25;
    color: var(--op-ink);
}

.opinie-page__group-title::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, rgba(168, 94, 44, 0.35), transparent);
}

.opinie-page__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(21rem, 100%), 1fr));
    gap: var(--op-gap);
    align-items: start;
}

/* 177 kart na jednej stronie — pozwalamy przeglądarce pominąć render tych
   poza ekranem, zachowując pełną treść w DOM-ie dla crawlerów i Ctrl+F.
   NIE przenosić na slajdy w torze: Swiper mierzy wysokość przy inicjalizacji
   i dostałby zera. */
.opinie-page__grid > .opinia {
    content-visibility: auto;
    contain-intrinsic-size: auto 420px;
}

.opinie-page__empty,
.opinie-page__content {
    max-width: 46rem;
}

/* Kotwica do pojedynczej opinii („Czytaj całość") musi omijać sticky header
   motywu — ma około 104 px, a bez tego karta wjeżdża pod niego.
   `id` i `scroll-margin-top` muszą siedzieć na tym samym elemencie. */
.opinia,
.opinie-page__group {
    scroll-margin-top: 7rem;
}

/* Podświetlenie celu kotwicy działa też w sekcji skróconej — te same
   identyfikatory #opinia-{ID} istnieją na ~24 podstronach. */
.opinia:target {
    outline: 2px solid var(--op-copper);
    outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
    /* main.css ustawia html{scroll-behavior:smooth} globalnie i nigdzie tego nie
       wyłącza — skok do 150. karty byłby płynnym przejazdem przez tysiące pikseli. */
    html {
        scroll-behavior: auto;
    }

    .opinie__cta,
    .opinie__arrow,
    .opinie-page__nav a {
        transition: none;
    }

    .opinie__cta:hover,
    .opinie__cta:focus-visible,
    .opinie__arrow:active {
        transform: none;
    }
}
