/**
 * Strona produktu OEM — moduł product_page.
 *
 * ⛔ Zero zmiennych CSS, twarde heksy ze skali Tailwinda — ten sam język wizualny,
 *    którym mówią przebudowane strony konta, checkout i lista części.
 *    Firmowy #127da8, akcent działania #c2410c, promienie 4/8/12.
 * ⛔ Żadnych własnych fontów. Numery katalogowe składamy krojem MASZYNOWYM systemu:
 *    klient porównuje `4TX283285000` znak po znaku z częścią w ręku.
 *
 * ⚠️ Ten arkusz obsługuje WŁASNĄ stronę (podmiana trasy), więc nie walczy z kaskadą
 *    motywu — poza kontrolkami zakupu, które CELOWO bierzemy z jego klas.
 */

/* ── KWOTY: krój z „karty katalogowej" (`produkt-wizje.html`, `.cena-glowna`) ─────
   ⛔ KWOTA NIE JEST NUMEREM KATALOGOWYM i nie idzie krojem maszynowym. Numer klient
      porównuje ZNAK PO ZNAKU z częścią w ręku — tam mono pomaga. Kwotę czyta się jako
      jedną wartość, a mono robi z niej paragon: szerokie, rozstrzelone cyfry.
   ⛔ NIE IDZIE TEŻ Ralewayem z motywu: proza i liczby mają się różnić, a cyfry Ralewaya
      mają różne szerokości, więc kwoty nie stają w kolumnie.
   Zostaje systemowy sans z makiety + figury tabularne: liczby ustawione w kolumnie,
   bez ściągania kolejnego webfontu (strona nie pobiera na to ani bajta).
   ⚠️ TEN SAM krój i te same figury MUSZĄ być na liście części — kwota ma wyglądać
      identycznie tam, gdzie klient wybiera, i tam, gdzie kupuje. */
.pp-decyzja .product-price,
.pp-decyzja .product-price-old,
.pp-repro-cena,
.pp-wyc-kwota {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-variant-numeric: tabular-nums;
}

/* ── pasmo tożsamości ──────────────────────────────────────────────── */
/* Szkielet 2: wąska kolumna obrazów, tożsamość obok, karta decyzji w trzecim pasie. */
.pp-pasmo {
  display: grid;
  gap: 24px;
  grid-template-columns: 1fr;
  align-items: start;
  /* ⚠️ Dolny odstęp NIESIE ODDECH między kartą decyzji a włoskową linią sekcji treści.
     Przy 8 px krawędź karty niemal dotykała tej linii (zgłoszone przez usera 17.08.2026)
     i całość czytała się jak jedno pudło. */
  margin: 0 0 30px;
}

/* ══════════════ TELEFON: NAJPIERW O CO CHODZI, POTEM JAK WYGLĄDA ══════════════
   Kolejność na wąskim ekranie: dane produktu, potem obrazy, potem karta decyzji.
   Znaczniki zostają bez zmian (obrazy przed treścią) - przestawia je `order`. Kolejność
   źródła czyta wyszukiwarka i czytnik ekranu, a tam obraz przed opisem jest poprawny.

   ⛔ Wcześniej klient na telefonie dostawał najpierw duży obraz na całą szerokość i musiał
   przewinąć, żeby dowiedzieć się, CO to w ogóle jest. Nazwa i numer katalogowy są tym,
   po czym rozpoznaje się część - i mają być pierwsze. */
.pp-toz     { order: 1; }
.pp-obrazy  { order: 2; }
.pp-decyzja { order: 3; }

/* ⛔ TRZY KOLUMNY MINIATUR, TAKŻE PRZY JEDNYM OBRAZKU. `repeat(3, …)` zamiast
   `auto-fit`: przy jednym kaflu `auto-fit` rozciągnąłby go na całą szerokość ekranu,
   czyli dokładnie to, od czego odchodzimy. Miniatura ma zostać miniaturą, a obrazek
   w pełnym rozmiarze jest jedno dotknięcie dalej - w powiększeniu. */
.pp-obrazy {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
}

@media (min-width: 768px) {
  .pp-pasmo { grid-template-columns: 200px minmax(0, 1fr); }
  .pp-decyzja { grid-column: 1 / -1; }

  /* Od tego progu obrazy wracają do swojej kolumny: jeden pod drugim, pełną jej
     szerokością, a kolejność bierze się ze znaczników. */
  .pp-obrazy { grid-template-columns: minmax(0, 1fr); }
  .pp-toz, .pp-obrazy, .pp-decyzja { order: 0; }
}

@media (min-width: 1200px) {
  /* Karta decyzji szersza — miejsca jest dużo (decyzja usera 17.08.2026). */
  .pp-pasmo { grid-template-columns: 200px minmax(0, 1fr) 400px; gap: 30px; }
  .pp-decyzja { grid-column: auto; }
}

/* ⛔ Rysunek POD zdjęciem, nie obok — wiąże je wspólna SZEROKOŚĆ kolumny, a wysokość
   wynika z proporcji każdego z nich. */
.pp-obrazy { display: grid; gap: 10px; align-content: start; }

.pp-kafel {
  position: relative;
  margin: 0;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  overflow: hidden;
}

/* ⛔ height:auto jest KONIECZNE. Atrybuty width/height na <img> (te przeciw CLS)
   mapują się na CSS jako podpowiedzi prezentacyjne — nadpisanie samego `width`
   zostawia twardą wysokość, a wtedy `aspect-ratio` jest ignorowane. */
.pp-kafel img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: #fff;
}

.pp-kafel-rys img { aspect-ratio: 3 / 2; }

/*  ⛔ RÓWNANIE WYSOKOŚCI TYLKO W UKŁADZIE POZIOMYM. Gdy kafle stoją OBOK SIEBIE w równych
    kolumnach, różne proporcje (naklejka 1:1, rysunek 3:2) dają różne wysokości i dolne
    krawędzie się nie schodzą — widać to na telefonie (zgłoszone 19.08.2026).
    ⛔ NA STOSIE NIE RUSZAMY. Tam każdy kafel ma własną szerokość kolumny, nierówność nie
       powstaje, a wymuszenie kwadratu tylko POWIĘKSZYŁOBY rysunek bez powodu — o to
       użytkownik prosił wprost.
    ⚠️ Rysunek zostaje CAŁY: obrazek ma `object-fit: contain`, więc w kwadracie tylko
       dostaje biały pas nad i pod, a nie zostaje przycięty. */
@media (max-width: 767px) {
  .pp-kafel-rys img { aspect-ratio: 1 / 1; }
}

/*  Podgląd też ustawia kafle poziomo (kolumny po 128 px), więc obowiązuje ta sama zasada. */
.pp-podglad .pp-kafel-rys img { aspect-ratio: 1 / 1; }

/* Kafel ze zdjęciem motocykla.
   ⚠️ KWADRAT, nie 3:2 jak rysunek. Zdjęcia mają 600×600 (zmierzone na próbce 60 kart:
      60/60 kwadratowych), motocykl stoi pośrodku, a przy dolnej krawędzi jest znak
      źródła. Kadr 3:2 uciąłby tę atrybucję, a dopasowanie z dopełnieniem dałoby biały
      pas na szarym tle kafla — zdjęcia mają białe tło, kafel szare. */
.pp-kafel-moto img { aspect-ratio: 1 / 1; }

/* ⚠️ Tło kafla na biel, żeby zlało się z tłem zdjęcia. Pozostałe kafle zostają szare:
   tam obraz wypełnia je po brzegi, więc tło i tak nie jest widoczne. */
