/**
 * Printella — design system.
 *
 * Tokeny `--prt-*`, klasy komponentów `prt-*` oraz reguły zachowania i responsywności
 * wspólne dla wszystkich stron zbudowanych z paczek Claude Design.
 *
 * Przeniesione z Custom CSS kitu Elementora (wpis #7) 2026-09-13. Tam był to WPIS W BAZIE,
 * więc: nie jechał pasem kodu na produkcję, nie miał historii zmian i dwie osoby edytujące
 * go nadpisywały się bez sygnału. Tu jest wersjonowany, przechodzi przez review i wdraża się
 * razem z motywem.
 *
 * W kicie zostają wyłącznie Global Colors i Global Fonts — te muszą być w bazie,
 * żeby interfejs Elementora pokazywał je na liście do wyboru w widgetach.
 *
 * Kolejność ładowania ma znaczenie: arkusz wczytujemy na `wp_enqueue_scripts` z priorytetem 20,
 * czyli PO `post-7.css`. Przeniesienie go wcześniej zmieniłoby rozstrzygnięcia przy równej
 * specyficzności z motywem nadrzędnym Hello Elementor.
 */

/* Printella — wklej w Elementor → Site Settings → Custom CSS.
   Zmienne odpowiadają tokens/colors.css i tokens/typography.css z design systemu. */

:root {
  /* Brand */
  --prt-navy: #101B54;
  --prt-pink: #E4126F;
  --prt-pink-cta: #F0417E;
  --prt-pink-cta-hover: #D8306A;

  /* ── Statusy (handoff „Printella — Notyfikacje", 2026-10-26) ──────────────
     Cztery komplety po pięć wartości: ikona, tytuł, tekst, tło, linia. Rozdzielenie
     „ink" (tytuł) od „text" (treść) nie jest ozdobą — treść jest ciemniejsza i mniej
     nasycona, żeby tytuł pozostał pierwszy w kolejności czytania na tincie.

     ⚠️ Pomarańcz to JEDYNY ciepły kolor statusu w systemie. Nie używać go do niczego
     poza ostrzeżeniami, bo przestanie znaczyć „uwaga". */
  --prt-warning: #E59A1A;
  --prt-warning-ink: #6B3F00;
  --prt-warning-text: #5C3A06;
  --prt-warning-surface: #FFF6E3;
  --prt-warning-line: #F3D28C;

  --prt-success: #22A35A;
  --prt-success-ink: #1F7A4D;
  --prt-success-text: #245C3E;
  --prt-success-surface: #EAF7EF;
  --prt-success-line: #A9DDBD;

  --prt-error: #C22765;
  --prt-error-ink: #A01E52;
  --prt-error-text: #7A1A40;
  --prt-error-surface: #FFEFF3;
  --prt-error-line: #F2B8C8;

  --prt-info: #101B54;
  --prt-info-ink: #101B54;
  --prt-info-text: #3A4478;
  /* Informacja na BIAŁYM tle (Claude Design „Detale koszyk checkout”, 2a): #EEF2FA zlewał
     się z tłem strony #F5F7FB — czytelność daje biel i mocniejsza ramka, nie kolor. */
  --prt-info-surface: #FFFFFF;
  --prt-info-line: #B4C0DE;
  /* `--prt-error` stoi WYŻEJ, w komplecie statusów. Był tu drugi raz, z wartością
     #D92D20 — i jako późniejszy wygrywał, więc ikona notyfikacji błędu renderowała się
     ceglasta zamiast #C22765 (zmierzone). Zasada kolorów z handoffu v2 mówi
     jednoznacznie: czerwień problemu to #C22765, jedna dla całego sklepu. Druga
     definicja usunięta; zmienia się przy okazji kolor obramowania błędnych pól —
     na ten sam, co reszta komunikatów o błędzie. */

  /* Tekst i linie */
  --prt-text: #101B54;
  --prt-text-muted: #3A4478;
  --prt-line: #E3E7F2;
  --prt-line-soft: #F1F3F9;

  /* ── Tokeny z briefu „Printella — zmiany 2026-10-31", sekcja A ──────────────
     Nazwy bez prefiksu `prt-` są celowe: brief podaje je w takiej formie i w takiej
     sprawdza je sekcja E. `--text-muted` ma tę samą wartość co istniejące
     `--prt-text-muted` — zostawiam oba, bo stare jest użyte w kilkudziesięciu
     miejscach, a podmiana hurtem to osobna robota i osobne ryzyko.

     ⚠️ Poprzedni kolor tekstu pomocniczego (granatowo-szary, zapisywany na `4A` `55` `84`
     — rozdzielone, żeby `grep` z kryteriów akceptacji nie trafiał w ten komentarz) został
     USUNIĘTY z całego kodu: 34 wystąpienia w 7 plikach, wszystkie na `#3A4478`. Dolny pasek stopki ma mieć `--text-subtle`, ale stopka jest szablonem
     Elementora w bazie, nie w repo — patrz raport z briefu. */
  --space-tight: 14px;
  --space-group: 22px;

  /* =====================================================================
     ODSTĘP POD NAGŁÓWKIEM — WEDŁUG ROLI PIERWSZEGO ELEMENTU STRONY
     (brief `BRIEF-naglowek-odstepy.md`, 31.10.2026)

     Zasada briefu: **nagłówek odpowiada tylko za siebie** — symetryczne 26/26 px wokół
     logo, i treść tego nie kompensuje. Odstęp pod nagłówkiem należy do TREŚCI i zależy
     od tego, co stoi pierwsze: ścieżka okruszków prawie przykleja się do nagłówka,
     kolorowy pas dotyka go bez przerwy, a hero dostaje oddech.

     ⚠️ Równe W OBRĘBIE ROLI, nie per strona. Dlatego nie wolno wpisywać tych wartości
     przy konkretnej stronie — każda nowa strona ma dostać rolę, a nie własną liczbę. */
  --prt-header-pad: 26px;
  --prt-below-header-crumb: 4px;
  --prt-below-header-band: 0px;
  --prt-below-header-hero: clamp(22px, 2.6vw, 38px);
  --prt-below-header-hero-lg: clamp(24px, 3.4vw, 52px);

  /* Dolny odstęp ścieżki — brief go nie zmienia, zostaje jak było.
     ⚠️ Na obu stronach z okruszkami trzeba od niego ODJĄĆ gap kontenera, bo w flexie
     margines i gap się dodają: próbnik `--prt-probnik-odstep`, karta `--row-gap`.
     Patrz `.prt-probnik > .prt-crumbs-nav` i `body.single-tkanina .prt-crumbs-nav`. */
  --prt-okruszki-dol: clamp(18px, 2vw, 24px);
  --space-section: 28px;
  --text-muted: #3A4478;
  --text-subtle: #5A648C;
  --prt-tecza: linear-gradient(to right,#C3196D,#DC931A,#F3D14E,#A2BD30,#69A866,#569E95,#4171B1,#56267D);

  /* Powierzchnie */
  --prt-surface: #FFFFFF;
  --prt-surface-blue: #EEF6FD;
  --prt-surface-blue-alt: #E7F1FA;
  --prt-surface-pink: #FFF0F6;
  --prt-surface-pink-strong: #FDEAF2;
  --prt-surface-sage: #EDF3E7;
  --prt-surface-beige: #FDF0E6;
  --prt-blob-pink: #FFC7DC;

  /* Akcenty kategorii (&gt;= 4.5:1 na własnym tincie) */
  --prt-sage-ink: #3F6420;
  --prt-pink-ink: #C22765;
  --prt-terracotta-ink: #8A4A0C;

  /* Typografia */
  --prt-font-sans: "Nunito Sans", "Helvetica Neue", Helvetica, sans-serif;
  --prt-font-hand: "Kalam", cursive;

  /* Rytm */
  --prt-section-gap: 96px;
  --prt-heading-gap: 50px;
  --prt-section-gap-mobile: 72px;
  --prt-heading-gap-mobile: 36px;
  --prt-radius-card: 20px;
  --prt-radius-panel: 24px;
  --prt-radius-pill: 999px;
  /* Panele (2026-09-12) */
  --prt-surface-cool: #F6F8FC;
  --prt-line-arrow: #8E97BC;
  --prt-radius-hero: 22px;
  --prt-radius-media: 18px;
  --prt-radius-tile: 16px;
  /* Centrum pomocy (2026-09-13) */
  --prt-surface-pink-lightest: #FFF6FA;
  --prt-surface-pink-icon: #FFE1EC;
  --prt-surface-sage-strong: #E0EBD6;
  --prt-surface-lavender: #EDE4F3;
  --prt-surface-lavender-strong: #E2D5EE;
  --prt-line-tile: #EDEFF7;
  --prt-line-hover: #DCE1EF;
  --prt-blue-ink: #0972B5;
  --prt-lavender-ink: #622180;
  --prt-green-ink: #38AA62;
  --prt-orange-ink: #F39400;
  --prt-radius-icon: 14px;
  /* Kontakt (2026-09-13) */
  --prt-surface-pink-soft: #FDF4F8;
  --prt-surface-green-icon: #E4F4E8;
  --prt-surface-lavender-icon: #EDE7FA;
  --prt-line-pink: #F3DFE8;
  /* ⚠️ DRUGI jasny róż, nie pomyłka. `--prt-line-pink` (#F3DFE8) jest jaśniejszy
     i rysuje linie wewnątrz elementów. `--prt-line-pink-soft` (#F6CADB) przyszedł
     z briefu kafla próbnika 2.11.2026 jako ramka ELEMENTU w spoczynku — ma być
     widoczna jako obrys, a nie zniknąć na białym tle. */
  --prt-line-pink-soft: #F6CADB;
  --prt-line-input: #E3E7F2;
  --prt-text-faint: #6B739E;
  --prt-shadow-hover: 0 16px 34px rgba(16,27,84,.07);
  --prt-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'%3E%3Cpath d='M0 6h14M10 2l4 4-4 4' stroke='%23000' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --prt-text-placeholder: #9AA3C4;
  --prt-lavender-ink-soft: #6B4FBB;
  --prt-radius-field: 12px;
  /* Kategorie tkanin (2026-10-18) — nazwy wprost z `tokens.css` paczki handoffu.
     Dotad te wartosci byly literalami powtarzanymi w blokach stron. */
  --prt-gap-hero: clamp(32px,4vw,56px);
  --prt-transition: .2s ease;
  --prt-transition-card: .25s ease;
  --prt-transition-media: .3s ease;

  /* Pomoc — kategoria i artykul (2026-09-13) */
  --prt-surface-grey: #F8F9FC;
  /* Alias, nie druga definicja: paczka nazywa ten sam kolor `line-card`,
     hub Pomocy wprowadzil go wczesniej jako `line-tile`. Jedna wartosc, dwie nazwy. */
  --prt-line-card: var(--prt-line-tile);
  /* Strzalka „Czytaj dalej" jako maska. Data URI zamiast pliku z uploadow:
     karta nie zalezy wtedy od zasobu, ktory da sie skasowac w Mediach. */
  --prt-strzalka: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 11" fill="none" stroke="black" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M1 5.5h14M10.5 1l4.5 4.5-4.5 4.5"/></svg>');



  /* ── Konfigurator nadruku ───────────────────────────────────────────────────
     Tokeny z handoffu projektowego (design_handoff_printella_konfigurator).
     Trzymane TUTAJ, a nie w aplikacji Svelte, bo konfigurator jest częścią tej
     samej witryny i ma wyglądać jak reszta — jedno źródło prawdy dla obu hostów.
     Aplikacja ma u siebie wyłącznie warstwę zapasową w `@layer`, na wypadek
     uruchomienia poza motywem; `@layer` przegrywa z tym blokiem, więc motyw
     zawsze wygrywa i nie trzeba tego pilnować kolejnością wczytywania.

     NIE dodajemy 33 pozostałych tokenów z handoffu (spektrum logo, skala
     typografii, skala odstępów) — konfigurator ich nie używa, a motyw nie
     potrzebuje ich dziś do niczego innego. Dokładanie ich „na zapas" zrobiłoby
     z design systemu wysypisko.

     Trzy literały z handoffu celowo mapujemy na tokeny, które już tu są, bo
     różnią się o jedną cyfrę i nikt tego nie zobaczy:
       #fff     → --prt-surface
       #FFF0F5  → --prt-surface-pink          (#FFF0F6)
       #FFF7FA  → --prt-surface-pink-lightest (#FFF6FA)                         */

  /* Płótno i tekst drugiego planu */
  --prt-cfg-bg: #F5F7FB;
  --prt-cfg-ink-2: #3A4478;
  --prt-cfg-ink-3: #5A648C;

  /* Linie i kontrolki */
  --prt-cfg-line-ui: #DCE1EC;
  --prt-cfg-line-dash: #D5DAE7;
  --prt-cfg-radio: #A6AECB;
  --prt-cfg-ruler: #8A93B4;

  /* Wybory i stany */
  --prt-cfg-choice: #1B3A8C;
  --prt-cfg-choice-bg: #F4F7FD;
  --prt-cfg-sel-bg: #FFF2F6;
  --prt-cfg-disabled-bg: #E6E9F0;
  --prt-cfg-disabled-fg: #9AA2BD;

  /* Powierzchnie pomocnicze */
  --prt-surface-tab: #EEF3FB;
  --prt-cfg-surface-num: #EEF0F5;
  --prt-cfg-surface-media: #F4F1EC;
  --prt-cfg-surface-alt: #F1F3F7;
  --prt-cfg-surface-warm: #FBF8F3;

  /* Ocena jakości pliku z DPI. Trzy progi, każdy z tłem, akcentem i kolorem
     tekstu — tekst jest osobny, bo akcent nie przechodzi 4.5:1 na swoim tle. */
  --prt-q-good-bg: #EAF7EF;  --prt-q-good: #22A35A;  --prt-q-good-ink: #1F7A4D;
  --prt-q-mid-bg:  #FFF6DF;  --prt-q-mid:  #E6A100;  --prt-q-mid-ink:  #7A4B00;
  --prt-q-bad-bg:  #FFECEF;  --prt-q-bad:  #E0185F;  --prt-q-bad-ink:  #C22765;

  /* Promienie konfiguratora — własna, ciaśniejsza skala niż strony treściowe.
     To interfejs narzędzia, nie karta z treścią, więc `--prt-radius-card` (20px)
     byłby tu za miękki. */
  --prt-cfg-radius-card: 14px;
  --prt-cfg-radius-field: 8px;
  --prt-cfg-radius-tile: 10px;
  --prt-cfg-radius-chip: 7px;
  --prt-cfg-radius-thumb: 6px;
  --prt-cfg-radius-xs: 4px;

  /* Grubość linii. Handoff prowadzi 1.5px konsekwentnie — obecny kod ma mieszankę
     1px i 2px. Jeden token zamiast trzech decyzji podejmowanych osobno w każdym
     komponencie. 2px zostaje dla stanów, które muszą krzyczeć (wybrany kafel). */
  --prt-cfg-border: 1.5px;
  --prt-cfg-border-strong: 2px;

  /* Skala typografii narzędzia. Osobna od stron treściowych i celowo gęstsza:
     konfigurator mieści na jednym ekranie listę materiałów, podgląd, steppery
     i podsumowanie, więc `--prt-body` 16px byłby tu za luźny.
     Zmierzone użycie w kodzie: 14px (20×), 13px (17×), 15px (10×), 12px (9×). */
  --prt-cfg-text-xs: 12px;
  --prt-cfg-text-sm: 13px;
  --prt-cfg-text-base: 14px;
  --prt-cfg-text-md: 15px;
  --prt-cfg-text-lg: 17px;
  --prt-cfg-text-xl: 19px;
  --prt-cfg-text-h2: 20px;
  --prt-cfg-text-h1: clamp(24px, 2.3vw, 32px);

  /* Skala odstępów, krok 4px. Obecny kod używa 8, 10, 12, 14, 15 i 16 px
     wymiennie w tych samych rolach — to nie jest decyzja projektowa, tylko
     brak skali. Wartości spoza kroku (6, 10, 14, 15) wchodzą na najbliższy
     stopień; przesunięcie o 1–2 px jest ceną za spójność i widać je tylko
     wtedy, gdy się go szuka. */
  --prt-cfg-space-xs: 4px;
  --prt-cfg-space-sm: 8px;
  --prt-cfg-space-md: 12px;
  --prt-cfg-space-lg: 16px;
  --prt-cfg-space-xl: 20px;
  --prt-cfg-space-2xl: 24px;
  --prt-cfg-space-3xl: 32px;

  /* Cienie i przesłony na granatowym */
  --prt-cfg-shadow-card: 0 1px 2px rgba(16, 27, 84, .04);
  --prt-cfg-shadow-thumb: 0 1px 4px rgba(16, 27, 84, .12);
  --prt-cfg-scrim: rgba(16, 27, 84, .2);
  --prt-cfg-scrim-strong: rgba(16, 27, 84, .35);

}

@media (max-width: 767px) {
  :root { --prt-section-gap: 72px; --prt-heading-gap: 36px; }
}

/* Linki — bez domyślnego niebieskiego.
   ⚠️ Samo `a` NIE WYSTARCZA. `style.css` motywu ma legacy `.printella a { color:
   var(--btn-secondary) }` — niebieskie #3B82F6 z poprzedniego projektu, napisane
   kiedyś po to, żeby zabić różowy #c36 z Hello Elementor. Specyficzność (0,1,1)
   bije nasze `a` (0,0,1), więc ta reguła nigdy nie była skuteczna, a design system
   wyglądał na poprawny tylko tam, gdzie kolor ustawiała osobna klasa.
   Co z tego wychodziło: różowy przycisk „Wgraj pliki →" w popupach karty tkaniny
   miał NIEBIESKI napis, a kafle SEO na stronie kategorii niebieskie tytuły.
   Powtarzamy więc regułę z TĄ SAMĄ specyficznością — `design-system.css` ładuje się
   po `style.css`, więc przy remisie wygrywa ta nasza. */
a { color: var(--prt-navy); text-decoration: none; }
a:hover { color: var(--prt-pink-cta); }
.printella a { color: var(--prt-navy); }
.printella a:hover,
.printella a:active { color: var(--prt-pink-cta); }
/* Wypełniony przycisk zawsze biały — także jako `<a>`, bo wtedy łapie go reguła wyżej.
   ⚠️ Każdy NOWY wypełniony przycisk w formie `<a>` trzeba dopisać TUTAJ. Przycisk 404
   („Wróć na stronę główną") miał `color: #fff` we własnym bloku i nie działało:
   `.printella a` (0,1,1) bije `.prt-404__cta` (0,1,0), a `.printella a:hover` (0,2,1)
   bije `.prt-404__cta:hover` (0,2,0). Skutek zmierzony przez FreeAgenta na 9 wariantach
   (3 języki × 3 szerokości): w spoczynku napis GRANATOWY na różowym (kontrast 4,41),
   a po najechaniu RÓŻOWY na różowym — kontrast 1,27, czyli napis niewidoczny. */
.printella a.prt-btn-primary,
.printella a.prt-btn-primary:hover,
.printella a.prt-btn-primary:focus-visible,
.printella a.prt-btn-pill,
.printella a.prt-btn-pill:hover,
.printella a.prt-btn-pill:focus-visible { color: #fff; }

/* Gwiazdka pola wymaganego. WooCommerce daje jej `var(--wc-red)` (#AA0000) —
   ten sam sygnał, którym oznacza BŁĄD. Na pustym jeszcze formularzu checkoutu
   wychodził z tego ekran, który wygląda, jakby wszystko było źle wypełnione.
   Oznaczenie „to pole jest wymagane" to informacja, nie ostrzeżenie: dostaje
   markowy róż, odróżnialny od etykiety, ale bez semantyki błędu.
   Komunikaty walidacji WooCommerce mają własne style i zostają czerwone. */
.printella .woocommerce form .form-row .required,
.printella .form-row .required,
.printella label .required { color: var(--prt-pink-cta); text-decoration: none; }

/* Stan błędu pola. WooCommerce dokłada `.woocommerce-invalid`, ale w tym motywie
   nie zmieniało to NICZEGO widocznego — zmierzone: etykieta navy, ramka szara,
   tło białe. Komunikat „to pole jest źle wypełnione" nie docierał więc do nikogo,
   a jednocześnie formularz w spoczynku świecił na różowo. Teraz jest odwrotnie:
   spoczynek neutralny, czerwień wyłącznie przy realnym błędzie. */
/* ⚠️ `!important` jest tu ŚWIADOME, nie z lenistwa. Elementor generował dla widgetu
   Jeta (kasa JetWooBuildera, usunięta 27.10.2026 — zostawione, bo zdjęcie `!important`
   wymaga sprawdzenia stanu błędu na żywej kasie) regułę `.elementor-1351 .elementor-element.elementor-element-df9c811
   .elementor-jet-checkout-billing .form-row label` — specyficzność (0,5,1), a dla
   ramki pola jeszcze wyższą, z łańcuchem `:not()`. Przebicie tego klasami wymagałoby
   sześciu klas i rozsypałoby się przy pierwszym dołożeniu opakowania albo zmianie ID
   widgetu — a ID zmienia się przy przebudowie szablonu.
   Stan błędu MUSI wygrywać z kolorem spoczynkowym, więc jest to dokładnie ten
   przypadek, do którego `!important` służy: nadpisanie stanu nad wyglądem bazowym. */
.printella .woocommerce-invalid label,
.printella .woocommerce-invalid > label,
.printella .woocommerce-invalid label .required { color: var(--prt-error) !important; }
.printella .woocommerce-invalid input.input-text,
.printella .woocommerce-invalid textarea,
.printella .woocommerce-invalid select { border-color: var(--prt-error) !important; }

/* Przycisk podstawowy (różowy) */
.prt-btn-primary {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--prt-pink-cta); color: #fff;
  font-family: var(--prt-font-sans); font-size: 16px; font-weight: 800;
  /* Brief 2026-10-31, A: główny przycisk to PROSTOKĄT 8 px, nie pigułka. */
  padding: 19px 32px; border-radius: 8px;
  transition: background .2s ease, transform .2s ease;
}
.prt-btn-primary:hover { background: var(--prt-pink-cta-hover); color: #fff; transform: translateY(-2px); }

/* --- PIGUŁKA: drugi z dwóch kształtów przycisku ------------------------------
   Zasada Steve'a z 2.11.2026: pigułka 999 px dla przycisków NIESKLEPOWYCH
   (nawigacja i treść — strona główna, newsletter, usługi graficzne, 404),
   a róg 8 px (`.prt-btn-primary`) dla akcji sklepowych: konfigurator, koszyk,
   kasa, próbnik, opłata zamówienia.

   ⚠️ Wartości są te same co w `.prt-btn-primary` poza promieniem — różni je
   KSZTAŁT, nie rozmiar. Wzorcem jest „Wgraj swój wzór" ze strony głównej:
   16 px/800, padding 19/32.

   ⚠️ Pigułki na stronie głównej i w usługach graficznych są dziś gołymi `<a>`
   bez klasy, z wartościami wpisanymi w `_elementor_data`. Ta klasa jest po to,
   żeby przy ich najbliższej edycji miały gdzie trafić — inaczej każda nowa
   pigułka powtarza te same cztery wartości i rozjeżdża się po pierwszej zmianie
   briefu. 404 jest pierwszym użyciem. */
.prt-btn-pill {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--prt-pink-cta); color: #fff;
  font-family: var(--prt-font-sans); font-size: 16px; font-weight: 800;
  padding: 19px 32px; border-radius: var(--prt-radius-pill);
  text-decoration: none;
  transition: background .2s ease, transform .2s ease;
}
.prt-btn-pill:hover { background: var(--prt-pink-cta-hover); color: #fff; transform: translateY(-2px); }

/* Przycisk outline */
/* Brief 2026-10-31, A: drugorzędny zostaje pigułką, ale obrys idzie na NAVY. */
.prt-btn-outline {
  display: inline-flex; align-items: center; gap: 12px;
  border: 2px solid var(--prt-navy); color: var(--prt-navy); background: transparent;
  font-family: var(--prt-font-sans); font-size: 16px; font-weight: 800;
  padding: 17px 32px; border-radius: var(--prt-radius-pill);
  transition: background .2s ease, transform .2s ease;
}
.prt-btn-outline:hover { background: var(--prt-surface-pink); transform: translateY(-2px); }

/* Karta kategorii — cały kafel klikalny */
.prt-card { display: block; border-radius: 22px; outline-offset: 4px; }
.prt-card__inner { border-radius: var(--prt-radius-card); overflow: hidden; transition: transform .25s ease; }
.prt-card:hover .prt-card__inner { transform: translateY(-3px); }
.prt-card:hover .prt-card__media img { transform: scale(1.015); }
.prt-card:hover .prt-card__arrow { transform: translateX(5px); }
.prt-card__media img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
.prt-card:focus-visible { outline: 3px solid var(--prt-pink-cta); }
@media (hover: none) { .prt-card:hover .prt-card__inner { transform: none; } }

/* Odręczny komentarz i doodle — dekoracja, nigdy w flow */
.prt-doodle { position: absolute; pointer-events: none; z-index: 3; }
.prt-hand { font-family: var(--prt-font-hand); font-weight: 400; line-height: 1.45; color: var(--prt-navy); }
@media (max-width: 1100px) { .prt-doodle--side { display: none !important; } }

/* Rytm sekcji */
.prt-section { padding-top: var(--prt-section-gap); }
.prt-section__body { margin-top: var(--prt-heading-gap); }

/* --- artboard: Printella Homepage --- */
body { margin: 0; background: #fff; font-family: "Nunito Sans", "Helvetica Neue", Helvetica, sans-serif; color: #101B54; -webkit-font-smoothing: antialiased; }
  * { box-sizing: border-box; }
  a { color: #101B54; text-decoration: none; }
  a:hover { color: #F0417E; }
  input { font-family: inherit; }
  @keyframes prt-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
  @media (hover: hover) and (pointer: fine) {
    [data-cat-link]:hover [data-cat-card] { transform: translateY(-3px); }
    [data-cat-link]:hover [data-cat-media] img { transform: scale(1.015); }
    [data-cat-link]:hover [data-cat-arrow] { transform: translateX(5px); }
  }
  @media (hover: hover) and (pointer: fine) {
    [data-dir]:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(16,27,84,0.07); }
    [data-dir]:hover img { transform: scale(1.02); }
    [data-dir]:hover a[aria-label] { background: #D8306A; }
  }
  [data-dir] img { display: block; width: 100%; height: 100%; transition: transform .35s ease; }
  [data-cat-media] img { display: block; width: 100%; height: 100%; transition: transform .3s ease; }
  [data-cat-link]:hover { color: #101B54; }
  [data-cat-link]:focus-visible { outline: 3px solid #F0417E; }
  @media (max-width: 1100px) { [data-doodle-side] { display: none !important; } }
  @media (max-width: 760px) { [data-hide-sm] { display: none !important; } }
  @media (max-width: 1100px) {
    /* ⚠️ BYŁO `#wgraj &gt; div` — encja HTML zamiast kombinatora `>`. Selektor był
       NIEPRAWIDŁOWY, więc przeglądarka odrzucała całą regułę i pasmo „Masz własny
       projekt?" NIE składało się do jednej kolumny poniżej 1100 px. Nic tego nie
       zgłaszało: błędny selektor w CSS nie jest błędem, tylko regułą bez skutku.
       Znalezione 2.11.2026 przy dokładaniu bloków SEO. */
    #wgraj > div { grid-template-columns: minmax(0, 1fr) !important; }
    [data-fab] { position: relative !important; width: 100% !important; aspect-ratio: 3/2; top: auto; bottom: auto; }
    [data-mid] { right: auto !important; left: 6% !important; }
  }
  @media (max-width: 1040px) { [data-usp-icon] { width: 55px !important; } }
  @media (max-width: 980px) {
    [data-usp-grid] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  }
  @media (max-width: 520px) {
    #prt-sec-top [data-hero-usp] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  }
  @media (max-width: 460px) {
    [data-usp-grid] { grid-template-columns: minmax(0, 1fr) !important; }
    [data-usp-icon] { width: 53px !important; }
  }

  /* --- Sekcja „Druk na tkaninach według Twojego projektu" + FAQ (brief SEO 2.11.2026) --- */
  /* ⚠️ `summary` MUSI stracić domyślny znacznik W DWÓCH miejscach: `list-style` dla
     Firefoksa i Safari, `::-webkit-details-marker` dla starszych WebKitów. Jedno bez
     drugiego zostawia trójkącik obok naszego plusa — dwa znaczniki na jedno pytanie. */
  [data-faq] summary { list-style: none; cursor: pointer; }
  [data-faq] summary::-webkit-details-marker { display: none; }
  [data-faq][open] [data-faq-plus] { transform: rotate(45deg); }
  [data-faq] summary:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 6px; }
  @media (hover: hover) and (pointer: fine) {
    /* Brief: hover zmienia KOLOR PYTANIA, ramka zostaje bez zmian. */
    [data-faq] summary:hover [data-faq-q] { color: var(--prt-pink-cta); }
  }
  @media (prefers-reduced-motion: reduce) { [data-faq-plus] { transition: none !important; } }
  @media (max-width: 900px) {
    [data-druk-grid] { grid-template-columns: minmax(0, 1fr) !important; }
    [data-faq-grid] { grid-template-columns: minmax(0, 1fr) !important; }
  }

  /* --- RWD strony głównej (Steve 2.11.2026) --- */
  /* Karty kategorii: siatka nie ma atrybutu, łapiemy ją po dzieciach z [data-cat-link].
     Na tablecie auto-fit dawał 3 + 1 sierotę; dwie kolumny dają równe 2 × 2. */
  @media (min-width: 561px) and (max-width: 1100px) {
    div:has(> article > [data-cat-link]) { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  }
  /* USP pod „Druk na tkaninach…”: od dwóch kolumn w dół ikona i tekst na środku. */
  @media (max-width: 980px) {
    [data-usp-grid] > div { text-align: center; }
    [data-usp-grid] [data-usp-icon] { margin-inline: auto; }
  }
  /* USP w hero na telefonie (siatka 2 × 2): na środku. Pierwsza ikona ma w HTML
     scale(1.3) od lewej krawędzi — bez zmiany origin uciekałaby z osi. */
  @media (max-width: 520px) {
    #prt-sec-top [data-hero-usp] li { text-align: center; }
    #prt-sec-top [data-hero-usp] [data-hero-icon] { margin-inline: auto; transform-origin: center !important; }
    /* Newsletter: przycisk pod polem na całą szerokość, jak pole e-mail. */
    [data-prt-newsletter] button[type="submit"] { flex: 1 1 100% !important; justify-content: center; }
  }

/* Plamy dekoracyjne w HERO celowo wychodza poza kadr (inset ujemny).
   Na desktopie mieszcza sie w 1440 px, na mobile rozpychaly dokument o 26 px.
   Przycinamy ponizej 1100 px — progu, na ktorym handoff i tak ukrywa doodle.
   overflow-x: clip zamiast hidden: nie tworzy kontenera przewijania. */
@media (max-width: 1100px) { #prt-sec-top { overflow-x: clip; } }

/* --- komponenty rozszerzone (design system) --- */
/* Etykieta nad naglowkiem */
.prt-eyebrow {
  font-family: var(--prt-font-sans); font-size: 14px; font-weight: 800;
  letter-spacing: .16em; text-transform: uppercase; color: var(--prt-pink-cta); margin: 0;
}
.prt-eyebrow--sage { color: var(--prt-sage-ink); }
.prt-eyebrow--pink { color: var(--prt-pink-ink); }
.prt-eyebrow--terracotta { color: var(--prt-terracotta-ink); }

/* Akapit prowadzacy */
.prt-lead {
  font-size: clamp(17px, 1.5vw, 20px); line-height: 1.55; font-weight: 500;
  color: var(--prt-text-muted); margin: 0;
}

/* Obraz wypelniajacy kadr — 8 wystapien w markupie strony glownej */
.prt-media-cover { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Karta kategorii: tekst i odnosnik */
.prt-card__title {
  margin: 0 24px; font-size: clamp(22px, 2vw, 28px); font-weight: 800; letter-spacing: -.02em;
}
.prt-card__desc {
  margin: 12px 24px 0; font-size: 14px; line-height: 1.5; font-weight: 500; color: var(--prt-text-muted);
}
.prt-card__link {
  display: flex; align-items: center; gap: 10px; margin-top: 14px; font-size: 15px; font-weight: 800;
}

/* Pasek korzysci w HERO */
.prt-usp__label { margin: 14px 0 0; font-size: 14px; font-weight: 700; }

/* Kolko social w stopce — 5 wystapien */
.prt-social {
  display: flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border-radius: 999px; background: var(--prt-navy); transition: background .2s ease;
}
.prt-social:hover { background: var(--prt-pink-cta); }

/* Pole formularza w pigulce — wyszukiwarka i newsletter */
.prt-input {
  border: 1.5px solid var(--prt-line); border-radius: var(--prt-radius-pill);
  padding: 10px 18px; font-family: var(--prt-font-sans); font-size: 15px; color: var(--prt-navy);
  background: var(--prt-surface); outline-offset: 3px;
}
.prt-input:focus-visible { outline: 3px solid var(--prt-pink-cta); }

/* === Panele (2026-09-12) === */
[data-use] { transition: transform .25s ease; }
[data-use-media] img { transition: transform .3s ease; }
[data-play] { transition: transform .25s ease, background .25s ease; }
[data-use]:focus-visible,
[data-video]:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 4px; }

@media (hover: hover) and (pointer: fine) {
  [data-cta-primary]:hover { background: var(--prt-pink-cta-hover) !important; color: #fff; transform: translateY(-2px); }
  [data-cta-outline]:hover { background: var(--prt-surface-pink); transform: translateY(-2px); }
  [data-use]:hover { transform: translateY(-3px); }
  [data-use]:hover [data-use-media] img { transform: scale(1.02); }
  [data-video]:hover [data-play] { transform: translate(-50%, -50%) scale(1.06); background: var(--prt-pink-cta-hover); }
}

/* Doodle HERO skalujemy, nie przesuwamy — `left` trzyma prawą krawędź 28 px przed kadrem. */
@media (max-width: 1279px) { [data-hero-doodle] { transform: scale(.9); } }
@media (max-width: 1120px) { [data-hero-doodle] { transform: scale(.82); top: 24% !important; } }
@media (max-width: 1023px) { [data-hero-doodle] { display: none !important; } }

@media (max-width: 1080px) {
  #prt-sec-panele-kroki [data-steps] { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  #prt-sec-panele-kroki [data-step-arrow] { display: none !important; }
}
@media (max-width: 900px) {
  [data-cta-spark] { right: -32px !important; top: -22px !important; width: 48px; height: 45px; }
  #prt-sec-panele-top [data-hero] { grid-template-columns: minmax(0, 1fr) !important; }
  #prt-sec-panele-top [data-hero-media] { height: 340px !important; }
  [data-video-grid] { grid-template-columns: minmax(0, 1fr) !important; }
}
@media (max-width: 820px) { [data-uses] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }
@media (max-width: 620px) {
  #prt-sec-panele-kroki [data-steps] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  #prt-sec-panele-kroki [data-steps] > div:last-child { grid-column: 1 / -1; }
}
@media (max-width: 440px) {
  #prt-sec-panele-kroki [data-steps] { grid-template-columns: minmax(0, 1fr) !important; }
  [data-uses] { grid-template-columns: minmax(0, 1fr) !important; }
}

@media (prefers-reduced-motion: reduce) {
  [data-use], [data-use-media] img, [data-play] { transition: none; }
  [data-cta-primary]:hover, [data-cta-outline]:hover,
  [data-use]:hover, [data-use]:hover [data-use-media] img,
  [data-video]:hover [data-play] { transform: none; }
}
/* === Centrum pomocy (2026-09-13) === */
[data-topic-arrow], [data-cat], [data-cat-wrap], [data-cat-cta], [data-chip] {
  transition: transform .2s ease, background .2s ease, border-color .2s ease, box-shadow .2s ease, color .2s ease;
}
[data-topic]:focus-visible,
[data-cat]:focus-visible,
[data-chip]:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 4px; }
/* Kafel kategorii jest jednym odnośnikiem — tekst w środku nie może różowieć razem z nim. */
[data-cat]:hover, [data-cat]:hover h3, [data-cat]:hover li, [data-cat]:hover p { color: var(--prt-text); }
[data-search] input::placeholder { color: var(--prt-text-muted); }
[data-search] input:focus { outline: 0; border-color: var(--prt-pink-cta) !important; }

@media (hover: hover) and (pointer: fine) {
  [data-chip]:hover { border-color: var(--prt-pink-cta); color: var(--prt-text); }
  [data-topic]:hover { transform: translateY(-2px); border-color: var(--prt-line-hover); box-shadow: 0 10px 24px rgba(16,27,84,0.06); }
  [data-topic]:hover [data-topic-arrow] { transform: translateX(4px); }
  [data-cat]:hover, [data-cat-wrap]:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(16,27,84,0.07); }
  [data-cat]:hover [data-cat-cta],
  [data-cat-wrap]:hover [data-cat-cta] { background: var(--prt-pink-cta) !important; border-color: var(--prt-pink-cta) !important; color: #fff !important; }
  [data-cat]:hover [data-cat-cta] svg path,
  [data-cat-wrap]:hover [data-cat-cta] svg path { stroke: #fff !important; }
}

@media (max-width: 1180px) {
  #prt-sec-sciezka [data-steps] { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; row-gap: 36px !important; }
  #prt-sec-sciezka [data-step-arrow] { display: none !important; }
}
@media (max-width: 960px) {
  [data-cats] { grid-template-columns: minmax(0, 1fr) !important; }
  [data-contact] { grid-template-columns: minmax(0, 1fr) !important; }
  [data-contact-art] { min-height: 240px !important; }
}
@media (max-width: 700px) {
  #prt-sec-sciezka [data-steps] { grid-template-columns: minmax(0, 1fr) !important; text-align: left !important; }
  #prt-sec-sciezka [data-steps] > div { display: flex !important; align-items: flex-start; gap: 16px; text-align: left !important; }
  #prt-sec-sciezka [data-step-icon] { margin: 0 !important; }
  [data-search] { flex-direction: column !important; align-items: stretch !important; border-radius: var(--prt-radius-card) !important; }
  [data-search] button { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  [data-topic-arrow], [data-cat], [data-cat-wrap], [data-cat-cta], [data-chip] { transition: none; }
  [data-topic]:hover, [data-cat]:hover, [data-cat-wrap]:hover,
  [data-topic]:hover [data-topic-arrow] { transform: none; }
}
/* === Rytm pionowy (2026-09-13) === */
/* Paczki oznaczają sekcje `data-section`; odstęp należy do systemu, nie do strony. */
[data-section] { padding-top: var(--prt-section-gap); }
[data-section-body] { padding-top: var(--prt-heading-gap); }

@media (max-width: 767px) {
  [data-section] { padding-top: var(--prt-section-gap-mobile); }
  [data-section-body] { padding-top: var(--prt-heading-gap-mobile); }
}
/* === Kolor odnosnikow w sekcjach (2026-09-13) === */
/* Motyw daje linkom niebieski (#3B82F6), a treść wewnątrz <a> go dziedziczy — tytuły
   kafli i pozycje list wychodziły na niebiesko. Prototypy resetują to regułą na `a`,
   którą pominąłem jako „sprawę motywu". Zakres ogranicza reset do naszych sekcji,
   żeby nie ruszać linków w reszcie serwisu. Kolory wpisane inline (białe CTA,
   wyszarzone opisy) wygrywają ze specyficznością i zostają nietknięte. */
[id^="prt-sec-"] a { color: var(--prt-text); text-decoration: none; }
[id^="prt-sec-"] a:hover { color: var(--prt-pink-cta); }

/* === Kontakt (2026-09-13) === */
/* Pola formularza: zakres na nasze sekcje, żeby nie ruszać formularzy WooCommerce. */
[id^="prt-sec-"] input,
[id^="prt-sec-"] select,
[id^="prt-sec-"] textarea { font-family: inherit; }
[id^="prt-sec-"] input::placeholder,
[id^="prt-sec-"] textarea::placeholder { color: var(--prt-text-placeholder); }
[id^="prt-sec-"] input:focus,
[id^="prt-sec-"] select:focus,
[id^="prt-sec-"] textarea:focus { outline: 0; border-color: var(--prt-pink-cta) !important; }

@media (max-width: 960px) {
  #prt-sec-kontakt-top [data-hero] { grid-template-columns: minmax(0, 1fr) !important; }
  #prt-sec-kontakt-formularz [data-form-grid] { grid-template-columns: minmax(0, 1fr) !important; }
}
@media (max-width: 560px) {
  #prt-sec-kontakt-formularz [data-name-row] { grid-template-columns: minmax(0, 1fr) !important; }
  #prt-sec-kontakt-top [data-hero-usp] { grid-template-columns: minmax(0, 1fr) !important; }
}

/* === Przewijanie poziome (2026-09-13) === */
/* Dekoracje (plamy, doodle) maja ujemne offsety i wystaja poza kontener 1280px.
   W pasmie ~1100-1440px wypychaly dokument i strona przewijala sie w poziomie —
   zmierzone na Kontakcie (1225px) i na stronie glownej (1248px przy oknie 1200).
   Kontenery sekcji maja pelna szerokosc okna, wiec przyciecie na nich odcina
   wylacznie to, co i tak jest poza ekranem; nic widocznego nie ginie.

   MUSI byc `clip`, nie `hidden`. Przy `hidden` druga os liczy sie jako `auto`,
   wiec kazda sekcja stawala sie wlasnym kontenerem przewijania i hero scrollowalo
   sie osobno od strony (zmierzone: scrollHeight 472 przy clientHeight 456).
   `clip` przycina bez tworzenia kontenera i zostawia os pionowa `visible`. */
[id^="prt-sec-"] { overflow-x: clip; }

@media (max-width: 440px) { #prt-sec-panele-top [data-hero-usp] { grid-template-columns: minmax(0, 1fr) !important; } }

/* === Klasy odbudowy natywnej (2026-09-13) === */
/* Instrukcja odsyla do tych klas jako "sa w site-settings-custom-css.css",
   ale paczka zadnej z nich nie definiuje. Bez nich plama jest niewidoczna,
   przypisy skleja sie z linkiem, a kropka w H1 nie jest rozowa. */
.prt-ink-pink { color: var(--prt-pink-cta); }
.prt-note { display: block; margin-top: 5px; font-size: 13px; font-weight: 500; color: var(--prt-text-muted); }
.prt-hero-art { position: relative; height: clamp(300px, 32vw, 400px); }
.prt-hero-blob { position: absolute; inset: -6% -10% -4% 4%; background: var(--prt-surface-pink-strong);
  border-radius: 46% 54% 48% 52% / 54% 46% 54% 46%; }
.prt-hero-art img { position: relative; width: 100%; height: 100%; object-fit: contain; }
.prt-tile { transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
@media (hover: hover) and (pointer: fine) {
  .prt-tile:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(16,27,84,.07);
    border-color: var(--prt-line-hover); }
}
/* ⚠️ Elementor 4.2.4 renderuje ikony Font Awesome jako inline SVG
   (`.e-font-icon-svg`), ale NIE dolacza do nich `fill: currentColor` — bez tej
   reguly kazda taka ikona jest czarna niezaleznie od ustawionego `color`.
   Sprawdzone: w `plugins/elementor/assets/css/frontend.min.css` jedyna regula
   dla tej klasy ustawia `height`. Reguła jest ogolna, bo dotyczy kazdego
   widgetu Icon i Icon List w serwisie. */
.e-font-icon-svg { fill: currentColor; }

/* Reset koloru odnosnikow obejmuje tez sekcje odbudowy (id bez prefiksu prt-sec-). */
#kontakt-hero a, #kontakt-formularz a, #kontakt-tematy a { color: var(--prt-text); }
#kontakt-hero a:hover, #kontakt-formularz a:hover, #kontakt-tematy a:hover { color: var(--prt-pink-cta); }

/* ==========================================================================
   Centrum pomocy — kategoria i artykul (2026-09-13)

   Selektory celuja w DOM widgetu **Posts z Elementora Pro** (`.elementor-post*`,
   `.elementor-pagination`). To nie jest przypadek: paczka projektowa napisala je
   pod ten widget, bo tylko on daje natywna paginacje na prawdziwych URL-ach
   (`paginate_links`). JetEngine nie ma paginacji w ogole, a JetSmartFilters
   renderuje pusty div i dobudowuje numery JavaScriptem — niewidoczne dla Google.
   Zmiana widgetu na inny wymaga przepisania wszystkich tych selektorow.
   ========================================================================== */

/* --- Pasmo HERO (kategoria i artykul dziela ten sam komponent) --- */
.prt-help-hero { position: relative; background: var(--prt-surface-pink-lightest); overflow: hidden; }
.prt-help-hero::before, .prt-help-hero::after {
  content: ""; position: absolute; border-radius: 50%;
  background: var(--prt-surface-pink-strong); pointer-events: none;
}
.prt-help-hero::before { width: 280px; height: 280px; left: -90px; top: -60px; }
.prt-help-hero::after  { width: 340px; height: 340px; right: -110px; bottom: -90px; }
.prt-help-hero > * { position: relative; z-index: 2; }

/* Okruszki Pomocy używają wspólnego `.prt-crumbs` — patrz niżej. */

/* --- Licznik wynikow (shortcode [prt_wyniki]) --- */
.prt-wyniki { font-size: 14px; font-weight: 700; color: var(--prt-text-muted); margin: 0; }

/* --- Karta artykulu — wspolna dla listingu i „Powiazanych artykulow" --- */
.prt-article-card .elementor-post {
  position: relative; display: flex; flex-direction: column;
  border: 1.5px solid var(--prt-line-card); border-radius: 16px; padding: 26px; background: #fff;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.prt-article-card .elementor-post__text { display: flex; flex-direction: column; flex: 1; }

/* Typografia karty — JEDNO zrodlo prawdy dla listingu i „Powiazanych artykulow".
   Wczesniej rozmiary siedzialy w ustawieniach widgetu Archive Posts, wiec Elementor
   generowal je tylko dla listingu. Karty powiazanych, renderowane shortcodem, spadaly
   na globalna typografie kitu (Montserrat 28/500 zamiast Nunito Sans 17/800).
   Potrojona klasa daje (0,5,0) i bije generowana regule widgetu (0,4,0).

   ⚠️ Selektor MUSI obejmowac takze `a` w srodku. Elementor generuje swoja regule
   na OBA elementy (`.elementor-post__title, .elementor-post__title a`), wiec
   stylowanie samego naglowka nic nie dawalo: link ma wlasna deklaracje, a ta bije
   dziedziczenie. Tytuly kart w listingu Pomocy szly przez to rozmiarem globalnego
   presetu „Primary" — czyli 58px, tyle co H1 hero. */
.prt-article-card.prt-article-card.prt-article-card .elementor-post__title,
.prt-article-card.prt-article-card.prt-article-card .elementor-post__title a {
  font-family: var(--prt-font-sans); font-size: 17px; font-weight: 800;
  line-height: 1.35; letter-spacing: -.01em; margin: 0;
}
.prt-article-card.prt-article-card.prt-article-card .elementor-post__excerpt,
.prt-article-card.prt-article-card.prt-article-card .elementor-post__excerpt p {
  font-family: var(--prt-font-sans); font-size: 14px; font-weight: 500;
  line-height: 1.55; color: var(--prt-text-muted);
}
.prt-article-card .elementor-post__excerpt { margin: 10px 0 0; }
.prt-article-card .elementor-post__excerpt p { margin: 0; }
.prt-article-card.prt-article-card.prt-article-card .elementor-post__read-more {
  font-family: var(--prt-font-sans); font-size: 14px; font-weight: 800; line-height: 1;
  margin-top: auto; padding-top: 18px;
}
/* Caly kafel klikalny: nakladka z tytulu. „Czytaj dalej" wychodzi nad nia z-indeksem,
   zeby nie powstal link w linku — czytniki ekranu czytaja taki uklad dwa razy. */
.prt-article-card .elementor-post__title a::after { content: ""; position: absolute; inset: 0; }
.prt-article-card .elementor-post__title a { color: var(--prt-navy); }
.prt-article-card .elementor-post__read-more {
  margin-top: auto; position: relative; z-index: 1;
  color: var(--prt-pink-cta); font-weight: 800; font-size: 14px;
  display: inline-flex; align-items: center;
}
/* Strzalka jako maska na currentColor — bez zaleznosci od wgranego pliku SVG. */
.prt-article-card .elementor-post__read-more::after {
  content: ""; display: inline-block; width: 17px; height: 11px; margin-left: 9px;
  background: currentColor; transition: transform .2s ease;
  -webkit-mask: var(--prt-strzalka) center/contain no-repeat;
          mask: var(--prt-strzalka) center/contain no-repeat;
}
@media (hover: hover) and (pointer: fine) {
  .prt-article-card .elementor-post:hover {
    transform: translateY(-2px); border-color: var(--prt-line-hover);
    box-shadow: 0 10px 24px rgba(16,27,84,.06);
  }
  .prt-article-card .elementor-post:hover .elementor-post__read-more::after { transform: translateX(4px); }
}
.prt-article-card .elementor-post__title a:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }
@media (max-width: 820px) { .prt-article-card .elementor-posts { grid-template-columns: minmax(0,1fr) !important; } }

/* --- Paginacja natywna (Posts → Numbers + Previous/Next) --- */
/* Kontener musi byc flexem — Elementor daje mu `text-align: center`, co dziala
   tylko na elementy liniowe. */
.prt-pagination .elementor-pagination {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 9px;
}
/* `inline-flex`, NIE `flex`: `display: flex` czyni element blokowym, wiec kazdy numer
   zajmowal cala szerokosc kolumny i strony ustawialy sie jedna pod druga.
   Marginesy zerujemy, bo Elementor generuje wlasne `margin: calc(42px/2)` z kontrolki
   odstepu i sumowalyby sie z `gap`. */
/* Odstep od siatki kart. Zerujac marginesy miedzy numerami (wyzej) skasowalismy
   tez ten odstep — stad jawny margin-top. */
.prt-pagination .elementor-pagination { margin-top: 42px; }
@media (max-width: 767px) { .prt-pagination .elementor-pagination { margin-top: 30px; } }

/* Rozmiar i krój MUSZA byc na samym numerze. Elementor ustawia je na kontenerze
   `.elementor-pagination` z globalnej typografii „Secondary" (Montserrat 34 px),
   a numery dziedziczyly to bez zmian — cyfry wychodzily w rozmiarze naglowka.
   Kolor nieaktywnych to `--prt-text-muted`, nie granat linku: paginacja jest
   nawigacja pomocnicza i nie ma konkurowac z tytulami kart. */
.prt-pagination .page-numbers {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 42px; height: 42px; padding: 0 12px; margin: 0 !important;
  border: 1.5px solid var(--prt-line-card); border-radius: 12px;
  font-family: var(--prt-font-sans); font-size: 15px; font-weight: 700; line-height: 1;
  color: var(--prt-text-muted); transition: border-color .2s ease, color .2s ease;
}
.prt-pagination .page-numbers.current { font-size: 15px; font-weight: 800; }
@media (hover: hover) and (pointer: fine) {
  .prt-pagination a.page-numbers:hover { color: var(--prt-navy); }
}
.prt-pagination .page-numbers.current { background: var(--prt-pink-cta); color: #fff; border-color: var(--prt-pink-cta); font-weight: 800; }
.prt-pagination .page-numbers.dots { border-color: transparent; }
@media (hover: hover) { .prt-pagination a.page-numbers:hover { border-color: var(--prt-pink-cta); } }
.prt-pagination a.page-numbers:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }

/* --- Nawigacja kategorii — sticky, chipy na tablecie --- */
.prt-help-nav .current-menu-item a, .prt-help-nav [aria-current="page"] { font-weight: 800; }
@media (max-width: 1000px) {
  .prt-help-nav .elementor-nav-menu { display: flex; flex-wrap: wrap; gap: 10px; }
  .prt-help-nav .elementor-nav-menu > li { flex: 1 1 auto; }
}

/* --- Tresc artykulu (widget Post Content z klasa prt-prose) --- */
/* Specyficznosc celowo podbita piecioma klasami. Elementor wymusza
   `.elementor.elementor .e-con > .elementor-widget { max-width:100% }` (cztery klasy),
   wiec samo `.prt-prose` przegrywa i kolumna rozlewa sie na pelne 1280 px.
   Natywna kontrolka szerokosci widgetu tego nie zalatwia — stad regula tutaj.

   `min(700px, 100%)`, nie samo `700px`: nadpisujac regule Elementora skasowalismy
   jednoczesnie jego ograniczenie do 100%, wiec przy waskim oknie kolumna rozciagala sie
   do minimalnej szerokosci tabeli (460 px przy oknie 360) i rozpychala dokument. */
.elementor.elementor .e-con > .elementor-widget.prt-prose { max-width: min(700px, 100%); }
.prt-prose { max-width: min(700px, 100%); }
.prt-prose p { font-size: 17px; line-height: 1.7; font-weight: 500; color: var(--prt-text-muted); margin: 16px 0 0; }
.prt-prose h2 { font-size: clamp(22px,2.2vw,29px); line-height: 1.15; font-weight: 800; letter-spacing: -.022em; color: var(--prt-navy); margin: clamp(34px,3.6vw,46px) 0 0; }
.prt-prose h3 { font-size: clamp(18px,1.7vw,22px); font-weight: 800; letter-spacing: -.018em; color: var(--prt-navy); margin: clamp(26px,2.6vw,32px) 0 0; }
.prt-prose h2:first-child { margin-top: 0; }
.prt-prose strong { font-weight: 800; color: var(--prt-navy); }
.prt-prose a { color: var(--prt-pink-cta); font-weight: 700; }
.prt-prose a:hover { text-decoration: underline; }

/* --- Callout „Zapamietaj" — jeden na artykul --- */
.prt-callout { background: var(--prt-surface-blue); border-radius: 18px; padding: clamp(22px,2.4vw,30px); margin: clamp(28px,3vw,38px) 0 0; }
.prt-callout__label { font-size: 14px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--prt-blue-ink); margin: 0; }
.prt-callout p { font-size: 16px; line-height: 1.6; font-weight: 600; color: var(--prt-navy); margin: 12px 0 0; }

/* --- Tabela w tresci — semantyczna <table> --- */
.prt-table { width: 100%; border-collapse: separate; border-spacing: 0; border: 1.5px solid var(--prt-line-card); border-radius: 18px; overflow: hidden; margin: clamp(22px,2.4vw,30px) 0 0; }
.prt-table th { text-align: left; background: var(--prt-surface-grey); font-size: 13px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--prt-text-muted); padding: 15px 22px; }
.prt-table td { font-size: 15px; line-height: 1.5; padding: 16px 22px; border-top: 1.5px solid var(--prt-line-card); }
.prt-table td:first-child { font-weight: 600; color: var(--prt-text-muted); }
.prt-table td:last-child { font-weight: 800; color: var(--prt-navy); width: 130px; }
@media (max-width: 560px) { .prt-table th, .prt-table td { padding: 13px 16px; } }

/* --- Spis tresci (widget Table of Contents z klasa prt-toc) --- */
.prt-toc .elementor-toc__list-wrapper { border-left: 2px solid var(--prt-line-soft) !important; padding-left: 18px; margin: 0; }
.prt-toc .elementor-toc__list-item-text-wrapper { font-weight: 600; }
.prt-toc .elementor-item-active .elementor-toc__list-item-text { font-weight: 700; color: var(--prt-navy); }

/* --- Ocena przydatnosci (shortcode [prt_ocena]) --- */
.prt-helpful { max-width: 700px; border: 1.5px solid var(--prt-line-card); border-radius: 18px; padding: clamp(22px,2.4vw,28px); display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-top: clamp(34px,3.6vw,48px); }
.prt-helpful__q { font-size: 16px; font-weight: 800; color: var(--prt-navy); margin: 0; }
.prt-helpful__akcje { display: flex; gap: 10px; flex-wrap: wrap; }
.prt-helpful button { display: flex; align-items: center; gap: 9px; background: #fff; border: 1.5px solid var(--prt-line-card); border-radius: var(--prt-radius-pill); padding: 12px 22px; font-family: var(--prt-font-sans); font-size: 14px; font-weight: 800; color: var(--prt-navy); cursor: pointer; transition: border-color .2s ease, background .2s ease; }
.prt-helpful button[disabled] { opacity: .55; cursor: default; }
@media (hover: hover) and (pointer: fine) { .prt-helpful button:not([disabled]):hover { border-color: var(--prt-pink-cta); background: var(--prt-surface-pink-lightest); } }
.prt-helpful button:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }
/* Nota lamie sie do wlasnego wiersza — inaczej przy space-between ladowalaby obok przyciskow. */
.prt-helpful__note { flex: 1 0 100%; font-size: 13px; font-weight: 600; color: var(--prt-text-muted); margin: 12px 0 0; }

/* --- Wylaczenie ruchu na zyczenie systemu --- */
@media (prefers-reduced-motion: reduce) {
  .prt-article-card .elementor-post, .prt-btn-primary, .prt-btn-pill, .prt-btn-outline { transition: none; }
  .prt-article-card .elementor-post:hover, .prt-btn-primary:hover, .prt-btn-pill:hover, .prt-btn-outline:hover { transform: none; }
}

/* --- Uklad dwukolumnowy: nawigacja/spis tresci + kolumna glowna ---
   UWAGA na strukture: kontener Boxed renderuje sie jako
   `.e-con > .e-con-inner > dzieci`, wiec kolumny NIE sa bezposrednimi dziecmi
   elementu z id. Selektor bez `.e-con-inner` nie trafia w nic.
   Kontener Elementora z Content Width = Full dostaje `width: 100%`. W rodzicu
   ustawionym na Row oznacza to, ze kolumna glowna bierze CALA szerokosc rodzica
   (1280 px), a `flex-grow` dokłada do tego jeszcze raz — dokument rozpychal sie
   o 276 px i strona przewijala sie w poziomie na kazdej szerokosci >= 820 px.
   `flex: 1 1 0%` + `min-width: 0` sprawia, ze kolumna liczy sie od zera i bierze
   wylacznie to, co zostalo. `min-width: 0` jest konieczne osobno: domyslne
   `min-width: auto` na elemencie flex nie pozwala mu zwezic sie ponizej tresci. */
#pomoc-listing > .e-con-inner > .e-con,
#artykul-tresc > .e-con-inner > .e-con { min-width: 0; }
#pomoc-listing > .e-con-inner > .e-con:first-child,
#artykul-tresc > .e-con-inner > .e-con:first-child { flex: 0 0 250px; width: 250px; }
#pomoc-listing > .e-con-inner > .e-con:last-child,
#artykul-tresc > .e-con-inner > .e-con:last-child { flex: 1 1 0%; width: auto; }

/* Ponizej 1000 px kolumna boczna przestaje byc sticky i rozklada sie na pelna
   szerokosc. Spis tresci idzie NAD tresc — czytelnik na telefonie ma zobaczyc
   mape artykulu, zanim zacznie go czytac, a nie po. */
@media (max-width: 1000px) {
  /* Przelaczenie na pion robimy TUTAJ, nie kontrolka „Direction: Tablet".
     Elementor liczy tablet od 1024 px, a projekt lamie uklad na 1000 px; poleganie
     na cudzym breakpoincie dawalo wiersz, w ktorym kolumna glowna zapadala sie do 0 px. */
  #pomoc-listing > .e-con-inner,
  #artykul-tresc > .e-con-inner { flex-direction: column; }
  /* `:first-child`/`:last-child` sa tu konieczne: regula desktopowa ma je w selektorze,
     wiec bez nich ta ma NIZSZA specyficznosc i nie nadpisuje szerokosci 250 px
     — niezaleznie od kolejnosci w pliku. */
  #pomoc-listing > .e-con-inner > .e-con:first-child,
  #pomoc-listing > .e-con-inner > .e-con:last-child,
  #artykul-tresc > .e-con-inner > .e-con:first-child,
  #artykul-tresc > .e-con-inner > .e-con:last-child {
    position: static; flex: 0 1 auto; width: 100%;
  }
  #artykul-tresc > .e-con-inner > .e-con:first-child { order: -1; }
}

/* --- Wysrodkowanie blokow w pasmie HERO ---
   Kontrolka Margin w Elementorze nie przyjmuje `auto`, wiec blok naglowka o stalej
   szerokosci (620 px na kategorii, 760 px w artykule) przyklejal sie do lewej krawedzi
   pasma. Okruszki i wyszukiwarka to widgety, nie kontenery, wiec ta regula ich nie rusza
   — a okruszki maja z projektu byc wlasnie przy lewej krawedzi. */
#pomoc-hero .e-con-inner > .e-con,
#artykul-hero .e-con-inner > .e-con { margin-inline: auto; }

/* --- Wyszukiwarka (widget Search Form, skin Classic) ---
   Zadne z ustawien wygladu tego widgetu nie da sie ustawic tak, zeby odpowiadalo
   projektowi: skin Classic renderuje `form > .elementor-search-form__container`
   jako blok, bez odstepu miedzy polem a przyciskiem i bez ikony lupy. Styl w calosci
   tutaj — to samo zalecenie daje instrukcja odbudowy w paczce.

   Selektory celowo zawieraja `input`/`button`: arkusz widgetu ma
   `.elementor-search-form input[type="search"] { border-color: currentcolor; padding: 0 }`,
   czyli dwie klasy + element + atrybut. Sama para klas przegrywa z tym mimo pozniejszego
   ladowania, a `border-color: currentcolor` przy granatowym tekscie dawal granatowa ramke
   zamiast jasnej linii z projektu.

   `.prt-search.prt-search` to nie literowka, tylko celowe podbicie wagi. Elementor
   generuje dla widgetu regule
   `.elementor-6213 .elementor-element.elementor-element-pkszuk .elementor-search-form__input
    { padding-left: calc(50px / 3) }`
   — cztery klasy. Bez zdublowanej klasy poziomy padding zostawal na 16,6667 px
   niezaleznie od tego, co wpiszemy tutaj.

   Przycisk potrzebuje JESZCZE jednego powtorzenia, bo jego selektor w generowanym CSS
   ma piec klas: `...-pkszuk.elementor-search-form--button-type-text .elementor-search-form__submit`.
   Natywna kontrolka tego nie zalatwia: jedna wartosc `size` ustawia naraz min-height,
   min-width przycisku i poziomy padding jako `size / 3`, wiec nie da sie nia wyrazic
   projektu (pole 14/22/14/48, przycisk 15/30 przy wysokosci 50). */
.prt-search .elementor-search-form { max-width: 620px; margin-inline: auto; }
.prt-search.prt-search .elementor-search-form__container {
  display: flex; gap: 12px; align-items: stretch; background: transparent; border: 0; padding: 0;
}
.prt-search.prt-search .elementor-search-form input.elementor-search-form__input {
  flex: 1 1 auto; min-width: 0;
  background: #fff no-repeat 20px center; background-size: 18px 18px;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%233A4478" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>');
  border: 1.5px solid var(--prt-line-card); border-radius: var(--prt-radius-pill);
  padding: 14px 22px 14px 48px;
  font-family: var(--prt-font-sans); font-size: 15px; font-weight: 600; color: var(--prt-navy);
  transition: border-color .2s ease;
}
.prt-search.prt-search .elementor-search-form input.elementor-search-form__input::placeholder { color: var(--prt-text-placeholder); opacity: 1; }
.prt-search.prt-search .elementor-search-form input.elementor-search-form__input:focus { border-color: var(--prt-pink-cta); outline: none; }
.prt-search.prt-search.prt-search .elementor-search-form button.elementor-search-form__submit {
  flex: 0 0 auto; background: var(--prt-pink-cta); color: #fff; border: 0;
  border-radius: var(--prt-radius-pill); padding: 15px 30px;
  font-family: var(--prt-font-sans); font-size: 15px; font-weight: 800; cursor: pointer;
  transition: background .2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .prt-search.prt-search.prt-search .elementor-search-form button.elementor-search-form__submit:hover { background: var(--prt-pink-cta-hover); }
}
.prt-search.prt-search .elementor-search-form input.elementor-search-form__input:focus-visible,
.prt-search.prt-search.prt-search .elementor-search-form button.elementor-search-form__submit:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }
/* Ponizej 700 px pole i przycisk jeden pod drugim — inaczej na telefonie
   na tekst w polu zostaje kilkanascie pikseli. */
@media (max-width: 700px) {
  .prt-search.prt-search .elementor-search-form__container { flex-direction: column; }
  .prt-search.prt-search .elementor-search-form input.elementor-search-form__input { border-radius: 20px; }
  .prt-search.prt-search.prt-search .elementor-search-form button.elementor-search-form__submit { width: 100%; }
}

/* --- Powiazane artykuly ---
   Siatka trzykolumnowa; karty biora styl z bloku `.prt-article-card` wyzej,
   bo shortcode wypisuje te same klasy co widget Posts. */
.prt-powiazane { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
@media (max-width: 1000px) { .prt-powiazane { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .prt-powiazane { grid-template-columns: minmax(0, 1fr); } }

/* Link „Wszystkie z kategorii …" w wierszu naglowka sekcji */
.prt-wszystkie-z {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 800; color: var(--prt-navy); white-space: nowrap;
}
/* Dluzsze nazwy kategorii („Zamowienia i dostawa") nie mieszcza sie w jednej linii
   na telefonie — `nowrap` rozpychal wtedy dokument o 23 px. Powyzej 700 px etykieta
   i tak sie miesci, wiec nowrap zostaje tam, gdzie wyglada lepiej. */
@media (max-width: 700px) { .prt-wszystkie-z { white-space: normal; } }
.prt-wszystkie-z__strzalka {
  width: 17px; height: 11px; background: var(--prt-pink-cta);
  -webkit-mask: var(--prt-strzalka) center/contain no-repeat;
          mask: var(--prt-strzalka) center/contain no-repeat;
  transition: transform .2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .prt-wszystkie-z:hover { color: var(--prt-pink-cta); }
  .prt-wszystkie-z:hover .prt-wszystkie-z__strzalka { transform: translateX(4px); }
}

/* --- Przycisk w widgecie Button Elementora ---
   `_css_classes` sadzi klase na OPAKOWANIU widgetu, nie na `<a>`. Klasa `.prt-btn-primary`
   nalozona wprost na widget dawala rozowy prostokat na cala szerokosc kolumny, a prawdziwy
   link w srodku zostawal nieostylowany. Dlatego osobna klasa, ktora celuje w `<a>`. */
.prt-btn-widget .elementor-button-wrapper { display: flex; }
.prt-btn-widget .elementor-button {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--prt-pink-cta); color: #fff;
  font-family: var(--prt-font-sans); font-size: 16px; font-weight: 800; line-height: 1.2;
  /* ⚠️ POZIOMY PADDING ZWEZA SIE NA WASKICH EKRANACH, i to jest cala poprawka.
     Zmierzone przez FreeAgenta na 390 px: „Otworz formularz" lamal sie na dwie linie
     (przycisk 218×76). Kolumna ma 218 px, a 32 + 32 paddingu, 16 ikona, 12 gap i ~150
     tekstu daje ~242. Przy 18 px paddingu wychodzi ~214 i napis mieci sie w jednej linii.

     ⚠️ CELOWO BEZ `white-space: nowrap`, choc to byla pierwsza propozycja. `nowrap`
     naprawia dzisiejszy napis, a przy dluzszym — albo po niemiecku — kazalby przyciskowi
     wyjsc poza kolumne zamiast sie zlamac. Zawijanie zostaje jako zawor bezpieczenstwa;
     usuwamy tylko powod, dla ktorego dzis sie wlacza. */
  padding: 19px clamp(18px, 4vw, 32px); border-radius: var(--prt-radius-pill); border: 0;
  transition: background .2s ease, transform .2s ease;
}
.prt-btn-widget .elementor-button:hover { color: #fff; }
@media (hover: hover) and (pointer: fine) {
  .prt-btn-widget .elementor-button:hover { background: var(--prt-pink-cta-hover); transform: translateY(-2px); }
}
.prt-btn-widget .elementor-button:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }

/* --- Spis tresci: wylaczamy wlasny naglowek i ramke widgetu ---
   Widget renderuje naglowek „Table of Contents" (159 px wysokosci) w ramce, mimo ze
   nad nim stoi juz nasze „W TYM ARTYKULE". Kontrolki stylu pudelka nie potrafia go
   usunac, moga tylko przemalowac. */
.prt-toc .elementor-toc__header { display: none !important; }
/* Ramka siedzi na KORZENIU widgetu (`.elementor-element`), nie na wewnetrznych
   kontenerach — celowanie w `.elementor-widget-container` jej nie dotykalo.
   Zostawiamy ja, ale w tokenach Printelli zamiast domyslnej szarosci Elementora,
   i z paddingiem, zeby tekst nie dotykal krawedzi. */
.prt-toc.elementor-element {
  border: 1.5px solid var(--prt-line-card) !important;
  border-radius: 18px !important;
  background: #fff !important;
  padding: clamp(20px, 2vw, 26px) !important;
}
.prt-toc .elementor-toc__body {
  border: 0 !important; background: transparent !important; padding: 0 !important;
  min-height: 0 !important; max-height: none !important; overflow: visible !important;
}

/* --- Pasmo kontaktu (Saved Section, wspolne dla obu szablonow) --- */
.prt-kontakt-panel { position: relative; }
@media (max-width: 820px) {
  .prt-kontakt-tango { display: none !important; }
}

/* Tabela w tresci artykulu przewija sie sama, nie ciagnie za soba strony.
   `min-width` trzyma kolumny czytelne; ponizej tej szerokosci pojawia sie
   poziomy pasek WEWNATRZ ramki, a dokument zostaje bez scrolla. */
.prt-table-scroll { max-width: 100%; overflow-x: auto; margin: clamp(22px,2.4vw,30px) 0 0; -webkit-overflow-scrolling: touch; }
.prt-table-scroll .prt-table { margin-top: 0; min-width: 460px; }


/* ===================================================================
   USLUGI GRAFICZNE  (/uslugi-graficzne/)
   Landing czterech uslug. Instrukcja: handoff „odbudowa-natywna-uslugi-graficzne”.

   ⚠️ PODZIAL ODPOWIEDZIALNOSCI — nie mieszac. Ten blok trzyma WYLACZNIE wyglad:
   tla, kolory, dekoracje, typografie wewnatrz widgetow. Uklad kontenerow
   (kierunek, odstepy, szerokosci, paddingi) siedzi w bloku „USLUGI GRAFICZNE —
   UKLAD KONTENEROW” na koncu pliku i musi byc pisany zmiennymi Elementora.
   Wczesniej te same kontenery byly stylowane w obu miejscach zwyklymi
   wlasciwosciami i reguly po cichu sie znosily.
   =================================================================== */

/* Hero tej strony ma WLASNY wariant klasy, a nie wspoldzieli `.prt-hero-art`.
   Tamten (uzywany przez strone glowna) ma sztywna wysokosc clamp(300px,32vw,400px)
   i osobny element `.prt-hero-blob` o organicznym ksztalcie. Tutaj dekoracja to
   okragly `::before` na kontenerze, a wysokosc wynika z tresci — nadpisanie
   wspolnej klasy przestawiloby hero na stronie glownej. */
/* ⚠️ Ksztalt ORGANICZNY, nie kolo — mimo ze prototyp tej podstrony rysowal
   `border-radius: 50%`. Serwis ma wlasna konwencje plamy w hero (strona glowna:
   `border-radius: 48% 52% 46% 54%/52% 44% 56% 48%`, patrz `.prt-hero-blob`)
   i okragla plama odstawala od reszty. Decyzja swiadoma: spojnosc serwisu
   wygrywa z prototypem pojedynczej strony. */
/* ⚠️ `position: relative` MUSI byc tu jawnie. Na `/uslugi-graficzne/` ta klasa
   siedzi na kontenerze Elementora, ktory ma relative domyslnie — ale na
   `/uslugi-graficzne/wycena/` na zwyklym `div` w widgecie HTML. Bez tego plama
   ponizej zaczepia sie o dalszego przodka i ucieka poza ekran (zmierzone:
   scrollWidth 1475 przy viewport 1440). */
.prt-hero-art--uslugi { position: relative; }
.prt-hero-art--uslugi::before {
  content: ""; position: absolute; right: -9%; top: -1%;
  width: 82%; padding-top: 78%;
  border-radius: 48% 52% 46% 54% / 52% 44% 56% 48%;
  background: var(--prt-surface-pink-strong); pointer-events: none;
}
.prt-hero-art--uslugi > * { position: relative; z-index: 2; }

/* ⚠️ Ponizej 1080 px art schodzi POD tekst i traci pozycjonowanie absolutne.
   Trzy rzeczy, ktore ten blok zalatwia i ktore latwo zepsuc:
   1. NIE dawac `order: -1` — inaczej pierwszy ekran to sam pies bez naglowka.
   2. Kula znika: jest procentem szerokosci kolumny, ktora w jednej kolumnie
      robi sie ~2,4x szersza i przestaje sie miescic.
   3. Notki Kalam wracaja do przeplywu — inaczej ladują na siersci psa.
   Breakpoint jest ZAPYTANIEM MEDIA, nie ustawieniem Elementora: viewport_laptop
   na tym serwisie wynosi 1440 i uzywa go 11 szablonow (naglowek, obie stopki,
   Pomoc, Panele, Kontakt), wiec przestawienie go na 1080 przesunuloby ich uklad. */
@media (max-width: 1080px) {
  .prt-hero-art--uslugi::before { display: none; }
  .prt-hero-art--uslugi img {
    max-height: clamp(220px,34vw,320px); max-width: min(480px, 100%);
    object-fit: contain; object-position: center; margin: 0 auto;
  }
  .prt-hero-art--uslugi .elementor-widget-heading {
    position: static !important; max-width: 340px !important;
    transform: none !important; text-align: center;
  }
}

/* --- Karty uslug --------------------------------------------------- */
.prt-svc { transition: transform .25s ease, box-shadow .25s ease; }
.prt-svc--jakosc  { background: var(--prt-surface-blue);   --ink: #0972B5; }
.prt-svc--korekta { background: var(--prt-surface-pink);   --ink: #C22765; }
.prt-svc--zmiany  { background: var(--prt-surface-sage);   --ink: #3F6420; }
.prt-svc--projekt { background: var(--prt-surface-beige);  --ink: #8A4A0C; }

/* Jedna zmienna `--ink` na karcie zamiast ustawiania koloru w trzech widgetach
   razy cztery karty. Kazdy z tych kolorow ma >=4.5:1 na wlasnym tincie. */
.prt-svc .prt-eyebrow,
.prt-svc .elementor-icon-list-icon svg,
.prt-svc .elementor-icon-list-icon i { color: var(--ink); fill: var(--ink); }

/* ⚠️ Byly tu `min-height: 168px` na `__head` i `124px` na `__list`, zeby
   wyrownac grafiki miedzy kartami. Zmierzone na zywo: wszystkie cztery karty
   maja naturalnie head 120 px i list 135 px — wyrownanie nic nie wnosilo,
   a wymuszone 168 px dokladalo 48 px pustki nad kazda grafika. Usuniete.
   Jesli ktorys lead urosnie do trzech linii, grafiki w rzedzie sie rozjada;
   wtedy skrocic tekst, a nie wracac do sztywnej wysokosci. */

/* Grafiki „przed -> po” leza wprost na tincie: PNG maja alfe i NIE dostaja tla. */
.prt-svc__media img { width: 100%; aspect-ratio: 2 / 1; object-fit: contain; }

.prt-svc__price { margin: 0; font-size: 16px; font-weight: 700; color: var(--prt-text-muted); }
.prt-svc__price strong { font-size: clamp(24px,2.2vw,30px); font-weight: 900; color: var(--prt-navy); letter-spacing: -.02em; }

/* CTA karty: pelny przycisk w kolorze `--ink` tej karty, nie goly link.
   ⚠️ Celowac w `<a>`, nie w widget — `_css_classes` sadzi klase na OPAKOWANIU
   widgetu, wiec regula nalozona na widget pomalowalaby prostokat na cala
   szerokosc kolumny, a link w srodku zostalby nieostylowany. Ten sam wzorzec
   co `.prt-btn-widget` wyzej, tylko w mniejszym rozmiarze — przycisk stoi
   w jednym wierszu z cena. */
.prt-svc__foot .elementor-button {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--ink); color: #fff;
  font-size: 14px; font-weight: 800; line-height: 1.2;
  padding: 13px 22px; border-radius: var(--prt-radius-pill); border: 0;
  transition: filter .2s ease, transform .2s ease;
}
.prt-svc__foot .elementor-button:hover,
.prt-svc__foot .elementor-button:visited { color: #fff; }
@media (hover: hover) and (pointer: fine) {
  .prt-svc__foot .elementor-button:hover { filter: brightness(1.14); transform: translateY(-2px); }
}

/* Karta NIE jest linkiem — klikalne jest tylko CTA. Zadnego `::after{inset:0}`,
   bo cena i przycisk przestalyby byc osiagalne osobno. */
@media (hover: hover) and (pointer: fine) {
  .prt-svc:hover { transform: translateY(-3px); box-shadow: var(--prt-shadow-hover); }
}
@media (max-width: 620px) {
  .prt-svc__foot .elementor-button { width: 100%; justify-content: center; }
}

/* --- „Jak to dziala?” ---------------------------------------------- */
/* Strzalka tylko PO krokach 1-3. `:not(:last-child)` zalatwia brak strzalki
   w czwartym kroku bez osobnej klasy. Maska jako data URI, a nie plik
   w uploads — nie ma czego wgrywac i nie zniknie przy porzadkach w mediach. */
.prt-step:not(:last-child)::after {
  content: ""; position: absolute; right: -16px; top: 26px;
  width: 18px; height: 12px; background: var(--prt-pink-cta);
  -webkit-mask: var(--prt-arrow) center/contain no-repeat;
  mask: var(--prt-arrow) center/contain no-repeat;
}
@media (max-width: 920px) { .prt-step::after { display: none !important; } }

/* Numerek w rogu kolka jest pozycjonowany wzgledem kolka, wiec kolko MUSI
   zostac `relative` — `.e-con` ma to domyslnie, ale zapisane wprost, zeby
   przypadkowa zmiana `--position` w buildera tego nie zdjela. */
.prt-step__icon { position: relative; background: var(--prt-surface-pink-icon); }
.prt-step__icon .elementor-icon { color: var(--prt-pink-cta); }
.prt-step__n { position: absolute; left: -6px; top: -6px; z-index: 2; }
.prt-step__n p, .prt-step__n span {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin: 0; border-radius: var(--prt-radius-pill);
  background: #fff; font-size: 13px; font-weight: 900; line-height: 1;
}
.prt-step__t p { margin: 0; max-width: 170px; font-size: 14px; font-weight: 700; color: var(--prt-navy); }

/* --- Kafel „dropzone” w pasmie wyceny ------------------------------ */
/* ⚠️ To NIE jest dzialajacy upload, tylko link na /uslugi-graficzne/wycena/.
   Prawdziwy upload istnieje w jednym miejscu: w formularzu wyceny. */
.prt-dropzone {
  background: rgba(255,255,255,.72); border: 2px dashed var(--prt-line-pink);
  transition: border-color .2s ease, background .2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .prt-dropzone:hover { border-color: var(--prt-pink-cta); background: #fff; }
}
.prt-dropzone__formats { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.prt-dropzone__formats span { background: #fff; border-radius: 8px; padding: 7px 12px; font-size: 12px; font-weight: 800; color: var(--prt-text-muted); }
.prt-dropzone__t p { margin: 0; font-size: 17px; font-weight: 800; color: var(--prt-navy); }
.prt-dropzone__s p { margin: 4px 0 0; font-size: 14px; font-weight: 600; color: var(--prt-text-muted); }

@media (prefers-reduced-motion: reduce) {
  .prt-svc, .prt-dropzone, .prt-svc__foot .elementor-button { transition: none; }
  .prt-svc:hover, .prt-svc__foot .elementor-button:hover { transform: none; }
}

/* --- Breadcrumb ---------------------------------------------------- */
/* Tekstem, bo serwis nie ma Yoasta ani Rank Matha (jest The SEO Framework,
   ktorego widget Breadcrumbs Elementora nie obsluguje). Zapas przewidziany
   wprost w instrukcji odbudowy. Wyrownanie do LEWEJ krawedzi tresci idzie
   przez `--text-align` na kontenerze (blok ukladu), tu tylko sam akapit. */
/* Okruszki — JEDNA definicja na cały serwis (Pomoc, tkaniny, Usługi, Wycena).
   Markup składa `Printella_Okruszki::render()`; odstęp 9px i kolory są z paczki
   projektowej (`.prt-breadcrumbs`).
   ⚠️ Odstęp robi WYŁĄCZNIE `gap` — nie dokładać marginesów na separatorze.
   Wcześniej `.prt-crumbs span { margin: 0 6px }` sumowało się z `gap: 9px`
   z nadpisania na karcie tkaniny i dawało tam 30px zamiast 9px.
   ⚠️ Krój ustawiamy WPROST, razem z `inherit` na dzieciach. Bez tego okruszki
   dziedziczą go z kontekstu: na czterech stronach wychodził Montserrat
   z globalnej typografii kitu, a w widgecie text-editor na Usługach graficznych
   Nunito Sans — ta sama ścieżka w dwóch krojach. Projekt mówi Nunito Sans. */
.prt-crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; margin: 0; text-align: left; font-family: var(--prt-font-sans); font-size: 13px; line-height: 1.4; font-weight: 600; color: var(--prt-text-muted); }
.prt-crumbs a,
.prt-crumbs span { font-family: inherit; }
.prt-crumbs a { color: var(--prt-text-muted); text-decoration: none; }
.prt-crumbs a:hover { color: var(--prt-pink-cta); }
.prt-crumbs__sep { color: var(--prt-line-arrow); }
/* Stopien biezacy. Celowo po klasie, a nie po `<strong>` ani `[aria-current]`:
   separator tez jest `<span>`, a stopien srodkowy bez adresu ma zostac w kolorze
   pozostalych stopni (handoff kreatora, pkt 11). */
.prt-crumbs__teraz { font-weight: 700; color: var(--prt-navy); }

/* --- Notki odreczne ------------------------------------------------ */
/* OBIE wyrownane do gory (top 2%) — to swiadoma decyzja projektowa, nie
   przypadek. Kalam wylacznie tutaj, nigdy w naglowkach ani UI.
   Jeden styl dla wszystkich notek w serwisie (handoff kreatora, pkt 10):
   Kalam 400 w granacie, bez pogrubienia i bez kolorow akcentowych. */
.prt-uslugi-note { position: absolute; z-index: 3; }
/* ⚠️ Celowac w `.elementor-heading-title`, NIE w `h2`. Kit ma globalna
   typografie naglowkow pod selektorem `.elementor-widget-heading
   .elementor-heading-title` (0,2,0); `.prt-uslugi-note h2` to 0,1,1 i przegrywa
   — notki dostawaly wtedy rozmiar naglowka H2 i zaslanialy cale hero.
   Sam `.prt-uslugi-note` jest tu rowniez celem, a nie tylko rodzicem: Wycena
   grafiki renderuje notke jako `<p class="prt-uslugi-note--l">` z tekstem
   bezposrednio w elemencie, wiec reguly na potomkach jej nie dosiegaly
   i notka szla goly Nunito Sans 16px. */
.prt-uslugi-note,
.prt-uslugi-note .elementor-heading-title,
.prt-uslugi-note p {
  margin: 0; font-family: var(--prt-font-hand); font-weight: 400;
  line-height: 1.4; font-size: clamp(15px,1.4vw,18px); color: var(--prt-navy);
}
.prt-uslugi-note--l { left: -15px; top: 2%; width: 180px; transform: rotate(-4deg); }
.prt-uslugi-note--r { right: 0; top: 2%; width: 150px; transform: rotate(3deg); }

/* --- Pasek zaufania: „cichy”, bez tla i bez ramek ------------------ */
.prt-trust__t p { margin: 0; font-size: 14px; font-weight: 700; color: var(--prt-navy); }

/* Focus musi byc widoczny na obu wyjsciach do formularza. */
.prt-svc .elementor-button:focus-visible,
.prt-dropzone:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }

/* ===================================================================
   WYCENA  (/uslugi-graficzne/wycena/)
   Formularz w szesciu krokach. Zbudowany WARIANTEM C z instrukcji odbudowy:
   markup pisany recznie w widgecie HTML, nie widgetem Form Elementora.
   Dzieki temu selektory ponizej sa wlasne i nie walcza z klasami Elementora
   (`.elementor-field-subgroup`, `.elementor-field-option` itd.).
   Obsluga: `Printella_Wycena_Form` w printella-core.
   =================================================================== */

.prt-wycena-layout { display: flex; align-items: flex-start; gap: clamp(24px,2.8vw,38px); }
@media (max-width: 1080px) { .prt-wycena-layout { flex-direction: column; } }

.prt-form-card { flex: 1 1 auto; min-width: 0; background: #F8F9FC; border-radius: var(--prt-radius-panel); padding: clamp(24px,3vw,40px); }
.prt-form { display: flex; flex-direction: column; gap: clamp(26px,3vw,38px); }
.prt-form fieldset { margin: 0; padding: 0; border: 0; }
.prt-form legend { padding: 0; }

/* Naglowek kroku: numer w rozowym kolku + tytul + podtytul. */
.prt-step-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: clamp(14px,1.6vw,22px); }
.prt-step-head__n { flex: none; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: var(--prt-radius-pill); background: var(--prt-pink-cta); color: #fff; font-size: 15px; font-weight: 900; }
.prt-step-head__t { margin: 0; font-size: clamp(18px,1.7vw,22px); font-weight: 900; letter-spacing: -.02em; color: var(--prt-navy); }
.prt-step-head__s { margin: 5px 0 0; font-size: 14px; font-weight: 600; color: var(--prt-text-muted); }

/* Krok 1 — kafle uslug z miniatura i cena.
   ⚠️ Cena jest atrybutem `data-cena` w HTML, a nie `content: ""` w CSS.
   Instrukcja odbudowy nazywa tamto wprost dlugiem technicznym: ceny w CSS sa poza
   CMS-em i poza tlumaczeniami, a musza zgadzac sie z cennikiem na landingu. */
.prt-usluga { display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: clamp(10px,1.2vw,14px); }
.prt-usluga__o { position: relative; display: flex; }
.prt-usluga__o input { position: absolute; opacity: 0; width: 0; height: 0; }
.prt-usluga__o label {
  display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%;
  background: #fff; border: 2px solid var(--prt-line-card); border-radius: var(--prt-radius-tile);
  padding: 14px 12px 16px; cursor: pointer; text-align: center;
  font-size: 13px; line-height: 1.35; font-weight: 800; color: var(--prt-navy);
  transition: border-color .2s ease;
}
.prt-usluga__o img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }
.prt-usluga__o label::after { content: attr(data-cena); font-size: 13px; font-weight: 700; color: var(--prt-text-muted); }
.prt-usluga__o input:checked + label { border-color: var(--prt-pink-cta); }
.prt-usluga__o input:checked + label::after { color: var(--prt-pink-cta); }
.prt-usluga__o input:focus-visible + label { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .prt-usluga__o label:hover { border-color: var(--prt-line-pink); } }
@media (max-width: 720px) { .prt-usluga { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 460px) { .prt-usluga { grid-template-columns: minmax(0,1fr); } }

/* Krok 2 — strefa upuszczania. Tu jest PRAWDZIWY upload, w odroznieniu od kafla
   na landingu, ktory jest wylacznie linkiem. */
.prt-strefa { position: relative; display: block; background: #fff; border: 2px dashed var(--prt-line-input); border-radius: 20px; padding: clamp(26px,3vw,40px) 20px; text-align: center; cursor: pointer; transition: border-color .2s ease, background .2s ease; }
.prt-strefa input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.prt-strefa__t { margin: 0; font-size: 16px; font-weight: 800; color: var(--prt-navy); }
.prt-strefa__s { margin: 5px 0 0; font-size: 14px; font-weight: 600; color: var(--prt-text-muted); }
.prt-strefa[data-nad], .prt-strefa:focus-within { border-color: var(--prt-pink-cta); background: var(--prt-surface-pink-lightest, #FFF6FA); }
@media (hover: hover) and (pointer: fine) { .prt-strefa:hover { border-color: var(--prt-pink-cta); background: var(--prt-surface-pink-lightest, #FFF6FA); } }

.prt-pliki { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.prt-plik { display: flex; align-items: center; gap: 12px; background: #fff; border: 1.5px solid var(--prt-line); border-radius: 12px; padding: 10px 12px; }
.prt-plik__n { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; color: var(--prt-navy); }
.prt-plik__r { flex: none; font-size: 13px; font-weight: 700; color: var(--prt-text-faint); }
.prt-plik__x { flex: none; width: 26px; height: 26px; border: 0; border-radius: var(--prt-radius-pill); background: var(--prt-surface-pink-strong); color: var(--prt-pink-cta); font-size: 17px; font-weight: 900; line-height: 1; cursor: pointer; }

/* Krok 3 — opis z licznikiem znakow. */
.prt-form textarea { width: 100%; min-height: 130px; resize: vertical; background: #fff; border: 1.5px solid var(--prt-line); border-radius: 16px; padding: 16px 18px; line-height: 1.55; font-size: 15px; font-weight: 500; font-family: inherit; color: var(--prt-navy); }
.prt-counter { margin: 8px 0 0; font-size: 13px; font-weight: 700; color: var(--prt-text-faint); text-align: right; }

/* Krok 4 — chipy zastosowania. */
.prt-zastosowanie { display: flex; flex-wrap: wrap; gap: 10px; }
.prt-zastosowanie__o input { position: absolute; opacity: 0; width: 0; height: 0; }
.prt-zastosowanie__o label { display: inline-flex; background: #fff; border: 1.5px solid var(--prt-line); border-radius: var(--prt-radius-pill); padding: 12px 22px; font-size: 14px; font-weight: 700; color: var(--prt-navy); cursor: pointer; transition: border-color .2s ease, background .2s ease; }
.prt-zastosowanie__o input:checked + label { background: var(--prt-surface-pink-strong); border-color: var(--prt-pink-cta); font-weight: 800; }
.prt-zastosowanie__o input:focus-visible + label { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .prt-zastosowanie__o label:hover { border-color: var(--prt-pink-cta); } }

/* Krok 5 — rozmiar docelowy. */
.prt-rozmiar { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; }
.prt-rozmiar > * { flex: 1 1 140px; min-width: 0; }
.prt-x { flex: 0 0 auto; align-self: flex-end; padding-bottom: 13px; font-size: 16px; font-weight: 800; color: var(--prt-text-faint); }

/* Krok 6 i pola wspolne. */
.prt-pola { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px 14px; }
.prt-pola--1 { grid-template-columns: minmax(0,1fr); }
@media (max-width: 620px) { .prt-pola { grid-template-columns: minmax(0,1fr); } }
.prt-pole { display: flex; flex-direction: column; gap: 7px; }
.prt-pole > span { font-size: 13px; font-weight: 700; color: var(--prt-text-muted); }
.prt-form input[type="text"], .prt-form input[type="email"], .prt-form input[type="tel"], .prt-form input[type="number"] {
  width: 100%; background: #fff; border: 1.5px solid var(--prt-line); border-radius: 12px;
  padding: 13px 16px; font-size: 15px; font-weight: 500; font-family: inherit; color: var(--prt-navy);
}
.prt-form input::placeholder, .prt-form textarea::placeholder { color: var(--prt-text-faint); }
.prt-form input:focus-visible, .prt-form textarea:focus-visible { outline: 0; border-color: var(--prt-pink-cta); box-shadow: 0 0 0 3px rgba(240,65,126,.16); }
/* `.prt-form` nie występuje w żadnym szablonie motywu ani wtyczki (sprawdzone grepem
   2026-10-26) — reguła martwa. Zostawiona zakomentowana do czasu decyzji, czy klasa
   wraca; gdyby wróciła, `accent-color` musi być granatowy, nie różowy (zasada kolorów v2). */
/* .prt-form input[type="checkbox"], .prt-form input[type="radio"]:not(.prt-usluga__o input):not(.prt-zastosowanie__o input) { accent-color: var(--prt-pink-cta); width: 19px; height: 19px; } */

.prt-zgoda { display: flex; align-items: flex-start; gap: 12px; font-size: 14px; line-height: 1.5; font-weight: 600; color: var(--prt-text-muted); }
.prt-zgoda a { color: var(--prt-pink-cta); font-weight: 800; }
.prt-zgoda input { flex: none; margin-top: 2px; }

.prt-wyslij { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 12px; border: 0; border-radius: var(--prt-radius-pill); background: var(--prt-pink-cta); color: #fff; font-size: 17px; font-weight: 800; font-family: inherit; padding: 19px 30px; cursor: pointer; transition: background .2s ease; }
.prt-wyslij:hover { background: var(--prt-pink-hover, #D8306A); }
.prt-wyslij[disabled] { opacity: .6; cursor: progress; }
.prt-nota { margin: 12px 0 0; font-size: 14px; font-weight: 700; color: var(--prt-text-muted); text-align: center; }
.prt-status { margin: 14px 0 0; font-size: 15px; font-weight: 700; line-height: 1.5; text-align: center; }
.prt-status[data-stan="ok"] { color: var(--prt-green-ink, #38AA62); }
.prt-status[data-stan="blad"] { color: var(--prt-pink-cta); }

/* Pulapka na boty — musi byc niewidoczna dla ludzi, ale NIE `display:none`,
   bo czesc botow pomija pola ukryte tym sposobem. */
.prt-hp { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }

/* --- Panel boczny --------------------------------------------------- */
.prt-aside { flex: 0 0 370px; width: 370px; position: sticky; top: 24px; z-index: 5; display: flex; flex-direction: column; gap: clamp(18px,2vw,24px); }
@media (max-width: 1080px) { .prt-aside { position: static; width: 100%; flex-basis: auto; } }
.prt-next { background: var(--prt-surface-pink); border-radius: var(--prt-radius-panel); padding: clamp(24px,2.6vw,32px); }
.prt-next h2 { margin: 0 0 clamp(16px,1.8vw,22px); font-size: clamp(22px,2.2vw,28px); line-height: 1.08; font-weight: 900; letter-spacing: -.028em; color: var(--prt-navy); }
.prt-next__k { display: flex; align-items: flex-start; gap: 16px; }
.prt-next__k + .prt-next__k { margin-top: clamp(16px,1.8vw,20px); }
.prt-next__i { flex: none; display: flex; align-items: center; justify-content: center; width: 52px; height: 52px; border-radius: var(--prt-radius-pill); background: var(--prt-surface-pink-strong); color: var(--prt-pink-cta); }
.prt-next__t { margin: 0; font-size: 16px; font-weight: 800; color: var(--prt-navy); }
.prt-next__o { margin: 4px 0 0; font-size: 14px; line-height: 1.5; font-weight: 600; color: var(--prt-text-muted); }
.prt-ask { display: flex; align-items: flex-start; gap: 14px; background: #fff; border-radius: var(--prt-radius-media); padding: clamp(18px,2vw,22px); margin-top: clamp(18px,2vw,22px); }
.prt-ask__t { margin: 0; font-size: 15px; font-weight: 800; color: var(--prt-navy); }
.prt-ask__o { margin: 4px 0 0; font-size: 14px; line-height: 1.5; font-weight: 600; color: var(--prt-text-muted); }
.prt-ask a { color: var(--prt-pink-cta); font-weight: 800; }
.prt-doodle-panel { background: var(--prt-surface-pink-lightest, #FFF6FA); border-radius: var(--prt-radius-panel); padding: clamp(22px,2.4vw,28px); overflow: hidden; text-align: center; }
.prt-doodle-panel__a,
.prt-doodle-panel__b { font-family: var(--prt-font-hand); font-weight: 400; color: var(--prt-navy); }
.prt-doodle-panel__a { margin: 0; font-size: clamp(22px,2.2vw,28px); line-height: 1.15; }
.prt-doodle-panel__b { margin: 6px 0 0; font-size: 17px; }
.prt-doodle-panel img { display: block; max-width: 280px; width: 100%; height: auto; margin: clamp(14px,1.6vw,18px) auto 0; }
.prt-trust-2x2 { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 16px; margin-top: clamp(18px,2vw,22px); text-align: left; }
.prt-trust-2x2 div { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; font-weight: 700; color: var(--prt-navy); }
.prt-trust-2x2 svg { flex: none; }

/* Wycena — hero i breadcrumb. Te same proporcje co landing, ale kolumna z Tango
   jest WEZSZA (38% zamiast 50%): bohaterem tej strony jest formularz, nie grafika. */
/* `flex-start`, nie `center`: od kiedy okruszki siedza w kolumnie tekstu, srodkowanie
   wzgledem wysokiej grafiki spychalo cala kolumne w dol i sciezka ladowala w polowie
   wysokosci hero zamiast przy jego gorze. */
/* Wycena też zaczyna się od okruszków — rola „breadcrumb na bieli". */
.prt-wycena__hero { display: flex; align-items: flex-start; gap: clamp(28px,3.4vw,48px); padding-top: var(--prt-below-header-crumb); }
.prt-wycena__hero-txt { flex: 1 1 auto; min-width: 0; }
.prt-wycena__art { flex: 0 0 38%; width: 38%; }
.prt-wycena__h1 { margin: 0; font-size: clamp(34px,4.6vw,62px); line-height: 1.02; font-weight: 900; letter-spacing: -.035em; color: var(--prt-navy); }
.prt-wycena__h1 span { color: var(--prt-pink-cta); }
.prt-wycena__lead { max-width: 560px; margin: clamp(16px,1.8vw,22px) 0 0; font-size: clamp(17px,1.5vw,20px); line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
#wycena-tresc { padding-top: 58px; }
@media (max-width: 1080px) {
  .prt-wycena__hero { flex-direction: column; align-items: stretch; }
  .prt-wycena__art { flex-basis: auto; width: 100%; }
  /* `min(..., 100%)`, nie samo 420px — inaczej ilustracja rozpycha strone
     w poziomie na telefonie (zmierzone: scrollWidth 448 przy viewport 390). */
  .prt-wycena__art img { max-height: clamp(200px,30vw,280px); max-width: min(420px, 100%); margin-inline: auto; }
}
@media (max-width: 767px) { #wycena-tresc { padding-top: 48px; } }

/* ===================================================================
   USLUGI GRAFICZNE — UKLAD KONTENEROW
   -------------------------------------------------------------------
   ⚠️ CZYTAJ PRZED EDYCJA. Kontener Elementora nie przyjmuje zwyklych
   wlasciwosci flexa. Cztery pulapki, kazda kosztowala tu jedno podejscie:

   1. SPECYFICZNOSC. `.e-con.e-flex` (0,2,0) ustawia `--flex-direction: column`,
      `--width`, `--flex-basis/grow/shrink` i `--flex-wrap`. Selektor `.prt-x`
      ma 0,1,0, wiec PRZEGRYWA i zmienna nigdy nie dochodzi — mimo ze arkusz
      motywu laduje sie po Elementorze. Dlatego kazdy selektor kontenera ma tu
      prefiks `.e-con.e-flex` (0,3,0) i wygrywa niezaleznie od kolejnosci.

   2. `--gap` NIE STERUJE ODSTEPEM. Elementor pisze
      `gap: var(--row-gap) var(--column-gap)`. Ustawiamy OBIE te zmienne.

   3. KONTENER BOXED MA DWA POZIOMY. `.e-con-boxed.e-flex` ma twarde
      `flex-direction: column` (wartosc, nie zmienna); kierunek dziala dopiero
      na `.e-con > .e-con-inner`, ktory czyta `var(--flex-direction)`
      odziedziczona z rodzica. Zmienna ustawiamy wiec na kontenerze,
      a `flex-direction` wprost NIE ZADZIALA NIGDY — ani tu, ani inline.
      Z tego samego powodu dzieci kontenera to `> .e-con-inner > .e-con`,
      nie `> .e-con`.

   4. Widgety to NIE kontenery — `.prt-ug-h1`, `.prt-eyebrow`, `.prt-svc__il`
      itd. stylujemy zwyklymi wlasciwosciami. Elementor generuje dla widgetow
      reguly 0,4,0, ale tylko gdy w `_elementor_data` siedza ustawienia stylu;
      ta strona trzyma w danych wylacznie strukture, klasy i tresc, wiec
      konkurencji nie ma.

   Wszystkie kontenery tej strony to `e-con-boxed` (sprawdzone w DOM).
   =================================================================== */

/* --- rytm sekcji: 96 px, ponizej 767 px — 72 px --- */
.e-con.e-flex.prt-ug-karty,
.e-con.e-flex.prt-ug-jak,
.e-con.e-flex.prt-ug-wyc,
.e-con.e-flex.prt-ug-trust { --padding-top: 96px; }
.e-con.e-flex.prt-ug-trust { --padding-bottom: 96px; }
.e-con.e-flex.prt-ug-crumbs { --padding-top: clamp(18px,2vw,26px); --padding-bottom: 0px; --text-align: left; }
@media (max-width: 767px) {
  .e-con.e-flex.prt-ug-karty,
  .e-con.e-flex.prt-ug-jak,
  .e-con.e-flex.prt-ug-wyc,
  .e-con.e-flex.prt-ug-trust { --padding-top: 72px; }
  .e-con.e-flex.prt-ug-trust { --padding-bottom: 72px; }
}

/* --- hero --- */
.e-con.e-flex.prt-ug-hero {
  --flex-direction: row; --align-items: center;
  --row-gap: var(--prt-gap-hero); --column-gap: var(--prt-gap-hero);
  --padding-top: clamp(36px,4.4vw,60px); --padding-bottom: 0px;
}
.e-con.e-flex.prt-ug-hero__txt { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }
.e-con.e-flex.prt-hero-art--uslugi { --flex-grow: 0; --flex-shrink: 0; --flex-basis: 46%; --width: 46%; }
@media (max-width: 1080px) {
  .e-con.e-flex.prt-ug-hero { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-hero-art--uslugi {
    --flex-basis: auto; --width: 100%;
    --align-items: center; --row-gap: 14px; --column-gap: 14px;
  }
}

/* --- pasek USP pod leadem --- */
.e-con.e-flex.prt-usp {
  --flex-direction: row; --row-gap: clamp(18px,2vw,26px); --column-gap: clamp(18px,2vw,26px);
  --padding-top: 26px;
}
.e-con.e-flex.prt-usp__i { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 8px; --column-gap: 8px; }
@media (max-width: 620px) { .e-con.e-flex.prt-usp { --flex-direction: column; } }

/* --- naglowek sekcji kart --- */
.e-con.e-flex.prt-sec-head {
  --text-align: center; --row-gap: 0px; --column-gap: 0px;
  /* ⚠️ Szerokosc wprost, NIE przez `--width`: Elementor domyka te zmienna
     regula `.e-con{max-width:min(100%,var(--width))}`, ktora obowiazuje
     dopiero powyzej breakpointu. Ponizej zostawalo samo `width: 660px`
     i sekcja rozpychala strone w poziomie na telefonie.
     `margin-inline: auto` tez wprost — `.e-con{--margin-left:auto}` siedzi
     w tym samym zapytaniu media, wiec blok trzymal sie lewej krawedzi. */
  max-width: 660px; margin-inline: auto;
}

/* --- siatka kart: dwa rzedy po dwie ------------------------------- */
/* Dwa rzedy zamiast jednego zawijajacego sie kontenera: Elementor rozdziela
   szerokosci po rowno w rzedzie, wiec dwa rzedy daja 50/50 bez `--flex-wrap`,
   ktorego builder nie zaleca. */
.e-con.e-flex.prt-svc-row {
  --flex-direction: row; --align-items: stretch;
  --row-gap: clamp(20px,2.4vw,30px); --column-gap: clamp(20px,2.4vw,30px);
  --margin-top: clamp(36px,4vw,50px);
}
.e-con.e-flex.prt-svc {
  --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0;
  --row-gap: clamp(16px,1.7vw,22px); --column-gap: clamp(16px,1.7vw,22px);
  --border-radius: var(--prt-radius-panel);
  --padding-top: clamp(26px,2.8vw,36px); --padding-right: clamp(26px,2.8vw,36px);
  --padding-bottom: clamp(26px,2.8vw,36px); --padding-left: clamp(26px,2.8vw,36px);
}
.e-con.e-flex.prt-svc__head { --row-gap: 6px; --column-gap: 6px; }
.e-con.e-flex.prt-svc__media { --row-gap: 14px; --column-gap: 14px; }
/* Stopka karty dosuwa sie do dolu — to ona wyrownuje ceny miedzy kartami. */
.e-con.e-flex.prt-svc__foot {
  --flex-direction: row; --align-items: center; --justify-content: space-between;
  --flex-wrap: wrap; --row-gap: 18px; --column-gap: 18px; --margin-top: auto;
}
.e-con.e-flex.prt-svc__foot-kol {
  --flex-grow: 0; --flex-shrink: 1; --flex-basis: auto;
  --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
  width: auto; max-width: none;
}
@media (max-width: 1024px) {
  .e-con.e-flex.prt-svc-row { --flex-direction: column; }
  .e-con.e-flex.prt-svc { --flex-basis: auto; --width: 100%; }
}
@media (max-width: 620px) {
  .e-con.e-flex.prt-svc__foot { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-svc__foot-kol { width: 100%; }
}

/* --- „Jak to dziala?” --- */
.e-con.e-flex.prt-ug-panel {
  --flex-direction: row; --align-items: center;
  --row-gap: clamp(28px,3.4vw,48px); --column-gap: clamp(28px,3.4vw,48px);
  --border-radius: var(--prt-radius-panel);
  --padding-top: clamp(28px,3.2vw,44px); --padding-right: clamp(28px,3.2vw,44px);
  --padding-bottom: clamp(28px,3.2vw,44px); --padding-left: clamp(28px,3.2vw,44px);
  border: 1.5px solid var(--prt-line-soft);
}
.e-con.e-flex.prt-ug-panel__l { --flex-grow: 0; --flex-shrink: 0; --flex-basis: 270px; --width: 270px; --row-gap: 6px; --column-gap: 6px; }
.e-con.e-flex.prt-steps-row {
  --flex-direction: row; --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0;
  --row-gap: clamp(16px,2vw,24px); --column-gap: clamp(16px,2vw,24px);
}
.e-con.e-flex.prt-step {
  --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0;
  --align-items: center; --row-gap: 14px; --column-gap: 14px; --text-align: center;
}
.e-con.e-flex.prt-step__icon {
  --align-items: center; --justify-content: center;
  --width: 64px; --height: 64px; --border-radius: var(--prt-radius-pill);
  --flex-grow: 0; --flex-shrink: 0; --flex-basis: 64px;
  --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
}
.e-con.e-flex.prt-step__n { --width: auto; --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px; width: auto; max-width: none; }
@media (max-width: 920px) {
  .e-con.e-flex.prt-ug-panel { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-ug-panel__l { --flex-basis: auto; --width: 100%; }
  .e-con.e-flex.prt-steps-row { --flex-wrap: wrap; }
  .e-con.e-flex.prt-step { --flex-basis: calc(50% - 12px); }
}
@media (max-width: 620px) { .e-con.e-flex.prt-step { --flex-basis: 100%; } }

/* --- pasmo wyceny --- */
.e-con.e-flex.prt-ug-wyc__p {
  --flex-direction: row; --align-items: center;
  --row-gap: clamp(28px,3.4vw,48px); --column-gap: clamp(28px,3.4vw,48px);
  --border-radius: var(--prt-radius-panel); --overflow: hidden;
  --padding-top: clamp(30px,3.4vw,48px); --padding-right: clamp(30px,3.4vw,48px);
  --padding-bottom: clamp(30px,3.4vw,48px); --padding-left: clamp(30px,3.4vw,48px);
  background: var(--prt-surface-pink-strong);
}
.e-con.e-flex.prt-ug-wyc__l { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }
.e-con.e-flex.prt-dropzone {
  --flex-grow: 0; --flex-shrink: 0; --flex-basis: 45%; --width: 45%;
  --align-items: center; --text-align: center;
  --row-gap: 4px; --column-gap: 4px; --border-radius: 20px;
  --padding-top: clamp(28px,3.2vw,40px); --padding-right: clamp(20px,2.4vw,32px);
  --padding-bottom: clamp(28px,3.2vw,40px); --padding-left: clamp(20px,2.4vw,32px);
}
@media (max-width: 920px) {
  .e-con.e-flex.prt-ug-wyc__p { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-dropzone { --flex-basis: auto; --width: 100%; }
}

/* --- pasek zaufania --- */
.e-con.e-flex.prt-trust-row { --flex-direction: row; --row-gap: clamp(20px,2.4vw,32px); --column-gap: clamp(20px,2.4vw,32px); }
.e-con.e-flex.prt-trust__i {
  --flex-direction: row; --align-items: flex-start;
  --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0;
  --row-gap: 14px; --column-gap: 14px;
}
@media (max-width: 620px) { .e-con.e-flex.prt-trust-row { --flex-direction: column; } }

/* ===================================================================
   USLUGI GRAFICZNE — TYPOGRAFIA WIDGETOW
   Zwykle wlasciwosci: widget nie jest kontenerem i nie ma tu zmiennych.
   ⚠️ Rozmiary sa PODSTRONY, nie strony glownej. Globalny „Display H1" ma
   w kicie sztywne 88 px — tyle dostawal ten naglowek, zanim reguly per
   element zniknely z `_elementor_data`. Podstrony serwisu sa mniejsze
   (Panele: clamp(38px,4.6vw,62px)).
   =================================================================== */
/* ⚠️⚠️ DLACZEGO TE SELEKTORY MAJA PRZEDROSTEK `.elementor`
   ================================================================
   Elementor WSTRZYKUJE do dokumentu bloki `<style>` PO wszystkich arkuszach z `<link>`,
   a w kazdym z nich siedzi:

       .elementor-widget-heading .elementor-heading-title { font-size: var(--e-global-typography-primary-font-size); ... }

   To (0,2,0) — dokladnie tyle, co `.prt-xxx .elementor-heading-title`. Przy rownej
   specyficznosci wygrywa to, co pozniej w dokumencie, a inline jest ZAWSZE pozniej niz
   nasz arkusz. Zmierzone 31.10.2026 na karcie tkaniny: cztery takie bloki na pozycjach
   44-47, podczas gdy `design-system.css` jest na 36. Skutek: H1 karty renderowal sie
   jako 24 px (wartosc `--e-global-typography-primary-font-size` z kitu) zamiast
   zadeklarowanych `clamp(32px,3.6vw,48px)`, „Parametry materialu" jako 24 zamiast 17,
   a cena rowniez z kitu. Steve zobaczyl to jako „obie karty znacznie sie roznia".

   Przedrostek `.elementor` (wrapper Elementora, przodek kazdego widzetu) daje (0,3,0)
   i wygrywa niezaleznie od kolejnosci. ⚠️ NIE USUWAC przy porzadkach — bez niego kit
   po cichu przejmuje typografie i strona wyglada inaczej, niz mowi arkusz. */
.elementor .prt-ug-h1 .elementor-heading-title {
  font-size: clamp(38px,4.6vw,62px); line-height: 1.02; font-weight: 900;
  letter-spacing: -.034em; color: var(--prt-navy); margin: 0;
}
.prt-ug-h1 span { color: var(--prt-pink-cta); }
.elementor .prt-ug-h2 .elementor-heading-title {
  font-size: clamp(30px,3.8vw,52px); line-height: 1.04; font-weight: 900;
  letter-spacing: -.03em; color: var(--prt-navy); margin: 0;
}
.prt-ug-h2 span { color: var(--prt-pink-cta); }
.elementor .prt-ug-h3 .elementor-heading-title {
  font-size: clamp(26px,2.8vw,38px); line-height: 1.06; font-weight: 900;
  letter-spacing: -.028em; color: var(--prt-navy); margin: 0;
}
.elementor-widget-heading.prt-eyebrow .elementor-heading-title {
  font-size: 14px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--prt-pink-cta); margin: 0 0 16px;
}
/* ⚠️ Warianty MUSZĄ mieć tę samą specyficzność co baza (0,3,0). Baza
   `.elementor-widget-heading.prt-eyebrow` została podniesiona, żeby przebić
   globalną typografię kitu — wariant zostawiony na 0,2,0 przestał działać
   i nadtytuły na kolorowych pasmach wracały do różu CTA (zmierzony kontrast
   3,16 zamiast 4,83). */
.elementor-widget-heading.prt-eyebrow--ink .elementor-heading-title { color: var(--prt-pink-ink, #C22765); }
/* Nadtytuł na niebieskim paśmie „Dlaczego…” — kontrast 4,71 na #EEF6FD. */
.elementor-widget-heading.prt-eyebrow--blue .elementor-heading-title { color: #0972B5; }
.prt-ug-lead p { max-width: 520px; margin: clamp(20px,2.2vw,26px) 0 0; font-size: clamp(17px,1.5vw,20px); line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.prt-usp__t p { margin: 0; max-width: 170px; font-size: 14px; font-weight: 700; color: var(--prt-navy); }
.elementor .prt-sec-head .elementor-heading-title { text-align: center; }
.prt-sec-head__lead p { max-width: 520px; margin: 0 auto; text-align: center; font-size: clamp(17px,1.5vw,20px); line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.elementor .prt-svc__t .elementor-heading-title { font-size: clamp(22px,2.2vw,30px); line-height: 1.08; font-weight: 900; letter-spacing: -.028em; color: var(--prt-navy); margin: 0; }
.prt-svc__lead p { margin: 0; font-size: 15px; line-height: 1.5; font-weight: 500; color: var(--prt-text-muted); }
/* Notka karty idzie jednym stylem notek (Kalam 400 granat), a nie akcentem
   `--ink` karty — handoff kreatora, pkt 10. */
.elementor .prt-note .elementor-heading-title { font-family: var(--prt-font-hand); font-size: 17px; font-weight: 400; text-align: center; color: var(--prt-navy); margin: 0; }
.prt-svc__il .elementor-icon-list-items { display: grid; gap: 11px; }
.prt-svc__il .elementor-icon-list-icon { color: var(--ink); font-size: 19px; }
.prt-svc__il .elementor-icon-list-text { font-size: 14px; font-weight: 700; color: var(--prt-navy); }
.prt-ug-panel__o p { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.prt-step__icon .elementor-icon { font-size: 30px; }
.prt-usp__i .elementor-icon { color: var(--prt-pink-cta); font-size: 26px; }
.prt-ug-wyc__l .elementor-widget-button { margin-top: clamp(20px,2.2vw,26px); }
.prt-dropzone .elementor-icon { color: var(--prt-pink-cta); font-size: 42px; }
.prt-trust__i .elementor-icon { font-size: 26px; color: var(--prt-navy); }

/* ===================================================================
   KATEGORIE TKANIN — archiwum rodzaju (/nadruk/{rodzaj}/)
   -------------------------------------------------------------------
   Projekt: handoff „Printella — kategorie materiałów”. Siedem sekcji wokół
   listy materiałów: hero z USP, katalog, „Dlaczego…”, inspiracje, blok SEO,
   FAQ i pasmo końcowe.

   Dwa rodzaje selektorów w tym bloku, celowo rozdzielone:

   1. KONTENERY ELEMENTORA (`.e-con.e-flex.prt-kat-*`) — układ sekcji.
      Obowiązuje kontrakt opisany niżej w bloku „USLUGI GRAFICZNE — UKLAD
      KONTENEROW”: prefiks `.e-con.e-flex` (0,3,0), odstępy przez
      `--row-gap`/`--column-gap` (nie `--gap`), kierunek wyłącznie zmienną.

   2. MARKUP Z SHORTCODÓW (`.prt-cat-usp`, `.prt-ben`, `.prt-insp`,
      `.prt-seo-*`, `.prt-faq`) — zwykłe właściwości. To HTML renderowany
      przez `Printella_Fabric_Landing`, nie kontenery Elementora, więc
      kontrakt z punktu 1 ich nie dotyczy.
   =================================================================== */

/* --- rytm sekcji --------------------------------------------------- */
/* Rytm bierzemy z `--prt-section-gap` — ten token sam schodzi na 72 px poniżej
   767 px, więc blok nie powtarza już tej samej reguły drugim media query. */
.e-con.e-flex.prt-kat-sec { --padding-top: var(--prt-section-gap); }
/* Rola „breadcrumb na bieli" — ta sama zmienna co w bloku ról niżej. Dwie reguły dla
   jednej klasy zostają, bo ta stoi w bloku kategorii, a tamta w bloku ról; wartość
   jest jedna, więc nie mają jak się rozjechać. */
.e-con.e-flex.prt-kat-hero { --padding-top: var(--prt-below-header-crumb); }

/* Kotwice sekcji nie mogą chować nagłówka pod nagłówkiem serwisu. */
.e-con.e-flex.prt-kat-sec[id], .e-con.e-flex.prt-kat-hero[id] { scroll-margin-top: var(--prt-section-gap); }

/* --- hero ---------------------------------------------------------- */
.e-con.e-flex.prt-kat-hero {
  --flex-direction: row; --align-items: center;
  --row-gap: var(--prt-gap-hero); --column-gap: var(--prt-gap-hero);
}
.e-con.e-flex.prt-kat-hero__txt { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }
/* Okruszki siedzą WEWNĄTRZ kolumny hero, nie w osobnym pasie — odstęp do
   nadtytułu musi więc dać margines, a nie padding sekcji. Na pozostałych
   podstronach (np. Usługi graficzne) ta przerwa wynosi 40 px, bo tam okruszki
   mają własny kontener i odstęp robi `--padding-top` hero. */
/* Okruszki w kolumnie tekstu hero: odstep na samej nawigacji, nie na `<p>` w srodku.
   Wczesniej 28–36 px siedzialo na `.prt-crumbs`, a 24 px na `.prt-crumbs-nav` — na ekranie
   wychodzilo 36 px, bo marginesy sie zlewaja (`<p>` jest ostatnim dzieckiem `<nav>`).
   Dzialalo, ale wynik zalezal od zlewania sie marginesow, wiec kazdy padding albo obramowanie
   dolozone kiedys do `<nav>` cicho zmienilby odstep na 24 + 36. Jedna deklaracja na
   nawigacji obejmuje teraz takze Wycene grafiki. */
.prt-kat-hero__txt .prt-crumbs-nav,
.prt-wycena__hero-txt .prt-crumbs-nav { margin-bottom: clamp(28px,3vw,36px); }

/* ⚠️ KARTA TKANINY jest wyjatkiem od reguly „okruszki w kolumnie tekstu hero".
   Probowane i cofniete: po przeniesieniu sciezki do kolumny `.prt-pdp__buy` wygladalo
   dobrze na desktopie (828,113 nad eyebrow), ale ponizej 940 px kolumny ukladaja sie
   w pion GALERIA → TEKST, wiec okruszki ladowaly POD galeria — zmierzone y=1060 przy
   900 px i y=596 przy 390 px, czyli ekran nizej. Sciezka zostaje nad hero, bo tam jest
   pierwsza na kazdej szerokosci.

   Zostaje za to wyrownanie: kontener okruszkow ma w Elementorze wyzerowany padding
   boczny, a kontener galerii nie, wiec sciezka zaczynala sie 28 px na lewo od galerii
   (zmierzone 80 vs 108 przy 1440 px) i DOTYKALA krawedzi ekranu ponizej szerokosci
   skrzynki (0 vs 28). Padding na samym kontenerze nic nie da — galeria dostalaby
   wtedy 56 px (sprawdzone). */
body.single-tkanina .prt-crumbs-nav { padding-inline: 28px; }
.e-con.e-flex.prt-kat-hero__art { --flex-grow: 0; --flex-shrink: 0; --flex-basis: 48%; --width: 48%; }
.e-con.e-flex.prt-kat-cta-row { --flex-direction: row; --flex-wrap: wrap; --row-gap: 14px; --column-gap: 14px; --margin-top: clamp(28px,3vw,36px); }
@media (max-width: 940px) {
  .e-con.e-flex.prt-kat-hero { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-kat-hero__art { --flex-basis: auto; --width: 100%; }
}

/* Zdjęcie hero leży na organicznej plamie — ta sama konwencja co na stronie
   głównej i w Usługach graficznych, nie koło. */
.prt-cat-hero-media { position: relative; }
.prt-cat-hero-media::before {
  content: ""; position: absolute; inset: -8% -12% -8% 2%;
  border-radius: 48% 52% 46% 54% / 52% 44% 56% 48%;
  background: var(--prt-surface-pink); pointer-events: none;
}
.prt-cat-hero-media > * { position: relative; z-index: 2; }
/* ⚠️ Poniżej 940 px hero jest jednokolumnowe i kolumna ze zdjęciem zajmuje całą
   szerokość — ujemny `inset` plamy wychodził wtedy poza viewport i dawał
   przewijanie w poziomie (zmierzone: scrollWidth 983 przy 940). */
@media (max-width: 940px) {
  .prt-cat-hero-media::before { inset: -6% 0 -6% 0; }
}
.prt-cat-hero-media img {
  display: block; width: 100%; height: clamp(320px,34vw,420px);
  object-fit: cover; border-radius: 22px;
}

/* Notka odręczna wisi po lewej stronie zdjęcia. Poniżej 1100 px nie ma dla niej
   miejsca i znika — tekst z niej nie niesie informacji, tylko ton. */
.prt-cat-hero-media .prt-doodle {
  left: -118px; top: 12%; width: 132px; margin: 0;
  transform: rotate(-8deg); text-align: center;
  font-family: var(--prt-font-hand); font-size: 19px; line-height: 1.3;
  font-weight: 400; color: var(--prt-navy);
}
.prt-doodle__serce { display: block; width: 34px; margin: 8px auto 0; color: var(--prt-pink-cta); }
.prt-doodle__serce svg { display: block; width: 100%; height: auto; }
@media (max-width: 1100px) { .prt-doodle-side { display: none !important; } }

/* Wariant outline dla widgetu Button — motyw miał dotąd tylko `.prt-btn-outline`
   dla gołego `<a>`. Ta sama zasada co przy `.prt-btn-widget`: klasa z
   `_css_classes` siedzi na OPAKOWANIU widgetu, więc celujemy w `<a>` w środku. */
/* Decyzja Steve'a 31.10.2026: ramka GRANATOWA, nie różowa. Różowy jest kolorem
   akcji głównej („Wgraj wzór"), a to przyciski drugorzędne — otwierają okno
   z informacją. Tło hoveru idzie za ramką na chłodny neutralny, bo granatowa
   ramka z różowym tłem to dwa akcenty w jednym elemencie. */
.prt-btn-widget--outline .elementor-button {
  background: transparent; color: var(--prt-navy);
  border: 2px solid var(--prt-navy); padding: 17px 30px;
}
.prt-btn-widget--outline .elementor-button:hover { color: var(--prt-navy); }
@media (hover: hover) and (pointer: fine) {
  .prt-btn-widget--outline .elementor-button:hover { background: var(--prt-surface-cool); }
}

/* --- USP w hero ---------------------------------------------------- */
.prt-cat-usp {
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
  gap: 18px; margin: clamp(34px,4vw,48px) 0 0; padding: 0; list-style: none;
}
.prt-cat-usp__i { display: flex; align-items: center; gap: 12px; }
.prt-cat-usp__ico {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: var(--prt-radius-pill);
}
.prt-cat-usp__ico svg { width: 20px; height: 20px; }
.prt-cat-usp__t { font-size: 13px; line-height: 1.35; }
.prt-cat-usp__t strong { display: block; font-weight: 700; color: var(--prt-navy); }
.prt-cat-usp__t span { display: block; font-weight: 500; color: var(--prt-text-muted); }
@media (max-width: 700px) { .prt-cat-usp { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 480px) { .prt-cat-usp { grid-template-columns: minmax(0,1fr); } }

/* --- wiersz nagłówka sekcji (katalog, FAQ) ------------------------- */
.e-con.e-flex.prt-kat-naglowek {
  --flex-direction: row; --justify-content: space-between; --align-items: flex-end;
  --flex-wrap: wrap; --row-gap: 24px; --column-gap: 24px;
}
.e-con.e-flex.prt-kat-naglowek__tx { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }

/* --- katalog materiałów (Loop Grid) -------------------------------- */
/* ⚠️ Typografia widgetów ma tu prefiks `.elementor-widget-<typ>` (0,3,0), nie
   samą klasę (0,2,0). Globalna typografia kitu jedzie regułą
   `.elementor-widget-heading .elementor-heading-title` o TEJ SAMEJ
   specyficzności 0,2,0, ale Elementor wstawia ją inline w <head>, czyli PÓŹNIEJ
   niż arkusz motywu — przy remisie wygrywa ona. Zmierzone: tytuł karty dostawał
   58 px zamiast 17 px.
   ⚠️ Text Editor z tagiem dynamicznym wypisuje GOŁĄ wartość pola, bez <p>.
   Dlatego font siedzi na wrapperze widgetu, a nie na akapicie w środku. */
/* ⚠️ Karta jest „otwarta”: bez ramki i bez cienia. To ją odróżnia od kart
   Centrum pomocy, które ramkę mają — nie ujednolicać. */
/* ⚠️ Liczba kolumn sterowana TU, nie ustawieniami Loop Grida. Elementor wiąże
   `columns_tablet`/`columns_mobile` ze swoimi breakpointami (tablet 1024,
   mobile 767), a projekt wymaga progów 1040 / 700 / 480. Przestawienie
   breakpointów serwisu odpada — używa ich 11 szablonów. */
.prt-mat .elementor-loop-container {
  margin-top: clamp(36px,4vw,50px);
  grid-template-columns: repeat(4, minmax(0,1fr));
  /* Odstęp TAKI SAM jak między boksami rodzajów na stronie głównej — polecenie Steve'a
     28.10.2026. Nie jest skokowy, tylko płynny: zmierzone na sekcji „Poznaj nasze
     tkaniny" 28 px przy 1440, 24 przy 1200, 22 przy 1100, 20,48 przy 1024 i płasko
     20 px od 1000 w dół. To `clamp(20px, 2vw, 28px)` — sprawdza się na każdym z tych
     punktów (2vw z 1024 = 20,48; z 1440 = 28,8, czyli ucięte do 28).
     Listing miał wcześniej sztywne 30 px z ustawień widżetu pętli w Elementorze.
     `!important`, bo tamto ustawienie generuje regułę o tej samej specyficzności,
     a o wyniku decydowałaby kolejność wczytania arkuszy — rzecz, na którą nie mamy
     wpływu i która zmienia się przy pierwszym włączeniu cache'owania CSS. */
  gap: clamp(20px, 2vw, 28px) !important;
}
@media (max-width: 1040px) { .prt-mat .elementor-loop-container { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 700px)  { .prt-mat .elementor-loop-container { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 480px)  { .prt-mat .elementor-loop-container { grid-template-columns: minmax(0,1fr); } }
/* ⚠️ Trzy poziomy muszą mieć `height: 100%`, żeby karty w rzędzie były równe:
   element pętli, karta w środku i — przez `margin-top: auto` na stopce — sama
   treść. Bez tego kafle z dwuliniowym tytułem są wyższe i cena skacze. */
.prt-mat .e-loop-item { display: flex; flex-direction: column; height: 100%; transition: transform var(--prt-transition-card); }
.prt-mat .e-loop-item > .prt-mat__karta { height: 100%; }
/* =========================================================
   RYTM KAFLA MATERIAŁU — odstępy liczone od elementu, nie z `gap`

   Uwagi Steve'a 28.10.2026 do wzorca z Archiwum_6:
     „za duże paddingi wokół obrazu tkaniny — usuń całe 20px",
     „usuń opisy i zastosowania, bo są różne i rozpieprzają wygląd",
     „Zobacz materiał bliżej ceny".

   Kontener karty miał `gap: 20px`, czyli DWADZIEŚCIA PIKSELI między KAŻDĄ parą
   elementów — także pod zdjęciem. Stąd wrażenie paddingu dookoła obrazu. Gap jest
   teraz zerowy, a każdy element ma własny odstęp, więc rytm da się ustawić tam, gdzie
   ma znaczenie: specyfikacja przykleja się do nazwy, cena dostaje oddech, a „Zobacz
   materiał" siedzi tuż pod ceną.

   ⚠️ `margin-top: auto` na „Zobacz materiał" ZDJĘTE. Dociskało je do dołu karty, żeby
   w rzędzie wszystkie strzałki stały w jednej linii — i to był powód, dla którego było
   daleko od ceny. Po usunięciu opisów karty mają tę samą liczbę wierszy, więc wyrównanie
   i tak wychodzi samo, bez odpychania.
   ========================================================= */
.elementor-widget-heading.prt-mat__t { margin-top: 14px; }
.elementor-widget-text-editor.prt-mat__spec { margin-top: 6px; }
.elementor-widget-text-editor.prt-mat__cena { margin-top: 16px; }
.elementor-widget-heading.prt-mat__more { margin-top: 8px; }
/* Kwadrat: packshoty tkanin są kwadratowe (1000×1000 w Mediach), więc 4:3 przycinało
   im górę i dół bez powodu. */
.prt-mat__media { aspect-ratio: 1 / 1; border-radius: 16px; overflow: hidden; background: var(--prt-surface-grey); }
/* Materiał bez packshotu (dziś: oba poliestry) dostaje pole w tej samej
   proporcji (kwadrat, jak zdjęcia) i kolorze co ramka zdjęcia. Bez tego karta zaczyna się od tytułu
   i rytm siatki się łamie — a brak zdjęcia przestaje być widoczny jako brak. */
.prt-mat__karta:not(:has(.prt-mat__media))::before {
  /* ⚠️ Proporcja przez `padding-top`, NIE `aspect-ratio`: pseudoelement jest
     dzieckiem flexa i `aspect-ratio` wyliczało wysokość z dostępnej przestrzeni,
     a nie z szerokości — placeholder rósł na całą kolumnę. */
  content: ""; display: block; height: 0; padding-top: 100%;
  border-radius: 16px; background: var(--prt-surface-grey);
  /* ⚠️ Dwie rzeczy, bez których to nie działa:
     `position: relative`, bo Elementor ma własne `.e-con:before
     { position: absolute }` dla nakładki tła i placeholder wypadał z flow;
     `flex: none`, bo karta jest kontenerem flex z `flex-wrap: wrap`
     (domyślka Elementora na mobile) — rozciągliwy pseudoelement urósł
     na całą wysokość i wypchnął tytuł z ceną do drugiej kolumny,
     dając przewijanie w poziomie. */
  position: relative; width: 100%; flex: none;
}
/* ---------------------------------------------------------
   OZNACZENIA NA KARCIE MATERIAŁU — NOWOŚĆ i HIT

   Handoff 28.10.2026: pigułka w lewym górnym rogu zdjęcia, 11px/900, odstęp liter .08em,
   biały tekst. NOWOŚĆ granatowa, HIT różowy. „PREMIUM" nie ma — jest w nazwie materiału.

   DANE: dwa pola własne wpisu `tkanina` — `oznaczenie_nowosc` i `oznaczenie_hit`.
   Dlaczego DWA, a nie jedno z wartością „NOWOŚĆ"/„HIT": kolor musi wynikać z rodzaju
   oznaczenia, a Elementor nie umie przełożyć wartości pola na klasę CSS. Jedno pole
   wymagałoby albo trzymania znacznika HTML w danych, albo rozgałęzienia w CSS po treści
   tekstu, czego CSS nie potrafi. Dwa osobne pola zostawiają dane czystym tekstem,
   a wygląd deklaratywny.

   ⚠️ To pola TYLKO WordPressa — PIM ich nie dostarcza. Ustawia się je ręcznie przy wpisie
   tkaniny. Sync z PMA nadpisuje pola, które zna (`cena`, `meta_line`, `szerokosc_zadruku`),
   więc tych dwóch nie powinien ruszać — ale jeśli kiedyś zacznie kasować nieznane klucze,
   oznaczenia znikną i to będzie pierwsze miejsce do sprawdzenia.

   PUSTE POLE = BRAK PIGUŁKI, bez żadnej reguły warunkowej: całość wyglądu siedzi na
   `p` WEWNĄTRZ widżetu. Elementor renderuje akapit tylko wtedy, gdy pole ma treść, więc
   przy pustym polu nie ma czego pokazać. Opieranie się na `:empty` samego widżetu byłoby
   kruche — wrapper i tak zawiera `.elementor-widget-container`.
   --------------------------------------------------------- */
/* Kontener obejmujący zdjęcie i oznaczenia. Istnieje WYŁĄCZNIE po to, żeby pigułki
   miały się od czego pozycjonować.

   Bez niego `position:absolute` liczyło się od `.prt-mat__karta`, a ta ma w Elementorze
   `padding: 0 28px`. Offsety absolutne liczą się od PADDING BOKSU, więc `left:12px`
   wypadało 16 px OBOK zdjęcia, nie na nim (zmierzone: −16 px względem lewej krawędzi
   zdjęcia). Alternatywą było zaszycie `left: calc(28px + 12px)`, czyli magiczna liczba
   tracąca sens przy pierwszej zmianie paddingu karty w edytorze. */
.prt-mat__mediabox {
    position: relative;
}

/* Plakietki oznaczeń (NOWOŚĆ, HIT i kolejne z PIM). Pozycjonowany jest JEDEN widżet,
   a w nim stoją statyczne pigułki — dlatego nie ma już reguły rodzeństwa `+` z ręcznym
   `top: 46px` dla drugiej plakietki ani prefiksu `.elementor-widget-text-editor`.
   Prefiks był potrzebny, gdy pigułką był sam widżet i kit Elementora bił jego typografię;
   teraz reguła stoi wprost na `<span>`, a reguła wprost zawsze bije dziedziczenie,
   niezależnie od specyficzności przodka. Liczba plakietek jest dowolna: układa je flex. */
.prt-mat__znaki {
    position: absolute;
    top: 12px;
    left: 12px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    margin: 0;
    pointer-events: none;   /* nad pigułkami ma dalej działać link całej karty */
}

.prt-mat__znak {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    margin: 0;
    padding: 5px 10px;
    border-radius: 999px;
    white-space: nowrap;
    font-size: 11px;
    font-weight: 900;
    line-height: 1;
    letter-spacing: .08em;
    color: #fff;
}

.prt-mat__znak--nowosc {
    background: var(--prt-navy);
}

.prt-mat__znak--hit {
    background: var(--prt-pink-cta);
}

.prt-mat__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--prt-transition-media); }
/* ⚠️ Cała karta jest jednym linkiem, ale kotwica siedzi na TYTULE, nie na
   kontenerze. Powody dwa: kontener Elementora renderuje `link` tylko ze stałym
   adresem — z tagiem `post-url` zostaje zwykłym `<div>` (sprawdzone na 4.2.4);
   a tekstem linku jest wtedy nazwa materiału, a nie „Zobacz materiał”, czyli
   czytnik ekranu w liście linków czyta coś sensownego.
   Karta nie ma innych elementów interaktywnych, więc rozciągnięcie jest bezpieczne. */
.prt-mat__karta { position: relative; }
/* ⚠️ SKALA TYPOGRAFII KAFLA PODNIESIONA 28.10.2026 (17→19 / 13→15 / 17→19 / 14→15).
   Steve: „kafelki wyglądają super na stronach Kategorii, a na stronie Tkaniny są
   skarlałe". Karty mają tam TĘ SAMĄ szerokość co na kategoriach (zmierzone 299 vs
   287 px przy 1280), więc nie są mniejsze — za mała była typografia. Na dedykowanej
   stronie kategorii uchodziło, ale na `/tkaniny/`, obok nagłówków sekcji 34 px,
   nazwa 17 px czytała się jak karzeł. Proporcje bliżej zrzutów wzorcowych. */
.elementor-widget-heading.prt-mat__t .elementor-heading-title { font-size: 19px; font-weight: 800; letter-spacing: -.01em; color: var(--prt-navy); margin: 0;  }
/* Dwa wiersze zarezerwowane na nazwę — nazwy materiałów mają różną długość
   („Canvas bawełniany Noris 155 g/m²" łamie się, „Panama 250 g/m²" nie), a bez rezerwy
   specyfikacja, cena i odnośnik w jednym rzędzie siadały na różnych wysokościach.
   Zmierzone: pierwsza karta w rzędzie miała wszystko 24 px niżej niż sąsiednie.
   `min-height` zamiast przycinania, bo ucięta nazwa materiału jest bezużyteczna. */
.elementor-widget-heading.prt-mat__t .elementor-heading-title {
    min-height: calc(2 * 1.25em);
}
.prt-mat__t a { color: inherit; text-decoration: none; }
.prt-mat__t a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
/* Obrys linku zdejmujemy tylko tam, gdzie zadziała ramka karty — bez :has() zostaje natywny. */
@supports selector(:has(*)) {
    .prt-mat__t a:focus-visible { outline: none; }
}
.prt-mat__karta:has(a:focus-visible) { outline: 3px solid var(--prt-pink-cta); outline-offset: 4px; border-radius: 18px; }
.elementor-widget-text-editor.prt-mat__spec { font-size: 15px; font-weight: 700; color: var(--prt-text-muted); }
.elementor-widget-text-editor.prt-mat__opis { font-size: 14px; font-weight: 500; line-height: 1.5; color: var(--prt-text-muted); }
.elementor-widget-text-editor.prt-mat__cena { font-size: 19px; font-weight: 900; color: var(--prt-navy); }
.elementor-widget-heading.prt-mat__more .elementor-heading-title {
  display: flex; align-items: center; gap: 9px;
  font-size: 15px; font-weight: 800; color: var(--prt-pink-cta); margin: 0;
}
/* ⚠️ Strzałka jako maska CSS, a NIE `<svg>` w danych Elementora. Zapis
   `_elementor_data` skryptem przechodzi przez kses, który `<svg>` wycina
   po cichu — kosztowało to już raz odtwarzanie nagłówka i stopki z kopii. */
.elementor-widget-heading.prt-mat__more .elementor-heading-title::after {
  content: ""; width: 17px; height: 11px; background: var(--prt-pink-cta);
  -webkit-mask: var(--prt-strzalka) center/contain no-repeat;
          mask: var(--prt-strzalka) center/contain no-repeat;
  transition: transform var(--prt-transition);
}
@media (hover: hover) and (pointer: fine) {
  .prt-mat .e-loop-item:hover { transform: translateY(-3px); }
  .prt-mat .e-loop-item:hover .prt-mat__media img { transform: scale(1.03); }
  .prt-mat .e-loop-item:hover .elementor-widget-heading.prt-mat__more .elementor-heading-title::after { transform: translateX(4px); }
}
.prt-mat a:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 4px; }

/* --- „Dlaczego…?” -------------------------------------------------- */
.e-con.e-flex.prt-kat-panel {
  --border-radius: var(--prt-radius-panel);
  --padding-top: clamp(30px,3.2vw,48px); --padding-right: clamp(30px,3.2vw,48px);
  --padding-bottom: clamp(30px,3.2vw,48px); --padding-left: clamp(30px,3.2vw,48px);
  --row-gap: 0px; --column-gap: 0px;
  background: var(--prt-surface-blue);
}
.prt-ben {
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
  gap: clamp(22px,2.4vw,32px); margin: clamp(32px,3.4vw,44px) 0 0; padding: 0; list-style: none;
}
.prt-ben__i { display: flex; align-items: flex-start; gap: 16px; }
/* Kółko jest BIAŁE, a ikona zachowuje swój kolor — na niebieskim paśmie tint
   pod ikoną zlewałby się z tłem. */
.prt-ben__ico {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 50px; height: 50px; border-radius: var(--prt-radius-pill); background: var(--prt-surface);
}
.prt-ben__ico svg { width: 24px; height: 24px; }
.prt-ben__tx h3 { margin: 0; font-size: 15px; font-weight: 800; line-height: 1.3; color: var(--prt-navy); }
.prt-ben__tx p { margin: 9px 0 0; font-size: 14px; font-weight: 500; line-height: 1.5; color: var(--prt-text-muted); }
@media (max-width: 940px) { .prt-ben { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 480px) { .prt-ben { grid-template-columns: minmax(0,1fr); } }

/* --- inspiracje ---------------------------------------------------- */
/* Bez linków i bez hoveru — kafle są ilustracją zastosowań, nie nawigacją. */
.prt-insp {
  display: grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: clamp(28px,3vw,44px); margin-top: clamp(36px,4vw,50px);
}
.prt-insp__i { margin: 0; }
.prt-insp__i img {
  display: block; width: 100%; aspect-ratio: 16 / 11; object-fit: cover;
  border-radius: 16px; background: var(--prt-surface-grey);
}
.prt-insp__i h3 { margin: 20px 0 0; font-size: 18px; font-weight: 800; line-height: 1.25; color: var(--prt-navy); }
.prt-insp__i p { margin: 9px 0 0; font-size: 14px; font-weight: 500; line-height: 1.5; color: var(--prt-text-muted); }
@media (max-width: 1040px) { .prt-insp { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 480px) { .prt-insp { grid-template-columns: minmax(0,1fr); } }

/* --- blok SEO ------------------------------------------------------ */
.e-con.e-flex.prt-kat-seo {
  --flex-direction: row; --align-items: flex-start;
  --row-gap: clamp(36px,4vw,64px); --column-gap: clamp(36px,4vw,64px);
}
.e-con.e-flex.prt-kat-seo__l { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }
.e-con.e-flex.prt-kat-seo__p { --flex-grow: 0; --flex-shrink: 0; --flex-basis: 49%; --width: 49%; --row-gap: 0px; --column-gap: 0px; }
@media (max-width: 1040px) {
  .e-con.e-flex.prt-kat-seo { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-kat-seo__p { --flex-basis: auto; --width: 100%; }
}
.elementor-widget-heading.prt-kat-seo__h3 .elementor-heading-title { font-size: clamp(19px,1.8vw,24px); font-weight: 800; letter-spacing: -.02em; color: var(--prt-navy); margin: clamp(28px,3vw,40px) 0 0; }
.prt-kat-seo__tresc { max-width: 620px; }
.elementor-widget-text-editor.prt-kat-seo__tresc p { margin: 16px 0 0; font-size: 16px; font-weight: 500; line-height: 1.65; color: var(--prt-text-muted); }
.elementor-widget-text-editor.prt-kat-seo__tresc p:first-child { margin-top: 14px; }
.prt-kat-seo__tresc strong { font-weight: 800; color: var(--prt-navy); }

/* Kolumna kafli jedzie ze scrollem na desktopie; poniżej 1040 px stoi. */
.prt-seo-aside { display: flex; flex-direction: column; gap: clamp(16px,1.8vw,22px); position: sticky; top: 24px; }
@media (max-width: 1040px) { .prt-seo-aside { position: static; } }
.prt-seo-tile {
  display: flex; align-items: flex-start; gap: 18px;
  border: 1.5px solid var(--prt-line-card); border-radius: 18px;
  padding: clamp(20px,2.2vw,26px); color: inherit; text-decoration: none;
  transition: transform var(--prt-transition-card), box-shadow var(--prt-transition-card);
}
.prt-seo-tile__icon {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 14px;
}
.prt-seo-tile__icon svg { width: 22px; height: 22px; }
.prt-seo-tile__tx strong { display: block; font-size: 15px; font-weight: 800; line-height: 1.3; color: var(--prt-navy); }
.prt-seo-tile__tx span { display: block; margin-top: 8px; font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--prt-text-muted); }
@media (hover: hover) and (pointer: fine) {
  .prt-seo-tile:hover { transform: translateY(-3px); box-shadow: var(--prt-shadow-hover); }
}
.prt-seo-tile:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 4px; }

/* --- FAQ ----------------------------------------------------------- */
/* ⚠️ Natywne `<details>`, nie widget Accordion. Dwie kolumny robi grid, a
   `align-items: start` sprawia, że otwarcie pytania NIE rozciąga sąsiada —
   tego wymaga projekt, a Accordion Elementora tego nie daje bez walki. */
.prt-faq {
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: clamp(14px,1.5vw,18px) clamp(22px,2.4vw,32px);
  align-items: start; margin-top: clamp(36px,4vw,50px);
}
@media (max-width: 940px) { .prt-faq { grid-template-columns: minmax(0,1fr); } }
.prt-faq__i { border: 1.5px solid var(--prt-line-card); border-radius: 14px; height: fit-content; }
.prt-faq__i summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 22px; cursor: pointer; list-style: none;
  font-size: 15px; font-weight: 700; line-height: 1.4; color: var(--prt-navy);
}
.prt-faq__i summary::-webkit-details-marker { display: none; }
/* Plus rysowany dwoma pseudoelementami — bez pliku i bez ikony z biblioteki. */
.prt-faq__plus { position: relative; flex: none; width: 16px; height: 16px; transition: transform var(--prt-transition); }
.prt-faq__plus::before, .prt-faq__plus::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: var(--prt-pink-cta);
}
.prt-faq__plus::before { width: 16px; height: 2px; transform: translate(-50%,-50%); }
.prt-faq__plus::after { width: 2px; height: 16px; transform: translate(-50%,-50%); }
.prt-faq__i[open] .prt-faq__plus { transform: rotate(45deg); }
.prt-faq__o { padding: 0 22px 18px; }
.prt-faq__o p { margin: 0; font-size: 14px; font-weight: 500; line-height: 1.6; color: var(--prt-text-muted); }
@media (hover: hover) and (pointer: fine) {
  .prt-faq__i summary:hover { color: var(--prt-pink-cta); }
}
.prt-faq__i summary:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 2px; border-radius: 14px; }

/* --- pasmo końcowe z Tango ----------------------------------------- */
.e-con.e-flex.prt-kat-cta {
  --flex-direction: row; --align-items: flex-end;
  --row-gap: clamp(24px,3vw,40px); --column-gap: clamp(24px,3vw,40px);
  --border-radius: var(--prt-radius-panel); --overflow: hidden;
  --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
  background: var(--prt-surface-pink-strong);
}
.e-con.e-flex.prt-kat-cta__l {
  --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px;
  --padding-top: clamp(32px,3.4vw,48px); --padding-right: 0px;
  --padding-bottom: clamp(32px,3.4vw,48px); --padding-left: clamp(32px,3.4vw,48px);
}
/* Tango STOI na dolnej krawędzi pasma — stąd `align-self: flex-end`, zerowy
   padding dolny i `object-position: bottom`. */
.e-con.e-flex.prt-kat-cta__tango {
  --flex-grow: 0; --flex-shrink: 0; --flex-basis: 42%; --width: 42%;
  --align-self: flex-end;
  --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
}
.prt-kat-cta__tango img {
  display: block; width: 100%; height: clamp(200px,19vw,250px);
  object-fit: contain; object-position: bottom center;
}
@media (max-width: 940px) {
  .e-con.e-flex.prt-kat-cta { --flex-direction: column; --align-items: stretch; }
  .e-con.e-flex.prt-kat-cta__tango { display: none; }
}

/* --- typografia sekcji --------------------------------------------- */
.elementor-widget-heading.prt-kat-h1 .elementor-heading-title {
  font-size: clamp(38px,4.6vw,62px); line-height: 1.02; font-weight: 900;
  letter-spacing: -.034em; color: var(--prt-navy); margin: 0;
}
.elementor-widget-heading.prt-kat-h2 .elementor-heading-title {
  font-size: clamp(30px,3.6vw,46px); line-height: 1.04; font-weight: 900;
  letter-spacing: -.03em; color: var(--prt-navy); margin: 0;
}
/* Brief 2026-10-31, A i C.10: jedna skala H2 sekcji pod hero. */
.elementor-widget-heading.prt-kat-h2--panel .elementor-heading-title { font-size: clamp(28px,3.2vw,42px); line-height: 1.06; font-weight: 900; letter-spacing: -.03em; }
.elementor-widget-heading.prt-kat-h2--seo .elementor-heading-title { font-size: clamp(28px,3.2vw,42px); }
.elementor-widget-heading.prt-kat-h2--cta .elementor-heading-title { font-size: clamp(22px,2.2vw,28px); line-height: 1.06; }
/* Sekcja „Polecane tkaniny" na karcie produktu — handoff chce clamp(26px,2.8vw,36px),
   czyli mniej niż nagłówek katalogu, bo to blok uzupełniający, nie tytuł strony. */
.elementor-widget-heading.prt-kat-h2--polecane .elementor-heading-title { font-size: clamp(28px,3.2vw,42px); line-height: 1.06; }
/* Wewnętrzne kontenery sekcji dostawały kitowe 28 px: nagłówek był wcięty względem kafli,
   a na telefonie miał ~80 px i nachodził na „Wszystkie materiały". */
.e-con:has(> .e-con-inner > .prt-kat-naglowek .prt-kat-h2--polecane) .prt-kat-naglowek,
.e-con:has(> .prt-kat-naglowek .prt-kat-h2--polecane) .prt-kat-naglowek,
.prt-kat-naglowek:has(.prt-kat-h2--polecane) .prt-kat-naglowek__tx { --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px; padding: 0; }
@media (max-width: 600px) {
  .prt-kat-naglowek:has(.prt-kat-h2--polecane) .prt-kat-naglowek__tx { --flex-basis: 100%; }
  .prt-kat-naglowek:has(.prt-kat-h2--polecane) { --row-gap: 8px; }
}
.elementor-widget-text-editor.prt-kat-lead p, .elementor-widget-text-editor.prt-kat-lead { max-width: 480px; margin: 24px 0 0; font-size: clamp(16px,1.4vw,19px); line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.prt-kat-lead strong { font-weight: 800; color: var(--prt-navy); }
.elementor-widget-text-editor.prt-kat-panel-lead p, .elementor-widget-text-editor.prt-kat-panel-lead { max-width: 540px; margin: 16px 0 0; font-size: 16px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.elementor-widget-text-editor.prt-kat-cta-lead p, .elementor-widget-text-editor.prt-kat-cta-lead { max-width: 470px; margin: 8px 0 0; font-size: clamp(15px,1.3vw,18px); line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
/* Link „Porównaj wszystkie materiały” / „Zobacz wszystkie pytania” — tekst
   ze strzałką, nie przycisk. */
.prt-kat-link .elementor-button {
  display: inline-flex; align-items: center; gap: 10px; padding: 0 0 6px;
  background: transparent; color: var(--prt-navy); font-size: 15px; font-weight: 800;
}
.prt-kat-link .elementor-button:hover { color: var(--prt-pink-cta); }
.prt-kat-link .elementor-button::after {
  content: ""; width: 17px; height: 11px; background: var(--prt-pink-cta);
  -webkit-mask: var(--prt-strzalka) center/contain no-repeat;
          mask: var(--prt-strzalka) center/contain no-repeat;
}

@media (prefers-reduced-motion: reduce) {
  .prt-mat .e-loop-item, .prt-mat__media img, .prt-seo-tile, .prt-faq__plus,
  .elementor-widget-heading.prt-mat__more .elementor-heading-title::after { transition: none; }
  .prt-mat .e-loop-item:hover, .prt-seo-tile:hover { transform: none; }
  .prt-mat .e-loop-item:hover .prt-mat__media img { transform: none; }
}

/* --- kategoria bez treści: sekcja znika w całości ------------------- */
/* ⚠️ Szablon jest JEDEN dla wszystkich rodzajów, a pola termu wypełnia się
   po kolei. Rodzaj bez treści pokazywał pusty niebieski panel „Dlaczego…”,
   nagłówek FAQ bez pytań i dwa pasy samego paddingu. Shortcody zwracają wtedy
   pusty string, więc rozpoznajemy to po BRAKU wyrenderowanego markupu.

   `:has()` nie jest wspierane wszędzie (Firefox < 121), ale degradacja jest
   łagodna: sekcja zostaje pusta, dokładnie tak jak przed tą regułą. */
/* ⚠️ `:has()` NIE MOŻE zawierać `:has()` — taki selektor jest nieprawidłowy
   i przeglądarka odrzuca CAŁĄ grupę, więc żadna z reguł nie działa. Stąd dwa
   osobne `:has()` obok siebie zamiast jednego zagnieżdżonego. */
.e-con.e-flex.prt-kat-sec:has(.prt-kat-panel):not(:has(.prt-ben__i)),
.e-con.e-flex.prt-kat-sec#inspiracje:not(:has(.prt-insp__i)),
.e-con.e-flex.prt-kat-sec#o-materiale:not(:has(.prt-seo-tile)),
.e-con.e-flex.prt-kat-sec#faq:not(:has(.prt-faq__i)) { display: none; }

/* Nagłówek z pustym polem dynamicznym zostawia sam margines — nie pokazujemy
   pustych wierszy między sekcjami. */
.prt-kat-h1 .elementor-heading-title:empty,
.prt-kat-h2 .elementor-heading-title:empty,
.prt-eyebrow .elementor-heading-title:empty,
.prt-kat-seo__h3 .elementor-heading-title:empty { display: none; }

/* ===================================================================
   STRONA PRODUKTU (PDP) — karta tkaniny `/tkanina/{slug}/` (2026-10-18)

   Z paczki `Printella_strona_produktu.zip`. Szablon Elementora 5679
   „Karta tkaniny" sklada strone z NATYWNYCH widgetow, wiec selektory
   celuja albo w klasy z `_css_classes`, albo w markup shortcodow
   `Printella_Fabric_Produkt` (galeria, specyfikacja, popupy).

   ⚠️ Czego tu NIE ma, celowo: `.prt-table`, `.prt-callout`, `.prt-prose`,
   `.prt-insp` i przyciski zyja juz w tym arkuszu w wersji Printelli i to
   ONE obowiazuja. Paczka ma wlasne, inne warianty tych komponentow —
   nie nadpisujemy nimi systemu, tylko dokladamy modyfikatory tam, gdzie
   PDP naprawde potrzebuje czegos innego (`.prt-table--tiers`).

   ⚠️ Popupy to `<dialog>`, wiec siedza poza kontenerem Elementora i nie
   da sie ich zagniezdzic pod klasa strony — stad wlasny prefiks
   `printella-popup`, zgodny z nazwa z paczki.
   =================================================================== */

:root {
  /* Popupy (2026-10-18). Reszta palety PDP jedzie na istniejacych tokenach:
     surface-cool (tlo kafli galerii), surface-grey (wiersz specyfikacji),
     surface-blue (pasek zakladek i pasmo probki), surface-blue-alt (plakietka
     rabatu) — paczka nazywa je inaczej, ale to te same role i te same odcienie. */
  --prt-shadow-modal: 0 30px 80px rgba(16, 27, 84, .18);
  --prt-overlay:
    radial-gradient(ellipse at 3% 8%, rgba(255, 150, 183, .48), transparent 58%),
    radial-gradient(ellipse at 6% 94%, rgba(177, 148, 247, .40), transparent 60%),
    radial-gradient(ellipse at 94% 6%, rgba(118, 203, 251, .42), transparent 57%),
    radial-gradient(ellipse at 98% 48%, rgba(157, 229, 203, .36), transparent 53%),
    radial-gradient(ellipse at 94% 96%, rgba(255, 187, 151, .40), transparent 59%),
    rgba(248, 247, 255, .52);
  --prt-z-popup: 1001;
}

/* --- uklad dwukolumnowy ------------------------------------------- */
.e-con.e-flex.prt-pdp {
  --flex-direction: row; --align-items: flex-start;
  --row-gap: clamp(28px,4vw,56px); --column-gap: clamp(28px,4vw,56px);
}
/* ⚠️ PODZIAŁ KOLUMN PRZEZ `flex-grow`, NIE PRZEZ PROCENT.
   `flex-basis: 52%` liczy się od CAŁEJ szerokości kontenera, a `fr` w gridzie dzieli
   przestrzeń PO odjęciu gapu — dlatego 52% i 1.08fr/1fr nie są tym samym, choć
   1,08/2,08 = 51,9%. Policzone na 1440: kontener 1280 − 2×28 = 1224. Próbnik dzieli
   1224 − 56 = 1168 → 606,5 i 561,5. Karta brała 52% z 1224 = 636,5, a reszta po gapie
   szła do drugiej kolumny → 531,5. Zmierzone przez FreeAgenta: 30 px różnicy w każdej
   kolumnie na 1440 i 22 px na 1024.
   Z `--flex-basis: 0` i proporcją w `--flex-grow` podział reszty jest identyczny z `fr`.
   `--width` musi zejść na `auto`, bo inaczej nadpisuje `width` i basis przestaje liczyć.

   ⚠️⚠️ SPECYFICZNOŚĆ MUSI BYĆ WYŻSZA OD REGUŁY PER-ELEMENT ELEMENTORA, A NIE TYLKO
   WYŻSZA OD JEGO DOMYŚLNYCH. 5.112.4 wyszło z selektorem o TRZECH klasach
   (`.e-con.e-flex.prt-pdp__media`) i **zwinęło kolumnę galerii do 0 px na desktopie** —
   zdjęć nie było widać. Elementor trzyma dla tego kontenera regułę per-element
   w `uploads/elementor/css/post-5679.css`:
   `.elementor-5679 .elementor-element.elementor-element-pdp0002.e-con { --flex-grow: 0;
   --flex-shrink: 0 }`, czyli CZTERY klasy. Przechodziły więc tylko te zmienne, których
   Elementor tam nie ustawia (`--flex-basis`, `--width`): basis 0 bez wzrostu = szerokość 0.
   Wcześniej zerowy `--flex-grow` nie szkodził, bo szerokość dawało `--width: 52%`.

   Dlatego selektor ma pięć klas. ⚠️ I dlatego nadpisanie mobilne NIŻEJ musi mieć tę samą
   specyficzność — przy trzech klasach przegrałoby z tą regułą i uklad na telefonie
   wróciłby do dwóch kolumn. */
.elementor .prt-pdp > .e-con.e-flex.prt-pdp__media { --flex-grow: 1.08; --flex-shrink: 1; --flex-basis: 0%; --width: auto; }
.elementor .prt-pdp > .e-con.e-flex.prt-pdp__buy   { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0%; --row-gap: 0px; --column-gap: 0px; }

/* Odstęp między kolumnami taki jak na stronie próbnika (decyzja Steve'a 31.10.2026:
   próbnik jest wzorem, karta się dostosowuje).

   ⚠️ `--column-gap` na `.prt-pdp` BYŁ już identyczny — `clamp(28px,4vw,56px)`, tyle samo
   co `.prt-probnik__karta`. Cała różnica brała się z 28 px paddingu POZIOMEGO, który
   Elementor nakłada na obie kolumny: zmierzone przez FreeAgenta na 1440 px odstęp
   treść–treść wynosił **111,5 px na karcie i 55,5 px na próbniku** (56 gapu + 2×28).
   Na 390 px ten sam podwójny padding zwężał treść do 278 px zamiast 334.

   Dlatego zerujemy padding kolumn, a odstęp zostawiamy tam, gdzie jego miejsce — na
   kontenerze.

   ⚠️ Pierwsza wersja (5.112.3) zostawiała tu zdanie, że „52% karty to praktycznie
   1.08fr/1fr próbnika, więc szerokości już się zgadzają". To było BŁĘDNE — procent
   i `fr` liczą się od różnych podstaw, patrz komentarz przy `.prt-pdp__media` niżej. */
.e-con.e-flex.prt-pdp__media,
.e-con.e-flex.prt-pdp__buy { --padding-left: 0px; --padding-right: 0px; }
@media (max-width: 940px) {
  .e-con.e-flex.prt-pdp { --flex-direction: column; --align-items: stretch; }
  /* Ta sama specyficzność co reguła bazowa wyżej (pięć klas) — inaczej nie wygra. */
  .elementor .prt-pdp > .e-con.e-flex.prt-pdp__media { --flex-basis: auto; --width: 100%; }
}

/* --- okruszki karty tkaniny --------------------------------------- */
/* ⚠️ GÓRNY ODSTĘP KARTY PRZYCHODZI Z ELEMENTORA, nie z tego arkusza: kontener okruszków
   ma `--padding-top: 28px` w `uploads/elementor/css/post-5679.css`. Rola „breadcrumb na
   bieli" mówi 4 px, więc przykrywamy to tokenem.

   Selektor jest STRUKTURALNY, nie po identyfikatorze elementu: „pierwszy kontener
   szablonu pojedynczego wpisu na karcie tkaniny". Dzięki temu przetrwa zmianę id
   w Elementorze, a jednocześnie ma (0,3,1) i bije regułę per-element Elementora (0,3,0)
   niezależnie od kolejności arkuszy. Ten sam wzorzec stoi niżej przy `prt-strona-dostawy`. */
body.single-tkanina .elementor-location-single > .e-con:first-of-type {
    --padding-top: var(--prt-below-header-crumb);
}

/* Odstęp pod paskiem okruszków. Sam pasek stylują `.prt-crumbs` wyżej —
   karta tkaniny miała tu własną kopię tych samych deklaracji i to ona
   rozjeżdżała odstęp z resztą serwisu. */
.prt-crumbs-nav { margin: 0 0 var(--prt-okruszki-dol); }

/* --- galeria ------------------------------------------------------ */
.prt-gallery__main { position: relative; aspect-ratio: 1 / 1; border-radius: var(--prt-radius-media); overflow: hidden; background: var(--prt-surface-cool); }
.prt-gallery__main img { display: block; width: 100%; height: 100%; object-fit: cover; }
.prt-gallery__thumbs { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 12px; margin: 12px 0 0; padding: 0; list-style: none; }
.printella .prt-gallery__thumb,
.prt-gallery__thumb { position: relative; aspect-ratio: 1 / 1; padding: 0; border: 2px solid transparent; border-radius: 12px; overflow: hidden; background: var(--prt-surface-cool); cursor: pointer; }
/* Aktywna miniatura: NAVY, nie różowa (brief 2026-10-31, A i C.9). Próbnik miał navy
   już wcześniej — to wyrównanie karty produktu do niego. Dwie reguły, bo jedna jest
   podniesiona o `.printella` dla przebicia stylów Woo. */
.printella .prt-gallery__thumb[aria-current="true"] { border-color: var(--prt-navy); }
.prt-gallery__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.prt-gallery__thumb[aria-current="true"] { border-color: var(--prt-navy); }
.prt-gallery__caption { margin: 12px 0 0; font-size: 13px; font-weight: 600; color: var(--prt-text-muted); }

/* Placeholder tam, gdzie w PIM nie ma zdjecia. Ramka kreskowana, zeby bylo
   widac, ze to brak danych, a nie element projektu. */
.prt-placeholder { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 8px; text-align: center; font-size: 12px; font-weight: 700; line-height: 1.3; color: var(--prt-text-muted); border: 1.5px dashed var(--prt-line); border-radius: inherit; }

/* ⚠️ W MINIATURZE 66 px NAPIS ZASTĘPCZY SIĘ NIE MIEŚCI i jest UCINANY PRZEZ PRZYCISK.
   Zmierzył FreeAgent na `/en/fabric/french-terry-250/`: „Brak zdjęcia" wychodziło 40 px
   poza miniaturę na każdej z trzech i na każdej szerokości od 320 do 390.

   To nie była regresja — widać to dopiero od kiedy bramka mierzy TEKST UCINANY PRZEZ
   PRZODKA Z `overflow`, a nie tylko wychodzący poza okno. Przy `overflow: hidden` na
   przycisku strona się nie przewija, więc żaden wcześniejszy pomiar nie miał tego jak
   zobaczyć — a klient widział ucięte słowo.

   ⚠️ PRZYCZYNA ŹRÓDŁOWA JEST GDZIE INDZIEJ: angielska wersja karty nie ma podpiętych
   zdjęć galerii (polska i niemiecka mają), więc w ogóle nie powinno tam być zastępnika.
   To zgłaszam osobno — tutaj naprawiam tylko to, żeby zastępnik był czytelny, kiedy już
   musi się pokazać. */
.prt-gallery__thumb .prt-placeholder {
    padding: 4px;
    font-size: 11px;
    /* ⚠️ `white-space: normal` MUSI BYĆ, I TO ONO NAPRAWIA. Sam `overflow-wrap` nie
       wystarczył — pierwsza wersja tej reguły miała tylko jego i pomiar nie drgnął.
       Powód: `nowrap` przychodzi z przycisku (reset stylów), a przy `white-space: nowrap`
       wiersz NIE ŁAMIE SIĘ NIGDY, niezależnie od `overflow-wrap`. Dokładnie ten sam
       mechanizm, co godzinę wcześniej przy linku pomocy w polu upuszczania. */
    white-space: normal;
    overflow-wrap: anywhere;
}

/* --- kolumna zakupowa --------------------------------------------- */
/* Kolumna ma `flex_gap: 0`, więc rytm robią WYŁĄCZNIE marginesy pojedynczych
   elementów — część z projektu siedzi w ustawieniach widgetów (nagłówek, cena,
   rabaty, CTA, nota), część tutaj. Przy przenoszeniu zgubiłem `.prt-steps`
   i `.prt-pdp__info`; oba wróciły niżej.
   ⚠️ Nadtytuł wymaga reguły na elemencie WEWNĘTRZNYM, nie na wrapperze.
   `margin-bottom` wrappera zbija się z marginesem dziecka i wygrywa większy,
   więc `.prt-pdp__eyebrow { margin-bottom: 12px }` było martwe — odstęp
   zostawał na 16px z `.prt-eyebrow`. Specyficzność 0,3,0 dobrana, żeby przebić
   tamtą regułę, która sama jest podniesiona przeciw typografii kitu. */
.elementor-widget-heading.prt-pdp__eyebrow .elementor-heading-title { margin-bottom: 12px; font-size: 13px; }
.elementor .prt-pdp__title .elementor-heading-title { font-size: clamp(32px,3.6vw,48px); line-height: 1.04; font-weight: 900; letter-spacing: -.03em; color: var(--prt-navy); text-wrap: balance; }
.prt-pdp__lead { margin-top: var(--space-tight); max-width: 480px; }
.prt-pdp__lead p { font-size: 17px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); margin: 0; }
/* ⚠️ C.4 (brief 2026-10-31): „Parametry materiału" ma mieć `28px 0 14px`. Margines
   NALEŻY DO WIDŻETU, nie do nagłówka — Elementor trzyma dla pdp0006 regułę per-element
   `margin: 28px 0 calc(var(--kit-widget-spacing) + 12px) 0`. Gdybym ustawił margines na
   `.elementor-heading-title`, DODAŁBY SIĘ do tych 12 px i wyszłoby 26 px zamiast 14.
   Dlatego nadpisujemy margines widżetu, i to selektorem o CZTERECH klasach: reguła
   Elementora ma trzy (`.elementor-5679 .elementor-element.elementor-element-pdp0006`),
   a przy równej specyficzności decydowałaby kolejność arkuszy — czyli przypadek.
   Ta sama pułapka zwinęła kolumnę galerii w 5.112.4. */
.elementor .elementor-element.elementor-widget-heading.prt-pdp__h { margin-block: var(--space-section) var(--space-tight); }
.elementor .prt-pdp__h .elementor-heading-title { font-size: 17px; font-weight: 800; color: var(--prt-navy); }

/* Specyfikacja — nie <table>, tylko grid: wiersze skladamy z meta w shortcodzie,
   a grid nie wymaga pustych komorek, gdy ktoregos pola w PIM nie ma. */
.prt-spec { display: grid; grid-template-columns: 46% minmax(0,1fr); border: 1.5px solid var(--prt-line); border-radius: 12px; overflow: hidden; }
.prt-spec__k, .prt-spec__v { padding: 12px 16px; font-size: 14px; line-height: 1.4; }
.prt-spec__k { font-weight: 600; color: var(--prt-text-muted); background: var(--prt-surface-grey); }
.prt-spec__v { font-weight: 700; color: var(--prt-navy); }
.prt-spec__k:not(:nth-child(1)):not(:nth-child(2)),
.prt-spec__v:not(:nth-child(1)):not(:nth-child(2)) { border-top: 1.5px solid var(--prt-line); }
.prt-spec--lg { max-width: 720px; }

/* Brak danych w PIM. Ma byc WIDOCZNY: pusty wiersz wyglada jak komplet
   i nikt go nie zglosi, a to sa pola do uzupelnienia, nie element projektu. */
.prt-brak { display: inline-block; padding: 2px 8px; border: 1.5px dashed var(--prt-line-input); border-radius: 6px; font-size: 12px; font-weight: 700; color: var(--prt-text-faint); white-space: normal; }
.prt-lead-time strong .prt-brak { font-size: 12px; }
.prt-spec--lg .prt-spec__k, .prt-spec--lg .prt-spec__v { padding: 14px 18px; font-size: 15px; }

/* ---------------------------------------------------------------------------
   Zakladka Parametry: dwie tabele obok siebie (polecenie Steve'a 2.11.2026).
   Lewa kolumna to parametry, prawa pielegnacja dziedziczona z kategorii.

   FLEX, NIE GRID, i to jest wybor pod Elementora: kontener zakladki ma wlasne
   `display:flex` z kitu, a nasz wrapper siedzi w srodku widzetu shortcode'u.
   `flex: 1 1 320px` daje dwie rowne kolumny, gdy sa dwie, PELNA szerokosc, gdy
   jest jedna (kategoria bez tresci pielegnacji), i zawija do jednej kolumny
   ponizej ~760 px bez ani jednego media query.

   `max-width: none` na `--lg` jest konieczne: 720 px bylo limitem dla JEDNEJ
   tabeli na calej szerokosci. W kolumnie szerokosc ogranicza juz sama kolumna,
   a zostawiony limit zrobilby z prawej kolumny pusty pas przy 1440 px.
   --------------------------------------------------------------------------- */
.prt-param { display: flex; flex-wrap: wrap; gap: clamp(24px,3vw,44px); align-items: flex-start; }
.prt-param__kol { flex: 1 1 320px; min-width: 0; }
.prt-param__kol .prt-spec--lg { max-width: none; }
.prt-spec--care .prt-spec__k, .prt-spec--care .prt-spec__v { padding: 14px 18px; font-size: 15px; }

.prt-care__h { margin: 0 0 14px; font-size: 21px; line-height: 1.2; font-weight: 900; letter-spacing: -.01em; color: var(--prt-navy); }
.prt-care__wp, .prt-care__wyjatki { margin-top: clamp(18px,2vw,24px); }
.prt-care__wp-h, .prt-care__wyjatki-h { margin: 0 0 10px; font-size: 16px; line-height: 1.3; font-weight: 800; color: var(--prt-navy); }
.prt-care__wp-nota { margin-top: 12px; }
.prt-care__wp-nota, .prt-care__wyjatki { font-size: 14px; line-height: 1.6; font-weight: 500; color: var(--prt-text-muted); }
.prt-care__wp-nota p, .prt-care__wyjatki p { margin: 0 0 10px; }
.prt-care__wp-nota p:last-child, .prt-care__wyjatki p:last-child { margin-bottom: 0; }

.elementor .prt-price .elementor-heading-title { font-size: clamp(34px,3.4vw,44px); line-height: 1; font-weight: 900; letter-spacing: -.03em; color: var(--prt-navy); }
.prt-price__note p { margin: var(--space-tight) 0 0; font-size: 14px; line-height: 1.5; font-weight: 500; color: var(--prt-text-muted); }

/* Link-przycisk: wyglada jak link, jest <button>, bo otwiera popup. */
/* ⚠️ Prefiks `.printella` nie jest ozdobą. `style.css` ubiera KAŻDY goły
   <button> regułą `.printella button` (0,1,1) — ramka 1,5 px #cbd5e1 plus
   `--btn-radius`. Sama `.prt-link-u` (0,1,0) z tym przegrywa i linki, ✕ popupu,
   miniatury galerii oraz przełącznik brutto/netto dostawały ramki, których
   projekt nie ma. Dlatego wszystkie te komponenty prowadzimy przez `.printella`. */
.printella .prt-link-u,
.prt-link-u { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; text-decoration: underline; text-underline-offset: 4px; background: none; border: 0; border-radius: 0; padding: 0; cursor: pointer; color: var(--prt-navy); text-align: left; font-family: inherit; }
.printella .prt-link-u:hover { background: none; border-color: transparent; }
.prt-link-u--pink { color: var(--prt-pink-cta); font-weight: 800; }
.prt-link-u svg { flex: none; }
@media (hover: hover) and (pointer: fine) { .prt-link-u:hover { color: var(--prt-pink-cta); } }

.prt-steps { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 22px 0 0; padding: 0; list-style: none; font-size: 14px; font-weight: 700; color: var(--prt-navy); }
.prt-steps li { display: flex; align-items: center; gap: 9px; }
.prt-steps__n { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--prt-radius-pill); background: var(--prt-surface-blue); font-size: 13px; font-weight: 900; }
.prt-steps__sep { color: var(--prt-blue-ink); }

/* Trzy kafelki pod ceną: rabaty, dostawa, zwroty.
   Zastąpiły linki tekstowe ze strzałką — te siedziały w dwóch różnych miejscach
   kolumny i czytały się jak drobiazgi, a są trzema równorzędnymi odpowiedziami
   na tę samą wątpliwość przed zakupem.
   ⚠️ `grid-template-columns: repeat(3, 1fr)`, nie `auto-fit`: trzy kafle mają
   trzymać równą szerokość także wtedy, gdy etykiety są różnej długości. Na wąskim
   ekranie łamiemy je jawnie w media query niżej, zamiast pozwolić siatce decydować. */
.prt-pdp__akcje { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.prt-pdp__akcja {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; min-height: 112px; padding: 16px 10px;
  background: #fff; border: 1.5px solid var(--prt-line); border-radius: 14px;
  font-family: var(--prt-font-sans); font-size: 15px; font-weight: 800; line-height: 1.25;
  color: var(--prt-navy); text-align: center; cursor: pointer;
  transition: border-color var(--prt-transition), background var(--prt-transition);
}
.prt-pdp__akcja:hover { border-color: var(--prt-pink-cta); background: var(--prt-surface-grey); }
.prt-pdp__akcja:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 2px; }
.prt-pdp__akcja svg { color: var(--prt-navy); flex: none; }
.prt-pdp__akcja-txt { display: flex; flex-direction: column; }

@media (max-width: 460px) {
  .prt-pdp__akcje { grid-template-columns: 1fr; }
  .prt-pdp__akcja { flex-direction: row; justify-content: flex-start; gap: 12px; min-height: 0; padding: 12px 14px; text-align: left; }
  .prt-pdp__akcja-txt { flex-direction: row; gap: 4px; }
}

/* --- zakladki (natywny widget nested-tabs) ------------------------- */
/* Celujemy w markup Elementora, bo zakladki to widget, nie nasz HTML.
   `.e-n-tabs-heading` to pasek, `.e-n-tab-title` pojedyncza zakladka. */
/* ⚠️ Specyficzność. Elementor maluje zakładki regułą
   `.elementor .elementor-element.elementor-widget-n-tabs:not(:has(…)) > .e-n-tabs … .e-n-tab-title`
   w kolorze akcentu z kitu — zmierzone: tło #D8306A na aktywnej zakładce.
   Sama `.prt-pdp-tabs .e-n-tab-title` (0,2,0) z tym przegrywa, więc
   prowadzimy selektor przez `.elementor .elementor-element`, tak jak oni.
   Projekt chce paska z podkreśleniem, nie pigułek. */
/* Widget wystawia własne zmienne i to ONE wygrywają — reguła Elementora dla
   aktywnej zakładki czyta `--n-tabs-title-background-color-active` (zmierzone:
   #D8306A z akcentu kitu). Nadpisanie samego `background` przegrywało, bo ich
   selektor jest dłuższy; ustawienie zmiennych rozbraja to bez walki na wagi. */
.elementor .elementor-element.prt-pdp-tabs {
  --n-tabs-title-background-color: transparent;
  --n-tabs-title-background-color-active: transparent;
  --n-tabs-title-background-color-hover: transparent;
  --n-tabs-title-color-normal: var(--prt-navy);
  --n-tabs-title-color-active: var(--prt-navy);
  --n-tabs-title-border-radius: 0;
  --n-tabs-gap: 0px;
}
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs-heading {
  gap: clamp(8px,2vw,28px);
  border-top: 1.5px solid var(--prt-line); border-bottom: 1.5px solid var(--prt-line);
  overflow-x: auto; scrollbar-width: none;
}
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs-heading::-webkit-scrollbar { display: none; }
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs .e-n-tab-title,
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs .e-n-tab-title[aria-selected="false"],
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs .e-n-tab-title[aria-selected="true"] {
  flex: none; padding: 18px 6px 16px;
  background: transparent; background-image: none;
  border: 0; border-bottom: 3px solid transparent; border-radius: 0;
  font-family: var(--prt-font-sans); font-size: 15px; font-weight: 600;
  white-space: nowrap; color: var(--prt-navy);
}
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs .e-n-tab-title[aria-selected="true"] {
  border-bottom-color: var(--prt-navy); font-weight: 900;
}
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs .e-n-tab-title:hover { color: var(--prt-pink-cta); }
.elementor .elementor-element.prt-pdp-tabs .e-n-tabs-content > .e-con { padding-top: clamp(36px,4vw,56px); }

/* --- zakladki na telefonie: to NIE sa zakladki, to akordeon ------------- */
/* ⚠️ Ponizej 768 px Elementor SAM zamienia ten widget w akordeon — robi to klasa
   `e-n-tabs-mobile` (ustawienie „Breakpoint" widgetu), ktora w swoim `@media`
   daje `--n-tabs-heading-display: contents` i przeplata tytuly z panelami przez
   `order`. Czyli pasek przestaje istniec, a tytuly staja sie wierszami listy.

   I wlasnie dlatego wygladalo to na „lamiace sie zakladki" (Steve, 31.10.2026,
   punkt 3 porownania): tytuly dalej mialy styl paska — `white-space: nowrap`,
   poziomy padding 6 px, podkreslenie 3 px tylko na aktywnym — a obramowania paska
   (`border-top`/`border-bottom` na `.e-n-tabs-heading`) znikaly razem z paskiem,
   bo `display: contents` nie rysuje nic. Zostawala lista napisow bez separatorow,
   z trescia wsuniueta pomiedzy i odstepem 36-56 px od swojego tytulu.

   ⚠️ SPECYFICZNOSC: regula Elementora to `.elementor.elementor .elementor-widget-n-tabs
   .e-n-tab-title` — podwojona `.elementor` celowo. Dlatego tutaj tez podwajam, inaczej
   samo `@media` nic nie wygrywa (ta sama lekcja co pigulka probnika tego samego dnia:
   zapytanie medialne nie podnosi wagi selektora). */
@media (max-width: 767px) {
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title,
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title[aria-selected="false"],
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title[aria-selected="true"] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    /* ⚠️ W trybie paska boczny rytm dawal KONTENER Elementora. `display: contents` na
       `.e-n-tabs-heading` zdejmuje pasek z ukladu, wiec tytuly wyladowaly na calej
       szerokosci okna: tekst na x=0, strzalka przy krawedzi, podczas gdy cala reszta
       strony — takze tresc rozwinietej zakladki — trzymala 28 px (zmierzyl FreeAgent
       na 390 px). Padding daje rytm TEKSTOWI, a linie zostaja od krawedzi do krawedzi,
       bo to separatory listy, a nie obramowanie kafelka. */
    padding: 16px var(--prt-margines-boczny);
    border-bottom: 1.5px solid var(--prt-line);
    font-size: 17px;
    font-weight: 700;
    white-space: normal;
    text-align: left;
  }

  /* Pierwszy wiersz dostaje gorna linie, zeby lista miala zamknieta gore —
     pasek ja mial, akordeon musi odtworzyc. `:first-of-type` liczy sie w `.e-n-tabs-heading`,
     bo `display: contents` zmienia UKLAD, a nie drzewo dokumentu. */
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title:first-of-type {
    border-top: 1.5px solid var(--prt-line);
  }

  /* Otwarty wiersz: bez podkreslenia 3 px (to byl znacznik AKTYWNEJ ZAKLADKI w pasku,
     a w liscie czytalo sie jak podwojna linia), zostaje sama waga pisma. */
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title[aria-selected="true"] {
    border-bottom-color: transparent;
    font-weight: 900;
  }

  /* Strzalka: bez niej lista napisow nie mowi, ze da sie ja rozwinac. Rysowana
     CSS-em, bo widget nie ma tu wlasnej ikony, a dokladanie jej przez Elementora
     oznaczaloby edycje `_elementor_data`. */
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title::after {
    content: "";
    flex: none;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--prt-navy);
    border-bottom: 2px solid var(--prt-navy);
    transform: rotate(45deg) translateY(-2px);
    transition: transform .15s;
  }

  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tab-title[aria-selected="true"]::after {
    transform: rotate(225deg) translateY(-2px);
  }

  /* Tresc nalezy do tytulu nad soba, wiec odstep jest „powiazany", nie „sekcyjny". */
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile .e-n-tabs-content > .e-con {
    padding-top: var(--space-tight);
    padding-bottom: var(--space-group);
  }

  /* ⚠️ W AKORDEONIE NAGLOWEK PANELU DUBLUJE NAZWE WIERSZA. W pasku zakladek tak nie bylo:
     nazwa stala w pasku, a H2 otwieral tresc pod nim. Po rozwinieciu „Parametry" czytalo
     sie „Parametry" dwa razy, raz 17/900 i raz ~30 px (zmierzyl FreeAgent na 390 px).

     ⚠️ PIERWSZY PANEL JEST WYJATKIEM i dlatego nie ukrywam wszystkich: zakladka nazywa sie
     „O materiale", a jej naglowek to haslo tkaniny („Miekka baza. Nieskonczone mozliwosci.")
     — czyli tresc, a nie powtorzenie. Pozostale cztery powtarzaja nazwe zakladki znak
     w znak (sprawdzone na :10003: Parametry, Przygotowanie pliku, Dostawa i zwroty,
     Producent i bezpieczenstwo).

     Warunek jest WIEC POZYCYJNY, nie tekstowy — CSS nie porowna napisow. Jesli pierwszy
     panel przestanie byc „O materiale" albo ktorys dostanie wlasny naglowek, trzeba tu
     wrocic. Nazwa zostaje w przycisku, wiec struktura dokumentu nic nie traci. */
  .elementor.elementor .elementor-element.prt-pdp-tabs.e-n-tabs-mobile
    .e-n-tabs-content > .e-con:not(:first-of-type) > .prt-kat-h2--panel {
    display: none;
  }
}

.prt-list { display: flex; flex-direction: column; gap: 10px; max-width: 640px; margin: 0; padding-left: 20px; list-style: disc; font-size: 16px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.elementor .prt-insp-title .elementor-heading-title { font-size: 19px; font-weight: 800; color: var(--prt-navy); }

/* --- treści z PIM w zakładkach karty (pakiet PIM, 31.10.2026) --------------
   Nagłówek i opis sekcji wychodzą z JEDNEGO shortcode'a (`prt_tk_tresc`), więc
   nie mają wrappera widgetu Elementora — natywne `prt-kat-h2--panel`
   i `prt-kat-lead` tu nie trafiają. Klasy własne muszą dać tę samą skalę, bo
   w tym samym panelu stają oba warianty: treść z PIM i zapas wpisany
   w szablonie (gdy PIM jeszcze nie zatwierdził treści).

   ⚠️ Odstęp nagłówek → tekst to `--space-tight`. Na starym szablonie wychodzi
   68 px i składa się z TRZECH wartości, nie dwóch: 20 px gapu kontenera plus
   24 px marginesu opakowania `prt-kat-lead` plus 24 px marginesu `<p>` w środku.
   Te dwa ostatnie nie zlewają się w jeden, bo **element flexa tworzy niezależny
   kontekst formatowania**, a to blokuje scalanie marginesów przez jego krawędź
   — sam margines rodzica z marginesem pierwszego dziecka scaliłby się w zwykłym
   bloku. Zmierzone przez FreeAgenta na literach: 64 px stary, 10 px nowy
   (różnica między literami a pudełkami to wcięcia z line-height).
   W jednym widgecie zostaje sam margines `prt-tresc__tekst`. */
.prt-tresc__h {
  font-size: clamp(28px,3.2vw,42px); line-height: 1.06; font-weight: 900;
  letter-spacing: -.03em; color: var(--prt-navy); margin: 0;
}
/* ⚠️ BEZ `max-width`. Kolumnami rządzi opakowanie niżej, a kiedy kolumny schodzą
   do jednej (≤900 px), ten cap znowu by się włączył i tekst kończyłby się przed
   krawędzią panelu — czyli dokładnie to, co wyglądało chaotycznie. */
.prt-tresc__tekst {
  margin: var(--space-tight) 0 0;
  font-size: 16px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted);
}

/* ⚠️ ŻADNYCH `columns` / `column-count` w zakładce „O materiale". Układ
   wielokolumnowy CSS rozcinał akapity w połowie zdania między kolumnami —
   brief z 1.11.2026 zabrania go wprost. Zakładka ma własne siatki
   (`.prt-om__gora`, `.prt-om__bloki`), w których każdy akapit należy do
   JEDNEJ komórki i nie ma gdzie się przelać. */

/* === ZAKŁADKA „O MATERIALE" — układ z briefu 1.11.2026 ===================
   Treść z PIM, jeden shortcode `prt_tk_o_materiale`. Wartości wpisane za
   briefem; tam, gdzie brief podaje heks, który JEST już tokenem, używamy
   tokenu (#E3E7F2 = --prt-line, #101B54 = --prt-navy, #3A4478 =
   --prt-text-muted, #F0417E = --prt-pink-cta). Dwa odcienie z briefu nie mają
   tokenu i stoją heksem, z adnotacją — dopisywanie tokenu pod jedno użycie
   zaśmieca paletę bardziej, niż pomaga. */

/* --- 1. wstęp obok tabeli cech --- */
.prt-om__gora {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.prt-om__h2 {
  margin: 0;
  font-size: clamp(28px, 3.2vw, 42px); line-height: 1.06; font-weight: 900;
  letter-spacing: -.03em; color: var(--prt-navy); text-wrap: balance;
}
.prt-om__lead {
  margin: var(--space-tight) 0 0; max-width: 62ch;
  font-size: 17px; line-height: 1.6; font-weight: 500;
  color: var(--prt-text-muted); text-wrap: pretty;
}
.prt-om__lead strong { font-weight: 800; color: var(--prt-navy); }

/* --- 2. tabela cech --- */
/* ⚠️ `max-content` na kolumnie etykiet działa TYLKO dlatego, że `<dt>` i `<dd>`
   są bezpośrednimi dziećmi tej siatki. Każde opakowanie wiersza w `<div>`
   zrobiłoby z wiersza osobną siatkę i etykiety przestałyby stać w jednej linii. */
.prt-om__cechy {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  margin: 0; font-size: 15px;
  border: 1.5px solid var(--prt-line); border-radius: 12px; overflow: hidden;
}
.prt-om__cechy dt, .prt-om__cechy dd { margin: 0; padding: 12px 16px; }
.prt-om__cechy dt {
  font-weight: 700; color: var(--prt-navy);
  background: #F7F9FD; /* brief; brak tokenu — najbliższy --prt-surface-cool to #F6F8FC */
}
.prt-om__cechy dd { font-weight: 500; color: var(--prt-text-muted); }
.prt-om__cechy dt:not(:first-of-type), .prt-om__cechy dd:not(:first-of-type) {
  border-top: 1.5px solid var(--prt-line);
}

/* --- 3. bloki --- */
/* ⚠️ `padding-top`, NIE `margin-top`, i BEZ linii oddzielającej (brief v2).
   Margines na siatce w zwiniętym wrapperze zostawiałby pusty odstęp pod
   przyciskiem, bo margines nie zwija się razem z wierszem siatki o wysokości
   0fr — padding tak. Linia zniknęła, bo zakładka rozdziela sekcje odstępem
   i hierarchią nagłówków, nie kreskami. */
.prt-om__bloki {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(24px, 3vw, 44px);
  padding-top: clamp(24px, 2.6vw, 32px);
}
.prt-om__blok { min-width: 0; }
.prt-om__h3 {
  margin: 0;
  font-size: 21px; line-height: 1.2; font-weight: 900; color: var(--prt-navy);
}
.prt-om__p {
  margin: var(--space-tight) 0 0;
  font-size: 16px; line-height: 1.6; font-weight: 500;
  color: var(--prt-text-muted); text-wrap: pretty;
}
.prt-om__p strong { font-weight: 800; color: var(--prt-navy); }
/* Dalsze akapity: `padding-top`, nie `margin-top` — brief. Margines pierwszego
   akapitu w ukrytym wrapperze scaliłby się z jego krawędzią i przy zwinięciu
   zostawiał 14 px pustego miejsca pod widocznym akapitem. */
.prt-om__p--dalszy { margin-top: 0; padding-top: 12px; }

/* --- 4. rozwijanie --- */
/* Animacja na `grid-template-rows` 0fr → 1fr: jedyny sposób, żeby przejście
   objęło NIEZNANĄ wysokość treści. `height: auto` się nie animuje, a stała
   wysokość w pikselach ucina dłuższe akapity. */
.prt-om__wiecej {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .35s ease;
}
.prt-om__wiecej-in { overflow: hidden; min-height: 0; }
.prt-om--otwarty .prt-om__wiecej { grid-template-rows: 1fr; }
@media (prefers-reduced-motion: reduce) {
  .prt-om__wiecej { transition: none; }
}

.prt-om__btn {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: clamp(24px, 2.6vw, 32px); height: 44px; padding: 0 20px;
  /* Etykieta zawsze w jednej linii — „Więcej o materiale" i „More about this
     material" przy 920 px łamały się na dwa wiersze i przycisk rósł do 70 px. */
  white-space: nowrap;
  border: 0; border-radius: 999px; background: #EEF2FA; /* brief; brak tokenu */
  font-size: 15px; font-weight: 800; color: var(--prt-navy);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .prt-om__btn:hover { background: var(--prt-line); }
}
.prt-om__btn:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 2px; }
.prt-om__btn-ch { flex: none; transition: transform .2s; }
.prt-om__btn[aria-expanded="true"] .prt-om__btn-ch { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .prt-om__btn-ch { transition: none; }
}

/* --- 5. „Co uszyjesz…" — zawsze widoczne, pełna szerokość, bez linii --- */
.prt-om__zast { margin-top: clamp(32px, 3.6vw, 48px); }
.prt-om__zast-p {
  margin: var(--space-tight) 0 0; max-width: 75ch;
  font-size: 17px; line-height: 1.6; font-weight: 500;
  color: var(--prt-text-muted); text-wrap: pretty;
}
.prt-om__zast-p strong { font-weight: 800; color: var(--prt-navy); }
/* Drugi i kolejne akapity: `padding-top`, tak jak w blokach (brief). */
.prt-om__zast-p--dalszy { margin-top: 0; padding-top: 12px; }

/* --- 6. inspiracje ---------------------------------------------------- */
/* ⚠️ REGUŁY ZAWĘŻONE DO `.prt-om`. Klasa `.prt-insp` jest WSPÓLNA z landingiem
   kategorii (`Printella_Fabric_Landing`), więc stylowanie jej globalnie
   zmieniłoby tamte strony, o których brief nie mówi. */
.prt-om__insp-h {
  margin: 28px 0 16px;
  font-size: 21px; line-height: 1.2; font-weight: 900; color: var(--prt-navy);
}
.prt-om .prt-insp {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px;
}
.prt-om .prt-insp__i { margin: 0; }
/* ⚠️ KWADRAT, nie 4:3 (Steve, 1.11.2026: „miały być kwadraty"). Brief
   multimediów dopuszczał wyświetlanie w ~5:4, więc dałem 4/3 — a dostarczone
   pliki są 1000×1000. Przy 4/3 `object-fit: cover` obcinał im ok. 25 %
   wysokości (zmierzył FreeAgent: kafel 396×297 przy 1440). Proporcja kafla
   równa proporcji pliku = zero przycięcia. */
.prt-om .prt-insp__media {
  aspect-ratio: 1 / 1; overflow: hidden; border-radius: 16px;
}
.prt-om .prt-insp__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.prt-om .prt-insp figcaption {
  margin-top: 10px; text-align: center;
  font-size: 15px; font-weight: 600; color: var(--prt-navy);
}

/* --- progi z briefu --- */
@media (max-width: 1100px) {
  .prt-om__gora { grid-template-columns: minmax(0, 1fr); row-gap: 22px; }
  .prt-om__cechy { max-width: 610px; }
}
@media (max-width: 900px) {
  .prt-om__bloki { grid-template-columns: minmax(0, 1fr); }
}

/* ≤640 px inspiracje jadą poziomym paskiem ze snapem, nie kolumną.
   Ujemne marginesy równe paddingowi panelu wypuszczają pasek do krawędzi ekranu,
   a `scroll-padding` trzyma pierwsze zdjęcie w tej samej linii co tekst.
   `grid-auto-columns: 78%` daje widoczne ~1,3 zdjęcia — to jest sygnał, że jest
   co przewijać; przy 100% nic nie wystaje i pasek wygląda jak pojedyncze zdjęcie. */
@media (max-width: 640px) {
  .prt-om .prt-insp {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin: 0 -28px;
    padding: 0 28px 6px;
    scroll-padding: 0 28px;
    scrollbar-width: none;
  }
  .prt-om .prt-insp::-webkit-scrollbar { display: none; }
  .prt-om .prt-insp__i { scroll-snap-align: start; }
}

/* ⚠️ NA TELEFONIE ETYKIETA IDZIE NAD WARTOŚĆ, nie obok. Brief nie opisuje tabeli
   przy 375 px, a `max-content` działa tam przeciwko czytelności: FreeAgent zmierzył
   na WP260, że najdłuższa etykieta zjada 179 px z 319 px tabeli, więc na wartość
   zostaje 138 px i 79-znakowa wartość zajmuje OSIEM linii. Po spiętrzeniu wartość
   dostaje całą szerokość.

   Obramowanie zmienia się razem z układem: w jednej kolumnie `border-top` na `<dd>`
   rysowałby kreskę MIĘDZY etykietą i jej własną wartością, czyli w środku wiersza. */
@media (max-width: 480px) {
  .prt-om__cechy { grid-template-columns: minmax(0, 1fr); }
  .prt-om__cechy dt { padding-bottom: 2px; }
  .prt-om__cechy dd { padding-top: 2px; background: var(--prt-surface); }
  .prt-om__cechy dd:not(:first-of-type) { border-top: 0; }
  .prt-om__cechy dt:not(:first-of-type) { border-top: 1.5px solid var(--prt-line); }
}
.prt-tresc__tekst > :first-child { margin-top: 0; }
.prt-tresc__tekst p { margin: var(--space-tight) 0 0; }
.prt-tresc__tekst strong { font-weight: 800; color: var(--prt-navy); }
.prt-tresc__tekst a { color: var(--prt-navy); text-decoration: underline; }
.prt-tresc__tekst ul, .prt-tresc__tekst ol {
  display: flex; flex-direction: column; gap: 10px;
  margin: var(--space-tight) 0 0; padding-left: 20px;
}

/* ⚠️ WSZYSTKIE sekcje PIM jadą z JEDNEGO widgetu shortcode'a i odstęp między
   nimi daje ta reguła, a nie gap kontenera. Osobny widget na sekcję wygląda
   czyściej w edytorze, ale widget Elementora renderuje swój div ZAWSZE — także
   gdy shortcode nic nie zwrócił. Trzy niewypełnione sekcje to były trzy puste
   elementy flexa, czyli 60 px martwego miejsca przed „Inspiracjami", i to one
   zjadły odstęp zaoszczędzony na nagłówku. W jednym widgecie pusta sekcja nie
   zostawia niczego, bo nie ma własnego wrappera. */
.prt-tresc + .prt-tresc { margin-top: var(--space-section); }
/* Lista właściwości należy do nagłówka nad sobą, więc odstęp jest „powiązany". */
.prt-tresc + .prt-wlasc { margin-top: var(--space-tight); }
.prt-wlasc + .prt-tresc { margin-top: var(--space-section); }

/* Właściwości „cecha → opis" (`prt_tk_wlasciwosci`). Etykieta ma stałą kolumnę,
   żeby opisy startowały w jednej linii pionowej; na telefonie kolumny nie ma,
   bo przy 390 px na etykietę i opis zostaje po ~170 px i oba się łamią. */
.prt-wlasc { display: grid; gap: var(--space-tight); margin: 0; }
.prt-wlasc__poz { display: grid; grid-template-columns: minmax(0,180px) minmax(0,1fr); gap: 4px 18px; }
.prt-wlasc__nazwa { margin: 0; font-size: 15px; font-weight: 800; color: var(--prt-navy); }
.prt-wlasc__opis { margin: 0; font-size: 16px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
@media (max-width: 600px) {
  .prt-wlasc__poz { grid-template-columns: 1fr; }
}

/* --- pasmo probki -------------------------------------------------- */
/* ⚠️ Tło idzie zwykłą właściwością, nie `--background-color`. Elementor czyta
   tę zmienną tylko wtedy, gdy kontener MA ustawione tło w panelu — bez tego
   nie emituje reguły, która by ją odczytała. Zmierzone: promień i padding
   z własnych zmiennych zadziałały, tło zostało przezroczyste. */
.e-con.e-flex.prt-sample {
  --flex-direction: row; --align-items: center; --flex-wrap: wrap;
  --row-gap: clamp(18px,3vw,36px); --column-gap: clamp(18px,3vw,36px);
  --border-radius: var(--prt-radius-card);
  /* Brief 2026-10-31, C.12: białe tło + ramka zamiast niebieskiego tła, i niższy
     padding pionowy. Ramka próbki na PRÓBNIKU zostaje różowa (#F6CADB) — D.10 mówi
     wprost „bez zmian", więc nie ujednolicam ich. */
  --padding-top: clamp(20px,2.4vw,26px); --padding-bottom: clamp(20px,2.4vw,26px);
  --padding-left: clamp(24px,3vw,40px); --padding-right: clamp(24px,3vw,40px);
  background-color: var(--prt-surface);
  border: 1.5px solid var(--prt-line);
}
.e-con.e-flex.prt-sample__txt { --flex-grow: 1; --flex-shrink: 1; --flex-basis: 0; --row-gap: 0px; --column-gap: 0px; }
.prt-sample__img { position: relative; width: 110px; height: 90px; border-radius: 10px; overflow: hidden; background: var(--prt-surface); flex: none; }
.prt-sample__size { margin: 0; font-size: 14px; font-weight: 600; color: var(--prt-text-muted); }
.prt-sample__size strong { color: var(--prt-navy); }
.prt-sample__price { margin: 4px 0 0; font-size: 26px; font-weight: 900; color: var(--prt-navy); }
@media (max-width: 940px) { .e-con.e-flex.prt-sample { --flex-direction: column; --align-items: stretch; } }

/* --- popupy -------------------------------------------------------- */
.printella-popup { position: fixed; z-index: var(--prt-z-popup); width: calc(100% - 32px); max-width: 580px; max-height: calc(100dvh - 32px); margin: auto; padding: clamp(24px,3.4vw,40px); border: 0; border-radius: var(--prt-radius-tile); background: var(--prt-surface); color: var(--prt-text); font-family: var(--prt-font-sans); box-shadow: var(--prt-shadow-modal); overflow-y: auto; overscroll-behavior: contain; }
.printella-popup--wide { max-width: 640px; }
.printella-popup::backdrop { background: var(--prt-overlay); }
.printella-popup[open] { animation: prt-pop .22s ease; }
@keyframes prt-pop { from { opacity: 0; transform: translateY(8px); } }
.printella .printella-popup__close,
.printella-popup__close { position: absolute; top: 20px; right: 20px; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; background: none; border: 0; border-radius: var(--prt-radius-pill); cursor: pointer; color: var(--prt-navy); }
.printella-popup__close:hover { background: var(--prt-surface-blue); }
.printella-popup__eyebrow { margin: 0 0 10px; font-size: 12px; font-weight: 800; letter-spacing: var(--prt-eyebrow-tracking, .16em); text-transform: uppercase; color: var(--prt-pink-cta); }
.printella-popup__title { margin: 0; font-size: clamp(28px,3vw,36px); line-height: 1.06; font-weight: 900; letter-spacing: -.03em; padding-right: 40px; color: var(--prt-navy); }
.printella-popup__title--lg { font-size: clamp(32px,3.6vw,46px); line-height: 1.04; }
.printella-popup__sub { margin: 8px 0 0; font-size: 17px; font-weight: 500; color: var(--prt-blue-ink); }
.printella-popup__tagline { margin: 18px 0 0; font-size: clamp(20px,2vw,24px); font-weight: 600; color: var(--prt-navy); }
.printella-popup__h3 { margin: 26px 0 12px; font-size: 21px; font-weight: 900; color: var(--prt-navy); }
.printella-popup__note { margin: 14px 0 0; font-size: 14px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.printella-popup__cta { margin-top: 22px; }

/* Zachęta do wyceny pod tabelą progów — notka, nie kolejny wiersz cennika. */
.prt-wycena-zacheta { margin: 18px 0 0; padding-top: 16px; border-top: 1.5px solid var(--prt-line-card); font-size: 15px; line-height: 1.7; font-weight: 600; color: var(--prt-text-muted); }
.printella .prt-wycena-zacheta .prt-link-u { margin-top: 4px; }

.prt-field { display: block; margin-top: 24px; font-size: 15px; font-weight: 700; color: var(--prt-navy); }
.prt-select { display: block; width: 100%; margin-top: 8px; padding: 13px 14px; border: 1.5px solid var(--prt-line-input); border-radius: 8px; font: inherit; font-size: 16px; font-weight: 600; color: var(--prt-navy); background: var(--prt-surface); }

/* Tabela w popupie. Baza `.prt-table` jest nasza (Pomoc, Wysylki) — tu tylko
   to, czym PDP sie od niej rozni: wyrownanie do srodka i kolumna ceny bez
   narzuconej szerokosci 130 px. */
.printella-popup .prt-table { margin-top: 0; }
.prt-table--tiers th:not(:first-child), .prt-table--tiers td { text-align: center; }
.prt-table--tiers td:last-child { width: auto; font-size: 17px; font-weight: 900; }
.prt-table--tiers td + td, .prt-table--tiers th + th { border-left: 1.5px solid var(--prt-line-card); }
.prt-badge { display: inline-block; min-width: 76px; padding: 4px 10px; border-radius: 6px; background: var(--prt-surface-blue-alt); font-size: 15px; font-weight: 800; color: var(--prt-navy); }

.prt-lead-time { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 18px; }
.prt-lead-time > div { display: flex; gap: 14px; align-items: flex-start; }
.prt-lead-time > div + div { border-left: 1.5px solid var(--prt-line); padding-left: 18px; }
.prt-lead-time p { margin: 0; font-size: 14px; font-weight: 600; color: var(--prt-blue-ink); }
.prt-lead-time strong { display: block; margin-top: 4px; font-size: 18px; font-weight: 900; color: var(--prt-navy); }

/* Wlasny pasek informacyjny PDP. NIE `.prt-callout` — tamten jest blokiem
   z naglowkiem i akapitem (Pomoc), ten jest jednowierszowy z ikona. */
.prt-pdp-callout { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 20px; padding: 16px 20px; background: var(--prt-surface-blue); border-radius: 10px; font-size: 17px; font-weight: 600; color: var(--prt-navy); }
.prt-pdp-callout strong { font-size: 20px; font-weight: 900; }
.prt-pdp-callout svg { flex: none; color: var(--prt-pink-cta); }
.prt-pdp-callout--strong { background: var(--prt-surface-blue-alt); font-weight: 800; flex-wrap: nowrap; padding: 18px 22px; }

.prt-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin: 22px 0 14px; font-size: 16px; font-weight: 600; color: var(--prt-navy); }
.prt-toggle { display: flex; gap: 4px; padding: 0; border: 0; border-radius: var(--prt-radius-pill); }
.printella .prt-toggle button,
.prt-toggle button { padding: 9px 28px; border: 0; border-radius: var(--prt-radius-pill); background: transparent; cursor: pointer; font-family: inherit; font-size: 15px; font-weight: 800; color: var(--prt-navy); }
.printella .prt-toggle button[aria-pressed="true"],
.prt-toggle button[aria-pressed="true"] { background: var(--prt-navy); color: var(--prt-surface); }
.printella .prt-toggle button:hover { border-color: transparent; }

.prt-policy { display: grid; grid-template-columns: 44px minmax(0,1fr); gap: 18px; margin-top: 26px; }
.prt-policy--sep { margin-top: 24px; padding-top: 24px; border-top: 1.5px solid var(--prt-line); }
.prt-policy svg { color: var(--prt-pink-cta); }
.prt-policy h3 { margin: 0; font-size: 21px; font-weight: 900; color: var(--prt-navy); }
.prt-policy p { margin: 8px 0 0; font-size: 15px; line-height: 1.55; font-weight: 500; color: var(--prt-text-muted); }
.prt-policy h3 + p { margin-top: 10px; }
.prt-policy__law { font-size: 13px; color: var(--prt-blue-ink); }
.prt-policy .prt-link-u { margin-top: 16px; }

@media (max-width: 640px) {
  .prt-lead-time { grid-template-columns: minmax(0,1fr); }
  .prt-lead-time > div + div { border-left: 0; padding-left: 0; }
  .prt-gallery__thumbs { grid-template-columns: repeat(4, minmax(0,1fr)); }
}

/* Host konfiguratora. Shortcode wtyczki musi być na stronie, bo wnosi
   `preselectFabricSlug`, overlay i własny przycisk — ale przycisk chowamy:
   rolę CTA pełnią przyciski z projektu, a dwa różne „Otwórz konfigurator"
   obok siebie to pytanie, w co kliknąć. */
.prt-konfigurator-host #printella-configurator-open { display: none; }

@media (prefers-reduced-motion: reduce) { .printella-popup[open] { animation: none; } }

/* ──────────────────────────────────────────────────────────────────────────────
   PIGUŁKA SPOSOBU DRUKU — jedno miejsce na kod kolorów

   Changelog handoffu koszyka (pkt 3): kolor idzie za SPOSOBEM DRUKU i ma być ten sam
   w koszyku, w konfiguratorze, w kasie, w mailach i na koncie klienta. Dlatego reguła
   mieszka tutaj, w arkuszu wczytywanym na każdej stronie, a nie w CSS koszyka.

   Kolory to tokeny „category accents" i „surfaces" systemu — nie nowe wartości.
   ────────────────────────────────────────────────────────────────────────────── */
.prt-tryb {
    display: inline-block;
    margin: 0;
    padding: 5px 12px;
    border-radius: 999px;
    background: var(--prt-surface-pink-strong, #FFEEF5);
    font-size: 13px;
    font-weight: 800;
    line-height: 1.3;
    color: var(--prt-pink-ink, #C22765);
}

/* Nadruk na metry */
.prt-tryb--metry {
    background: var(--prt-surface-blue-strong, #E3EEFB);
    color: var(--prt-blue-ink, #0972B5);
}

/* Panele — jeden i wiele w rzędzie to dla klienta ten sam sposób druku */
.prt-tryb--panele {
    background: var(--prt-surface-lilac, #EDE7FA);
    color: var(--prt-purple, #622180);
}

/* Próbka */
.prt-tryb--probka {
    background: var(--prt-surface-sage, #EDF3E7);
    color: var(--prt-sage-ink, #3F6420);
}

/* ══════════════════════════════════════════════════════════════════════════════
   NOTYFIKACJE (handoff „Printella — Notyfikacje", 2026-10-26)

   W `design-system.css`, a nie w arkuszu koszyka czy kasy, bo komunikaty WooCommerce
   pojawiają się na KAŻDEJ stronie sklepu — także na produkcie, koncie i przy logowaniu.
   Markup składa `printella_noty_html()` w motywie; kolory idą z tokenów statusów wyżej.
   ══════════════════════════════════════════════════════════════════════════════ */

/* `.printella` w przedrostku nie jest ozdobą: arkusz WooCommerce rysuje
   `.woocommerce-error, .woocommerce-info, .woocommerce-message { border-top: 3px solid #720eec }`
   — ta sama specyficzność co goła klasa komponentu, a ładuje się później. Zmierzone:
   nad notyfikacją stała fioletowa kreska. */
.printella .printella-noty,
.printella-noty {
    display: grid;
    grid-template-columns: 32px minmax(0, 1fr) auto;
    gap: 14px;
    align-items: start;
    margin: 0;
    padding: 16px 20px;
    border: 1.5px solid var(--prt-noty-line);
    border-radius: 12px;
    background: var(--prt-noty-surface);
}

/* Bez akcji trzecia kolumna jest pusta i zabiera prawy margines treści. */
.printella-noty:not(:has(.printella-noty__akcja)) {
    grid-template-columns: 32px minmax(0, 1fr);
}

.printella-noty--sukces {
    --prt-noty-line: var(--prt-success-line);
    --prt-noty-surface: var(--prt-success-surface);
    --prt-noty-icon: var(--prt-success);
    --prt-noty-ink: var(--prt-success-ink);
    --prt-noty-text: var(--prt-success-text);
}

.printella-noty--blad {
    --prt-noty-line: var(--prt-error-line);
    --prt-noty-surface: var(--prt-error-surface);
    --prt-noty-icon: var(--prt-error);
    --prt-noty-ink: var(--prt-error-ink);
    --prt-noty-text: var(--prt-error-text);
}

.printella-noty--uwaga {
    --prt-noty-line: var(--prt-warning-line);
    --prt-noty-surface: var(--prt-warning-surface);
    --prt-noty-icon: var(--prt-warning);
    --prt-noty-ink: var(--prt-warning-ink);
    --prt-noty-text: var(--prt-warning-text);
}

.printella-noty--info {
    --prt-noty-line: var(--prt-info-line);
    --prt-noty-surface: var(--prt-info-surface);
    --prt-noty-icon: var(--prt-info);
    --prt-noty-ink: var(--prt-info-ink);
    --prt-noty-text: var(--prt-info-text);
}

/*
 * WooCommerce nadaje komunikatowi błędu `tabindex="-1"` i przenosi na niego focus, żeby
 * czytnik ekranu i klawiatura wylądowały na błędzie. To zostaje — zmieniamy tylko WYGLĄD
 * pierścienia: domyślny jest niebieski (zmierzone: `1px auto rgb(0,95,204)`) i wokół
 * różowej notyfikacji wyglądał jak druga, obca ramka.
 *
 * ⚠️ Pierścienia NIE gasimy. Pierwsze podejście brzmiało `:focus:not(:focus-visible)
 * { outline: none }` przy założeniu, że focus programowy nie zapala `:focus-visible`.
 * Zmierzone: w Chromium zapala, więc reguła nie trafiała w nic. Nawet gdyby trafiła,
 * gaszenie zabrałoby jedyny wizualny sygnał, że kursor przeskoczył na komunikat.
 */
.printella-noty:focus,
.printella-noty:focus-visible {
    outline: 2px solid var(--prt-noty-icon);
    outline-offset: 2px;
}

.printella-noty__ikona {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: var(--prt-noty-icon);
    color: #fff;
}

.printella-noty__ikona svg {
    width: 20px;
    height: 20px;
}

.printella-noty__tytul {
    margin: 0;
    font-size: 16px;
    font-weight: 800;
    line-height: 1.3;
    color: var(--prt-noty-ink);
}

/* Treść wyśrodkowana względem ikony, gdy jest jednolinijkowa (min. wysokość = ikona).
   Dłuższa treść i lista zaczynają się od góry jak dotąd — `justify-content` działa
   tylko wtedy, gdy zostaje wolne miejsce. Bez tego tytuł 21 px wisiał przy górnej
   krawędzi 32-pikselowej ikony i pod tekstem zostawało wyraźnie więcej miejsca. */
.printella-noty__tresc {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 32px;
}

.printella-noty__tresc > * + * {
    margin-top: 4px;
}

/* Clearfix WooCommerce (`.woocommerce-error::after { content: ""; display: table }`, to samo
   dla `-message` i `-info`) w siatce staje się TRZECIM elementem siatki: pustym wierszem
   pod treścią plus `gap` 14 px. Zmierzone 28.10.2026: dolny odstęp tekstu 42 px przy
   górnym 17 px. Klasę WooCommerce mają boksy z `notices/*.php` (doklejana w PHP) i boksy
   błędów z `printella-kasa-noty.js` (`zbudujBoks()`), więc gasimy pseudoelement
   na komponencie, a nie na klasie WooCommerce. */
.printella .printella-noty::before,
.printella .printella-noty::after,
.printella-noty::before,
.printella-noty::after {
    content: none;
    display: none;
}

.printella-noty__lista {
    margin: 6px 0 0;
    padding-left: 18px;
    font-size: 15px;
    font-weight: 500;
    line-height: 1.55;
    color: var(--prt-noty-text);
}

.printella-noty__akcja {
    align-self: center;
    white-space: nowrap;
}

/* Odnośnik akcji przychodzi z WooCommerce jako `.button.wc-forward` — tu ma być
   odnośnikiem, nie przyciskiem, więc chrome przycisku jest zdejmowany jawnie.
   
   ⚠️ Pięć klas i DWA elementy (`div` + `a`) są konieczne. `style.css` ubiera każdy
   przycisk WooCommerce regułą `.printella .woocommerce a.button:not(…):not(…)` — to
   (0,5,1), stary fiolet #6F3FA6 i 13px/600. Zmierzone przed poprawką: akcja „Zobacz
   koszyk" renderowała się fioletowa i drobna. Liczba elementów rozstrzyga remis klas. */
.printella .woocommerce .printella-noty div.printella-noty__akcja a.button,
.printella .woocommerce .printella-noty div.printella-noty__akcja a,
.printella .printella-noty__akcja .button,
.printella .printella-noty__akcja a {
    display: inline;
    height: auto;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 15px;
    font-weight: 800;
    line-height: 1.3;
    letter-spacing: 0;
    text-transform: none;
    color: var(--prt-noty-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.printella .woocommerce .printella-noty div.printella-noty__akcja a.button:hover,
.printella .woocommerce .printella-noty div.printella-noty__akcja a:hover,
.printella .printella-noty__akcja .button:hover,
.printella .printella-noty__akcja a:hover {
    background: none;
    color: #101B54;
}

/* Opis pod tytułem (handoff „Detale”: 15/500, lh 1.5). Odstęp 4 px daje
   `.printella-noty__tresc > * + *`. */
.printella-noty__opis {
    margin: 0;
    font-size: 15px;
    font-weight: 500;
    line-height: 1.5;
    color: var(--prt-noty-text);
    text-wrap: pretty;
}

/* Zamknięcie sukcesu — 32×32, × 12 px w kolorze tytułu, hover tło tytułu @ 12%.
   Krzyżyk rysują pseudoelementy PRZYCISKU (zgaszone są tylko te na samym `.printella-noty`).
   `color-mix` zamiast rgba, bo kolor przychodzi z tokenu wariantu. Selektor z `.printella`
   i elementem — kit Elementora ubiera każdy `button` (tło, ramka, padding). */
.printella .printella-noty button.printella-noty__zamknij,
.printella-noty button.printella-noty__zamknij {
    position: relative;
    display: block;
    width: 32px;
    height: 32px;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: none;
    box-shadow: none;
    color: var(--prt-noty-ink);
    cursor: pointer;
}

.printella .printella-noty button.printella-noty__zamknij:hover,
.printella-noty button.printella-noty__zamknij:hover {
    background: color-mix(in srgb, var(--prt-noty-ink) 12%, transparent);
}

.printella .printella-noty button.printella-noty__zamknij:focus-visible,
.printella-noty button.printella-noty__zamknij:focus-visible {
    outline: 2px solid var(--prt-noty-icon);
    outline-offset: 2px;
}

.printella-noty__zamknij::before,
.printella-noty__zamknij::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 14px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
}

.printella-noty__zamknij::before {
    transform: translate(-50%, -50%) rotate(45deg);
}

.printella-noty__zamknij::after {
    transform: translate(-50%, -50%) rotate(-45deg);
}

/* Stos kilku komunikatów. */
.printella-noty + .printella-noty {
    margin-top: 12px;
}

/* ⚠️ Prefiks `.printella` musi być także tutaj. Bez niego reguła miała niższą
   specyficzność niż bazowa `.printella .printella-noty` i działała tylko na części
   komunikatów: sukces na telefonie miał 16/20 px i trzy kolumny, błąd kuponu 14/16 px
   (zmierzone 28.10.2026). Padding zostaje jeden dla wszystkich szerokości — wzorem
   jest zielony sukces, który wyglądał dobrze na obu widokach. */
@media (max-width: 519px) {
    .printella .printella-noty,
    .printella .printella-noty:not(:has(.printella-noty__akcja)),
    .printella-noty,
    .printella-noty:not(:has(.printella-noty__akcja)) {
        grid-template-columns: 32px minmax(0, 1fr);
    }

    /* Akcja schodzi pod treść — przy 390 px nie ma miejsca na trzecią kolumnę. */
    .printella-noty__akcja {
        grid-column: 2;
        align-self: start;
        margin-top: 8px;
        white-space: normal;
    }

    /* Zamknięcie zostaje w trzeciej kolumnie: 32 px mieści się zawsze, a pod treścią
       samotny krzyżyk wyglądałby jak osobny element. */
    .printella .printella-noty:has(.printella-noty__akcja--zamknij),
    .printella-noty:has(.printella-noty__akcja--zamknij) {
        grid-template-columns: 32px minmax(0, 1fr) 32px;
    }

    .printella-noty__akcja.printella-noty__akcja--zamknij {
        grid-column: 3;
        align-self: center;
        margin-top: 0;
    }
}

/* Nota „Skórę syntetyczną wysyłamy zawsze na rolce." — koszyk, kasa i konto klienta.
   W `design-system.css`, bo pojawia się na trzech stronach o trzech różnych arkuszach;
   maile mają własną kopię wartości w stylu inline (arkusze tam nie działają). */
.printella-dostawa__nota {
    display: block;
    margin: 4px 0 0;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.4;
    color: #3A4478;
}

/* =========================================================
   PLAKIETKA LICZNIKA KOSZYKA W NAGŁÓWKU

   Markup wstawia szablon Elementora (nagłówek 6151, widżet `html`), a liczbę podmienia
   `printella_koszyk_licznik_html()` w motywie — razem z fragmentem WooCommerce, więc
   plakietka nadąża także po AJAX-owym dodaniu do koszyka. Style siedzą TUTAJ, nie w
   atrybucie `style` szablonu, bo fragment podmienia cały `<span>`: gdyby style były
   inline, trzeba by je powtórzyć w PHP i pilnować, żeby obie kopie się nie rozjechały.
   ========================================================= */
.prt-koszyk-licznik {
    position: absolute;
    top: -6px;
    right: -7px;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--prt-pink-cta);
    color: #fff;
    font-size: 11px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    pointer-events: none;
}

/* Pusty koszyk: plakietki nie widać, ale element ZOSTAJE w drzewie — fragment
   WooCommerce podmienia po selektorze, więc musi mieć co podmienić przy pierwszym
   dodaniu do koszyka. `display: none` zamiast usuwania z markupu. */
.prt-koszyk-licznik--pusty {
    display: none;
}

/* Poniżej 900 px nagłówek jest ciasny i wysunięcie o 7 px wypychało stronę w bok
   — ta sama przyczyna co przy plakietkach Elementora, patrz `style.css`. */
@media (max-width: 899px) {
    .prt-koszyk-licznik {
        right: 0;
    }
}

/* =========================================================
   NAGŁÓWEK SKLEPU — białe tło i odstęp NA STAŁE

   Do 27.10.2026 nagłówek nie miał własnego tła: `<header class="elementor-6151">`
   i `<header>` w środku widżetu były PRZEZROCZYSTE, więc wyglądał biało tylko dlatego,
   że biała była strona pod nim. Każda podstrona z innym tłem (kreator wyceny dostał
   `#F5F7FB`) pokazywała przez nagłówek swoje tło i trzeba było to poprawiać u siebie.
   Zmierzone na `/kreator-wyceny/`: pas 1440 × 85 px w kolorze `rgb(245, 247, 251)`,
   `margin-bottom: 0`.

   Tło i odstęp siedzą więc TUTAJ, raz, na wrapperze Elementora — ten jest pełnej
   szerokości (1440 px przy oknie 1440), podczas gdy `<header>` w środku jest skrzynką
   1280 px i biel kończyłaby się na jego krawędziach.

   ⚠️ Selektor celuje w NUMER szablonu, bo nagłówek sklepu i nagłówek kasy to dwa różne
   szablony Theme Buildera: 6151 („Nagłówek Printella 2026", warunki `include/general`
   minus strony 1358 i 1361) oraz 1188 („Nagłówek koszyk clean", tylko te dwie strony).
   Kasa ma własny wygląd ze stepperem i NIE ma dostawać tego tła. Gdyby szablon sklepu
   kiedyś został zastąpiony innym, trzeba podmienić numer tutaj — to jedyne miejsce.
   ========================================================= */
/*
 * Samo TŁO. Odstęp u dołu daje symetryczny `padding: 26px 28px` wewnętrznego `<header>`
 * w szablonie 6151 — tam, gdzie od zawsze stoi padding górny.
 *
 * Dwa podejścia, które tu nie przeszły:
 *  - `margin-bottom` pokazywał tło strony: na kreatorze między białym nagłówkiem a białym
 *    hero powstawał szary pasek `#F5F7FB` i wyglądał jak szew;
 *  - `padding-bottom` na tym wrapperze trzymał biel ciągłą, ale odstęp dolny (28 px) nie
 *    zgadzał się z górnym (26 px z szablonu) i był liczony od innego elementu niż górny.
 *    Jedna wartość w jednym miejscu jest odporniejsza niż dwie, które trzeba trzymać równo.
 */
header.elementor-6151 {
    background: #fff;
}

/* =========================================================
   NAGŁÓWEK SKLEPU — UKŁAD I NAWIGACJA Z MENU WordPressa

   28.10.2026 nagłówek 6151 przestał być jednym widżetem `html` z zaszytymi na sztywno
   pięcioma odnośnikami. Dziś to kontener flex z trzema dziećmi: logo (`html`),
   nawigacja (`nav-menu` Elementora Pro podpięty pod menu `main-menu`) i ikony (`html`).
   Decyzja Steve'a: „Main menu — go".

   CO TO DAJE: menu edytuje się w Wygląd → Menu, a nie w `_elementor_data`, i WPML może je
   podmieniać per język swoim `wp_nav_menu_args_filter`. Dopóki pozycje menu nie mają
   tłumaczeń, WPML cofa się do polskiego menu — czyli dokładnie to, co było przed zmianą,
   więc regresji nie ma, a tłumaczenie zadziała samo, gdy strony docelowe dostaną wersje
   DE/EN (patrz TODO).

   DLACZEGO WYGLĄD SIEDZI TUTAJ, A NIE W USTAWIENIACH WIDŻETU
   Ta sama przyczyna co przy `.prt-koszyk-licznik` wyżej: w `_elementor_data` trzymamy
   WYŁĄCZNIE strukturę (które menu, układ, brak wskaźnika, brak zwijania do burgera),
   bo wartości wyglądowe zapisane w bazie są poza gitem i rozjeżdżają się z CSS-em.
   Font jest poza tym `clamp()`, a kontrolki Elementora nie przyjmują `clamp()`.

   ⚠️ `--content-width` Elementora działa od 481 px w górę (tak generuje kit), ale niżej
   skrzynka i tak jest węższa od okna, więc nic z tego nie wynika.
   ========================================================= */

/* 1. SKRZYNKA 1280 px Z MARGINESEM BOCZNYM WEWNĄTRZ

      Padding poziomy MUSI być na `.e-con-inner`, nie na kontenerze. Elementor kładzie
      swój padding na zewnętrznym `.e-con`, a skrzynka 1280 px jest centrowana w tym, co
      po paddingu zostanie — logo wychodziło wtedy na x=80 zamiast x=108 (zmierzone przy
      1440 px). Pion zostaje w Elementorze (26 px), poziom bierzemy z tokenu, tego samego
      co reszta serwisu. */
#prt-sec-header > .e-con-inner {
    padding-inline: var(--prt-margines-boczny);
    /* Odstęp też tutaj, a nie w kontrolce Elementora: kontrolka przyjmuje jedną liczbę,
       a wzorzec ma `clamp()`. Przy 22 px zamiast tego odnośniki menu siadały 4 px w lewo
       względem stanu sprzed przebudowy (zmierzone przy 1440 px: 332 vs 336). */
    gap: 14px clamp(14px, 1.8vw, 30px);
}

/* 2. TRZY DZIECI W JEDNYM WIERSZU

      `margin-left: auto` na ikonach zastępuje dawny `<div style="flex:1">` — rozpórka
      była osobnym elementem w markupie tylko po to, żeby rozepchnąć wiersz, a przy
      zawijaniu zachowywała się nieprzewidywalnie (sama szła do nowego wiersza). */
#prt-naglowek-logo {
    flex: 0 0 auto;
}

#prt-naglowek-nawigacja {
    flex: 0 1 auto;
}

#prt-naglowek-ikony {
    flex: 0 0 auto;
    margin-left: auto;
}

/* 3. ODNOŚNIKI MENU — WYGLĄD SPRZED PRZEBUDOWY

      Widżet dziedziczy typografię z globalnego kitu Elementora (zmierzone: 24 px przy
      1440 px, 20 px przy 390 px) i dokłada własny padding pozycji. Oba trzeba zdjąć,
      żeby wrócić do stanu z zaszytego `<nav>`: 15 px przy 1440, 13 px przy 390, waga 700,
      odstęp 13 px. Specyficzność: `#prt-naglowek-nawigacja` (1,0,0) bije reguły Elementora
      pisane klasami. */
#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-nav-menu {
    gap: 13px;
    flex-wrap: wrap;
}

#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item {
    padding: 0;
    font-size: clamp(13px, 1.05vw, 15px);
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
    fill: currentColor;
}

/* Kolor i hover jak w pozostałych odnośnikach serwisu. Elementor nie dostał ich
   z ustawień widżetu z powodu opisanego w nagłówku tej sekcji. */
#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item,
#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item:focus,
#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item.elementor-item-active {
    color: var(--prt-navy);
    background: transparent;
}

#prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item:hover {
    color: var(--prt-pink-cta);
    background: transparent;
}


/* =========================================================
   NAGŁÓWEK KOSZYKA I KASY (szablon 1188) — treść wyśrodkowana w pionie

   Kontenery mają symetryczny `padding: 1rem` u góry i u dołu, ale zawartość była
   przyklejona do góry (`align-items: flex-start`), a wiersz jest wyższy niż logo.
   Zmierzone: nad logo 16 px, pod logo 32 px — różnica brała się z rozciągnięcia
   kontenera do wysokości wiersza, nie z paddingu.

   Środkowanie zamiast dobierania paddingu: odstęp nad i pod zostaje równy niezależnie
   od tego, co w wierszu jest najwyższe (dziś stepper, jutro cokolwiek innego).
   ========================================================= */
header.elementor-1188 .e-con.e-flex {
    --align-items: center;
    align-items: center;
}

/* Strzałka „wstecz" siedziała 8 px wyżej od środka: `.elementor-icon` jest `inline-block`,
   więc pod glifem zostawała luka linii bazowej (ikona 20 px w pudełku 27 px). Flex zamiast
   bezszwowego dobierania `line-height` — nie zależy od kroju ani rozmiaru ikony. */
header.elementor-1188 .elementor-icon-wrapper,
header.elementor-1188 .elementor-icon {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* =========================================================
   HERO — JEDEN górny odstęp i zero marginesów

   Nagłówek niesie od 5.69.2 własne 26 px bieli u dołu, więc hero nie musi dokładać
   swojego oddechu. Przed ujednoliceniem każda strona miała własną wartość, zmierzone
   przy 1440 px:

     Tkaniny, karta tkaniny, Wycena grafiki, kategoria tkanin   28 px
     artykuł Pomocy                                             48 px  + margines 26 px
     Usługi graficzne                                           60 px
     Pomoc                                                      74 px  + margines 26 px
     strona główna                                              78 px
     Kontakt                                                     0 px  + margines 56 px
     Panele                                                      0 px  + margines 52 px

   Marginesy szły z atrybutów `style` w widżetach HTML szablonów Elementora, więc bez
   `!important` nie da się ich zdjąć z arkusza. Świadomie wybieramy `!important` w jednym
   miejscu zamiast edycji pięciu szablonów w bazie: szablony są POZA gitem, a ten blok
   da się skasować jednym ruchem i zobaczyć w diffie.

   ⚠️ ZAPIS HISTORYCZNY. Do 31.10.2026 wszystkie te strony dostawały JEDNĄ wartość
   (`--prt-hero-pt`). Brief z 31.10 dzieli odstęp według ROLI pierwszego elementu, więc
   wspólna zmienna zniknęła — zostaje ten opis, bo tłumaczy, skąd wzięły się `!important`
   niżej i dlaczego nie da się ich zdjąć bez ruszania szablonów w bazie.
   ========================================================= */
/* ⚠️ `--prt-hero-pt` USUNIĘTY 31.10.2026. Jedna wspólna wartość dla jedenastu stron była
   dobra, dopóki brief traktował odstęp pod nagłówkiem jako jedną rzecz. Teraz zależy on
   od ROLI pierwszego elementu (tokeny `--prt-below-header-*` na górze pliku), więc
   wspólna zmienna by te role z powrotem skleiła. */

/* ROLA „KOLOROWY PAS" — pas dotyka nagłówka, bez przerwy.
   `#szukaj` (Pomoc) i `pahero` (artykuł Pomocy) oraz `pkhero` (kategoria Pomocy).

   ⚠️ `!important` ZOSTAJE i to jest świadomy wybór. Marginesy siedzą w atrybutach `style`
   widżetów HTML w szablonach Elementora (`#szukaj`: `margin-top: 26px`), a szablony są
   POZA gitem. Jedno miejsce z `!important` da się skasować jednym ruchem i widać je
   w diffie; pięć edycji w bazie nie zostawia śladu nigdzie.

   ⚠️ `pkhero` DOSZŁO 31.10.2026 — kategoria Pomocy jako jedyna nie była objęta i miała
   `--margin-top: 26px` + `--padding-top: 48px` z `post-6213.css`, czyli 74 px zamiast 0.
   To była ostatnia kompensacja „26 px pod nagłówkiem" w serwisie (zmierzył FreeAgent).

   ⚠️⚠️ ZERUJEMY TYLKO MARGINES, NIE PADDING — i to jest sedno roli „pas".
   Na tych trzech stronach TŁO NIESIE TEN SAM ELEMENT, na którym stoi odstęp. Pierwsza
   wersja (5.120.0) ustawiała tu `padding-top: 0`, więc okruszki i eyebrow przykleiły się
   do górnej krawędzi różowego pasa — zmierzył FreeAgent, 0 px oddechu w środku.
   Rola mówi „pas zaczyna się od razu pod nagłówkiem", czyli margines 0; odstęp WEWNĄTRZ
   pasa brief zostawia bez zmian. U „Dostawy" pas jest osobnym elementem i jego 40 px
   nigdy nie było w tej regule — tam to działało przypadkiem, a nie z konstrukcji. */
body.printella section#szukaj,
body.printella .elementor-element-pahero,
body.printella .elementor-element-pkhero {
    margin-top: var(--prt-below-header-band) !important;
}

/* ROLA „HERO BEZ OKRUSZKÓW" — Usługi graficzne, Panele, Kontakt (i O nas, gdy wyjdzie
   ze szkicu). `section#top` jest WSPÓLNY dla tych stron i strony głównej, więc rozdziela
   je klasa strony: główna ma własną rolę niżej. */
body.printella:not(.home) section#top {
    margin-top: 0 !important;
    padding-top: var(--prt-below-header-hero) !important;
}

.e-con.e-flex.prt-ug-hero {
    --padding-top: var(--prt-below-header-hero);
}

/* ROLA „HERO GŁÓWNE" — strona główna i 404. Większy oddech, bo nad treścią nie ma ani
   okruszków, ani pasa, a pierwszy ekran jest obrazem marki. */
body.printella.home section#top {
    margin-top: 0 !important;
    padding-top: var(--prt-below-header-hero-lg) !important;
}

/* ROLA „BREADCRUMB NA BIELI" — kategorie tkanin. Karta, próbnik i wycena mają swoje
   reguły przy własnych blokach, bo tam odstęp niesie inny element. */
.e-con.e-flex.prt-kat-hero {
    --padding-top: var(--prt-below-header-crumb);
}

/* ⚠️ ARCHIWUM TKANIN NIE MA OKRUSZKÓW — rola „hero bez breadcrumba" (decyzja Steve'a
   31.10.2026: „Tkaniny wyłączone z breadcrumb").

   Brief zaliczał `/tkaniny/` do kolorowych pasów, a FreeAgent zmierzył biel bez ścieżki:
   pierwszy element to `#tka-hero.prt-kat-hero` z samym eyebrow. Klasę `.prt-kat-hero`
   dzieli z kategoriami tkanin, które okruszki MAJĄ — stąd osobna reguła dla archiwum
   zamiast trzeciej klasy w szablonie, którego i tak nie trzymamy w gicie. */
body.post-type-archive-tkanina .e-con.e-flex.prt-kat-hero {
    --padding-top: var(--prt-below-header-hero);
}

/* ⚠️ PODWÓJNY ODSTĘP: KONTENER I HERO W ŚRODKU. Na Wycenie i na archiwum tkanin odstęp
   dokładają DWA elementy — zewnętrzny kontener Elementora (28 px z `post-<id>.css`)
   i hero w jego wnętrzu (nasza rola). Zmierzone przez FreeAgenta: 56 px zamiast jednego
   odstępu. Rolę niesie hero, więc kontener schodzi do zera — inaczej każda zmiana tokenu
   zmieniałaby wynik o połowę tego, co się wpisało. */
body.post-type-archive-tkanina .elementor:not(.elementor-location-header) > .e-con:first-of-type,
body.page-id-6366 .elementor:not(.elementor-location-header) > .e-con:first-of-type {
    --padding-top: 0px;
}

/* „Dostawa i płatność" (PL/DE/EN) — pas zaczyna się przy nagłówku.
   Klasę dokłada `printella_strony_dostawy_slugs()`; identyfikator kontenera jest inny
   w każdym tłumaczeniu, więc nie da się go użyć.

   ⚠️ `:not(.elementor-location-header)` NIE JEST OZDOBĄ. Bez tego reguła łapała też
   NAGŁÓWEK — `header.elementor-6151` ma klasę `.elementor`, a jego pierwszym `.e-con`
   jest `#prt-sec-header`. Skutek: na stronach dostawy nagłówek miał 113 px zamiast 111
   i padding 28/26 zamiast symetrycznych 26/26, czyli dokładnie to, czego brief zakazuje.
   Zmierzył FreeAgent 31.10.2026; w arkuszu nie było tego widać, bo selektor wygląda
   niewinnie i celuje „w treść". */
body.prt-strona-dostawy .elementor-location-single > .e-con:first-of-type,
body.prt-strona-dostawy .elementor:not(.elementor-location-header) > .e-con:first-of-type {
    --padding-top: var(--prt-below-header-band);
}

/* =========================================================
   PRZEGLĄD MOBILE WSZYSTKICH PODSTRON (27.10.2026)
   =========================================================
   Pomiar: Playwright, 19 podstron × 390 px (iPhone 14) i 320 px (iPhone SE),
   `hasTouch`, `deviceScaleFactor: 2`. Żadna strona nie przewijała się w bok —
   wszystkie usterki to treść UCIĘTA przez `overflow-x: clip` na `[id^="prt-sec-"]`,
   czyli niewidoczna w metrykach, a widoczna na ekranie.

   1. SZTYWNE `minmax()` W SIATKACH
      Siatki są stylowane atrybutem `style` w widżetach HTML, więc wartości nie da się
      zmienić z arkusza — można tylko nadpisać całą deklarację. Zamiast progu
      w `@media` używamy `minmax(min(X, 100%), 1fr)`: powyżej X zachowanie jest
      IDENTYCZNE jak dotąd (więc desktop nie ma jak się zmienić), a poniżej kolumna
      zwęża się do szerokości kontenera zamiast go rozpychać.

      Zmierzone (320 px, dostępne 264 px lub 208 px):
        strona główna  `#top`                      track 340 px → ucięte 48 px
        strona główna  `#wzory` (kafle wzorów)     track 320 px → ucięte 28 px
        Kontakt        `#tematy`                   track 280 px → ucięte 16 px
        Pomoc          szybkie pytania             track 290 px → ucięte 26 px
   ========================================================= */
body.printella section#top {
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)) !important;
}

body.printella section#wzory > div:has(> [data-dir]) {
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)) !important;
}

body.printella section#tematy > [data-section-body] {
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)) !important;
}

body.printella #prt-sec-szybkie [data-section-body] {
    grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)) !important;
}

/* 2. PODWÓJNY PADDING 28 + 28 px
      Kontakt, Pomoc i Panele mają padding i na kontenerze Elementora, i na sekcji HTML
      w środku — na 320 px zostawiało to 208 px treści z 320 (35 % ekranu na marginesy).
      Pozostałe strony mają zero na kontenerze, więc nie można zdjąć padding'u kontenera
      „na wszelki wypadek": na stronie głównej zabrałoby to jedyny odstęp od krawędzi.
      Zdejmujemy więc padding SEKCJI, a selektor celuje w sposób zapisu — `padding-left:28px`
      w atrybucie `style` występuje wyłącznie na tych trzech stronach (11 sekcji,
      sprawdzone w HTML wszystkich 19 podstron). Hero strony głównej zapisane jest
      skrótem `padding: … 28px 0`, więc tu nie trafia. */
@media (max-width: 480px) {
    body.printella [id^="prt-sec-"] > .elementor-widget > section[style*="padding-left:28px"] {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
}

/* 3. DŁUGIE NIEŁAMLIWE SŁOWA
      Blok kontaktowy na `/kontakt/` potrzebował 187 px min-content w boksie 152 px
      (adres `info@printella.pl` nie ma gdzie się złamać). `break-word` łamie TYLKO
      słowa, które i tak by wystawały, więc nie zmienia łamania poprawnych wierszy. */
body.printella p,
body.printella li,
body.printella a,
body.printella dd,
body.printella td {
    overflow-wrap: break-word;
}

/* =========================================================
   PRAWA KOLUMNA KARTY — JEDEN BLOK PHP (`[prt_tk_zakup]`, 2026-10-31)

   ⚠️ Te reguly celuja w ZWYKLE elementy, nie w `.elementor-heading-title` — i to jest
   cala idea. Elementor wstrzykuje swoj CSS po arkuszach motywu, a jego
   `.elementor-widget-heading .elementor-heading-title` z typografia kitu ma te sama
   specyficznosc co nasze reguly (0,2,0) i wygrywa kolejnoscia. Dopoki kolumna byla
   zlozona z widzetow naglowka, kazda nasza wartosc musiala to przebijac przedrostkiem
   `.elementor`. Teraz w kolumnie nie ma ani jednego widzetu naglowka, wiec nie ma czego
   przejmowac i wystarcza pojedyncza klasa.

   Odstepy sa sekcja B briefu z 31.10.2026 i trzymaja siatke {12, 14, 22, 28}:
   eyebrow -> H1 to 12 (jedyny wyjatek), reszta 14, grupy 22, nowa grupa 28.
   ========================================================= */
.prt-pdp__zakup { display: block; }
.prt-pdp__zakup > :first-child { margin-top: 0; }

.prt-pdp__zakup .prt-pdp__eyebrow { margin: 0 0 12px; font-size: 13px; }

.prt-pdp__h1 {
    margin: 0;
    font-size: clamp(32px, 3.6vw, 48px);
    line-height: 1.04;
    font-weight: 900;
    letter-spacing: -.03em;
    color: var(--prt-navy);
    text-wrap: balance;
}

.prt-pdp__zakup .prt-mat-kod { margin: var(--space-tight) 0 0; }

.prt-pdp__opis {
    margin: var(--space-tight) 0 0;
    max-width: 480px;
    font-size: 17px;
    line-height: 1.55;
    font-weight: 500;
    color: var(--text-muted);
}

.prt-pdp__spec-h {
    margin: var(--space-section) 0 var(--space-tight);
    font-size: 17px;
    font-weight: 800;
    color: var(--prt-navy);
}

.prt-pdp__cena {
    margin: var(--space-section) 0 0;
    font-size: clamp(34px, 3.4vw, 44px);
    line-height: 1;
    font-weight: 900;
    letter-spacing: -.03em;
    color: var(--prt-navy);
}

.prt-pdp__cena-nota { margin: var(--space-tight) 0 0; }
.prt-pdp__cena-nota p { margin: 0; font-size: 14px; line-height: 1.5; font-weight: 500; color: var(--text-muted); }
.prt-pdp__cena-nota p + p { margin-top: 4px; }

.prt-pdp__zakup .prt-pdp__akcje { margin-top: var(--space-group); }

/* Przycisk: te same wartosci co CTA w widzecie Elementora (szerokosc kolumny, 56 px,
   18/800, promien 8). Tu bez walki o specyficznosc, bo to nasz wlasny element. */
.prt-pdp__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin-top: var(--space-group);
    min-height: 56px;
    padding: 0 32px;
    border-radius: 8px;
    background: var(--prt-pink-cta);
    color: #fff;
    font-size: 18px;
    font-weight: 800;
    line-height: 1.2;
    text-align: center;
    transition: background .2s ease;
}
.printella a.prt-pdp__btn { color: #fff; }
.prt-pdp__btn:hover { background: var(--prt-pink-cta-hover); color: #fff; }
.prt-pdp__btn:focus-visible { outline: 3px solid var(--prt-navy); outline-offset: 3px; }
.prt-pdp__btn svg { flex: none; }

.prt-pdp__zakup .prt-pdp__zaufanie { margin-top: var(--space-tight); }

/* --- odnośnik do próbnika pod listą zaufania (brief 31.10 C.7) --------------
   Odstęp `--space-group`, bo to osobna grupa w kolumnie, a nie dopisek do listy
   zaufania nad nim (brief 31.10 A: 22 px między grupami). */
/* Kafel wg briefu z 2.11.2026: SPOKOJNY LINK-KAFEL, nie przycisk. Rola jest
   drugorzędna — nie konkuruje z „Dodaj do koszyka" obok, więc żadnej różowej
   pigułki ani wypełnienia.

   ⚠️ PROMIEŃ 10 px, A NIE 8 px Z REGUŁY AKCJI SKLEPOWYCH. Brief uzasadnia to
   wprost: kafel stoi w kolumnie zakupowej między polami i selectami, więc ma
   pasować do nich, a nie do kart (16–20 px). Nie wyrównywać do 8. */
.prt-pdp__probnik {
  display: flex; align-items: center; gap: 14px;
  margin-top: var(--space-group);
  padding: 14px 18px;
  border: 1.5px solid var(--prt-line-pink-soft); border-radius: 10px;
  background: #fff;
  color: var(--prt-navy); text-decoration: none;
  /* ⚠️ NIGDY `transition: all`. Na `all` animuje się też `outline` fokusu
     i `transform` strzałki przy każdej innej zmianie — brief wymienia
     właściwości po nazwie i to jest celowe. */
  transition: border-color .2s ease, background-color .2s ease;
}
/* ⚠️ Kolor ikony przez `color` na SVG, nie `fill`/`stroke` — sprite używa
   `currentColor`, więc jedna właściwość wystarcza na obrys i na kropkę. */
.prt-pdp__probnik-i { flex: none; color: var(--prt-pink-cta); }
/* `flex: 1` + `min-width: 0` — bez `min-width` długi podpis rozepchnąłby kafel
   zamiast zawinąć się do drugiej linii. Ikona i strzałka mają `flex: none`,
   więc nie kurczą się nigdy (brief: „ikona i strzałka nie mogą się kurczyć"). */
.prt-pdp__probnik-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.prt-pdp__probnik-tx strong { font-size: 15px; font-weight: 800; color: var(--prt-navy); }
.prt-pdp__probnik-tx span { font-size: 14px; font-weight: 600; color: var(--prt-text-muted); }
.prt-pdp__probnik-a { flex: none; color: var(--prt-pink-cta); transition: transform .2s ease; }
@media (hover: hover) and (pointer: fine) {
  /* ⚠️ TREŚĆ NIE ZMIENIA KOLORU i nie ma podkreślenia — brief zabrania
     „różowienia treści". Poprzednia wersja podkreślała tytuł; to sygnał
     przycisku, a nie spokojnego kafla. Zmienia się RAMKA, TŁO i STRZAŁKA.
     Bez `translateY` i bez cienia: kafel siedzi w gęstej kolumnie zakupowej
     i podskakiwanie byłoby za głośne. */
  .prt-pdp__probnik:hover { border-color: var(--prt-pink-cta); background: #FFF7FA; }
  .prt-pdp__probnik:hover .prt-pdp__probnik-a { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .prt-pdp__probnik, .prt-pdp__probnik-a { transition: none; }
  .prt-pdp__probnik:hover .prt-pdp__probnik-a { transform: none; }
}
/* Promień fokusu równy promieniowi kafla — przy 8 px obrys odstawał od narożnika. */
.prt-pdp__probnik:focus-visible { outline: 3px solid var(--prt-pink-cta); outline-offset: 3px; border-radius: 10px; }

/* =========================================================
   KARTA TKANINY — BLOK ZAKUPU I OKNA WG HANDOFFU FINALNEGO (28.10.2026)

   `Printella_karta-produktu_new` zastępuje wcześniejszy brief i ma pierwszeństwo.
   Większość reguł okien była już zgodna (szerokości 580/640, promień, przycisk
   zamknięcia 40×40 bez ramki, H2 `clamp(28px,3vw,36px)/900`) — tutaj tylko różnice.
   ========================================================= */

/* 1. PRZYCISKI ŚCIEŻKI ZAKUPOWEJ MAJĄ 8 px, NIE PIGUŁKĘ

      Pigułki zostają na stronach marketingowych (hero strony głównej, newsletter),
      więc NIE ruszamy `--prt-radius-pill` ani `.prt-btn-primary` globalnie — zmiana
      jest zawężona do karty i okien. Bez wersalików i bez `letter-spacing`: na stagingu
      w oknach wychodziło „WGRAJ PLIKI”. */
.prt-pdp__cta .elementor-button,
.printella-popup__cta {
    border-radius: 8px;
    text-transform: none;
    letter-spacing: normal;
}

/* Główny przycisk na karcie: 56 px i 18 px, pełna szerokość kolumny. */
.prt-pdp__cta .elementor-button {
    width: 100%;
    justify-content: center;
    min-height: 56px;
    padding-block: 0;
    font-size: 18px;
    font-weight: 800;
}

/* W oknach: 52 px, 16 px, szerokość do treści, WYŚRODKOWANY (Steve, 31.10.2026).
   ⚠️ `inline-flex` nie da się wyśrodkować `margin-inline: auto` — element inline
   nie ma czego rozepchnąć auto-marginesami. Musi być blokowy `flex`. */
.printella-popup__cta {
    display: flex;
    width: fit-content;
    margin-inline: auto;
    min-height: 52px;
    padding-block: 0;
    font-size: 16px;
    font-weight: 800;
}

/* 2. NAGŁÓWEK OKNA — podtytuł spoza palety

      Był 17px/500 w `--prt-blue-ink`, czyli niebieskim, którego handoff nie ma w palecie.
      Ma być 15px/600 w #3A4478. Nadtytuł 12 → 13 px. */
.printella-popup__eyebrow {
    font-size: 13px;
}

.printella-popup__sub {
    font-size: 15px;
    font-weight: 600;
    color: #3A4478;
}

/* Hover przycisku zamknięcia dokładnie z handoffu. */
.printella .printella-popup__close:hover,
.printella-popup__close:hover {
    background: #EEF2FA;
}

.printella-popup__close:focus-visible {
    outline: 3px solid var(--prt-pink-cta);
    outline-offset: 2px;
}

/* 3. BOKSY POD CENĄ

      Mają być WIZUALNIE SŁABSZE od CTA — to nie są wezwania do działania, tylko
      wejścia do informacji. Stąd cienka ramka i brak wypełnienia; różowa ramka
      z poprzedniej wersji konkurowała z przyciskiem zakupu. */
body.printella .prt-pdp__akcje {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-top: 22px;
}

/* ⚠️ `body.printella button.` zamiast gołej klasy: boksy są elementami `<button>`,
   a kit Elementora nadaje przyciskom własny promień i ramkę o wyższej specyficzności —
   zmierzone 8 px i #CBD5E1 zamiast 10 px i #DCE1EC, mimo że ta reguła leży w pliku
   NIŻEJ od poprzedniej wersji. Kolejność nie wystarczyła, bo przegrywała nie z nią. */
body.printella button.prt-pdp__akcja {
    min-height: 96px;
    padding: 14px 10px;
    border: 1.5px solid #DCE1EC;
    border-radius: 10px;
    background: #fff;
    gap: 10px;
}

body.printella button.prt-pdp__akcja .prt-pdp__akcja-txt {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.25;
    color: #3A4478;
}

body.printella button.prt-pdp__akcja svg {
    width: 28px;
    height: 28px;
}

body.printella button.prt-pdp__akcja:hover {
    border-color: var(--prt-navy);
    background: #F5F7FC;
}

body.printella button.prt-pdp__akcja:hover .prt-pdp__akcja-txt {
    color: var(--prt-navy);
}

/* ⚠️ TO MEDIA QUERY MUSI MIEĆ PREFIKS `body.printella`, inaczej nic nie robi.
   Wyżej w pliku stoi `@media (max-width: 460px) { .prt-pdp__akcje { grid-template-columns: 1fr } }`
   i NIE działało: `body.printella .prt-pdp__akcje` (0,2,1) bije `.prt-pdp__akcje` (0,1,0),
   a media query NIE dodaje specyficzności. Skutek zmierzony na :10003 przy oknie 390 px:
   siatka zostawała trzykolumnowa, a napis „Jak przygotować plik” sięgał 443 px.
   Strona się przy tym NIE przewijała, bo `body` ma `overflow-x: clip` — czyli 53 px
   etykiety było po prostu UCIĘTE, bez żadnego sposobu, żeby je zobaczyć. `scrollWidth`
   pokazywał 443 i wyglądało to na przewijanie poziome; nie było nim.

   `min-width: 0` na przycisku i na tekście: bez tego element siatki i element flex nie
   zejdą poniżej szerokości min-content i nadal wystają. `flex-wrap` pozwala złamać
   dwuwyrazową etykietę, zamiast rozpychać rząd. */
@media (max-width: 460px) {
    body.printella .prt-pdp__akcje {
        grid-template-columns: 1fr;
    }

    body.printella button.prt-pdp__akcja {
        flex-direction: row;
        justify-content: flex-start;
        min-width: 0;
        min-height: 0;
        padding: 12px 14px;
        gap: 12px;
        text-align: left;
    }

    body.printella button.prt-pdp__akcja .prt-pdp__akcja-txt {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 4px;
        min-width: 0;
    }
}

/* 4. LINIJKA ZAUFANIA POD CTA */
/* ⚠️ PUNKT 12 POROWNANIA: RZAD POD PRZYCISKIEM TAKI SAM NA OBU STRONACH.
   Probnik ma trzy korzysci w trzech kolumnach (ikona obok tekstu, 15/700), karta miala
   ptaszki w jednym zawijanym rzedzie. Teraz oba to siatka trzech kolumn — a na waskim
   ekranie oba schodza do jednej, tak jak `.prt-probnik__korzysci`.
   Sekcja B briefu zada dla tych rzedow 15 px/700 i to zostaje. */
.prt-pdp__zaufanie {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    margin: var(--space-tight) 0 0;
    padding: 0;
    list-style: none;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-muted);
}

.prt-pdp__zaufanie li {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    line-height: 1.3;
}

/* 5. RAMKA „INFORMACJA" — jeden styl dla wszystkich okien

      Handoff: białe tło i ramka #B4C0DE. Poprzednio bywało różowo na niebieskim,
      czyli dwa akcenty naraz w bloku, który ma tylko informować. */
.prt-info-ramka {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 22px 0 0;
    padding: 16px 18px;
    border: 1.5px solid #B4C0DE;
    border-radius: 12px;
    background: #fff;
    font-size: 16px;
    font-weight: 800;
    line-height: 1.4;
    color: var(--prt-navy);
}

.prt-info-ramka__i {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--prt-radius-pill);
    background: var(--prt-navy);
    color: #fff;
}

/* 6. OKNO „JAK PRZYGOTOWAĆ PLIK?" */
.prt-plik-wymogi {
    margin: 24px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 18px;
}

.prt-plik-wymogi li {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.prt-plik-wymogi svg {
    color: var(--prt-pink-cta);
}

.prt-plik-wymogi h3 {
    margin: 0;
    font-size: 17px;
    font-weight: 800;
    color: var(--prt-navy);
}

.prt-plik-wymogi p {
    margin: 4px 0 0;
    font-size: 15px;
    font-weight: 500;
    line-height: 1.5;
    color: #3A4478;
}

/* Stopka okna: CTA po lewej, odnośnik po prawej, zawijanie na wąskich. */
.printella-popup__stopka {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px 20px;
    margin-top: 24px;
}

.printella-popup__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 800;
    color: var(--prt-navy);
    text-decoration: none;
}

.printella-popup__link:hover,
.printella-popup__link:focus-visible {
    color: var(--prt-pink-cta);
}

/* 7. TABELE W OKNACH — bez pionowych linii, ceny do prawej

      Handoff, §4 i §5. `.prt-table` ma ramkę dookoła i stałą szerokość ostatniej
      kolumny; w oknach ma być lżej: tylko linie poziome i wyrównanie, które pozwala
      porównywać liczby wzrokiem. */
.printella-popup .prt-table {
    border: 0;
    border-radius: 0;
}

.printella-popup .prt-table th {
    background: #F7F8FC;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #5A648C;
    white-space: nowrap;
}

.printella-popup .prt-table td,
.printella-popup .prt-table th {
    border-left: 0;
    border-right: 0;
}

.printella-popup .prt-table td {
    border-top: 1.5px solid var(--prt-line);
}

/* Ostatnia kolumna to ZAWSZE cena: do prawej, cyframi o równej szerokości, bez zawijania.
   `tabular-nums` jest tu treścią, nie ozdobą — bez niego kolumna „89,90 / 104,00" skacze. */
.printella-popup .prt-table td:last-child,
.printella-popup .prt-table th:last-child {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    width: auto;
}

/* Tabela progów ma trzy kolumny: ilość do lewej, rabat na środku, cena do prawej. */
.printella-popup .prt-table--tiers td:nth-child(2),
.printella-popup .prt-table--tiers th:nth-child(2) {
    text-align: center;
}

/* 8. TERMIN REALIZACJI — etykieta słabsza, wartość mocniejsza */
.prt-lead-time p {
    font-size: 13px;
    font-weight: 700;
    color: #5A648C;
}

.prt-lead-time strong {
    display: block;
    margin-top: 4px;
    font-size: 18px;
    font-weight: 900;
    color: var(--prt-navy);
}

/* 9. OKNO ZWROTÓW — dwa odnośniki obok siebie, stopka do lewej

      Handoff: „Masz już swój projekt?" wyrównane do lewej, nad CTA. Było wyśrodkowane,
      a przycisk pod nim z lewej — dwa różne wyrównania w jednym bloku. */
.prt-policy__linki {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 22px;
    margin: 14px 0 0;
}


/* =========================================================
   STRONA ZBIORCZA /tkaniny/ — BOKSY RODZAJÓW I SEKCJE

   Handoff 28.10.2026, punkt 2: zamiast filtrów podział na kategorie, bo „około
   15 materiałów, nie ma co filtrować". Markup składa shortcode
   `[printella_tkaniny_katalog]` z danych taksonomii `rodzaj-tkaniny` — po stronie
   SERWERA, nie jak w makiecie skryptem w przeglądarce, żeby treść kategorii była
   w HTML-u dla wyszukiwarek i bez JS.
   ========================================================= */

/* 1. SIATKA BOKSÓW — 4 → 2 → 1, nigdy 3+1

      Handoff wprost zakazuje stanu 3+1, dlatego poniżej 980 px idziemy od razu na dwie
      kolumny, a nie na trzy. Odstęp jak w makiecie. */
.prt-rodzaje {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(16px, 1.8vw, 24px);
    margin-top: clamp(28px, 3vw, 40px);
}

@media (max-width: 980px) {
    .prt-rodzaje { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 480px) {
    .prt-rodzaje { grid-template-columns: minmax(0, 1fr); }
}

/* 2. BOKS

      `height: 100%` na odnośniku i `flex: 1` na karcie dają RÓWNĄ WYSOKOŚĆ w rzędzie
      niezależnie od długości opisu — wymóg handoffu. Zdjęcie przypięte do dołu przez
      `margin-top: auto` na swoim kontenerze. */
.prt-rodzaj {
    display: flex;
    flex-direction: column;
    height: 100%;
    color: var(--prt-navy);
    text-decoration: none;
    border-radius: 22px;
    outline-offset: 4px;
}

.prt-rodzaj__karta {
    flex: 1;
    display: flex;
    flex-direction: column;
    border-radius: 20px;
    overflow: hidden;
    padding: 22px 0 0;
    transition: transform var(--prt-transition-card);
}

.prt-rodzaj__nazwa {
    margin: 0 22px;
    font-size: clamp(20px, 1.8vw, 24px);
    font-weight: 800;
    letter-spacing: -.02em;
}

.prt-rodzaj__opis {
    margin: 8px 22px 0;
    font-size: 14px;
    line-height: 1.5;
    font-weight: 500;
    color: var(--prt-text-muted);
}

.prt-rodzaj__licznik {
    margin: 6px 22px 0;
    font-size: 13px;
    font-weight: 700;
    color: #5A648C;
}

/* ⚠️ `object-fit: cover` UCINA kadr, a handoff prosi o „cały kadr, bez ucinania".
   Nie da się mieć obu rzeczy naraz, dopóki zdjęcia boksów nie mają proporcji 570/398:
   dziś boks pokazuje miniaturę pierwszej tkaniny z kategorii, bo osobnego zdjęcia
   dla boksu nie ma w danych. Na teksturze materiału ucięcie jest nieszkodliwe,
   `contain` zostawiałby za to puste pasy w kolorowym boksie. Prawdziwą naprawą jest
   dodanie zdjęć 570×398 jako pola termu — zgłoszone. */
.prt-rodzaj__media {
    margin-top: auto;
    border-top: 18px solid transparent;
    aspect-ratio: 570 / 398;
    position: relative;
    overflow: hidden;
}

.prt-rodzaj__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--prt-transition-media);
}

.prt-rodzaj__cta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
    font-size: 15px;
    font-weight: 800;
}

.prt-rodzaj__strzalka {
    color: var(--prt-pink-cta);
    transition: transform var(--prt-transition);
}

@media (hover: hover) and (pointer: fine) {
    .prt-rodzaj:hover .prt-rodzaj__karta { transform: translateY(-3px); }
    .prt-rodzaj:hover .prt-rodzaj__media img { transform: scale(1.03); }
    /* Strzałka w dół, bo prowadzi do sekcji NIŻEJ na tej samej stronie. */
    .prt-rodzaj:hover .prt-rodzaj__strzalka { transform: translateY(4px); }
}

.prt-rodzaj:focus-visible {
    outline: 3px solid var(--prt-pink-cta);
}

/* 3. SEKCJA RODZAJU — tekst obok zdjęcia z hero strony kategorii */
.prt-rodzaj-sek {
    margin-top: clamp(64px, 7vw, 96px);
    scroll-margin-top: var(--prt-section-gap);
}

.prt-rodzaj-sek__glowa {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(24px, 4vw, 64px);
    align-items: center;
}

@media (max-width: 760px) {
    .prt-rodzaj-sek__glowa { grid-template-columns: minmax(0, 1fr); }
}

.prt-rodzaj-sek__h2 {
    margin: 0;
    font-size: clamp(24px, 2.6vw, 34px);
    line-height: 1.08;
    font-weight: 900;
    letter-spacing: -.02em;
    color: var(--prt-navy);
}

.prt-rodzaj-sek__lead {
    margin: 16px 0 0;
    font-size: clamp(15px, 1.3vw, 17px);
    line-height: 1.55;
    font-weight: 500;
    color: var(--prt-text-muted);
}

.prt-rodzaj-sek__wiecej {
    margin: 18px 0 0;
    font-size: 15px;
    font-weight: 800;
}

.prt-rodzaj-sek__wiecej a {
    color: var(--prt-navy);
    text-decoration: none;
}

.prt-rodzaj-sek__wiecej a:hover,
.prt-rodzaj-sek__wiecej a:focus-visible {
    color: var(--prt-pink-cta);
}

.prt-rodzaj-sek__media img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 20px;
}

/* 4. HERO STRONY /tkaniny/

      Układ bierze KLASY HERO KATEGORII (`prt-kat-hero`, `__txt`, `__art`), więc skala
      nagłówka, przełamanie na kolumnę poniżej 940 px i proporcje kolumn są te same, co
      w działach — polecenie Steve'a: „Hero jak w innych działach".

      ⚠️ Kolumna grafiki ZNIKA, dopóki nie ma obrazu. Plik ma dojść później, a pusta
      kolumna zabierała 588 px przy 1440 px, czyli połowa hero była biała. Obraz pojawi
      się sam po wgraniu do mediów ze slugiem `tkaniny-hero` — wtedy warunek `:has(img)`
      przestaje być spełniony i kolumna wraca. */
#tka-hero .prt-kat-hero__art:not(:has(img)) {
    display: none;
}


.prt-tka-hero__h1 {
    margin: 10px 0 0;
    font-size: clamp(32px, 4vw, 56px);
    line-height: 1.04;
    font-weight: 900;
    letter-spacing: -.03em;
    color: var(--prt-navy);
    text-wrap: balance;
}

.prt-tka-hero__lead {
    margin: 18px 0 0;
    max-width: 560px;
    font-size: clamp(16px, 1.4vw, 19px);
    line-height: 1.55;
    font-weight: 500;
    color: var(--prt-text-muted);
}

.prt-tka-hero__usp {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 26px;
    margin: 24px 0 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    font-weight: 700;
    color: var(--prt-navy);
}

.prt-tka-hero__usp li::before {
    content: "✓";
    margin-right: 8px;
    color: var(--prt-pink-cta);
    font-weight: 900;
}

/* 5. PASMO „Nie wiesz, który materiał wybrać?" z Tango

      Tango stoi ŁAPAMI NA DOLNEJ KRAWĘDZI pasma — `align-self: end` plus `display: block`
      na obrazku, bez żadnego ujemnego przesunięcia. Pytajniki siedzą NAD PRAWYM UCHEM,
      nie na głowie (handoff), więc są pozycjonowane od prawej krawędzi obrazka, a nie
      wyśrodkowane. */
.prt-tka-pomoc {
    display: grid;
    /* ⚠️ Kolumna Tango ma KONKRETNY wymiar, nie `auto`. Przy `auto` szerokość obrazka
       `min(100%, clamp(...))` zależała od szerokości kolumny, a ta od zawartości —
       zależność cykliczna, którą przeglądarka rozwiązuje na ZERO. Zmierzone: Tango
       miało 0 px przy 1440, 1000 i 900, a pojawiało się tylko tam, gdzie pasmo schodzi
       do jednej kolumny. */
    grid-template-columns: minmax(0, 1fr) clamp(210px, 24vw, 300px);
    gap: clamp(20px, 3vw, 48px);
    align-items: end;
    margin-top: clamp(64px, 7vw, 96px);
    padding: clamp(28px, 3vw, 40px) clamp(24px, 3vw, 40px) 0;
    border-radius: 24px;
    background: var(--prt-surface-pink);
    overflow: hidden;
}

.prt-tka-pomoc__h2 {
    margin: 0;
    font-size: clamp(24px, 2.6vw, 34px);
    line-height: 1.08;
    font-weight: 900;
    letter-spacing: -.02em;
    color: var(--prt-navy);
}

.prt-tka-pomoc__lead {
    margin: 14px 0 0;
    max-width: 520px;
    font-size: clamp(15px, 1.3vw, 17px);
    line-height: 1.55;
    font-weight: 500;
    color: var(--prt-text-muted);
}

.prt-tka-pomoc__cta {
    margin: 22px 0 clamp(28px, 3vw, 40px);
}

.prt-tka-pomoc__tango {
    position: relative;
    align-self: end;
    width: 100%;
}

.prt-tka-pomoc__tango img {
    display: block;
    width: 100%;
    height: auto;
}

.prt-tka-pomoc__znaki {
    position: absolute;
    top: 6%;
    right: 12%;
    font-family: Kalam, cursive;
    font-size: clamp(26px, 3vw, 40px);
    font-weight: 700;
    line-height: 1;
    color: var(--prt-pink-cta);
    transform: rotate(-8deg);
    pointer-events: none;
}

/* Poniżej 760 px pasmo idzie w jedną kolumnę, a Tango na środek pod tekstem —
   przy dwóch kolumnach na telefonie i tekst, i pies są za ciasne. */
@media (max-width: 760px) {
    .prt-tka-pomoc {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
        text-align: center;
    }

    .prt-tka-pomoc__cta { margin-bottom: 8px; }

    /* Jedna kolumna: nie ma już kolumny o danym wymiarze, więc ograniczenie wraca
       na sam obrazek — tu `100%` odnosi się do pełnej szerokości pasma, nie do
       kolumny zależnej od zawartości, więc cyklu nie ma. */
    .prt-tka-pomoc__tango { width: min(100%, clamp(210px, 40vw, 300px)); }
}

/* =========================================================
   TANGO W PASKU NEWSLETTERA (strona główna)

   Handoff 28.10.2026 przepisuje to pozycjonowanie od zera, bo poprzednie liczyło się od
   WIERSZA Z POLEM e-mail (`bottom: calc(100% + 23px)` na `div` otaczającym input), a ten
   wiersz przy zawijaniu wędruje — i przy 390 px pies wchodził na nagłówek „Dołącz do
   naszego newslettera" (znalezione przez FreeAgenta, potwierdzone pomiarem).
   Teraz obrazek jest dzieckiem RAMKI newslettera i stoi łapami na jej górnej krawędzi
   niezależnie od tego, jak zawinie się treść w środku.

   Szerokość poniżej 620 px potrzebuje `!important`, bo 190 px siedzi w atrybucie `style`.
   ========================================================= */
@media (max-width: 620px) {
    body.printella [data-tango-news] {
        width: 150px !important;
    }
}

/* ⚠️ USUNIĘTA STĄD STARA REGUŁA. Do 28.10.2026 w sekcji responsywnej wyżej (ok. linii 372)
   siedziało `@media (max-width: 620px) { [data-tango-news] { width: 104px !important;
   right: 0 !important; } }` — napisane pod POPRZEDNIE pozycjonowanie, gdy obrazek miał
   `right: 6px` i wisiał nad wierszem z polem. Po przeniesieniu Tango do ramki `right: 0`
   dociskało je do krawędzi: zmierzone 1 px odstępu zamiast ~25 px z `clamp(24px,4vw,64px)`.
   Szerokość moja reguła nadpisywała, `right` zostawało — klasyczna niewidoczna pozostałość
   po starym układzie. Skasowana, nie nadpisana drugim `!important`. */

/* =========================================================
   STOPKA GLOBALNA — UKŁAD, HOVER I STAN AKTYWNY

   28.10.2026, handoff „stopka, Tkaniny, listingi". Stopka to szablon Elementora 6150,
   jeden widżet `html`. W nim siedzi WYŁĄCZNIE markup i style, które nie mają gdzie się
   zepsuć; tutaj to, czego atrybut `style` nie potrafi:
     - stany (`:hover`, `[aria-current]`) — w makiecie zapisane jako `style-hover="…"`,
       czyli atrybut, którego żadna przeglądarka nie zna;
     - punkty łamania 1040 / 680 / 480 px — media queries nie istnieją w stylach inline.

   Dlatego w widżecie nie ma ANI JEDNEJ reguły hover ani responsywnej. Gdyby była,
   trzeba by ją trzymać równo z tym plikiem — a dwie kopie wyglądu zawsze się rozjeżdżają
   (ta sama przyczyna co przy `.prt-koszyk-licznik` i nagłówku).
   ========================================================= */

/* 1. ODNOŚNIKI — kolory z makiety; nagłówki kolumn granatowe, listy stonowane */
body.printella footer#kontakt a {
    color: inherit;
    text-decoration: none;
}

body.printella footer#kontakt [data-foot-oferta] p > a,
body.printella footer#kontakt [data-foot-help] p > a {
    color: var(--prt-navy);
}

body.printella footer#kontakt [data-foot-oferta] li > a,
body.printella footer#kontakt [data-foot-help] li > a,
body.printella footer#kontakt [data-foot-pasek] a {
    color: #3A4478;
}

body.printella footer#kontakt a:hover,
body.printella footer#kontakt a:focus-visible {
    color: var(--prt-pink-cta);
}

/* Strona, na której właśnie jesteśmy. Atrybut ustawia skrypt w stopce — statyczny
   widżet HTML nie wie, gdzie stoi. Kolor zostaje tu, żeby stan i reszta wyglądu
   mieszkały w jednym miejscu.

   ⚠️ `!important`, bo reguła nagłówka kolumny wyżej (`[data-foot-oferta] p > a`) ma
   wyższą specyficzność niż `a[aria-current]` i wygrywała z nią — zmierzone: aktywny
   odnośnik „Druk na materiałach" zostawał granatowy. Alternatywą byłoby dopisanie
   `[aria-current]` do każdej reguły kolorów osobno, czyli cztery miejsca do trzymania
   równo zamiast jednego. */
body.printella footer#kontakt a[aria-current="page"] {
    color: var(--prt-pink-cta) !important;
}

/* 2. SOCIAL — kółka 40 px, ikona biała, hover różowy */
body.printella footer#kontakt [data-foot-social] > a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: var(--prt-navy);
    transition: background .18s;
}

body.printella footer#kontakt [data-foot-social] > a:hover,
body.printella footer#kontakt [data-foot-social] > a:focus-visible {
    background: var(--prt-pink-cta);
}

/* 3. SIATKA 4 → 3 → 2 → 1

      ⚠️ Przy 3 kolumnach blok marki idzie na GÓRĘ jako pasek na całą szerokość
      (`grid-column: 1 / -1`) i układa się w poziomie: logo, hasło, social, a język
      dociśnięty w prawo. Bez tego marka zostawała wąską kolumną obok trzech innych
      i hasło łamało się po dwóch słowach.

      Kolumna „Pomoc" traci prawą linię wszędzie poniżej 1040 px — przy trzech i mniej
      kolumnach wypadała w środku rzędu i wyglądała jak przypadkowa kreska. */
/* ⚠️ `!important` w CAŁEJ tej sekcji nie jest ozdobą: siatka, kierunek flexa i linia
   kolumny „Pomoc" siedzą w atrybucie `style` widżetu, a styl inline bije każdy selektor.
   Zmierzone bez tego: przy 390 px stopka nadal miała CZTERY kolumny, a blok marki
   wystawał 524 px w siatce szerokiej na 334 px. Ten sam zabieg co w pasku newslettera
   wyżej w tym pliku. */
@media (max-width: 1040px) {
    body.printella footer#kontakt [data-foot-grid] {
        grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    }

    body.printella footer#kontakt [data-foot-brand] {
        grid-column: 1 / -1;
        flex-direction: row !important;
        align-items: center;
        flex-wrap: wrap;
        gap: 18px 24px;
    }

    body.printella footer#kontakt [data-foot-brand] > a {
        flex: none;
    }

    /* Blok marki jest elementem siatki, ale jego własny `min-width: auto` pozwalał mu
       rozepchnąć się szerzej niż kolumna (zmierzone: 524 px przy siatce 334 px).
       `min-width: 0` to standardowa poprawka dla dzieci grida i flexa. */
    body.printella footer#kontakt [data-foot-brand] {
        min-width: 0;
    }

    body.printella footer#kontakt [data-foot-lang] {
        margin-left: auto;
    }

    body.printella footer#kontakt [data-foot-help] {
        padding-right: 0 !important;
        border-right: 0 !important;
    }
}

@media (max-width: 680px) {
    body.printella footer#kontakt [data-foot-grid] {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
}

/* Jedna kolumna: blok marki wraca do pionu, a język schodzi POD social — w rzędzie
   z `margin-left:auto` zostawałby sam na końcu wiersza, oderwany od ikon. */
@media (max-width: 480px) {
    body.printella footer#kontakt [data-foot-grid] {
        grid-template-columns: minmax(0, 1fr) !important;
    }

    body.printella footer#kontakt [data-foot-brand] {
        flex-direction: column !important;
        align-items: flex-start;
    }

    body.printella footer#kontakt [data-foot-lang] {
        margin-left: 0;
    }
}

/* ⚠️ DŁUGIE ZŁOŻENIA W STOPCE — NIEMIECKI ŁAMIE TO, CZEGO POLSKI NIE ŁAMIE.
   Na 320 px nagłówek stopki „WIR DRUCKEN VERANTWORTUNGSVOLL" wychodził poza okno:
   pudełko `h6` ma 88 px, a sam napis 227 px — „VERANTWORTUNGSVOLL" nie ma gdzie się
   złamać, więc glify szły do x=343. `overflow-x: clip` na `body` ucinało je w pół słowa
   („VERANTWORTUNGSVO"), więc NIE BYŁO PASKA PRZEWIJANIA i nic tego nie zgłaszało.

   ⚠️ Nie znalazł tego nasz stały test przelewania, bo mierzył PROSTOKĄTY ELEMENTÓW —
   a prostokąt `h6` mieścił się w oknie, wystawały same glify. FreeAgent dołożył do testu
   drugi pomiar, po węzłach tekstu przez `Range`, i rozszerzył listę o adresy DE i EN.
   Do 31.10.2026 bramka mierzyła wyłącznie polskie strony, czyli język o najkrótszych
   napisach — po angielsku ten sam nagłówek ma 128 px i mieści się bez trudu.

   `hyphens` pierwszy, bo dzieli słowo w miejscu zgodnym z regułami języka (`<html lang>`
   ustawia WPML). `overflow-wrap` jako zapas tam, gdzie przeglądarka nie ma słownika —
   lepszy brzydki podział niż napis ucięty w pół. */
body.printella footer.elementor-location-footer .elementor-heading-title {
    hyphens: auto;
    overflow-wrap: break-word;
}

/* ⚠️ TO SAMO NA WSZYSTKICH NAGŁÓWKACH — bo problem nie dotyczy stopki, tylko NIEMIECKIEGO.
   Po poprawieniu stopki FreeAgent puścił bramkę na pełnej liście stron DE i EN i znalazł
   trzy kolejne wystąpienia tego samego mechanizmu, każde na innej stronie:
   „Datenschutzerklärung" w H1 polityki prywatności (54 px poza oknem przy 320),
   „Baumwollstoffe" w H1 kategorii (12 px) i „INNERGEMEINSCHAFTLICHE LIEFERUNGEN"
   w H2 regulaminu (8 px).

   Łatanie ich po jednym znaczyłoby czekanie, aż ktoś doda czwarte niemieckie złożenie.
   Reguła jest bezpieczna: `hyphens` i `overflow-wrap` DZIAŁAJĄ TYLKO WTEDY, gdy słowo
   i tak nie mieści się w wierszu — na krótszych napisach nie zmieniają niczego. */
body.printella h1,
body.printella h2,
body.printella h3,
body.printella h4,
body.printella h5,
body.printella h6,
body.printella .elementor-heading-title {
    hyphens: auto;
    overflow-wrap: break-word;
}

/* 4. CELE DOTYKU W NAGŁÓWKU I STOPCE
      Odnośniki menu w nagłówku miały 20 px wysokości (nagłówek 201 px, bo pięć pozycji
      zawija się na telefonie), a odnośniki prawne w stopce koszyka i kasy 19 px.
      WCAG 2.5.8 (AA) wymaga 24 px, wytyczne iOS/Androida mówią o 44 px.
      Dajemy padding pionowy do 36 px — bez zmiany rozmiaru tekstu i bez ruszania
      desktopu, gdzie nagłówek jest jednowierszowy. */
@media (max-width: 1024px) {
    body.printella #prt-naglowek-nawigacja .elementor-nav-menu--main .elementor-item,
    body.printella footer#kontakt li > a,
    body.printella footer.elementor-location-footer .elementor-heading-title > a {
        padding-block: 8px;
        display: inline-flex;
        align-items: center;
        min-height: 36px;
    }
}

/* 5. SZTYWNE `min-width` W PASKU NEWSLETTERA (strona główna)
      Kolumna z polem e-mail ma `min-width:300px` w atrybucie `style`, a na 320 px
      dostępne jest 264 px — pasek wystawał 36 px za ekran (pole i przycisk „Zapisz się"
      ucięte). Ta sama sztuczka co z siatkami: powyżej 300 px nic się nie zmienia.
      `min-width:300px` i `260px` występują w całym serwisie tylko tutaj, sprawdzone
      w HTML wszystkich 19 podstron (`240px` ze stopki mieści się i zostaje). */
body.printella [style*="min-width:300px"] {
    min-width: min(300px, 100%) !important;
}

body.printella [style*="min-width:260px"] {
    min-width: min(260px, 100%) !important;
}

/* 6. ZAGNIEŻDŻONE PADDINGI NA „USŁUGACH GRAFICZNYCH"
      Kafle usług to kontenery Elementora, nie widżety HTML, więc padding idzie
      ze zmiennych `--padding-*`. Na 320 px schodziliśmy przez cztery poziomy:
      28 + 28 px marginesu strony, 26 px kafla (`.prt-svc`, tło #EEF6FD) i jeszcze
      28 px na `.prt-svc__list`, który tła nie ma — zostawało 100 px treści,
      a lista ikon potrzebuje 130 px. Padding kafla zostaje, bo jest widoczny;
      znika tylko ten bez tła. */
@media (max-width: 767px) {
    .e-con.prt-svc__list {
        --padding-left: 0px;
        --padding-right: 0px;
        --padding-inline-start: 0px;
        --padding-inline-end: 0px;
    }
}

/* 7. WIERSZ KAFLI USŁUG — drugi padding bez tła
      `#uslugi-karty` daje 28 px marginesu strony, a `.prt-svc-row` dokłada drugie 28 px,
      więc kafle zaczynały się 56 px od krawędzi (jedyna strona w serwisie z takim
      odstępem — pozostałe 18 mierzy 28 px). Wiersz jest wrapperem bez tła. */
@media (max-width: 767px) {
    .e-con.prt-svc-row {
        --padding-left: 0px;
        --padding-right: 0px;
        --padding-inline-start: 0px;
        --padding-inline-end: 0px;
    }
}

/* 8. NAGŁÓWEK HERO NA BARDZO WĄSKICH EKRANACH
      Na Kontakcie „Porozmawiajmy." w 46 px to 286 px przy 264 px dostępnych — kropka
      (osobny `span` w kolorze CTA) wychodziła za ekran. Dolna granica `clamp()` w hero
      jest sztywna, więc poniżej 360 px podmieniamy ją na wartość liczoną z szerokości.
      Łamanie słów w nagłówku odpada — dzielilibyśmy wyraz w połowie. */
@media (max-width: 360px) {
    body.printella section#top h1 {
        font-size: clamp(32px, 11.5vw, 46px) !important;
    }
}

/* 9. „USŁUGI GRAFICZNE" — cała strona miała podwójny margines
      To jedyna podstrona zbudowana w całości z kontenerów Elementora, gdzie sekcja
      `.prt-ug-sec` daje 28 px marginesu strony, a kontener w środku dokłada własne 28 px.
      Nagłówki i lead startowały 56 px od krawędzi, przy 28 px na pozostałych 18 stronach.

      Padding zdejmujemy TYLKO z wrapperów bez tła — sprawdzone pomiarem tła, ramki
      i cienia każdego kontenera na tym poziomie. Zostaje na dwóch, które są kartami:
      `.prt-ug-panel` (ramka 1 px) i `.prt-ug-wyc__p` (tło #FDEAF2). Selektory są
      zagnieżdżone w `.prt-ug-sec`, więc te same klasy na innych stronach nie tracą
      odstępu od krawędzi, gdyby były tam jedynym marginesem. */
@media (max-width: 767px) {
    .prt-ug-sec > .e-con-inner > .prt-ug-hero__txt,
    .prt-ug-sec > .e-con-inner > .prt-hero-art--uslugi,
    .prt-ug-sec > .e-con-inner > .prt-sec-head,
    .prt-ug-sec > .e-con-inner > .prt-trust__i {
        --padding-left: 0px;
        --padding-right: 0px;
        --padding-inline-start: 0px;
        --padding-inline-end: 0px;
    }
}

/* ⚠️ TRZECI PADDING W TYM SAMYM MIEJSCU — widać go dopiero na 320 px.
   Kolumna z formularzem wyceny (`.prt-ug-wyc__l`) siedzi WEWNĄTRZ różowego panelu, więc
   na 320 px z każdej strony zjadają po 86 px trzy zagnieżdżone paddingi: sekcja 28,
   panel 30, kolumna 28. Na kolumnę zostaje 148 px, a przycisk „Otwórz formularz"
   potrzebuje ~192 — i łamie się na dwie linie niezależnie od tego, ile mu odejmiemy
   paddingu. Zmierzył FreeAgent 31.10.2026.

   Kolumna NIE MA WŁASNEGO TŁA — tło niesie panel — więc jej padding niczego nie oddziela
   i można go zdjąć bez zmiany wyglądu poza szerokością. Ta sama zasada, co w bloku wyżej:
   padding zostaje tam, gdzie jest karta, znika tam, gdzie jest wrapper.

   Próg 480, a nie 400: przy 360 px kolumna ma 188 px i przycisk też by się łamał, więc
   granica musi leżeć wyżej niż jedyna zmierzona szerokość, na której było dobrze (390). */
@media (max-width: 480px) {
    /* ⚠️ `.e-con-inner` POMIĘDZY: panel jest `e-con-boxed`, więc kolumna NIE jest jego
       bezpośrednim dzieckiem. Pierwsza wersja tego selektora pomijała ten stopień
       i nie trafiała w nic — bez żadnego błędu, po prostu bez skutku. */
    .prt-ug-wyc__p > .e-con-inner > .prt-ug-wyc__l {
        --padding-left: 0px;
        --padding-right: 0px;
        --padding-inline-start: 0px;
        --padding-inline-end: 0px;
    }
}

/* =========================================================
   10. WSPÓLNY MARGINES BOCZNY NA TELEFONIE (28 px)
   =========================================================
   Po przeglądzie mobile 19 podstron margines boczny miał pięć różnych wartości:
   28 px na czternastu stronach, 20 px na „Dostawie i płatności", 16–20 px w koszyku
   i kasie, 44 px w Kreatorze, a 10 px na Regulaminie, Polityce i Moim koncie.

   Te 10 px to Hello Elementor: `@media (max-width: 575px)` nakłada `padding-inline: 10px`
   na `body:not([class*=elementor-page-]) .site-main` ORAZ na `.page-header .entry-title`,
   czyli dwa razy po 10 px — boks nagłówka startował na 10, a jego tekst na 20.

   Prefiks `body.printella` nie jest ozdobą: `themes/printella/style.css` ładuje się PRZED
   `hello-elementor/assets/css/theme.css`, więc przy równej specyficzności wygrywałby
   motyw rodzica (ten sam powód co przy regule szerokości treści na górze `style.css`).
   Selektor `:not([class*="elementor-page-"])` jest przepisany z Hello 1:1 — celuje
   dokładnie w strony spoza Elementora, czyli prawne, konto i zwykłe.

   ⚠️ Nadpisanie motywu RODZICA. Przy aktualizacji Hello Elementora sprawdzić, czy
   selektor i próg 575 px nadal wyglądają tak samo.

   „Dostawa i płatność" NIE jest tutaj: tam 20 px siedziało w `_elementor_data`
   (28 kontenerów na stronach 6097/6099/6101), więc poprawione zostało w ustawieniach
   kontenerów, a nie arkuszem. Kreator i koszyk mają własne pliki — patrz `creator.css`
   i `printella-cart.css`.
   ========================================================= */
:root {
    --prt-margines-boczny: 28px;
}

@media (max-width: 575px) {
    /* Koszyk i kasa są WYŁĄCZONE świadomie: `printella-cart.css` ustawia im
       `main.site-main { padding-inline: 0 }`, bo margines dają tam `.page-header`,
       `.printella-cart-layout` i `.printella-cart-empty`. Bez tych dwóch `:not()`
       moja reguła (specyficzność 0,3,1) wygrywała z tamtą (0,2,1) i marginesy
       sumowały się do 56 px — zmierzone, zanim to poprawiłem. */
    body.printella:not([class*="elementor-page-"]):not(.woocommerce-cart):not(.woocommerce-checkout) main.site-main {
        padding-inline: var(--prt-margines-boczny);
    }

    /* Drugie 10 px z Hello — odstęp daje już `main.site-main` powyżej. */
    body.printella .page-header .entry-title {
        padding-inline: 0;
    }
}

/* ── Moje konto ───────────────────────────────────────────────────────────────────
   Komunikaty stały na styk z tym, co pod nimi (nagłówek sekcji, formularz), i ze sobą
   nawzajem — zmierzone 28.10.2026: odstęp 0 px w zamówieniach, adresach i danych konta. */
body.woocommerce-account.printella .printella-noty {
    margin-bottom: 16px;
}

/* Logowanie i reset hasła: pierwszy komunikat dotykał dolnej krawędzi nagłówka strony. */
body.woocommerce-account.printella:not(.logged-in) .printella-noty:first-child {
    margin-top: 32px;
}

/* ── Order-pay ────────────────────────────────────────────────────────────────────
   Przy złym linku do płatności WooCommerce drukuje SAM komunikat, bez szablonu strony —
   stał na całą szerokość okna, bez marginesów (szerokość: `style.css`, przy
   `.printella-order-pay-page`). Ostrzeżenie o zamówieniu gościa trafia pod tytuł
   (`checkout/form-pay.php`). */
body.woocommerce-order-pay .woocommerce > .printella-noty {
    margin: clamp(28px, 3.6vw, 52px) auto;
}

.printella-order-pay__noty {
    margin-bottom: 24px;
}

/* ==========================================================================
   Nagłówek 6151 na telefonie: menu jako hamburger (decyzja Steve'a 28.10.2026)
   Działa tylko, gdy widżet menu ma w Elementorze „Dropdown: Mobile”
   (klasa :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet)). Przy „None” nic się nie zmienia,
   więc CSS może wejść przed przełączeniem ustawienia i po jego cofnięciu.
   Układ: logo | konto+koszyk | przycisk menu w jednym rzędzie; rozwinięte menu
   to panel nad treścią (absolute), a nie blok spychający stronę.
   ========================================================================== */
/* ⚠️ UZUPEŁNIENIE 28.10.2026: selektory łapią teraz TAKŻE `--dropdown-tablet`.
   Blok powstał pod „Dropdown: Mobile", ale ustawienie widżetu to „Tablet" — progi kitu
   to mobile 480 i tablet 768, więc „Mobile" zostawiał cały przedział 481–768 px z menu
   zawiniętym w dwa wiersze (zmierzone 101–186 px), czyli ten stan, który mieliśmy usunąć.
   Przy samym „Tablet" hamburger się pokazywał, ale bez tego dopracowania: telefon miał
   wtedy 153 px zamiast 91. Stąd `:is()` na obu klasach. */
@media (max-width: 767px) {
    .elementor-6151 .e-con:has(> .e-con-inner > :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet)) {
        position: relative;
    }
    .elementor-6151 .e-con-inner:has(> :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet)) {
        flex-wrap: nowrap;
        align-items: center;
        gap: 8px;
    }
    .elementor-6151 .e-con-inner:has(> :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet)) > .elementor-element-c86aa78 {
        order: 1;
        flex: 0 1 auto;
    }
    .elementor-6151 .e-con-inner:has(> :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet)) > .elementor-element-b2c8d41 {
        order: 2;
        margin-left: auto;
    }
    .elementor-6151 :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet) {
        order: 3;
        position: static;
        width: auto;
        flex: none;
    }
    .elementor-6151 :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet) .elementor-menu-toggle {
        background: transparent;
        color: var(--prt-navy, #101B54);
        padding: 6px;
        font-size: 26px;
    }
    .elementor-6151 :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet) .elementor-menu-toggle svg {
        fill: currentColor;
    }
    .elementor-6151 :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet) nav.elementor-nav-menu--dropdown {
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
        margin: 0 !important;
        width: auto !important;
        background: #fff;
        border-top: 1px solid #F1E6EE;
        box-shadow: 0 18px 30px -18px rgba(16, 27, 84, .35);
        padding: 8px 12px 16px;
        z-index: 50;
    }
    .elementor-6151 :is(.elementor-nav-menu--dropdown-mobile,.elementor-nav-menu--dropdown-tablet) nav.elementor-nav-menu--dropdown a {
        font-size: 17px;
        padding: 14px 16px;
        color: var(--prt-navy, #101B54);
    }
}

/* ───────── Podmiot odpowiedzialny za produkt (GPSR) ─────────
   Blok w zakładce „Producent i bezpieczeństwo". Dane są stałą firmową, nie polem
   per tkanina — patrz `Printella_Fabric_Produkt::DANE_PRODUCENTA`. */
.prt-gpsr {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--prt-navy);
}

.prt-gpsr p {
    margin: 0;
}

.prt-gpsr__naglowek {
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .02em;
    color: #71717a;
}

.prt-gpsr__adres,
.prt-gpsr__kontakt {
    margin-top: 4px;
}

.prt-gpsr__kontakt a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ───────── Kod materiału na karcie tkaniny (handoff „probnik", punkt 2) ─────────
   Wersja ODWRÓCONA: biały środek, granatowy obrys i tekst. Ten sam kod jedzie na
   próbkach w próbniku i na fizycznej etykiecie, więc ma być nie do pomylenia —
   stąd obrys 2 px, 900 i `tabular-nums`, żeby cyfry nie tańczyły między kodami. */
.prt-mat-kod {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    margin: 14px 0 0;
}

.prt-mat-kod__znak {
    padding: 6px 13px;
    border: 2px solid var(--prt-navy);
    border-radius: 8px;
    background: #fff;
    font-size: 20px;
    font-weight: 900;
    line-height: 1.1;
    letter-spacing: .08em;
    color: var(--prt-navy);
    font-variant-numeric: tabular-nums;
}

.prt-mat-kod__opis {
    font-size: 14px;
    font-weight: 600;
    color: #3A4478;
}

.prt-mat-kod__opis a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ───────── Strona 404 (handoff „probnik", punkt 3) ───────── */
.prt-404 {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Góra z roli „hero główne" (brief 31.10.2026) — ta sama co strona główna.
       ⚠️ Musi stać TUTAJ, w regule z pełnym `padding`: osobna reguła `padding-top`
       wyżej w pliku przegrywała z tym skrótem, mimo że była bardziej szczegółowa
       w zamyśle. Skrót zapisuje wszystkie cztery strony, także tę, której nie dotyka. */
    padding: var(--prt-below-header-hero-lg) var(--prt-margines-boczny) clamp(56px, 6vw, 88px);
    text-align: center;
}

/* `96vh` w limicie szerokości: ilustracja jest szeroka i niska, więc na niskim oknie
   ograniczamy ją WYSOKOŚCIĄ okna, inaczej zjadałaby cały ekran i wypychała przycisk
   poniżej zgięcia. */
.prt-404__obraz {
    width: min(100%, 820px, 96vh);
    height: auto;
    mix-blend-mode: multiply;
}

.prt-404__tytul {
    margin: clamp(20px, 2.4vw, 36px) 0 0;
    font-size: clamp(28px, 3.8vw, 50px);
    font-weight: 900;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--prt-navy);
}

.prt-404__ups {
    color: var(--prt-pink-cta);
}

.prt-404__opis {
    margin: 12px 0 0;
    font-size: clamp(18px, 1.6vw, 20px);
    font-weight: 600;
    color: #3A4478;
}

/* ⚠️ WYGLĄD DAJE `.prt-btn-primary` — polecenie Steve'a 2.11.2026 („ustandaryzuj
   przycisk"). Ta klasa miała własną pigułkę 999 px, 18 px i padding 18/34/40, czyli
   trzeci wariant głównego przycisku w sklepie obok karty tkaniny i próbnika. Zostaje
   tu WYŁĄCZNIE to, czego standard nie zna: odstęp od tekstu nad przyciskiem i strzałka.
   Dzięki temu zmiana standardu w briefie zmienia też ten przycisk, zamiast go omijać. */
.prt-404__cta {
    margin-top: clamp(24px, 3vw, 38px);
}

.prt-404__strzalka {
    transition: transform var(--prt-transition);
}

.prt-404__cta:hover .prt-404__strzalka,
.prt-404__cta:focus-visible .prt-404__strzalka {
    transform: translateX(4px);
}

/* Ruch wyłączony dla osób, które go nie chcą — hover i tak zmienia kolor tła. */
@media (prefers-reduced-motion: reduce) {
    .prt-404__cta:hover,
    .prt-404__cta:focus-visible {
        transform: none;
    }

    .prt-404__cta:hover .prt-404__strzalka,
    .prt-404__cta:focus-visible .prt-404__strzalka {
        transform: none;
    }
}

/* ═════════ Próbnik tkanin (handoff „probnik", punkt 1) ═════════
   Struktura w `includes/probnik-strona.php`. Kontener i odstępy z handoffu. */
/* Miejsce na notyfikacje WooCommerce: szerokość treści, pod okruszkami.

   BEZ bocznego dopełnienia: komunikat ma być wyrównany do okruszków i do kolumn, a rodzic
   (blok okruszków, kontener karty produktu) ma już swoje. Dopełnienie dawało wcięcie 16 px
   i notyfikacja na karcie tkaniny stała na x=124 przy okruszkach na x=108. Wariant
   Wariant `--samodzielna` stoi tam, gdzie takiego rodzica nie ma, i daje sobie margines sam. */
.prt-noty-miejsce {
	width: 100%;
	max-width: 1224px;
	margin: 16px auto 24px;
	box-sizing: border-box;
}

/* Wariant SAMODZIELNY — dla miejsc, w których komunikat nie ma nad sobą kontenera
   z marginesem bocznym: początek treści buildera na archiwach i `before_single_product`
   na karcie produktu. Daje sobie margines sam, a `max-width` musi być szersze o te
   dopełnienia, inaczej pole treści zaczyna się o 28 px dalej niż logo, filtry i lista
   (zmierzone: x=136 przy treści na x=108). Nazwa mówi o WŁASNOŚCI, nie o stronie —
   pierwsza wersja nazywała się `--archiwum` i dlatego karta produktu, która potrzebuje
   dokładnie tego samego, została bez marginesu na telefonie. */
.prt-noty-miejsce--samodzielna {
	max-width: calc(1224px + 2 * var(--prt-margines-boczny, 16px));
	padding: 0 var(--prt-margines-boczny, 16px);
}

/* Karta tkaniny: 28 px bocznego dopełnienia siedzi na SAMYCH OKRUSZKACH
   (`body.single-tkanina .prt-crumbs-nav`), a nie na rodzicu — więc komunikat, który jest
   rodzeństwem okruszków, nie dostawał go wcale i na 390 szedł od krawędzi do krawędzi.
   Ta sama wartość w tym samym miejscu, żeby wyrównanie wynikało z konstrukcji, nie ze
   szczęścia. */
body.single-tkanina .prt-noty-miejsce {
	padding-inline: 28px;
}

/* Odstęp pod okruszkami ma być 16 px wszędzie, a `.prt-crumbs-nav` nosi własne
   `margin-bottom: clamp(18px, 2vw, 24px)` dla stron bez komunikatu. Gasimy je TYLKO wtedy,
   gdy komunikat faktycznie stoi niżej — wtedy liczy się jego własne 16 px. Gdy przeglądarka
   nie zna `:has()`, odstęp wychodzi 24 px zamiast 16 i nic się nie psuje. */
.prt-crumbs-nav:has(+ .prt-noty-miejsce) {
	margin-bottom: 0;
}

/* ⚠️ `.prt-noty-miejsce` jest DZIECKIEM FLEXA `.prt-probnik`, więc `row-gap` kontenera
   dokłada się do marginesów i żadne „margin: 16px" nie da 16 px. Zmierzone: 116 px pod
   okruszkami i 125 px do karty na 1440, 80/88 na 390 — czyli dokładnie odstęp plus gap.
   Dlatego odejmujemy gap tym samym wyrażeniem, z którego jest policzony; stoi raz, jako
   zmienna na `.prt-probnik`, żeby nie rozjechało się przy zmianie odstępów sekcji. */
.prt-probnik .prt-noty-miejsce {
	margin-block: calc(16px - var(--prt-probnik-odstep)) calc(24px - var(--prt-probnik-odstep));
	padding: 0;
}

.prt-probnik {
    --prt-probnik-odstep: clamp(64px, 7vw, 104px);
    max-width: 1280px;
    margin: 0 auto;
    padding: 0 var(--prt-margines-boczny);
    display: flex;
    flex-direction: column;
    gap: var(--prt-probnik-odstep);
}

/* ⚠️ OKRUSZKI MIALY NA KAZDEJ STRONIE INNE ODSTEPY i to widzial Steve jako
   „losowe odleglosci". Karta uzywa `.prt-crumbs` z rdzenia: `gap: 9px`, a odstep
   gorny daje kontener Elementora `.prt-ug-crumbs` przez `clamp(18px,2vw,26px)`.
   Probnik mial wlasny komponent z `gap: 6px` i sztywnym `padding-top: 22px`.
   Rownamy wartosci do karty.

   To obejscie, nie rozwiazanie: docelowo probnik ma uzywac tego samego komponentu
   okruszkow co reszta serwisu, bo dwa zapisy tej samej rzeczy rozjada sie znowu
   przy pierwszej zmianie. Tu wyrownuje liczby, zeby przestalo sie roznic dzis. */
/* Po przejściu na okruszki z rdzenia (5.116.0) zostają DWA odstępy do odtworzenia, bo
   na karcie tkaniny daje je kontener Elementora, a tutaj kontenera nie ma.

   GÓRA: token roli `--prt-below-header-crumb` (4 px) — ten sam, co na karcie tkaniny,
   kategoriach i wycenie. Wcześniej było tu 28 px odwzorowane z kontenera Elementora,
   a jeszcze wcześniej `clamp(18px,2vw,26px)`, czyli inna wartość na każdej szerokości.

   ⚠️ DÓŁ: `.prt-crumbs-nav` NIESIE WŁASNY `margin-bottom`, A `.prt-probnik` JEST FLEXEM
   Z `gap` — a w flexie margines i gap SIĘ DODAJĄ, nie zlewają. Odstęp wychodził więc
   `gap` (64–104 px) + 24 px, czyli 88–128 px zamiast 24. To ta dziura ze zrzutu Steve'a:
   fioletowa kreskowana wstęga w narzędziach to właśnie `gap`, dlatego nie było jej widać
   ani w paddingach, ani w marginesach.

   Odejmujemy gap TYM SAMYM wyrażeniem, z którego jest policzony — ta sama sztuczka,
   co przy `.prt-noty-miejsce` wyżej, i z tego samego powodu. */
.prt-probnik > .prt-crumbs-nav {
	padding-top: var(--prt-below-header-crumb);
	margin-bottom: calc(var(--prt-okruszki-dol) - var(--prt-probnik-odstep));
}

/* ⚠️ Z KOMUNIKATEM POD OKRUSZKAMI ODSTĘP LICZY SAM KOMUNIKAT (16 px, reguła wyżej),
   więc okruszki muszą wrócić do zera. Bez tej linii reguła nad nią — nowsza i o tej samej
   wadze co `.prt-crumbs-nav:has(+ .prt-noty-miejsce)` — odjęłaby gap DRUGI RAZ i komunikat
   wszedłby na okruszki. */
.prt-probnik > .prt-crumbs-nav:has(+ .prt-noty-miejsce) { margin-bottom: 0; }

/* ⚠️ KARTA TKANINY MA DOKŁADNIE TEN SAM PROBLEM, TYLKO Z INNYM GAPEM — i dlatego poprawka
   próbnika go nie ruszyła. Kontener okruszków `pdp0018` jest `e-con-boxed`, więc jego
   `.e-con-inner` to flex z `gap: var(--row-gap)`, a `--row-gap` bierze się z kitu
   (`--widgets-spacing-row: 20px`). Okruszki i `.prt-pdp` są jedynymi dziećmi tego
   kontenera, więc do 24 px marginesu dokładało się 20 px gapu.

   Zmierzył FreeAgent na 5.119.2: próbnik 28/24 na 1440 i 28/18 na 390 (dobrze), a karta
   28/44 i 28/38 — czyli równo +20 px. Moja bramka statyczna tego nie łapała, bo porównywała
   PADDING kontenera, a nie jego gap. Teraz sprawdza oba odejmowania.

   Odejmujemy `var(--row-gap)`, a NIE wpisane 20 px: zmienna jest dziedziczona z kontenera,
   więc wartość idzie za ustawieniem kitu zamiast je duplikować. Zerowanie gapu na samym
   kontenerze byłoby krótsze, ale dotknęłoby każdej pary dzieci, a nie tylko tej jednej. */
body.single-tkanina .prt-crumbs-nav {
	margin-bottom: calc(var(--prt-okruszki-dol) - var(--row-gap, 20px));
}

/* Z komunikatem pod okruszkami — jak wyżej na próbniku: odstęp liczy komunikat. */
body.single-tkanina .prt-crumbs-nav:has(+ .prt-noty-miejsce) { margin-bottom: 0; }


/* Zaślepka na zdjęcie do dostarczenia. Widoczna celowo — puste miejsce nie mówi,
   czego brakuje, a po wstawieniu zdjęcia układ nie skacze, bo proporcje są te same. */
.prt-slot {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed #C9D2E8;
    border-radius: 14px;
    background: #F4F1EC;
    padding: 12px;
    text-align: center;
}

.prt-slot__tekst {
    font-size: 13px;
    font-weight: 700;
    color: #8A93B5;
}

/* ── 1.2 karta produktu ── */
.prt-probnik__karta {
    display: grid;
    grid-template-columns: 1.08fr 1fr;
    gap: clamp(28px, 4vw, 56px);
    align-items: start;
    scroll-margin-top: 24px;
}

/* GALERIA NA POLACH RADIO, bez JavaScriptu.

   Radia stoją PRZED miniaturami i dużymi zdjęciami, bo `:checked ~` patrzy tylko w przód.
   Dzięki temu przełączanie działa z klawiatury i przy wyłączonych skryptach, a nie trzeba
   trzymać stanu w JS — handoff mówi o stanie `img`, ale nie o tym, czym ma być napędzany. */
.prt-probnik__galeria {
    display: grid;
    grid-template-columns: 84px 1fr;
    gap: 12px;
    align-items: start;
}

.prt-probnik__radio {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.prt-probnik__miniatury {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.prt-probnik__mini {
    display: block;
    width: 84px;
    height: 84px;
    border: 2px solid transparent;
    border-radius: 12px;
    overflow: hidden;
    cursor: pointer;
    background: #F5F7FB;
}

.prt-probnik__mini img,
.prt-probnik__mini .prt-slot {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    aspect-ratio: auto;
    font-size: 10px;
    border-radius: 0;
}

/* Obwódka aktywnej miniatury i widoczność dużego zdjęcia — jedna reguła na pozycję,
   bo CSS nie umie policzyć indeksu zaznaczonego radia. */
.prt-probnik__galeria .prt-probnik__duze-poz { display: none; }

#prt-probnik-zdj-0:checked ~ .prt-probnik__miniatury .prt-probnik__mini--0,
#prt-probnik-zdj-1:checked ~ .prt-probnik__miniatury .prt-probnik__mini--1,
#prt-probnik-zdj-2:checked ~ .prt-probnik__miniatury .prt-probnik__mini--2,
#prt-probnik-zdj-3:checked ~ .prt-probnik__miniatury .prt-probnik__mini--3 {
    border-color: var(--prt-navy);
}

#prt-probnik-zdj-0:checked ~ .prt-probnik__duze .prt-probnik__duze-poz--0,
#prt-probnik-zdj-1:checked ~ .prt-probnik__duze .prt-probnik__duze-poz--1,
#prt-probnik-zdj-2:checked ~ .prt-probnik__duze .prt-probnik__duze-poz--2,
#prt-probnik-zdj-3:checked ~ .prt-probnik__duze .prt-probnik__duze-poz--3 {
    display: block;
}

.prt-probnik__radio:focus-visible ~ .prt-probnik__miniatury .prt-probnik__mini {
    outline: 2px solid var(--prt-pink-cta);
    outline-offset: 2px;
}

.prt-probnik__duze-poz {
    margin: 0;
    border-radius: 18px;
    overflow: hidden;
    aspect-ratio: 1 / 1;
    background: #F5F7FB;
}

.prt-probnik__duze-poz img,
.prt-probnik__duze-poz .prt-slot {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 0;
}

.prt-probnik__eyebrow {
    margin: 0;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--prt-pink-cta);
}

.prt-probnik__h1 {
    /* Brief 2026-10-31, D.1 + B: ta sama skala co H1 karty produktu.
       Odstep od nadtytulu to 12 px — jedyny wyjatek od siatki 14/22/28 (sekcja A),
       taki sam jak `.prt-pdp__eyebrow { margin-bottom: 12px }` na karcie. */
    margin: 12px 0 0;
    font-size: clamp(32px, 3.6vw, 48px);
    font-weight: 900;
    line-height: 1.04;
    letter-spacing: -.03em;
    color: var(--prt-navy);
}

/* B: H1 -> kolejny element = 14 px. */
.prt-probnik__tagline {
    margin: var(--space-tight) 0 0;
    font-size: clamp(20px, 1.8vw, 24px);
    font-weight: 800;
    color: var(--prt-navy);
}

.prt-probnik__opis {
    margin: 14px 0 0;
    max-width: 480px;
}

/* Brief 2026-10-31, D.2: odstęp MIĘDZY akapitami 14 px, a nie margines dolny na każdym —
   ostatni akapit nie ma odpychać ceny, bo ona ma własne 28 px (sekcja B). */
.prt-probnik__opis p + p { margin-top: var(--space-tight); }
.prt-probnik__opis p {
    margin: 0;
    font-size: 17px;
    font-weight: 500;
    line-height: 1.55;
    color: #3A4478;
}

.prt-probnik__cena {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: var(--space-section) 0 0;
    font-size: clamp(34px, 3.4vw, 44px);
    font-weight: 900;
    color: var(--prt-navy);
}

.prt-probnik__cena .woocommerce-Price-amount { font-size: inherit; font-weight: inherit; }
.prt-probnik__brutto { font-size: .62em; font-weight: 800; color: var(--text-muted); }
/* B: element pod cena = 14 px (bylo 4 px, poza siatka). */
.prt-probnik__cena-nota { margin: var(--space-tight) 0 0; font-size: 14px; color: #3A4478; }

/* Darmowa dostawa: obietnica i zastrzeżenie są DWOMA akapitami, nie jednym zdaniem —
   handoff chce ikony i 17/800 na różowo, a pod tym 14/500 na granatowo. Zastrzeżenie
   zostaje OBOWIĄZKOWE: bez niego obietnica jest nieprawdziwa w koszyku mieszanym. */
.prt-probnik__gratis {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: var(--space-tight) 0 0;
    font-size: 17px;
    font-weight: 800;
    color: var(--prt-pink-cta);
}

/* Ikona w kolorze ZDANIA, nie domyślnym granacie: handoff daje jej obrys różowy, taki
   jak tekst obok (`currentColor` z akapitu). Bez tego ciężarówka była granatowa przy
   różowym napisie i czytała się jak element innej sekcji. */
.prt-probnik__gratis .prt-probnik__ikona { width: 30px; height: 30px; flex: none; color: inherit; }
/* B: linia pod blokiem gratis tez w siatce. */
.prt-probnik__gratis-nota { margin: var(--space-tight) 0 0; font-size: 14px; font-weight: 500; color: #3A4478; }

/* Odstęp pod odnośnikiem taki sam jak nad korzyściami (22 px) — formularz koszyka stoi
   zaraz pod nim i bez tego przyklejał się do linku. */
.prt-probnik__do-zestawu { margin: 14px 0 22px; }

.prt-probnik__do-zestawu a {
    font-size: 15px;
    font-weight: 800;
    color: var(--prt-navy);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.prt-probnik__do-zestawu span { color: var(--prt-pink-cta); }

/* ── Rytm prawej kolumny: formularz koszyka i komunikat Woo ───────────────────
   Brief 2026-10-31, D.5 (rząd ilość + „Dodaj do koszyka": 24 → 22 px) i D.6
   (komunikat „Dodano do koszyka": 12 → 14 px).

   ⚠️ Oba elementy renderuje WooCommerce i NIE MIAŁY u nas żadnej reguły — odstępy brały
   się z domyślnych marginesów Woo. To więc nie zmiana wartości, a jej USTALENIE: bez
   tego każda aktualizacja WooCommerce mogła je przestawić. Selektor z `body.printella`
   i `form.cart`, bo arkusz Woo jest specyficzniejszy od pojedynczej klasy. */
/* ── Rzad „ilosc + Dodaj do koszyka" na probniku ──────────────────────────────
   Decyzje Steve'a 31.10.2026: przycisk ma wygladac jak CTA karty tkaniny, a pole
   ilosci zostaje z nim W JEDNYM RZEDZIE.

   ⚠️ Specyficznosc nie jest tu ozdoba. `woocommerce.css` ma
   `.woocommerce:where(body:not(...)) ... button.button.alt` — `:where()` liczy sie
   jako zero, wiec to (0,3,1) i BIJE pojedyncza klase motywu. Dotad nie mielismy na ten
   przycisk ZADNEJ reguly (stylizowalismy tylko `.printella-cart-controls` z konfiguratora),
   wiec wygladal jak domyslny Woo: 202x48, radius 3px, WERSALIKI. Ponizsze selektory maja
   (0,4,3) i wygrywaja. NIE ruszamy przy tym konfiguratora.

   ⚠️ `form.cart` ma wiecej dzieci niz widac: `wc-order-attribution-inputs`,
   `.wc-stripe-clear` i kontener przyciskow Stripe. Przy `display: flex` weszlyby do
   rzedu, wiec dostaja `flex: 0 0 100%`. */
body.printella .prt-probnik__zakup form.cart {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* ⚠️ ROW-GAP ZERO, NIE 12. Zmierzone przez FreeAgenta na 5.115.0: formularz mial
       104-112 px wysokosci przy rzedzie 56. `form.cart` ma TRZY dzieci o zerowej
       wysokosci (attribution, stripe-clear, kontener Stripe), a kazde zawiniecie
       dokladalo pelny row-gap. Odstep pod rzedem daje wiec wylacznie kontener Stripe,
       i tylko wtedy, gdy cokolwiek wyrenderuje. */
    gap: 0 12px;
    margin: var(--space-group) 0 0;
}

/* ⚠️ CLEARFIX WOOCOMMERCE PRZESUWAL CALY RZAD W PRAWO O 12 PX.
   `form.cart::before` i `::after` maja `content: " "; display: table`. W ukladzie flex
   staja sie PELNOPRAWNYMI elementami rzedu o szerokosci zero — niewidocznymi, ale
   liczacymi sie do `gap`. Zmierzone: ilosc zaczynala sie na x=38 zamiast x=28.
   W ukladzie flex clearfix nie ma czego czyscic, wiec go wylaczamy. */
body.printella .prt-probnik__zakup form.cart::before,
body.printella .prt-probnik__zakup form.cart::after { content: none; }
body.printella .prt-probnik__zakup form.cart > .quantity { flex: 0 0 118px; margin: 0; }
body.printella .prt-probnik__zakup form.cart .quantity-wrapper { width: 100%; height: 56px; }
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button {
    flex: 1 1 180px;
    min-width: 0;
    height: 56px;
    padding: 0 24px;
    border-radius: 8px;
    background: var(--prt-pink-cta);
    color: #fff;
    font-family: inherit;
    font-size: 18px;
    font-weight: 800;
    line-height: 1;
    text-transform: none;
    letter-spacing: normal;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
}
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button:hover { background: var(--prt-pink-cta-hover); }
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button:focus-visible { outline: 3px solid var(--prt-navy); outline-offset: 3px; }
body.printella .prt-probnik__zakup form.cart > wc-order-attribution-inputs,
body.printella .prt-probnik__zakup form.cart > .wc-stripe-clear,
body.printella .prt-probnik__zakup form.cart > .wc-stripe-product-checkout-container { flex: 0 0 100%; }
/* ⚠️ Odstep TYLKO wtedy, gdy Stripe cokolwiek wyrenderuje. Kontener NIE jest pusty
   (ma w srodku `<ul>` ze szkieletem), wiec `:empty` go nie zlapie — zaczepiamy sie
   o klase `wc-stripe-express-loading`, ktora Stripe trzyma, dopoki nie ma portfela.
   Zmierzone przez FreeAgenta: w headless bez portfela kontener ma 0 px wysokosci
   takze po 6 s, a odstep 12 px robil wtedy przerwe donikad — i wypychal odleglosc
   formularz -> korzysci na 34 px, czyli poza siatke {12,14,22,28} z briefu.
   Z wartoscia 22 i tym zaczepem: bez portfela 22 px do korzysci, z portfelem 22 px
   nad przyciskami Stripe. ⚠️ Do potwierdzenia w prawdziwej przegladarce z Apple Pay —
   w headless nie da sie tego sprawdzic. */
body.printella .prt-probnik__zakup form.cart > .wc-stripe-product-checkout-container:not(.wc-stripe-express-loading) { margin-top: var(--space-group); }

/* ⚠️ STAN WYLACZONY BYL FIOLETOWY. WooCommerce daje `button:disabled` wlasne tlo
   `#7f54b3` (kolor marki Woo) z `opacity .5` — na rozowym przycisku wygladalo to jak
   element z innego serwisu. Zmierzone przez FreeAgenta: rgb(127,84,179).
   Zostawiamy nasz rozowy, samo przyciemnienie niesie informacje o niedostepnosci.
   Obie postacie, bo Woo uzywa raz atrybutu, raz klasy. */
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button:disabled,
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button.disabled {
    background: var(--prt-pink-cta);
    color: #fff;
    opacity: .5;
    cursor: not-allowed;
}
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button:disabled:hover,
body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button.disabled:hover {
    background: var(--prt-pink-cta);
}

/* Na 390 px kolumna ma 334: 118 ilosci + 10 odstepu zostawia 206 na przycisk, a napis
   „Dodaj do koszyka" w 17/800 zajmuje ~150 px. Mieci sie z zapasem takze po niemiecku
   („In den Warenkorb" to okolo 150 px).

   ⚠️ Probowalem tu zwezic ilosc do 104 px i to NIE DZIALALO — zmierzyl to FreeAgent.
   Powod: element flex ma domyslnie `min-width: auto`, wiec nie schodzi ponizej swojej
   tresci, a wrapper ilosci (dwa przyciski + pole) ma min-content 118 px. `flex-basis`
   tego nie przebija. Regula znikla zamiast byc naprawiana na sile, bo 118 i tak sie
   miesci — ale zapis zostaje, zeby ktos nie probowal drugi raz. */
/* Punkt 12: oba rzedy schodza do jednej kolumny w tym samym miejscu. */
@media (max-width: 640px) {
    .prt-pdp__zaufanie { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
    body.printella .prt-probnik__zakup form.cart { gap: 0 10px; }
    body.printella .prt-probnik__zakup form.cart button.single_add_to_cart_button { padding: 0 14px; font-size: 17px; }
}
body.printella .prt-probnik__zakup .woocommerce-message,
body.printella .prt-probnik__zakup .woocommerce-notices-wrapper > * { margin: var(--space-tight) 0 0; }

.prt-probnik__korzysci {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    /* Brief 2026-10-31, D.7: bez `border-top` i bez `padding-top` — lista zalet ma być
       grupą pod CTA, a nie osobną sekcją odciętą linią. */
    margin: var(--space-group) 0 0;
    padding: 0;
    list-style: none;
}

/* Ikona OBOK tekstu, nie nad nim (poprawka Steve'a 30.10.2026): przy trzech kolumnach
   układ pionowy zjadał wysokość, a napisy i tak łamią się na dwa wiersze. `flex-start`,
   żeby ikona trzymała się pierwszego wiersza tekstu, a nie środka dwóch. */
.prt-probnik__korzysci li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    /* Brief 2026-10-31, D.7 + B: zalety to 15px/700 na obu stronach. */
    font-size: 15px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--prt-navy);
}

.prt-probnik__korzysci li span { flex: 1; }

.prt-probnik__ikona { width: 28px; height: 28px; color: var(--prt-navy); }

/* ── sekcje ── */
/* Brief 2026-10-31, A: jedna skala H2 sekcji pod hero NA OBU stronach.
   ⚠️ Moje pierwsze sprawdzenie kryterium E.6 objelo tylko klasy karty
   (`prt-kat-h2--*`) i NIE DOTKNELO tej reguly — rozmiar byl juz dobry, ale
   `letter-spacing` miał -.02em zamiast -.03em, a `line-height` nie byl ustawiony
   wcale. Zglosil to Steve, patrzac na strony obok siebie. */
.prt-probnik__h2 {
    margin: 10px 0 0;
    font-size: clamp(28px, 3.2vw, 42px);
    font-weight: 900;
    line-height: 1.06;
    letter-spacing: -.03em;
    color: var(--prt-navy);
}

.prt-probnik__lead { margin: 12px 0 0; font-size: 17px; color: #3A4478; }

/* ── 1.3 zestaw ── */
.prt-probnik-zestaw {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 18px;
    margin-top: 28px;
}

.prt-probnik-grupa {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 12px 20px;
    border-radius: 20px;
}

/* Zdjęcie grupy — to samo, które stoi w boksie rodzaju na stronie głównej.
   16:9 i radius 14 z handoffu (punkt 1.3). */
.prt-probnik-grupa__obraz {
    border-radius: 14px;
    overflow: hidden;
    aspect-ratio: 16 / 9;
}

.prt-probnik-grupa__obraz img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.prt-probnik-grupa__glowa { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; padding: 0 6px; }
.prt-probnik-grupa__tytul { margin: 0; font-size: 19px; font-weight: 800; color: var(--prt-navy); }
.prt-probnik-grupa__licznik { font-size: 13px; font-weight: 700; color: #3A4478; }

.prt-probnik-grupa__lista { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0 6px; list-style: none; }

.prt-probnik-poz { display: flex; align-items: center; gap: 8px; }

.prt-probnik-poz__zdj { width: 36px; height: 24px; border-radius: 5px; object-fit: cover; flex: none; }

/* `anywhere`, bo nazwy materiałów są długie i w czterech kolumnach wychodzą poza kartę. */
.prt-probnik-poz__nazwa { flex: 1; font-size: 14px; font-weight: 700; color: var(--prt-navy); overflow-wrap: anywhere; }

.prt-probnik-grupa__link {
    margin: auto 6px 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--prt-navy);
    text-decoration: none;
}

.prt-probnik-grupa__link span { color: var(--prt-pink-cta); }


/* ── 1.3 próbka nadruku 46 × 46 (cross-sell) ── */
.prt-probnik__cross {
    display: grid;
    grid-template-columns: 120px 1fr auto 144px;
    align-items: center;
    gap: clamp(18px, 2.4vw, 28px);
    padding: clamp(20px, 2.4vw, 26px) clamp(24px, 3vw, 40px);
    border: 1.5px solid #F6CADB;
    border-radius: 20px;
    background: #fff;
    overflow: hidden;
}

.prt-probnik__cross-zdj img { width: 100%; height: auto; display: block; filter: drop-shadow(0 8px 14px rgba(16, 27, 84, .18)); }
.prt-probnik__cross-tekst h2 { margin: 0; font-size: clamp(22px, 2.2vw, 28px); font-weight: 900; color: var(--prt-navy); }
.prt-probnik__cross-tekst p { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: #3A4478; }

/* Tango wychyla się z dolnej krawędzi paska — ujemny margines równy dolnemu
   dopełnieniu, więc przy zmianie dopełnienia nie trzeba go poprawiać. */
.prt-probnik__cross-tango {
    align-self: end;
    margin-bottom: calc(-1 * clamp(20px, 2.4vw, 26px) - 4px);
}

.prt-probnik__cross-tango img { width: 144px; height: auto; display: block; }

/* ⚠️ PUNKT 10 POROWNANIA: JEDEN KSZTALT PRZYCISKU DRUGORZEDNEGO.
   Brief 2026-10-31, sekcja A: drugorzedny to pigulka z obrysem 2 px navy. Oba miejsca
   mialy juz ten ksztalt, ale rozne rozmiary — `.prt-btn-outline` 16/800 z paddingiem
   17/32, a ten 15/800 z 14/24. Teraz jedna definicja, zeby „drugorzedny" znaczyl to
   samo na karcie i na probniku.

   Czego ten punkt NIE obejmuje: kafelkow „Rabaty / Dostawa / Plik" na karcie. One nie
   sa przyciskami drugorzednymi, tylko wyzwalaczami okien z informacja — maja ikone,
   dwa wiersze tekstu i wysokosc 106 px. Zrobienie z nich pigulek zniszczyloby uklad,
   a nie ujednolicilo go. Jesli maja sie zmienic, to jako osobna decyzja o kafelkach. */
.prt-probnik__obrys {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 17px 32px;
    border: 2px solid var(--prt-navy);
    border-radius: var(--prt-radius-pill);
    background: transparent;
    color: var(--prt-navy);
    font-size: 16px;
    font-weight: 800;
    line-height: 1.2;
    text-decoration: none;
    transition: background .2s ease, transform .2s ease;
}

.prt-probnik__obrys:hover { background: var(--prt-navy); color: #fff; }
.prt-probnik__obrys .woocommerce-Price-amount { color: inherit; }

/* ── 1.5 jak to działa ── */
.prt-probnik__jak {
    display: grid;
    grid-template-columns: 1fr 1.6fr;
    gap: clamp(32px, 4vw, 56px);
    align-items: center;
}

.prt-probnik__kroki {
    display: grid;
    gap: 20px;
    margin: 26px 0 0;
    padding: 0;
    list-style: none;
}

/* Kółko z numerem i pionowa linia przerywana między kółkami. Linia jest tłem
   pseudoelementu, nie osobnym znacznikiem — inaczej trzeba by ją ukrywać przy ostatnim
   kroku ręcznie w PHP. */
.prt-probnik__krok {
    display: grid;
    grid-template-columns: 52px 1fr;
    gap: 20px;
    position: relative;
}

.prt-probnik__krok:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 25px;
    top: 56px;
    bottom: -20px;
    border-left: 2px dashed #C9CFE0;
}

.prt-probnik__krok-nr {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 999px;
    background: var(--prt-navy);
    color: #fff;
    font-size: 20px;
    font-weight: 900;
}

.prt-probnik__krok-tresc h3 {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    font-size: 20px;
    font-weight: 800;
    color: var(--prt-navy);
}

.prt-probnik__krok-tresc h3 .prt-probnik__ikona { width: 24px; height: 24px; flex: none; }
.prt-probnik__krok-tresc p { margin: 6px 0 0; max-width: 380px; font-size: 15px; line-height: 1.5; color: #3A4478; }

.prt-probnik__jak-zdj {
    border-radius: 24px;
    overflow: hidden;
    aspect-ratio: 16 / 10;
    background: #D3B8FB;
}

.prt-probnik__jak-zdj img,
.prt-probnik__jak-zdj .prt-slot { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; }

/* ── 1.6 FAQ: natywne <details>, bez JS ── */
.prt-probnik__faq-sekcja { max-width: 880px; }

/* ── podmiot odpowiedzialny za produkt (GPSR) ──
   Blok `.prt-gpsr` rysuje rdzeń — ten sam co w zakładce „Producent i bezpieczeństwo"
   na karcie tkaniny, więc tutaj tylko oprawa sekcji. Ta sama szerokość co pytania:
   to też treść do czytania, nie siatka kafelków. */
.prt-probnik__gpsr-sekcja { max-width: 880px; }

.prt-probnik__gpsr-sekcja .prt-gpsr { margin-top: var(--space-section); }

.prt-probnik__gpsr-nota {
    margin: var(--space-tight) 0 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--text-muted);
}
.prt-probnik__faq { margin-top: 22px; display: grid; gap: 10px; }

.prt-probnik__faq-poz { border-bottom: 1.5px solid #E3E7F2; padding-bottom: 12px; }

.prt-probnik__faq-poz summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    font-size: 17px;
    font-weight: 800;
    color: var(--prt-navy);
    cursor: pointer;
    list-style: none;
}

.prt-probnik__faq-poz summary::-webkit-details-marker { display: none; }

.prt-probnik__faq-poz summary::after {
    content: "+";
    color: var(--prt-pink-cta);
    font-size: 24px;
    font-weight: 800;
    line-height: 1;
    flex: none;
}

.prt-probnik__faq-poz[open] summary::after { content: "−"; }
.prt-probnik__faq-odp { font-size: 16px; line-height: 1.6; color: #3A4478; }

/* ── 1.7 CTA końcowe ── */
.prt-probnik__cta {
    display: grid;
    grid-template-columns: 1.15fr 1.3fr auto;
    align-items: center;
    gap: clamp(20px, 3vw, 40px);
    padding-right: clamp(24px, 3vw, 40px);
    border-radius: 20px;
    background: var(--prt-navy);
    overflow: hidden;
}

/* ⚠️ WYSOKOŚĆ WPROST, nie `height: 100%`.
   Zgłoszone przez Steve'a 30.10.2026: baner był trzy razy wyższy, niż powinien. Powód:
   `min-height: 220px` plus `height: 100%` nie ogranicza niczego, gdy wiersz siatki ma
   wysokość automatyczną — wtedy to ZDJĘCIE dyktuje wysokość wiersza, a fotografia dłoni
   jest pionowa (1086 × 1448), więc w kolumnie szerokiej na 400 px dawała ponad 530 px.
   Teraz kolumna ma własny zakres wysokości, a zdjęcie się w nim kadruje. */
.prt-probnik__cta-zdj {
    height: clamp(220px, 24vw, 300px);
    background: #9BDDA8;
}

.prt-probnik__cta-zdj img,
.prt-probnik__cta-zdj .prt-slot {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 52%;
    display: block;
    border-radius: 0;
}

.prt-probnik__cta-tekst h2 { margin: 0; font-size: clamp(24px, 2.4vw, 32px); font-weight: 900; color: #fff; }

.prt-probnik__cta-punkty {
    margin: 14px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 8px;
}

.prt-probnik__cta-punkty li {
    position: relative;
    padding-left: 26px;
    font-size: 16px;
    font-weight: 700;
    color: #fff;
}

.prt-probnik__cta-punkty li::before {
    content: "✓";
    position: absolute;
    left: 0;
    color: #6FE0A0;
}

/* Patrz komentarz przy `.prt-probnik__cta` nizej — to ta sama przyczyna. */
.prt-probnik__cta-akcje { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; justify-items: start; padding: clamp(20px, 3vw, 32px) 0; }

.prt-probnik__pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 54px;
    padding: 0 26px;
    /* Brief 2026-10-31, D.8 + A: główny (różowy) przycisk to prostokąt 8 px. */
    border-radius: 8px;
    background: var(--prt-pink-cta);
    color: #fff;
    font-size: 16px;
    font-weight: 800;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s;
}

/* Samo `minmax(0,1fr)` przenioslo by przelew na sama pigulke, wiec ona tez musi umiec
   sie zmiescic: na waskim ekranie napis moze sie zlamac, a padding maleje.

   ⚠️ TEN BLOK MUSI STAC PO REGULE BAZOWEJ. Oba selektory to `.prt-probnik__pill` (0,1,0),
   wiec `@media` nic nie wygrywa samym zapytaniem — decyduje kolejnosc w pliku. Stal
   okolo 340 linii WYZEJ i przegrywal: na 320 px computed bylo `nowrap` i `padding 0 26px`,
   pigulka miala 282,9 px w kolumnie 224 px i wychodzila 11 px za okno (zmierzyl FreeAgent
   31.10.2026, test `~/dev/printella-e2e/strony/przelewanie-mobile.mjs`). */
@media (max-width: 400px) {
    .prt-probnik__pill { white-space: normal; height: auto; min-height: 54px; padding: 0 18px; }
}

.prt-probnik__pill:hover { background: #D8306A; }
.prt-probnik__pill .woocommerce-Price-amount { color: inherit; }
.prt-probnik__cta-link { font-size: 14px; font-weight: 700; color: #fff; text-decoration: underline; text-underline-offset: 3px; }

/* ⚠️ KOLORY ODNOŚNIKÓW MUSZĄ BIĆ GLOBALNE `.printella a`.

   Zgłoszone przez Steve'a 30.10.2026: przycisk na granatowym banerze miał tekst granatowy
   zamiast białego, a po najechaniu różowy. Powód nie jest w tych regułach, a w dwóch
   globalnych: `.printella a { color: var(--prt-navy) }` i `.printella a:hover { color:
   var(--prt-pink-cta) }` mają specyficzność 0,2,0, a nasze klasy przycisków 0,1,0 — więc
   przegrywały, mimo że stoją niżej w pliku.

   Dlatego wszystkie odnośniki próbnika dostają tu prefiks `body.printella` (0,2,1) i każdy
   z nich ma podany stan `:hover` oraz `:focus-visible` WPROST. Brak stanu hover to nie
   „dziedziczenie", tylko oddanie koloru globalnej regule. Hover zmienia WYŁĄCZNIE tło. */
body.printella .prt-probnik__pill,
body.printella .prt-probnik__pill:hover,
body.printella .prt-probnik__pill:focus,
body.printella .prt-probnik__pill:focus-visible {
    color: #fff;
}

body.printella .prt-probnik__pill:hover { background: #D8306A; }

body.printella .prt-probnik__cta-link,
body.printella .prt-probnik__cta-link:hover,
body.printella .prt-probnik__cta-link:focus-visible {
    color: #fff;
}

body.printella .prt-probnik__obrys,
body.printella .prt-probnik__obrys:focus-visible {
    color: var(--prt-navy);
}

body.printella .prt-probnik__obrys:hover {
    background: var(--prt-navy);
    color: #fff;
}

body.printella .prt-probnik__do-zestawu a,
body.printella .prt-probnik__do-zestawu a:hover {
    color: var(--prt-navy);
}

body.printella .prt-probnik-grupa__link,
body.printella .prt-probnik-grupa__link:hover {
    color: var(--prt-navy);
}

/* Nagłówek i punkty banera też jawnie białe: `h2` i `li` nie są odnośnikami, ale kit
   Elementora ustawia im kolor nagłówków i przy równej specyficzności wygrywa kolejnością. */
body.printella .prt-probnik__cta-tekst h2,
body.printella .prt-probnik__cta-punkty li {
    color: #fff;
}

/* ── RWD: progi z handoffu ── */
@media (max-width: 1140px) {
    .prt-probnik-zestaw { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Pasek cross-sell: przycisk schodzi do nowego wiersza, Tango znika. */
@media (max-width: 1100px) {
    .prt-probnik__cross { grid-template-columns: 96px 1fr; }
    .prt-probnik__obrys { grid-column: 1 / -1; justify-self: start; }
    .prt-probnik__cross-tango { display: none; }
}

@media (max-width: 940px) {
    .prt-probnik__karta { grid-template-columns: 1fr; }
    .prt-probnik__jak { grid-template-columns: 1fr; }
    .prt-probnik__jak-zdj { display: none; }
}

@media (max-width: 900px) {
        /* ⚠️ `minmax(0, 1fr)`, NIE `1fr` — to samo, co wczesniej rozpychalo galerie.
       `1fr` znaczy `minmax(auto, 1fr)`, wiec sciezka nie schodzi ponizej min-content,
       a pigulka „Zamow probnik — 19,90 zl" ma `white-space: nowrap` i padding 0 26px,
       czyli min-content 283 px. Na ekranie 320 px rozpychalo to cala sekcje o 31 px
       (zmierzone przez FreeAgenta); `overflow-x: clip` na body ukrywal przelew przed
       paskiem przewijania, wiec widac bylo tylko ucieta tresc. */
    .prt-probnik__cta { grid-template-columns: minmax(0, 1fr); padding-right: 0; }
    .prt-probnik__cta-zdj { display: none; }
    .prt-probnik__cta-tekst { padding: clamp(20px, 4vw, 32px) clamp(20px, 4vw, 32px) 0; }
    .prt-probnik__cta-akcje { padding: 0 clamp(20px, 4vw, 32px) clamp(24px, 4vw, 32px); }
}

/* Miniatury poziomo pod zdjęciem (handoff 1.2). */
@media (max-width: 640px) {
    /* ⚠️ `1fr` to `minmax(auto, 1fr)`, czyli ścieżka NIE SCHODZI poniżej min-content.
       Miniatury ułożone w rząd mają min-content 366 px (4 × 84 + 3 × 10), więc kolumna
       rozpychała się do 366 px w kontenerze szerokim na 334 px (390 − 2 × 28). Zmierzone
       przez FreeAgenta: przelew 32 px, ukryty przez `overflow-x: clip`, więc widać go
       tylko jako zniknięty prawy margines — nie jako pasek przewijania.

       Stąd dwie zmiany naraz: `minmax(0, 1fr)` pozwala ścieżce być węższej od treści,
       a miniatury muszą umieć się zmieścić, więc stają się elastyczne z górnym
       ograniczeniem 84 px. Na 390 px wychodzi (334 − 30) / 4 = 76 px. Samo `minmax(0,1fr)`
       nie wystarczy — przelałby się wtedy sam rząd miniatur. */
    .prt-probnik__galeria { grid-template-columns: minmax(0, 1fr); }
    .prt-probnik__miniatury { flex-direction: row; order: 2; }
    .prt-probnik__mini { width: auto; height: auto; flex: 1 1 0; max-width: 84px; aspect-ratio: 1; }
    .prt-probnik__duze { order: 1; }
    .prt-probnik__korzysci { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
    .prt-probnik-zestaw { grid-template-columns: 1fr; }
}