.pp-kafel-moto { background: #fff; }

.pp-kafel-lupa {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  position: relative;
  width: 100%;
}

.pp-kafel-lupa:focus-visible { outline: 2px solid #127da8; outline-offset: 2px; }

.pp-kafel-ikona {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: rgba(255, 255, 255, .94);
  border: 1px solid #d1d5db;
  color: #6b7280;
  /* ⚠️ Rozmiar ikony, nie glifu. Wcześniej stał tu znak `⌕` (U+2315), który w większości
     fontów rysuje się drobny i nie wypełnia pola - przycisk wyglądał na pusty z małym
     znaczkiem pośrodku. FontAwesome rysuje lupę w pełnym kegle. */
  font-size: 13px;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity .15s ease;
}

.pp-kafel-lupa:hover .pp-kafel-ikona,
.pp-kafel-lupa:focus-visible .pp-kafel-ikona { opacity: 1; }

.pp-kafel-et {
  position: absolute;
  left: 9px;
  top: 9px;
  z-index: 2;
  background: rgba(31, 41, 55, .86);
  color: #fff;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 4px;
}

/* Numer pozycji na rysunku — ten sam, który stoi w tabeli technicznej. */
.pp-kafel-nr {
  position: absolute;
  right: 9px;
  top: 9px;
  z-index: 2;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #c2410c;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  display: grid;
  place-items: center;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .25);
}

/* ── tożsamość ─────────────────────────────────────────────────────── */
.pp-h1 { margin: 0; }

/* ⛔ Numer katalogowy PIERWSZY w treści H1 i mocniejszy wizualnie od nazwy — tym
   hasłem klienci szukają części oryginalnych. Znaczniki i style wewnątrz nagłówka
   są dla wyszukiwarki obojętne, liczy się tekst. */
.pp-h1-kod {
  display: block;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  font-weight: 700;
  color: #127da8;
  letter-spacing: -.025em;
  line-height: 1.15;
  word-break: break-all;
}

.pp-h1-nazwa {
  display: block;
  margin-top: 5px;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -.02em;
  color: #1f2937;
}

@media (min-width: 992px) {
  .pp-h1-kod { font-size: 30px; }
  .pp-h1-nazwa { font-size: 21px; }
}

/* ── tabliczki z numerami ──────────────────────────────────────────── */
/* Numer GŁÓWNY jest pierwszy i wyróżniony — regula sklepu: OEM przed MPN. */
.pp-boxy { display: flex; flex-wrap: wrap; gap: 9px; margin: 14px 0 0; }

.pp-box {
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 6px 12px 7px;
  background: #fff;
  line-height: 1.2;
}

.pp-box-et {
  display: block;
  font-size: 9.5px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: #9ca3af;
  font-weight: 700;
  margin-bottom: 3px;
}

.pp-box-wa { display: block; font-size: 16px; font-weight: 700; letter-spacing: -.02em; color: #1f2937; }

.pp-box.is-glowny { border-color: #127da8; background: #f2fafd; }
.pp-box.is-glowny .pp-box-et { color: #127da8; }
.pp-box.is-glowny .pp-box-wa { color: #127da8; font-size: 17px; }

/* Linia cech: producent i opis fabryczny. */

/* ── blok zapewnienia ──────────────────────────────────────────────── */
/* ⛔ BEZ PUDŁA I BEZ KOLOROWEJ KRESKI. Zwykły tekst: pogrubiony ciemny nagłówek,
   akapit pod nim — dokładnie tak, jak w zaakceptowanym układzie. Pudło z szarym
   tłem czytało się jak ostrzeżenie, a lewa kolorowa krawędź była ozdobą, której
   nikt nie zamawiał (uwagi usera 17.08.2026).
   Problem „smutnej szarości" rozwiązuje KONTRAST, nie ramka: tekst schodzi do
   #374151 i rośnie do 15 px, nagłówek jest ciemny i większy. */
.pp-zapewnienie {
  margin-top: 20px;
  max-width: 68ch;
  font-size: 15px;
  line-height: 1.62;
  color: #374151;
}

.pp-zapewnienie b {
  display: block;
  color: #1f2937;
  font-size: 16px;
  margin-bottom: 4px;
  letter-spacing: -.015em;
}

.pp-zap-tresc { display: block; }

/* Klauzula prawna — drobniejszy wiersz pod treścią. Treść zostaje w całości;
   przestaje tylko przygniatać zdanie o jakości produktu. */
.pp-zap-klauzula {
  display: block;
  margin-top: 9px;
  font-size: 12.5px;
  line-height: 1.55;
  color: #9ca3af;
}

/* ── boks reprodukcji ──────────────────────────────────────────────── */
/* Jak w makiecie: tintowane pudło z etykietą, a w środku BIAŁA KARTA z pozycją.
   Zagnieżdżona karta oddziela „jest odpowiednik" od „oto on". */
/* ── oświadczenia o stanie towaru ──────────────────────────────────────
   ⛔ TA SAMA BUDOWA CO BLOK REPRODUKCJI (ramka 1 px, promień 10, wersalikowy tytuł),
      bo oba są przypisem do towaru i mają czytać się jak rodzeństwo.
   ⚠️ INNA BARWA I TO JEST ROZRÓŻNIENIE ZNACZENIA, nie ozdoba: reprodukcja to propozycja
      (pomarańcz sklepu `#c2410c`), a stan towaru to OSTRZEŻENIE przed zakupem — bursztyn.
      Obie barwy z tej samej rodziny ciepłej, więc karta nie zyskuje trzeciego koloru.
   ⛔ Nie czerwień: czerwień w tym sklepie znaczy „niedostępne/błąd", a tu towar JEST
      dostępny i można go kupić — tylko trzeba wiedzieć, w jakim stanie. */
.pp-stan {
  margin-top: 20px;
  max-width: 68ch;
  /* Zapas na wypadek klasy wariantu, której arkusz nie zna — blok ma wyglądać na blok,
     a nie na tekst bez ramki. */
  border: 1px solid var(--ob, #fcd34d);
  border-radius: 10px;
  background: var(--tlo, #fffbeb);
  padding: 14px 16px;
}

/*  ⛔ WARIANT CZYSTY ZDEJMUJE TAKŻE ODSTĘPY, nie tylko barwy. Wypełnienie i obwódka
    istnieją PO TO, żeby tekst nie dotykał ramki — bez ramki są bezcelowe, a zostawione
    wcinają blok o 17 px wobec otoczenia, więc „czysty" tekst wyglądałby na przesunięty
    względem sąsiednich akapitów (uwaga użytkownika 19.08.2026).
    ⚠️ `border-width: 0`, a nie `border-color: transparent` — przezroczysta obwódka nadal
       zajmuje swój piksel.
    ⚠️ ODSTĘP OD GÓRY ZOSTAJE. On nie należy do ramki, tylko oddziela blok od tego, co
       nad nim; wyzerowany skleiłby oświadczenie z poprzednią sekcją. Schodzi z 20 px do
       16, bo bez ramki blok jest lżejszy i nie potrzebuje aż tyle powietrza. */
.pp-stan.pp-w-czysty {
  border-width: 0;
  border-radius: 0;
  padding: 0;
  margin-top: 16px;
}
/*  ⚠️ 14 px, NIE 11. Nagłówek oświadczenia o towarze („uszkodzona", „reprodukcja") ma być
    czytelny bez wysiłku — to nie jest podpis pomocniczy, tylko rzecz, którą klient MUSI
    przeczytać przed zakupem. Wersalikami i z rozstrzeleniem 11 px czytało się jak drobny
    druk, czyli dokładnie odwrotnie do zamiaru (uwaga użytkownika 19.08.2026).
    ⚠️ Przy 14 px rozstrzelenie schodzi z .09em do .06em — im większy stopień pisma, tym
       mniej rozstrzelenia potrzebują wersaliki, żeby nie wyglądać na rozsypane. */
.pp-stan-tyt {
  display: block;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tyt, #92400e);
  margin-bottom: 8px;
}

.pp-stan-tresc {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: #374151;
}

.pp-repro {
  margin-top: 20px;
  max-width: 68ch;
  border: 1px solid #fed7aa;
  border-radius: 10px;
  background: #fffbf7;
  padding: 14px 16px;
}

.pp-repro-tyt {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: #9a3412;
  margin-bottom: 10px;
}

.pp-repro-poz {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  background: #fff;
  border: 1px solid #fed7aa;
  border-radius: 7px;
  padding: 10px 13px;
}

.pp-repro-poz:hover { border-color: #c2410c; }
.pp-repro-co b { display: block; font-size: 14px; letter-spacing: -.01em; color: #1f2937; }
.pp-repro-co .pp-kod { display: block; font-size: 12.5px; color: #6b7280; }
.pp-repro-cena { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 15px; color: #1f2937; }
.pp-repro-cena[hidden] { display: none; }

.pp-kod { color: #374151; }
/* Zdanie o wielu modelach — to informacja handlowa, nie przypis, więc czyta się
   tak samo jak linia cech. */
.pp-nota { margin: 13px 0 0; font-size: 14.5px; line-height: 1.55; color: #4b5563; max-width: 62ch; }

.pp-kod {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

/* Odstęp w miejscu usuniętej linii cech — tabliczki z numerami nie mogą kleić się
   do bloku zapewnienia pod nimi. Puste pudełko zamiast marginesu na sąsiadach, żeby
   wysokość nie zależała od tego, który blok akurat istnieje. */
.pp-toz-luka { height: 14px; }

/* ── karta decyzji ─────────────────────────────────────────────────── */
/* Układ „karta katalogowa" z `produkt-wizje.html` (wersja A), wybrany 17.08.2026.
   ⚠️ Tło jest SZARE, a karta BEZ CIENIA — dokładnie jak w wizji. Biała karta z cieniem
   na białej stronie ledwie się odcinała, a cień udawał wypukłość, której nic tu nie ma. */
.pp-decyzja {
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 16px;
}

/* ⛔ TYPOGRAFIA KWOTY W CAŁOŚCI NASZA. Reguła ustawiała wcześniej TYLKO rozmiar i wagę,
   więc tracking i figury cyfr przychodziły z Journala — kwota była „po staremu zaciągnięta
   z motywu" (zgłoszone przez usera 17.08.2026). Wartości z makiety `.kwota`
   (`produkt-szkielety-dane.html`): 33 px, 700, `-.03em`, `line-height 1.05`.

   ⛔ `font-variant-numeric: tabular-nums` JEST TU ISTOTĄ, nie ozdobą. To najczęściej
      porównywana liczba na stronie: klient patrzy na oryginał i reprodukcję obok siebie.
      Figury proporcjonalne mają różne szerokości, więc „11" i „44" zajmują inną długość
      i kwoty nie stoją w kolumnie. Tak samo traktujemy numery katalogowe i numer pozycji
      na rysunku — na tej stronie KAŻDA liczba, którą się porównuje, jest tabularna.

   ⚠️ RODZINY NIE ZMIENIAM: strona dziedziczy Raleway z motywu i tak samo wygląda H1,
      nagłówki i opis. Wstawienie tu drugiego kroju sprawiłoby, że kwota wygląda na
      przypadek, a nie na decyzję. Zdjęcie Ralewaya to zmiana NA CAŁEJ STRONIE i należy
      ją podjąć osobno, a nie przemycić w regule ceny. */
.pp-decyzja .product-price {
  font-size: 33px;
  font-weight: 700;
  /* Zacieśnienie z makiety `.cena-glowna`. */
  letter-spacing: -.02em;
  line-height: 1.05;
  /* ⛔ Ta sama ochrona, co na liście części: waluta NIE MOŻE zjechać do drugiego wiersza.
     `9,999.00 PLN` przy 33 px zajmuje ~195 px, a karta ma 400 px, więc dziś jest luźno —
     `nowrap` pilnuje, żeby zostało tak przy każdej szerokości i każdej walucie. */
  white-space: nowrap;
  color: #1f2937;
}

/* Linia netto/VAT pod kwotą — wartości z makiety (`.kwota small`): 13 px, waga 400,
   bez zacieśnienia. ⚠️ Arkusz ceny (wspólny) daje jej 12 px; podnosimy TUTAJ, bo tam
   ta sama reguła obsługuje też inne miejsca sklepu. */
.pp-decyzja .md-tax {
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  margin-top: 4px;
}

.pp-decyzja .product-price[hidden],
.pp-decyzja .product-price-old[hidden] { display: none; }

.pp-decyzja .product-price-old {
  font-size: 15px;
  color: #9ca3af;
  text-decoration: line-through;
  margin-top: 2px;
}

/* ⛔ WYGLĄD KONTROLEK PRZEPISANY Z LISTY CZĘŚCI — świadoma, wymuszona kopia.
   Źródło prawdy: `category_lastchild.css`, reguły `.category-image-page .btn-cart`,
   `.stepper`, `.icon-btn`. Rozszerzenie TAMTYCH selektorów nie działa, bo tamten
   arkusz NIE JEST wczytywany na stronie produktu (sprawdzone 17.08.2026).
   ⚠️ ZMIANA W JEDNYM MIEJSCU WYMAGA ZMIANY W DRUGIM.
   ⛔ `!important` TYLKO na promieniu — reguła zapasowa `.btn` ze skinu ma je po swojej
   stronie i inaczej wraca pigułka 100 px. */
.pp-akcja { display: flex; gap: 10px; align-items: center; margin-top: 15px; }
.pp-akcja .stepper { --stepper-height: 36px; flex: 0 0 auto; }

/* ⚠️ KOLOR Z MAKIETY, ROZMIAR Z LISTY CZĘŚCI — tak zdecydował użytkownik 17.08.2026:
   pomarańcz `#c2410c` ożywia stronę, ale wysokość, pismo i promień zostają takie, jakie
   ma przycisk na liście części, żeby oba sklepowe przyciski były tym samym przyciskiem. */
.pp-akcja .btn-cart {
  flex: 1;
  background: #c2410c;
  color: #fff;
  border: 1px solid transparent;
  border-radius: 4px !important;
  padding: 0 16px;
  height: 36px;
  min-height: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  min-width: 0;
  gap: 7px;
}

/* ⚠️ Ciemniejszy pomarańcz z makiety zamiast `brightness()`. Rozjaśnianie pomarańczu
   idzie w stronę żółci i przy 1.08 przycisk zmieniał odcień, a nie tylko jasność. */
.pp-akcja .btn-cart:hover,
.pp-akcja .btn-cart:focus { background: #9a3412; color: #fff; }
.pp-akcja .btn-cart::before { font-size: 14px; }

/* ── koszt przesyłki i zasady — pod przyciskiem ─────────────────────────
   ⚠️ Oś stanu przeniosła się NAD przycisk, więc w tym pojemniku został tylko koszt
      przesyłki i odnośnik do zasad. Włoskową linię niesie teraz `.pp-dostawa > .pp-wyc`,
      a NIE ten pojemnik — dwie kreski jedna pod drugą wyglądałyby jak błąd. */
.pp-dostawa {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin-top: 15px;
}

/* ── odpowiednik ───────────────────────────────────────────────────── */
/* ── lista życzeń i porównanie ─────────────────────────────────────── */
/* ⛔ ODNOŚNIKI TEKSTOWE z ikoną, nie kwadratowe `icon-btn` z listy części. Tam gęsty
   wiersz wymaga ikony bez nazwy; tutaj karta ma miejsce na słowo, a makieta pokazuje
   właśnie taką formę. */
.pp-drobne {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 16px;
  padding-top: 15px;
  border-top: 1px solid #e5e7eb;
}

.pp-drobne-poz {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #6b7280;
  text-decoration: none;
}

.pp-drobne-poz:hover { color: #127da8; }
/* Znak wpisany wprost, bez fontu ikon — patrz komentarz przy tych odnośnikach w szablonie. */
.pp-drobne-znak { font-size: 15px; line-height: 1; }

/* Odnośnik do kosztów wysyłki — zamiast obietnicy daty dostarczenia.
   ⚠️ Bez własnego marginesu: stoi w `.pp-dostawa`, gdzie odstęp daje `gap`. */
.pp-wysylka-link {
  display: inline-block;
  font-size: 14.5px;
  color: #127da8;
  text-decoration: none;
  border-bottom: 1px solid #bae6fd;
}

/* ⛔ `text-decoration: none !important` JEST WYMUSZONE. Generowany arkusz ustawień
   Journala nadaje KAŻDEMU `<a>` `text-decoration: underline dotted`. Nasza włoskowa
   linia dokładała się do tego kropkowanego podkreślenia i na najechaniu wychodził
   „krokowany" podwójny podkreślnik (zgłoszone przez usera 17.08.2026). Odnośnik musi
   posiadać SWOJE podkreślenie na wyłączność — inaczej rysują je dwa różne mechanizmy. */
.pp-wysylka-link,
.pp-wysylka-link:hover,
.pp-wysylka-link:focus { text-decoration: none !important; }
.pp-wysylka-link:hover { border-bottom-color: #127da8; }

/* ── sekcje treści ─────────────────────────────────────────────────── */
.pp-sekcja { padding: 30px 0; border-top: 1px solid #e5e7eb; }
.pp-sekcja:last-child { padding-bottom: 8px; }

/* ── siatka treści: opis szerszy po lewej, dane po prawej ──────────────
   Układ dwukolumnowy (decyzja usera 17.08.2026): opis szerszy, obok węższy pas
   z tabelą techniczną, a pod nią spis modeli.

   ⚠️ Włoskowa linia siedzi na TYM pojemniku, a sekcjom w środku ją zdejmujemy.
      Gdyby każda rysowała własną, lewa kolumna dostałaby jedną kreskę, prawa dwie,
      i żadna nie zgadzałaby się w poprzek. Rozdzielenie w prawej kolumnie robi
      osobna reguła niżej. */
.pp-tresc { border-top: 1px solid #e5e7eb; }
.pp-tresc > .pp-sekcja,
.pp-tresc .pp-bok > .pp-sekcja { border-top: 0; }

/* Jedna kolumna to stan wyjściowy — siatka włącza się dopiero, gdy jest miejsce. */
.pp-tresc .pp-sekcja { padding-top: 30px; }

/* W prawej kolumnie sekcje rozdziela włoskowa linia, ale PIERWSZA jej nie dostaje —
   zaczyna się równo z opisem po lewej. */
.pp-bok > .pp-sekcja + .pp-sekcja { border-top: 1px solid #e5e7eb; }

@media (min-width: 992px) {
  .pp-tresc {
    display: grid;
    /* Opis wyraźnie szerszy od danych. `minmax(0, …)` po obu stronach jest konieczne:
       bez niego długie nazwy kart w spisie rozepchnęłyby prawą kolumnę ponad podział. */
    grid-template-columns: minmax(0, 1.45fr) minmax(0, .85fr);
    gap: 0 44px;
    align-items: start;
  }

  /* Pion między kolumnami zamiast poziomej kreski nad prawą sekcją — czytelniejszy
     podział niż druga linia biegnąca w tym samym miejscu, co ta u góry. */
  .pp-bok { border-left: 1px solid #f3f4f6; padding-left: 44px; margin-left: -44px; }
  .pp-bok > .pp-sekcja:first-child { padding-top: 30px; }
}

/* ⛔ TO SĄ `<h2>`, WIĘC MUSZĄ WYGLĄDAĆ JAK NAGŁÓWKI. Miałem tu 12 px, wersaliki
   i `#9ca3af` — mikro-etykietę przepisaną z makiety. Dwa realne problemy, oba zgłoszone
   przez usera 17.08.2026:
     1. 12 px dla nagłówka dokumentu jest po prostu małe, a wyszukiwarka czyta hierarchię
        także z tego, jak nagłówek wygląda;
     2. ⛔ KONTRAST: `#9ca3af` na białym to **2,6:1** — poniżej progu WCAG AA (4,5:1).
        `#1f2937` daje **14,7:1**.
   Rozmiar i kolor wzięte z „karty katalogowej" (`produkt-wizje.html`, `.sekcja > h2`),
   czyli z naszego własnego wzorca, a nie wymyślone. */
.pp-naglowek {
  margin: 0 0 16px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: #1f2937;
}

.pp-pod { margin: -8px 0 16px; font-size: 13.5px; color: #6b7280; }

/* ── pasuje do modeli ──────────────────────────────────────────────── */
/* Wiersz jak w makiecie: nazwa karty po lewej, numer pozycji na rysunku po prawej,
   rozdzielone włoskową linią. Szerokość ograniczona, bo to spis, nie tabela — wiersz
   przez całą stronę zmuszałby oko do skoku przez pustkę do numeru.
   ⛔ ŻADNYCH nagłówków w wierszach. Stary moduł zawijał każdą z 446 pozycji w `<h4>`. */
/* ⛔⛔ ZNACZNIK LISTY ZDEJMUJE SIĘ NA `li`, NIE NA `ul` — i to jest cała sztuczka.
      Generowany arkusz ustawień Journala (wstawka `<style>` w `<head>`) zawiera:
          ul > li { list-style-type: initial }
      `initial` znaczy `disc`, a reguła celuje WPROST w `li`, więc bije dziedziczenie
      z naszego `ul { list-style: none }`: własność ustawiona na elemencie zawsze wygrywa
      z odziedziczoną, niezależnie od specyficzności selektora rodzica.
   ⚠️ Zmierzone 18.08.2026 w przeglądarce: `ul` liczyło się jako `none`, a `li` jako `disc`
      — dlatego sprawdzenie samego pojemnika NICZEGO nie wykrywa. W spisie modeli kropki
      było widać, a w opisie „zniknęły" PRZYPADKIEM: przy `padding-left: 0` znacznik wypada
      poza obszar i nie widać go, dopóki ktoś nie przywróci wcięcia.
   ⚠️ `ol` ŚWIADOMIE NIETKNIĘTE — numer niesie kolejność. */
.pp-fit li,
.pp-opis ul > li { list-style: none; }

.pp-fit { margin: 0; padding: 0; list-style: none; max-width: 560px; }
.pp-fit li { border-bottom: 1px solid #e5e7eb; }
.pp-fit li:last-child { border-bottom: 0; }

.pp-fit a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 2px;
  text-decoration: none;
  color: inherit;
}

.pp-fit-nazwa { flex: 1; font-size: 14.5px; color: #374151; }
.pp-fit a:hover .pp-fit-nazwa { color: #127da8; }

/* Numer pozycji pismem o stałej szerokości — cyfry mają się układać w kolumnę. */
.pp-fit-ref {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: #9ca3af;
  font-variant-numeric: tabular-nums;
}

/* Licznik kart w nagłówku sekcji — liczba jest FAKTEM, nie obietnicą „pasuje do wielu". */
.pp-fit-licznik {
  display: inline-block;
  margin-left: 9px;
  padding: 2px 8px;
  vertical-align: 2px;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  background: #f9fafb;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  color: #6b7280;
  font-variant-numeric: tabular-nums;
}

/* Rozwinięcie ogona. Treść siedzi w HTML-u zawsze — `<details>` decyduje tylko o tym,
   czy jest widoczna, więc wyszukiwarka nie traci ani jednej karty. Bez JavaScriptu. */
.pp-fit-wiecej { margin-top: 4px; }

.pp-fit-wiecej > summary {
  display: inline-block;
  cursor: pointer;
  padding: 9px 2px;
  font-size: 13.5px;
  color: #127da8;
  list-style: none;
}

.pp-fit-wiecej > summary::-webkit-details-marker { display: none; }
.pp-fit-wiecej > summary::before { content: "\002B"; margin-right: 7px; font-weight: 700; }
.pp-fit-wiecej[open] > summary::before { content: "\2212"; }
.pp-fit-wiecej > summary:hover { text-decoration: underline; }

/* ── tabele: nasza techniczna i Wasza w środku opisu ───────────────────
   ⛔ `!important` JEST TU WYMUSZONE, nie wygodne. Generowany arkusz ustawień Journala
      (wstawka `<style>` w `<head>`, ~450 kB) narzuca KAŻDEJ tabeli w sklepie:
        table    { border-width:1px !important; border-style:solid !important;
                   border-color:rgba(221,223,228,1) !important; background-color:#fff }
        table td { padding:12px !important }
      Bez `!important` po naszej stronie obie tabele dostają obwódkę i cudze odstępy —
      i to jest ta „dziwna ramka" (zmierzone w przeglądarce 17.08.2026, nie zgadnięte).
   ⚠️ Naprawą NIE jest zmiana ustawienia Journala: tamto działa na CAŁY sklep, a my mamy
      poprawić dwie tabele na jednej stronie. Nasze selektory są wąskie i tak zostaje.
   ⚠️ Reguła Journala celuje w `table` i `table td` — dlatego my celujemy w te same
      własności, na tych samych elementach. Zdejmujemy obwódkę i tło, zostawiamy same
      poziome włoskowe linie między wierszami. */
.pp-spec,
.pp-opis table {
  border-width: 0 !important;
  border-style: none !important;
  background: transparent !important;
  border-collapse: collapse;
  width: 100%;
  margin: 0;
}

.pp-spec th,
.pp-spec td,
.pp-opis table th,
.pp-opis table td {
  border-left: 0 !important;
  border-right: 0 !important;
  border-top: 0 !important;
  border-bottom: 1px solid #f3f4f6 !important;
  background: transparent !important;
  vertical-align: top;
  line-height: 1.5;
}

/* Etykieta cicha, wartość mocna — czytelna hierarchia w obu tabelach. */
.pp-spec th,
.pp-opis table th {
  text-align: left;
  font-weight: 400;
  color: #6b7280;
  font-size: 14px;
  padding: 9px 16px 9px 0 !important;
  width: 45%;
}

.pp-spec td,
.pp-opis table td {
  color: #1f2937;
  font-size: 14.5px;
  padding: 9px 0 !important;
}

/* Ostatni wiersz bez kreski — inaczej tabela kończy się kreską wiszącą w powietrzu. */
.pp-spec tr:last-child th, .pp-spec tr:last-child td,
.pp-opis table tr:last-child th, .pp-opis table tr:last-child td { border-bottom: 0 !important; }

/* ── opis (Wasza treść) ────────────────────────────────────────────── */
/* ⚠️ Miara wiersza zostaje ograniczona, mimo że kolumna jest już węższa — długi wiersz
   męczy oko niezależnie od tego, ile miejsca jest na stronie. */
.pp-opis { max-width: 70ch; font-size: 16px; line-height: 1.72; color: #374151; }
.pp-opis h3 { margin: 26px 0 10px; font-size: 18px; letter-spacing: -.018em; color: #1f2937; }
.pp-opis p { margin: 0 0 14px; }
/* ⛔ LISTY PUNKTOWANE BEZ ZNACZNIKA. Pozycje opisów zaczynają się własnym znakiem (✅),
   więc kropka przeglądarki była DRUGIM znacznikiem w tym samym wierszu. Zdejmujemy też
   wcięcie — bez kropki wcięcie nie ma czego wyrównywać, a tekst ma stać w jednej osi
   z akapitami wokół.
   ⚠️ TYLKO `ul`. W `ol` numer niesie KOLEJNOŚĆ, więc jego usunięcie zabrałoby treść.
      Zmierzone 18.08.2026: 16 758 opisów ma `<ul>`, `<ol>` NIE MA ANI JEDEN — reguła na
      `ol` byłaby dziś pusta, a jutro cicho zepsułaby pierwszą listę kroków. */
/* ⛔ CAŁA LISTA WCIĘTA WZGLĘDEM NAGŁÓWKA, nie tylko zawinięte wiersze. Punkt jest treścią
   PODRZĘDNĄ wobec śródtytułu nad nim („Precision-Engineered Side Cowling Emblem"), więc ma
   zaczynać się dalej niż on — inaczej lista i nagłówek stoją w jednej osi i wygląda to jak
   ciąg akapitów, a nie wyliczenie. Wcięcie niesie hierarchię, nie ozdobę. */
.pp-opis ul { margin: 0 0 16px; padding-left: 1.5em; list-style: none; }
.pp-opis li { margin-bottom: 8px; }

/* WCIĘCIE WISZĄCE dla pozycji zaczynających się znakiem (✅ w 29 953 pozycjach na 30 086).
   Pierwszy wiersz zaczyna się znakiem, każdy następny stoi pod TREŚCIĄ, nie pod znakiem.

   ⚠️ REGUŁA CELOWO OBEJMUJE WSZYSTKIE POZYCJE, także te bez znaku — i to NIE jest
      niedoróbka. Ujemny `text-indent` znosi `padding-left` w pierwszym wierszu, więc
      pozycja, która się nie zawija, wygląda dokładnie tak, jakby wcięcia nie miała.
      Różnica jest widoczna wyłącznie przy pozycji DŁUGIEJ i BEZ znaku — a takich
      w katalogu nie ma ani jednej poprawnej (zmierzone 18.08.2026: 86 pozycji bez znaku
      to krótkie wiersze w rodzaju „Material: Vinyl decal", które nigdy się nie zawijają).
   ⛔ Rozróżnianie w PHP, od czego zaczyna się tekst, zostało napisane i WYCOFANE: dawało
      identyczny obraz kosztem metody skanującej każdy opis wyrażeniem regularnym.
   ⚠️ 1.5em NIE JEST DOBRANE NA OKO — zmierzona szerokość napisu „✅ " w kroju tej listy
      to 24,04 px przy 16 px, czyli 1,503 em. Zawinięty wiersz staje co do piksela
      pod treścią. */
.pp-opis li {
  padding-left: 1.5em;
  text-indent: -1.5em;
}
/* Tabela w środku opisu ma własny oddech od tekstu wokół. */
.pp-opis table { margin: 4px 0 20px !important; max-width: 480px; }
.pp-opis small { display: block; font-size: 12.5px; color: #9ca3af; margin-top: 10px; }

/* ══════════ TAKŻE DO TEGO MODELU ══════════
   Zastępuje moduł Journala 272 — patrz komentarz w szablonie. Trzy układy wybierane
   w panelu: `a` zakładki, `b` pasek z kaflami wejścia, `c` pasek z rozwijanymi grupami.
   Wygląd kafla ustalony na makiecie z 19.08.2026. */
.pp-tasma { display: grid; grid-auto-flow: column; grid-auto-columns: 152px; gap: 13px; overflow-x: auto; padding-bottom: 10px; }

.pp-pow-kafel { position: relative; display: flex; flex-direction: column; }

/* ⛔ WARTOŚCI PRZEPISANE Z LISTY CZĘŚCI (`part-thumb` w `category_lastchild.css`)
   i to jest tu istotą: ten sam odruch ma dawać ten sam efekt w obu miejscach.
   `zoom-in` mówi kursorem, że kliknięcie powiększa, zanim cokolwiek się pojawi. */
.pp-pow-obraz {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  padding: 0;
  cursor: zoom-in;
  width: 100%;
}
.pp-pow-obraz img { width: 100%; height: 100%; object-fit: contain; padding: 8px; }
.pp-pow-obraz:hover { border-color: #127da8; }

/* Pozycja bez zdjęcia — kafelek zostaje, żeby pasek trzymał jedną siatkę, ale nie
   udaje przycisku: obwódka przerywana i kursor bez zapowiedzi powiększenia. */
.pp-pow-obraz.jest-pusty {
  border-style: dashed;
  cursor: default;
  background: #f9fafb;
}
.pp-pow-obraz.jest-pusty::after {
  content: "\f03e";
  font-family: FontAwesome;
  font-size: 17px;
  color: #d1d5db;
}

/* Pasek podglądu wsuwa się od dołu — te same barwy i stopień pisma, co w liście części. */
.pp-pow-obraz .qv {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: rgba(18, 125, 168, .92);
  color: #fff;
  font-size: 9px;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-align: center;
  padding: 2px 0;
  opacity: 0;
  transition: opacity .12s;
}
.pp-pow-obraz:hover .qv, .pp-pow-obraz:focus-visible .qv { opacity: 1; }

/* ⚠️ Brak zdjęcia NIE JEST awarią — część katalogu nie ma jeszcze fotografii.
   Neutralny prostokąt mówi „tu będzie obraz", a nie „coś się zepsuło". */
.pp-pow-brak {
  width: 44px; height: 32px; border-radius: 3px;
  border: 1.6px solid #cbd5e1;
}

/* ⛔ NUMER, NIE NAZWA — patrz makro `kafel()` w szablonie. Figury tabularne, bo to
   liczba do porównywania: numery mają stać w kolumnie. */
.pp-pow-numer {
  margin-top: 6px;
  font-size: 13px; font-weight: 600; color: #1f2937;
  text-decoration: none; font-variant-numeric: tabular-nums;
}
.pp-pow-numer:hover { color: #127da8; }

/* ══════════ CENA W KAFLU: rezerwa i szkielet ══════════
   ⛔ REZERWA JEST OBOWIĄZKOWA. Cena i linia podatku przyjeżdżają odpowiedzią
      `stockInfo` — bez rezerwy pasek rósłby po doczytaniu i spychał wszystko pod
      sobą. Ta sama lekcja, co przy sekcji decyzji (zmierzone 19.08.2026: 39,5 px).
   ⚠️ Wysokości liczone z wysokości linii obu napisów, żeby zgaszenie szkieletu nie
      zmieniło ani piksela. */
.pp-pow-cena { min-height: 1.45em; font-size: 13.5px; font-weight: 700;
                 font-variant-numeric: tabular-nums; color: #1f2937; margin-top: 2px;
                 display: flex; align-items: center; }
.pp-pow-vat  { min-height: 1.4em; font-size: 11px; color: #6b7280;
                 display: flex; align-items: center; }

.pp-pow-cena:empty::before, .pp-pow-vat:empty::before {
  content: "";
  display: block;
  border-radius: 3px;
  background: linear-gradient(90deg, #f3f4f6 30%, #e5e7eb 50%, #f3f4f6 70%);
  background-size: 200% 100%;
  /* Skończona liczba przebiegów — patrz szkielety osi stanu. */
  animation: pp-szkielet 1.4s ease-in-out 12;
}
.pp-pow-cena:empty::before { width: 3.2em; height: .62em; }
.pp-pow-vat:empty::before  { width: 6.4em; height: .68em; }

/* ── kafel wejścia do karty ── */
.pp-tasma-wiecej {
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  padding: 12px; text-decoration: none; color: inherit;
  border: 1px dashed #e5e7eb; border-radius: 8px; background: #f9fafb;
}
.pp-tasma-wiecej:hover { border-style: solid; border-color: #127da8; }
.pp-tasma-wiecej-tyt { font-size: 13px; font-weight: 600; }
.pp-tasma-wiecej-ile { font-size: 12px; color: #127da8; }

/* Stos trzech miniatur — sygnalizuje, co jest w karcie, nie pokazując zawartości. */
.pp-tasma-stos { position: relative; height: 62px; margin-bottom: 4px; display: block; }
.pp-tasma-stos img, .pp-tasma-stos .pp-pow-brak {
  position: absolute; top: 0; left: calc(var(--i) * 26px);
  width: 56px; height: 56px; object-fit: contain;
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px; padding: 4px;
  transform: rotate(calc((var(--i) - 1) * 3deg));
}

/* ── zakładki (układ A) ── */
.pp-pow-zakladki { display: flex; gap: 2px; border-bottom: 1px solid #e5e7eb; margin-bottom: 16px; }
.pp-pow-zak {
  appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 8px 14px; font: inherit; font-size: 13.5px; color: #6b7280; cursor: pointer;
}
.pp-pow-zak.on { color: #1f2937; font-weight: 600; border-bottom-color: #127da8; }
.pp-pow-ile { color: #9ca3af; font-weight: 400; font-size: 12px; margin-left: 5px;
              font-variant-numeric: tabular-nums; }
.pp-pow-grupa[hidden] { display: none; }

/* ── rozwijane grupy (układ C) ── */
.pp-pow-tyt { font-size: 13.5px; font-weight: 600; margin: 0 0 12px; }
details.pp-pow-grupa { border-top: 1px solid #e5e7eb; margin-top: 16px; padding-top: 14px; }
details.pp-pow-grupa > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600;
  list-style: none; display: flex; align-items: center; gap: 8px;
}
details.pp-pow-grupa > summary::-webkit-details-marker { display: none; }
/* ⚠️ Strzałkę rysujemy sami, bo znacznik przeglądarki wygląda inaczej w każdej z nich,
   a `list-style` Journala i tak by go przykrył — patrz reguła `ul > li` w motywie. */
details.pp-pow-grupa > summary::before {
  content: ""; width: 0; height: 0;
  border: 5px solid transparent; border-left-color: #9ca3af;
  transition: transform .15s;
}
details.pp-pow-grupa[open] > summary::before { transform: rotate(90deg) translateX(-2px); }
details.pp-pow-grupa .pp-tasma { margin-top: 14px; }

/* ⚠️ Przy dotyku hover nie istnieje, więc pasek zostaje widoczny na stałe — inaczej
   na telefonie nic by nie mówiło, że kafelek otwiera podgląd. */
@media (hover: none) {
  .pp-pow-obraz .qv { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .pp-pow-cena:empty::before, .pp-pow-vat:empty::before { animation: none; }
}

/* ── powiększenie ──────────────────────────────────────────────────── */
/* Wartości przepisane z lightboxa listy części (`ci-lightbox`) — ten sam odruch
   na obu stronach sklepu. */
.pp-lupa { position: fixed; inset: 0; z-index: 9999; background: rgba(31, 41, 55, .85); display: grid; place-items: center; padding: 24px; }
.pp-lupa[hidden] { display: none; }
.pp-lupa figure { margin: 0; background: #fff; border-radius: 12px; overflow: hidden; max-width: min(880px, 92vw); }
.pp-lupa img { display: block; width: 100%; height: auto; max-height: 76vh; object-fit: contain; }
.pp-lupa figcaption { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 10px 12px; border-top: 1px solid #e5e7eb; font-size: 13.5px; color: #374151; }
.pp-lupa-akcje { display: flex; align-items: center; gap: 12px; }
.md-lupa-pelny { color: #127da8; text-decoration: none; white-space: nowrap; }
.md-lupa-x { background: #fff; border: 1px solid #d1d5db; border-radius: 4px; padding: 3px 12px; cursor: pointer; color: #374151; font-size: 18px; line-height: 1; }
body.md-lupa-otwarta { overflow: hidden; }

/* ── dostępność ────────────────────────────────────────────────────── */
/* ⛔ Rezerwa wysokości OBOWIĄZKOWA — pudło bez niej zapada się do zera, a skok w dół
   liczy się dokładnie tak samo jak skok w górę.
   ⚠️ Reguły `.pp-dostawa .md-stan/.md-ship` USUNIĘTE 17.08.2026: pigułek nie ma już na
   naszej stronie, zastąpiła je oś (`.pp-os`). Zostawione byłyby selektorami bez elementu —
   dokładnie tym rodzajem śmiecia, który następna osoba czyta jako obowiązujący.
   Same `.md-stan-pill` PONIŻEJ zostają: ten arkusz opisuje też pigułkę tam, gdzie jeszcze
   występuje. */

.md-stan-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  line-height: 1.5;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 5px;
  border: 1px solid #e5e7eb;
  background: #f9fafb;
  color: #374151;
}

/* ⛔ `[hidden]` MUSI mieć własną regułę — reguła przeglądarki ma siłę selektora typu
   i przegrywa z naszym `display` po klasie. Bez tego wisiałaby pusta pigułka. */
.md-stan-pill[hidden] { display: none; }

.md-stan-pill.is-tak { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
.md-stan-pill.is-tak::before { content: "\2713"; font-weight: 700; }
/* Termin — 72% katalogu. Neutralnie, bez alarmu: to normalna droga zakupu. */
.md-stan-pill.is-czeka { background: #f9fafb; border-color: #e5e7eb; color: #4b5563; }
/* Brak bez terminu — 25 pozycji w całym katalogu. */
.md-stan-pill.is-brak { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }

/* ── oś stanu i wysyłki ────────────────────────────────────────────────
   Przepisane ze szkieletu 2 (`produkt-szkielety-dane.html`, klasy `.os` / `.krok`):
   kółko 20 px, nagłówek 14,5 px pół-grubą, cicha linia 13,5 px pod nim.

   ⛔ REZERWA WYSOKOŚCI jest obowiązkowa. Oba kroki startują `hidden`, a treść dojeżdża
      żądaniem — bez `min-height` karta skakałaby po doczytaniu, a skok w dół liczy się
      do wyniku dokładnie tak samo jak w górę. Dwa kroki × 20 px + odstęp = 51 px. */
/* ══════════ OŚ STANU: szkielet PER KROK ══════════
   ⛔ KAŻDY KROK GASI SWÓJ SZKIELET SAM. Dwa kroki przychodzą z DWÓCH żądań — stan ze
      `stockInfo`, termin z `dispatchDate` — więc wspólny znacznik „mam dane" gasił oba po
      pierwszej odpowiedzi i drugi krok wpadał w puste miejsce. Przy wolnym łączu widać było
      wtedy wyraźny uskok (zgłoszone 18.08.2026).

   ⛔ SZKIELET MA KSZTAŁT TREŚCI, którą zastępuje: kółko po lewej, nad nim krótszy pasek
      nagłówka, pod nim dłuższy i cieńszy pasek linii szczegółu. Pasek na całą szerokość
      w miejscu, gdzie pojawi się kółko i dwie różne linie, wygląda jak coś innego niż
      docelowa treść — i to była druga uwaga użytkownika.

   ⚠️ Wymiary biorą się z gotowego kroku: kółko 20 px, nagłówek 14,5 px pisma × 1,4,
      szczegół 13,5 × 1,4. Dzięki temu zgaszenie szkieletu nie zmienia wysokości wiersza. */
@keyframes pp-szkielet { from { background-position: 100% 0 } to { background-position: -100% 0 } }

.pp-os { display: grid; gap: 11px; align-content: start; margin: 16px 0 4px; }

/* ══════════ CENA: rezerwa i szkielet ══════════
   ⛔ CENA TEŻ PRZYCHODZI ŻĄDANIEM, i to zostało przeoczone przy pierwszym podejściu.
      Kwota zależy od kraju dostawy (stawka VAT) i od reguł rabatowych, więc nie może stać
      w cache'owanej stronie — dociąga ją `stockInfo`. Zmierzone 18.08.2026: blok ceny rósł
      z 86 px do 125 px, czyli **39 px uskoku** tuż nad osią stanu i przyciskiem.
   ⚠️ Lista części ma ten szkielet od 16.08; strona produktu go nie dostała — ta sama klasa
      błędu, co przy osi stanu.

   ⛔ DWA OBSZARY, DWIE REZERWY. Kwota siedzi w `.price-group`, linia podatku w osobnym
      `.md-tax` poza nią — jedna rezerwa nie pokryje obu.
   ⚠️ Rezerwa podatku liczy się na DWIE linie: „incl. VAT (23%)" mieści się w jednej, ale
      „VAT-free · delivery to Netherlands" już nie, a rezerwa ma pasować do gorszego
      przypadku. Zapas przy krótszym napisie jest tańszy niż skok. */
.pp-decyzja .price-check {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  font-size: 33px;          /* stopień pisma kwoty — rezerwa liczy się z niego */
  min-height: 1.05em;       /* zmierzona wysokość linii kwoty: 33 px → 34,65 px */
  /* ⛔ BEZ MARGINESU. Wspólny arkusz `md_product_price.css` daje `.price-check`
     `margin-top: var(--md-cena-mt)` (8 px) — tam jest potrzebny, bo w liście części
     szkielet stoi pod nazwą pozycji. Tutaj zastępuje `.product-price`, która marginesu
     NIE MA, a `.price-check` jest usuwane z drzewa po odpowiedzi — więc margines znika
     razem z nim i CAŁA karta podjeżdża. Zmierzone 19.08.2026: 8 px z 39,5 px uskoku. */
  margin-top: 0;
}

.pp-decyzja .price-check::before,
.pp-decyzja .md-tax:empty::before {
  content: "";
  display: block;
  border-radius: 4px;
  background: linear-gradient(90deg, #f3f4f6 30%, #e5e7eb 50%, #f3f4f6 70%);
  background-size: 200% 100%;
  animation: pp-szkielet 1.4s ease-in-out 12;
}

/* Pasek kwoty — proporcje jak w liście części. */
.pp-decyzja .price-check::before { height: .62em; width: 3.4em; margin: .21em 0; }

/* Linia podatku: rezerwa dostrojona pomiarem, pasek w miejscu pierwszej linii.
   ⚠️ 2,48em, nie „dwie pełne linie" (2,86em) — zmierzone na żywej stronie: przy 2,86
      blok kurczył się po doczytaniu o 5 px, bo napis podatku zajmuje mniej niż dwa pełne
      wiersze. Rezerwa liczona „na oko z line-height" bywa za duża tak samo, jak bywa
      za mała; obie dają skok.
   ⛔ Dostrajamy do przypadku BEZ przekreślonej ceny, bo to większość katalogu (~5,5 tys.
      pozycji z narzutem wobec ~350 z rabatem). Przy rabacie zostaje +23 px z ceny „przed",
      której nie da się przewidzieć przed odpowiedzią — rezerwa na nią u wszystkich
      kosztowałaby 23 px pustki u 94% produktów. */
.pp-decyzja .md-tax:empty { min-height: 2.48em; }
.pp-decyzja .md-tax:empty::before { height: .75em; width: 9em; margin: .34em 0; }

/* ══════════ PLAKIETKI POD CENĄ: rezerwa i szkielet ══════════
   ⚠️ ZAKRES `.pp-decyzja` JEST NOŚNY. Same `.pp-plakietki` opisuje wspólny arkusz
      `md_oznaczenia.css`, którego używa też lista części — tam rezerwa w każdym wierszu
      byłaby pustym miejscem przy większości pozycji.
   ⛔ REZERWA, bo część plakietek zależy od STANU i przychodzi dopiero odpowiedzią. */
.pp-decyzja .pp-plakietki { min-height: 21px; }

.pp-decyzja .pp-plakietki:empty::before {
  content: "";
  display: block;
  width: 92px;
  height: 21px;
  border-radius: 4px;
  background: linear-gradient(90deg, #f3f4f6 30%, #e5e7eb 50%, #f3f4f6 70%);
  background-size: 200% 100%;
  animation: pp-szkielet 1.4s ease-in-out 12;
}

/* Po odpowiedzi bez plakietek pojemnik znika bez śladu. */
.pp-decyzja .pp-plakietki.pusta { min-height: 0; margin-top: 0; }
.pp-decyzja .pp-plakietki.pusta::before { content: none; }

@media (prefers-reduced-motion: reduce) {
  .pp-decyzja .price-check::before,
  .pp-decyzja .md-tax:empty::before,
  .pp-decyzja .pp-plakietki:empty::before { animation: none; }
}

/* Wspólne tło pasków — barwy z siatki szarości, pasek ma być widoczny, ale nie udawać treści. */
.pp-krok.jest-szkielet .pp-krok-tyt::before,
.pp-krok.jest-szkielet .pp-krok-det::before,
.pp-krok.jest-szkielet .pp-pkt::before {
  content: "";
  display: block;
  border-radius: 4px;
  background: linear-gradient(90deg, #f3f4f6 30%, #e5e7eb 50%, #f3f4f6 70%);
  background-size: 200% 100%;
  /* Skończona liczba przebiegów: gdy odpowiedź nie dojdzie, pasek przestaje migotać
     zamiast pulsować w nieskończoność nad martwym miejscem. */
  animation: pp-szkielet 1.4s ease-in-out 12;
}

/* Kółko: pełne koło w miejscu znacznika kroku. */
.pp-krok.jest-szkielet .pp-pkt::before { width: 20px; height: 20px; border-radius: 50%; }
.pp-krok.jest-szkielet .pp-pkt { border: 0; background: none; }

/* ⛔ WYSOKOŚĆ BIERZE SIĘ Z WYSOKOŚCI LINII, nie z marginesów przy pasku. Pierwsza wersja
   miała sztywne odstępy i krok ze szkieletem mierzył 29 px przy 41 px treści — czyli
   gaszenie dawało 23 px uskoku, dokładnie to, co szkielet ma likwidować.
   ⚠️ `1.45em` to ZMIERZONA wysokość linii obu elementów (14,5 px × 1,45 = 21,0;
      13,5 px × 1,45 = 19,6). W `em`, więc rezerwa idzie za pismem — przy zmianie stopnia
      nie trzeba tu nic poprawiać.
   ⚠️ `flex` zamiast `block`: pasek ma stać w PIONOWYM ŚRODKU linii, tak jak stałby tekst.
   ⛔ Szczegół pokazujemy ZAWSZE, choć w gotowej treści bywa pusty — inaczej krok ze
      szkieletem jest niższy niż wypełniony. */
.pp-krok.jest-szkielet .pp-krok-tyt,
.pp-krok.jest-szkielet .pp-krok-det {
  display: flex !important;
  align-items: center;
  min-height: 1.45em;
  color: transparent;
}

/* Nagłówek — krótszy pasek; szczegół — dłuższy i cieńszy, jak prawdziwa cicha linia. */
.pp-krok.jest-szkielet .pp-krok-tyt::before { width: 104px; height: 11px; }
.pp-krok.jest-szkielet .pp-krok-det::before { width: 168px; height: 9px; }

@media (prefers-reduced-motion: reduce) {
  .pp-krok.jest-szkielet .pp-krok-tyt::before,
  .pp-krok.jest-szkielet .pp-krok-det::before,
  .pp-krok.jest-szkielet .pp-pkt::before { animation: none; }
}

.pp-krok { display: grid; grid-template-columns: 20px 1fr; gap: 11px; align-items: start; }
.pp-krok[hidden] { display: none; }
/* ⚠️ Krok, którego nie będzie (brak na stanie i bez terminu), gasi szkielet i chowa się —
   inaczej pasek migotałby nad miejscem, w którym nic nigdy nie stanie. */

/* Kółko: pełne i zielone, gdy TAK; puste z szarą kropką, gdy CZEKAMY; czerwone, gdy BRAK. */
.pp-pkt {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #d1d5db;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 1px;
}

.pp-krok.is-tak .pp-pkt { background: #15803d; border-color: #15803d; }
/* Znak ptaszka rysujemy CSS-em, nie znakiem w treści — treść wypełnia skrypt i nie
   powinna nosić ozdób. */
.pp-krok.is-tak .pp-pkt::after {
  content: "";
  width: 9px; height: 5px;
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px);
}
.pp-krok.is-czeka .pp-pkt::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #9ca3af; }
.pp-krok.is-brak .pp-pkt { border-color: #fecaca; background: #fef2f2; }
.pp-krok.is-brak .pp-pkt::after { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #b91c1c; }

.pp-krok-op { min-width: 0; font-size: 13.5px; color: #6b7280; line-height: 1.45; }
.pp-krok-tyt { display: block; color: #1f2937; font-size: 14.5px; font-weight: 600; letter-spacing: -.01em; }
.pp-krok-det[hidden] { display: none; }

/* ── szacowanie kosztu wysyłki — WEWNĄTRZ karty decyzji ────────────────
   Stoi w `.pp-dostawa`, tam gdzie wcześniej był sam odnośnik do zasad wysyłki.
   ⛔ Bez własnego tła i bez ramki: jest CZĘŚCIĄ karty, nie pudełkiem w pudełku.
   ⚠️ Pisma podniesione do skali karty (15 px treść, 14,5 px odnośniki) — poprzednie
      13–14 px czytały się jak przypis, na co user zwrócił uwagę. */
/* ⚠️ `.pp-dostawa` ma `align-items: flex-start`, żeby plakietki stanu i terminu były
   szerokie na TREŚĆ, a nie na kolumnę. Wycena to nie plakietka — musi więc odzyskać
   pełną szerokość jawnie, inaczej ściska się do napisu i przycisk skacze do lewej.
   Włoskowa linia oddziela ją od plakietek: wyżej STAN, tutaj KOSZT. */
.pp-dostawa > .pp-wyc {
  width: 100%;
  margin-top: 6px;
  padding-top: 12px;
  border-top: 1px solid #e5e7eb;
}

.pp-wyc-glowa { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.pp-wyc-kraj {
  flex: 1;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  /* ⚠️ Zawijanie + `flex-basis:100%` na etykiecie łamią wiersz PO NIEJ, więc etykieta stoi
     nad krajem, a flaga zostaje przy nazwie. Bez tego trzeba by dokładać znacznik. */
  flex-wrap: wrap;
  column-gap: 8px;
  row-gap: 1px;
  font-size: 15px;
  color: #374151;
}

/* Etykieta „Wysyłka do:" przed nazwą kraju.
   ⛔ MUSI CZYTAĆ SIĘ JAKO ETYKIETA, NIE JAKO CZĘŚĆ ZDANIA — na tym stoi poprawność
      gramatyczna całego wiersza. Stąd stonowany kolor i mniejszy stopień: oko widzi parę
      „etykieta : wartość", a nie zdanie „Wysyłka do Niemcy", które byłoby błędem.
   ⚠️ `flex: 0 0 auto`, żeby przy długiej nazwie kraju kurczyła się NAZWA, nie etykieta —
      urwana etykieta przestaje tłumaczyć wiersz, a po to tu jest. */
.pp-wyc-etykieta {
  /* ⛔ CAŁA SZEROKOŚĆ = własny wiersz. Etykieta stoi NAD krajem, nie obok — inline gubiła
     się w wierszu i czytała się jak początek zdania („Wysyłka do Niemcy"), a to właśnie
     ten błąd gramatyczny mieliśmy ominąć. Nad wartością jest jednoznacznie podpisem. */
  flex: 0 0 100%;
  font-size: 11px;
  line-height: 1.45;
  color: #6b7280;
  white-space: nowrap;
}

/* Flaga: `flag-icons` rysuje ją TŁEM, więc potrzebuje własnego pudełka o proporcji 4:3.
   Zestaw dokłada moduł „Wysyłka do" na każdej stronie — nic nie pobieramy dodatkowo. */
.pp-wyc-flaga {
  flex: 0 0 auto;
  width: 21px;
  height: 15px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
}

/* Przycisk drugoplanowy — obrys, nie plama. Pomarańcz zostaje wyłącznie przy koszyku. */
.pp-wyc-licz {
  flex: 0 0 auto;
  appearance: none;
  background: #fff;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  padding: 0 15px;
  height: 34px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
}

.pp-wyc-licz:hover { border-color: #127da8; color: #127da8; }
.pp-wyc.is-czeka .pp-wyc-licz { opacity: .55; pointer-events: none; }

.pp-wyc-wynik:empty { display: none; }
.pp-wyc-wynik { margin-top: 8px; font-size: 15px; color: #374151; }

.pp-wyc-poz {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid #f3f4f6;
}

.pp-wyc-poz:last-child { border-bottom: 0; }
.pp-wyc-nazwa { flex: 1; min-width: 0; }
.pp-wyc-kwota { font-weight: 700; color: #1f2937; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Pytanie o inny kraj — zwinięte, bo to przypadek rzadszy niż „ile do mnie".
   ⚠️ `summary` nosi klasę `pp-wysylka-link`, czyli TEN SAM styl odnośnika, co zasady
      wysyłki pod spodem. Trzeci własny styl odnośnika w jednej karcie był tym, co user
      zgłosił jako „linki w innym stylu". */
.pp-wyc-inny { margin-top: 8px; }
.pp-wyc-inny > summary { cursor: pointer; list-style: none; }
.pp-wyc-inny > summary::-webkit-details-marker { display: none; }
.pp-wyc-pole { margin-top: 10px; }

/* Napis tylko dla czytnika ekranu. ⚠️ Nie `display:none` ani `visibility:hidden` —
   te dwa USUWAJĄ element z drzewa dostępności, czyli robią dokładnie odwrotnie. */
.pp-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ⛔ REGUŁY `.pp-lst-*` USUNIĘTE 17.08.2026 razem z drugą kopią kontrolki.
   Wygląd listy siedzi teraz w `md_select.css`, wspólnym dla strony produktu i checkoutu.
   Zostawione byłyby arkuszem bez elementu — a takie reguły następna osoba czyta jako
   obowiązujące i próbuje je stroić. */

/* ══════════════════ PODGLĄD SZYBKI ══════════════════
   ⛔ OSOBNY UKŁAD, NIE ZWĘŻONA STRONA. Podgląd jest oddzielnym dokumentem w ramce
      `iframe` (`common.js`: `route=journal3/product&popup=quickview`), więc widnia
      w środku to SZEROKOŚĆ MODALA (~1000 px), a nie okna. Reguła trójkolumnowa strony
      zaczyna się od `min-width: 1200px` i w ramce nie włączała się nigdy — wchodziła
      reguła 768 px z `grid-column: 1 / -1`, przez co karta decyzji spadała pod spód
      pełną szerokością (zgłoszone 18.08.2026).
   ⚠️ Progi są tu NIŻSZE, bo mierzą modal, nie ekran. To nie jest obejście — zapytania
      medialne w ramce działają poprawnie, tylko odnoszą się do mniejszej powierzchni. */

/* Bez marginesu pod pasmem — w podglądzie nie ma już nic poniżej. */
.pp-podglad .pp-pasmo { margin-bottom: 0; }

/* ⛔ DWIE KOLUMNY, NIE TRZY: [ informacja / pod nią obrazy ] [ karta decyzji ].
      Na stronie obrazy stoją w osobnej, wąskiej kolumnie z lewej — w modalu ten sam
      układ zjadał szerokość potrzebną treści i karcie. Tutaj informacja dostaje pełną
      szerokość lewej kolumny, a kafle idą POD nią (decyzja usera 18.08.2026).

   ⛔ WIERSZ OBRAZÓW MA `1fr`, A KAFLE `align-self: end` — i to jest cały mechanizm
      wyrównania. Karta decyzji rozpina się na oba wiersze, więc to ONA wyznacza wysokość
      siatki; pusty zapas ląduje w drugim wierszu NAD kaflami, przez co ich dolna krawędź
      siada równo z dolną krawędzią karty. Bez `1fr` zapas rozłożyłby się inaczej i dna
      by się rozjechały.

   ⚠️ Kolejność w znacznikach zostaje bez zmian (obrazy, informacja, karta) — przestawia
      je siatka. Znaczniki czyta wyszukiwarka i czytnik ekranu w kolejności źródła,
      a tam obraz przed opisem jest poprawny. */
@media (min-width: 700px) {
  .pp-podglad .pp-pasmo {
    grid-template-columns: minmax(0, 1fr) 320px;
    grid-template-rows: auto 1fr;
    gap: 18px 22px;
  }

  .pp-podglad .pp-toz     { grid-column: 1; grid-row: 1; }
  .pp-podglad .pp-obrazy  { grid-column: 1; grid-row: 2; align-self: end; }
  /* ⛔ `align-self: stretch` NA KARCIE — bez tego dna się nie zgadzają i to był realny
     rozjazd: zmierzone 150 px. Strona ustawia `.pp-pasmo { align-items: start }`, więc
     karta zatrzymuje się na swojej naturalnej wysokości, a lewa kolumna (informacja
     + kafle) bywa wyższa. Rozciągnięta karta kończy się dokładnie tam, gdzie siatka,
     czyli równo z dolną krawędzią kafli — o to prosił user.
     ⚠️ Działa w OBIE strony: gdy to karta jest wyższa, wysokość siatki wyznacza ona,
        a kafle dosuwa do dna `align-self: end` z reguły wyżej. */
  .pp-podglad .pp-decyzja { grid-column: 2; grid-row: 1 / -1; align-self: stretch; }

  /* ⛔ KAFLE OBOK SIEBIE, nie jeden pod drugim. Pod szeroką kolumną informacji pionowa
     kolumna kafli ciągnęłaby okno w dół — a podgląd ma się mieścić bez przewijania. */
  .pp-podglad .pp-obrazy {
    /* ⛔ `grid-template-columns: none` JEST TU WARUNKIEM DZIAŁANIA, nie porządkami.
       Reguła szerokoekranowa wyżej zostawia JAWNĄ kolumnę (`minmax(0, 1fr)`), a przy
       `grid-auto-flow: column` pierwszy kafel wpada właśnie w nią i bierze CAŁĄ
       szerokość okna — pozostałe dostają dopiero kolumny automatyczne po 128 px.
       Objaw: podgląd pokazywał jedno wielkie zdjęcie i miniaturkę obok (zgłoszone
       19.08.2026). Kolumny automatyczne nie nadpisują jawnych, tylko je uzupełniają. */
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 128px;
    justify-content: start;
    gap: 10px;
  }
}

/* Poniżej progu wszystko wraca do jednej kolumny — modal bywa wąski na telefonie. */
@media (max-width: 699px) {
  .pp-podglad .pp-obrazy { grid-template-columns: none; grid-auto-flow: column;
                           grid-auto-columns: 108px; justify-content: start; }
}

/* Nagłówek i tabliczki nieco ciaśniej — modal czyta się z bliska. */
.pp-podglad .pp-h1 { font-size: 20px; }
.pp-podglad .pp-toz-luka { height: 8px; }

/* ---------- obwódka wokół numeru TEJ naklejki na rysunku ----------
   Strona produktu dotyczy jednej naklejki, więc obwódka niczego nie wybiera — odpowiada
   na jedno pytanie: gdzie ta część siedzi na motocyklu. Stąd brak stanów, brak klikania
   i brak najeżdżania; jest widoczna od razu i cały czas.

   ⛔ Barwa BŁĘKITNA (ta sama co na liście części), bo numery na rysunku są bordowe.
   Ciepła obwódka zlewałaby się z samą cyfrą.

   ⚠️ `pointer-events: none` jest tu konieczne, nie kosmetyczne: obwódka leży wewnątrz
   przycisku powiększenia, więc bez tego przechwytywałaby kliknięcia w miejscu numeru
   i lupa przestawałaby się otwierać akurat tam, gdzie klient celuje najczęściej. */
.pp-ref-layer {
  position: absolute;
  box-sizing: border-box;
  border: 2.5px solid rgb(14, 165, 233);
  border-radius: 5px;
  box-shadow: 0 0 0 3px rgba(14, 165, 233, .22);
  background: rgba(14, 165, 233, .16);
  pointer-events: none;
}

.pp-ref-layer[hidden] { display: none; }

/* Sceny, względem których liczą się współrzędne obwódki. `pp-kafel-lupa` ma już
   `position: relative` (trzyma ikonę lupy), więc powtarzać nie trzeba. */
.pp-rys-scena { position: relative; display: block; }
.pp-lupa-scena { position: relative; display: block; }

/* W powiększeniu obrazek jest kilka razy większy, więc ta sama kreska wygląda cieniej. */
.pp-lupa-scena .pp-ref-layer { border-width: 3px; }

/* Dymek przy numerze na rysunku - ta sama klasa i ten sam wygląd co na liście części.
   ⛔ NIE `title=`: systemowy dymek ma opóźnienie narzucone przez przeglądarkę i nie da
   się go skrócić. Powtórzona definicja, bo arkusze obu modułów są rozdzielne, a moduły
   ładują się niezależnie od siebie.

   ⚠️ Dwa wiersze: etykieta drobna i przygaszona, wartość wyraźna. Bez tej różnicy „Position
   on diagram" waży tyle samo co numer, którego dotyczy - a czyta się je jako parę. */
.ref-tip{position:fixed;z-index:10050;max-width:260px;
  display:grid;gap:1px 0;
  padding:6px 10px;border-radius:5px;
  background:#1f2937;color:#fff;
  font-size:12.5px;line-height:1.35;
  box-shadow:0 4px 12px rgba(0,0,0,.22);
  pointer-events:none}
.ref-tip[hidden]{display:none}
.ref-tip .ref-tip-et{font-size:10.5px;letter-spacing:.04em;text-transform:uppercase;
  color:#9ca3af}
.ref-tip .ref-tip-v{font-weight:600}
/* Odstęp przed drugą parą, żeby wiersze nie zlewały się w jeden blok tekstu. */
.ref-tip .ref-tip-et + .ref-tip-v + .ref-tip-et{margin-top:5px}

/* ══════════════ UKŁAD B: DWIE KOLUMNY ══════════════
   Do wyboru w panelu, obok układu domyślnego (trzy kolumny). Ten sam pomysł, który
   sprawdził się w podglądzie szybkim: treść dostaje pełną szerokość lewej kolumny,
   a kafle idą POD nią - zamiast zjadać osobną, wąską kolumnę z lewej.

   ⛔ REGUŁY SĄ WŁASNE, NIE WSPÓLNE Z `.pp-podglad`, i to jest świadome. Podgląd mierzy
   szerokość MODALA, więc jego progi (700 px) i szerokość karty (320 px) opisują inną
   powierzchnię. Zlanie obu w jeden selektor znaczyłoby, że korekta układu w modalu
   po cichu zmienia stronę - albo odwrotnie.

   ⚠️ Kolejność w znacznikach zostaje bez zmian (obrazy, treść, karta) - przestawia je
   siatka. Znaczniki czyta wyszukiwarka i czytnik ekranu w kolejności źródła, a tam
   obraz przed opisem jest poprawny. */
@media (min-width: 992px) {
  .pp-uklad-b .pp-pasmo {
    grid-template-columns: minmax(0, 1fr) 380px;
    grid-template-rows: auto 1fr;
    gap: 22px 26px;
  }

  .pp-uklad-b .pp-toz    { grid-column: 1; grid-row: 1; }
  /* ⛔ WIERSZ OBRAZÓW MA `1fr`, A KAFLE `align-self: end` - i to jest cały mechanizm
     wyrównania dna. Karta rozpina się na oba wiersze, więc ONA wyznacza wysokość siatki;
     pusty zapas ląduje NAD kaflami, przez co ich dolna krawędź siada równo z dolną
     krawędzią karty. */
  .pp-uklad-b .pp-obrazy { grid-column: 1; grid-row: 2; align-self: end; }
  .pp-uklad-b .pp-decyzja{ grid-column: 2; grid-row: 1 / -1; align-self: stretch; }

  /* Kafle obok siebie, nie jeden pod drugim: pod szeroką kolumną treści pionowa kolumna
     kafli ciągnęłaby stronę w dół bez powodu. */
  .pp-uklad-b .pp-obrazy {
    /* ⛔ `grid-template-columns: none` JEST TU KONIECZNE. Reguła progu 768 px ustawia
       pierwszą kolumnę na `minmax(0, 1fr)`, a `grid-auto-columns` rządzi tylko kolumnami
       DOROBIONYMI - więc pierwszy kafel brał całą szerokość kolumny (zmierzone: 630 px
       przy 150 px pozostałych), zamiast stanąć w rzędzie równych miniatur. */
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 150px;
    justify-content: start;
    gap: 12px;
  }
}

/* Przycisk koszyka dla części, której nie da się kupić.
   ⛔ WYGLĄDA JAK WYŁĄCZONY, bo jest wyłączony - to `<span>`, nie odnośnik, więc nie ma
   czego kliknąć ani gdzie trafić klawiaturą. Sam wyszarzony wygląd przy działającym
   kliknięciu byłby kłamstwem. */
.pp-akcja .btn-cart.is-blocked {
  background: #e5e7eb;
  border-color: #d1d5db;
  color: #6b7280;
  cursor: not-allowed;
  box-shadow: none;
  /* Napis bywa dłuższy niż „Add to cart" - w jednej linii, bez rozpychania przycisku. */
  white-space: nowrap;
}
.pp-akcja .btn-cart.is-blocked:hover { background: #e5e7eb; border-color: #d1d5db; }

/* Krokowanie ilości nie ma sensu, gdy dodać nie można. `display:none`, nie `visibility`,
   żeby nie zostawiać po nim luki w rzędzie. */
.pp-akcja .stepper.is-hidden { display: none; }

/* ══════════════ UKŁAD C: NAJPIERW DANE ══════════════
   Dane z lewej i na całą szerokość swojej kolumny, kafle z obrazami w wąskiej kolumnie
   obok nich, karta z ceną z prawej. Odwrotność układu A, gdzie obrazy stoją pierwsze.

   Po co: przy częściach zamiennych numer katalogowy i opis niosą więcej niż zdjęcie -
   klient szuka konkretnego numeru, a nie ogląda towaru. Wtedy zdjęcie ma być dostępne,
   ale nie pierwsze.

   ⚠️ Kolejność w znacznikach zostaje bez zmian - przestawia je siatka. Kolejność źródła
   czyta wyszukiwarka i czytnik ekranu. */
@media (min-width: 992px) {
  .pp-uklad-c .pp-pasmo {
    grid-template-columns: minmax(0, 1fr) 200px 380px;
    gap: 24px 26px;
  }

  .pp-uklad-c .pp-toz     { grid-column: 1; grid-row: 1; }
  .pp-uklad-c .pp-obrazy  { grid-column: 2; grid-row: 1; }
  .pp-uklad-c .pp-decyzja { grid-column: 3; grid-row: 1; }

  /* Kafle jeden pod drugim, pełną szerokością swojej wąskiej kolumny. */
  .pp-uklad-c .pp-obrazy {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-flow: row;
    align-content: start;
  }
}

/* ---------- miniatura motocykla na kaflu rysunku ----------
   Rysunek i zdjęcie motocykla pochodzą z tej samej karty. Miniatura tę zależność POKAZUJE,
   zamiast tylko jej pilnować - i oszczędza trzeciego kafla w kolumnie, który nie był
   towarem ani jego położeniem, tylko kontekstem.

   ⚠️ Róg PRZECIWNY do plakietki z numerem (`pp-kafel-nr` siedzi po prawej u góry), żeby
   dwa oznaczenia nie walczyły o to samo miejsce.
   ⛔ Bez podpisu „Fits" - na 46 px podpis zjadłby obraz. Wraca dopiero w powiększeniu. */
.pp-kafel-rys .pp-moto-mini {
  position: absolute;
  left: 8px;
  bottom: 8px;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 2px solid #fff;
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .22);
  cursor: zoom-in;
  transition: transform .12s, box-shadow .12s;
}
.pp-kafel-rys .pp-moto-mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pp-kafel-rys .pp-moto-mini:hover { transform: scale(1.06); box-shadow: 0 2px 8px rgba(0, 0, 0, .3); }
.pp-kafel-rys .pp-moto-mini:focus-visible { outline: 2px solid #127da8; outline-offset: 2px; }

/* Plakietka rodzaju obrazu w powiększeniu - tu jest miejsce, więc podpis wraca. */
.pp-lupa-badge {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 2;
  padding: 3px 9px;
  border-radius: 4px;
  background: rgba(31, 41, 55, .88);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.pp-lupa-badge[hidden] { display: none; }

/* Miniatura motocykla przy pozycji spisu „Pasuje do modeli".
   Sekcja odpowiada na pytanie „do czego to pasuje", a zdjęcie odpowiada na nie szybciej
   niż nazwa - zwłaszcza przy kilkunastu pozycjach, gdzie nazwy różnią się jednym członem.

   ⚠️ `flex: 0 0 auto`, żeby miniatura nie kurczyła się przy długiej nazwie, i stała
   wysokość wiersza - inaczej pozycje ze zdjęciem i bez rozjeżdżałyby rytm listy. */
.pp-fit a { display: flex; align-items: center; gap: 10px; }
.pp-fit-foto {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  object-fit: cover;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  background: #fff;
}
.pp-fit a:hover .pp-fit-foto { border-color: #127da8; }
/* Nazwa bierze resztę wiersza, numer trzyma się prawej krawędzi. */
.pp-fit-nazwa { flex: 1 1 auto; }
