/**
 * PhoenixB2B — PB2B LISTING SYSTEM (v2.10.4) — single source of truth listingu.
 * ======================================================================
 * Jedna, OSTATNIA w kaskadzie warstwa dla CAŁEGO listingu produktów:
 *   - kafelek  (.pb2b-card)            — public/views/partials/product-card.php
 *   - wiersz   (.pb2b-row / .pb2b-list)— public/views/partials/product-row.php
 *   - siatka   (.pb2b-shop-results .pb2b-card-grid)
 *   - przełącznik widoku (.pb2b-shop-view-toggle / .pb2b-shop-view-btn)
 *   - quick view (.pb2b-qv-modal / .pb2b-qv)
 *
 * DLACZEGO TEN PLIK ISTNIEJE
 * Wcześniejsze poprawki dokładały kolejne nakładki (panel-v3-1…-12, shop-v22,
 * product-card), które biły się o ten sam element z `!important`. O wyniku
 * decydowała kolejność ładowania / cache → regresje wracały. Ten plik jest
 * ładowany JAKO OSTATNI w obu kontekstach (publiczny sklep i panel klienta),
 * więc kończy „loterię kaskady”. Kolory wyłącznie z tokenów `--pb2b-card-*`
 * (light + dark) → motyw działa wszędzie, także w modalu quick view, który
 * renderuje się POZA `.phoenix-b2b-panel` (dotąd zawsze biały w dark mode).
 *
 * ZAKRES BEZPIECZEŃSTWA
 *   - ZERO zmian w logice (PHP/JS/ceny/B2B/koszyk). Warstwa wyłącznie wizualna.
 *   - Reguły scoped do elementów listingu/quick view → nie ruszają headera,
 *     dolnej nawigacji, koszyka, checkoutu, dashboardu.
 */

/* ======================================================================
 * 1) TOKENY KART — JEDNO ŹRÓDŁO KOLORÓW (LIGHT = domyślny)
 * ----------------------------------------------------------------------
 * Brief wymaga osobnych zmiennych karty. Definiujemy pełny zestaw
 * `--pb2b-card-*` i NA NIM opieramy wszystko (kafelek, wiersz, modal).
 * Stare `--card-*` (używane przez product-card.css) remapujemy niżej na te
 * tokeny, więc istniejące reguły dalej działają, ale z JEDNEGO źródła.
 * ====================================================================== */
.pb2b-card-grid,
.pb2b-card,
.pb2b-list,
.pb2b-row,
.pb2b-shop-results,
.pb2b-qv-modal {
	--pb2b-card-bg:            #ffffff;
	--pb2b-card-bg-soft:       #f7f7fb;
	--pb2b-card-border:        #e6e6ef;
	--pb2b-card-border-strong: #d7d7e3;
	--pb2b-card-text:          #15151d;
	--pb2b-card-text-soft:     #3a3a48;
	--pb2b-card-muted:         #6b6b7b;
	--pb2b-card-image-bg:      #f4f4f7;
	--pb2b-card-pill-bg:       #f1f1f6;
	--pb2b-card-pill-text:     #3a3a48;
	--pb2b-card-button-bg:     linear-gradient(135deg, #7c3aed, #6d28d9);
	--pb2b-card-button-text:   #ffffff;
	--pb2b-card-ghost-bg:      #ffffff;
	--pb2b-card-ghost-text:    #15151d;
	--pb2b-card-primary:       #7c3aed;
	--pb2b-card-primary-strong:#6d28d9;
	--pb2b-card-primary-soft:  rgba(124, 58, 237, .10);
	--pb2b-card-fav-bg:        rgba(255, 255, 255, .94);
	--pb2b-card-fav-idle:      #9a9aab;
	--pb2b-card-fav-active:    #db2777;
	--pb2b-card-fav-active-bd: #f9a8d4;
	--pb2b-card-ok:            #15803d;
	--pb2b-card-warn:          #b45309;
	--pb2b-card-danger:        #b91c1c;
	--pb2b-card-radius:        18px;
	--pb2b-card-shadow:        0 1px 2px rgba(22, 22, 29, .05), 0 1px 3px rgba(22, 22, 29, .04);
	--pb2b-card-shadow-hover:  0 16px 38px rgba(22, 22, 29, .14), 0 4px 12px rgba(22, 22, 29, .08);
	--pb2b-card-focus:         0 0 0 3px rgba(124, 58, 237, .30);
}

/* ----------------------------------------------------------------------
 * 1a) DARK MODE — sklep standalone + MODAL (poza .phoenix-b2b-panel).
 * Przełącznik motywu (theme-toggle.js + boot w client-panel.php) ustawia
 * data-pb2b-theme="dark" na <html> ORAZ klasę pb2b-theme-dark na <body>,
 * więc modal (dziecko <body>) też dostaje ciemny motyw. To naprawia
 * „biały modal w dark mode”.
 * -------------------------------------------------------------------- */
html[data-pb2b-theme="dark"] .pb2b-card-grid,
html[data-pb2b-theme="dark"] .pb2b-card,
html[data-pb2b-theme="dark"] .pb2b-list,
html[data-pb2b-theme="dark"] .pb2b-row,
html[data-pb2b-theme="dark"] .pb2b-shop-results,
html[data-pb2b-theme="dark"] .pb2b-qv-modal,
body.pb2b-theme-dark .pb2b-card-grid,
body.pb2b-theme-dark .pb2b-card,
body.pb2b-theme-dark .pb2b-list,
body.pb2b-theme-dark .pb2b-row,
body.pb2b-theme-dark .pb2b-shop-results,
body.pb2b-theme-dark .pb2b-qv-modal {
	--pb2b-card-bg:            #111827;
	--pb2b-card-bg-soft:       #151b2e;
	--pb2b-card-border:        rgba(255, 255, 255, .10);
	--pb2b-card-border-strong: rgba(255, 255, 255, .16);
	--pb2b-card-text:          #f5f7fb;
	--pb2b-card-text-soft:     #cbd5e1;
	--pb2b-card-muted:         #94a3b8;
	/* v2.12.9 / ETAP 2 — „płyta” pod zdjęciem produktu w DARK MODE musi być
	   JASNA. Zdjęcia katalogowe to PNG/transparent na bieli; na ciemnym tle
	   (#0e1422) znikały. Jasna płyta pod zdjęciem w dark mode to standardowy,
	   poprawny wzorzec e-commerce. Brief #2/#7: zakaz przyciemniania zdjęć. */
	--pb2b-card-image-bg:      #eef0f4;
	--pb2b-card-pill-bg:       #1b2237;
	--pb2b-card-pill-text:     #cbd5e1;
	--pb2b-card-button-bg:     linear-gradient(135deg, #a855f7, #7c3aed);
	--pb2b-card-button-text:   #ffffff;
	--pb2b-card-ghost-bg:      #151b2e;
	--pb2b-card-ghost-text:    #f5f7fb;
	--pb2b-card-primary:       #a855f7;
	--pb2b-card-primary-strong:#c084fc;
	--pb2b-card-primary-soft:  rgba(168, 85, 247, .18);
	--pb2b-card-fav-bg:        #151b2e;
	--pb2b-card-fav-idle:      #94a3b8;
	--pb2b-card-fav-active:    #f472b6;
	--pb2b-card-fav-active-bd: rgba(244, 114, 182, .55);
	--pb2b-card-ok:            #4ade80;
	--pb2b-card-warn:          #fbbf24;
	--pb2b-card-danger:        #f87171;
	--pb2b-card-shadow:        0 1px 2px rgba(0, 0, 0, .45);
	--pb2b-card-shadow-hover:  0 14px 34px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .35);
}

/* ----------------------------------------------------------------------
 * 1b) PANEL KLIENTA — tokeny karty podążają za motywem panelu (.phoenix-b2b-panel
 * ma data-pb2b-theme i pełny system --pb2b-* w panel-v3-tokens.css). Dzięki
 * temu kafelek/wiersz w panelu są IDENTYCZNE z resztą panelu w light i dark,
 * a sklep B2B i „Sklep w panelu” mają ten sam, jeden system kart.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-card-grid,
.phoenix-b2b-panel .pb2b-card,
.phoenix-b2b-panel .pb2b-list,
.phoenix-b2b-panel .pb2b-row,
.phoenix-b2b-panel .pb2b-shop-results {
	--pb2b-card-bg:            var(--pb2b-bg-2);
	--pb2b-card-bg-soft:       var(--pb2b-bg-3);
	--pb2b-card-border:        var(--pb2b-border);
	--pb2b-card-border-strong: var(--pb2b-border-strong);
	--pb2b-card-text:          var(--pb2b-text);
	--pb2b-card-text-soft:     var(--pb2b-text-soft);
	--pb2b-card-muted:         var(--pb2b-text-muted);
	--pb2b-card-image-bg:      var(--pb2b-bg-3);
	--pb2b-card-pill-bg:       var(--pb2b-bg-3);
	--pb2b-card-pill-text:     var(--pb2b-text-soft);
	--pb2b-card-button-bg:     var(--pb2b-accent-grad);
	--pb2b-card-button-text:   var(--pb2b-primary-contrast);
	--pb2b-card-ghost-bg:      var(--pb2b-bg-2);
	--pb2b-card-ghost-text:    var(--pb2b-text);
	--pb2b-card-primary:       var(--pb2b-primary);
	--pb2b-card-primary-strong:var(--pb2b-primary-strong);
	--pb2b-card-primary-soft:  var(--pb2b-primary-soft);
	--pb2b-card-fav-bg:        var(--pb2b-bg-2);
	--pb2b-card-fav-idle:      var(--pb2b-text-muted);
	--pb2b-card-fav-active:    #ec4899;
	--pb2b-card-fav-active-bd: #f9a8d4;
	--pb2b-card-ok:            var(--pb2b-success-strong);
	--pb2b-card-warn:          var(--pb2b-warning-strong);
	--pb2b-card-danger:        var(--pb2b-danger-strong);
	--pb2b-card-shadow:        var(--pb2b-shadow-sm);
	--pb2b-card-shadow-hover:  var(--pb2b-shadow);
}

/* ----------------------------------------------------------------------
 * 1c) REMAP starych `--card-*` (product-card.css) → `--pb2b-card-*`.
 * Dwie skopione deklaracje (panel 0,2,0 i nie-panel 0,1,0), ładowane JAKO
 * OSTATNIE → wygrywają z definicjami w product-card.css i panel-v3-12.
 * -------------------------------------------------------------------- */
.pb2b-card-grid,
.pb2b-card,
.pb2b-list,
.pb2b-row,
.phoenix-b2b-panel .pb2b-card-grid,
.phoenix-b2b-panel .pb2b-card,
.phoenix-b2b-panel .pb2b-list,
.phoenix-b2b-panel .pb2b-row {
	--card-bg:            var(--pb2b-card-bg);
	--card-border:        var(--pb2b-card-border);
	--card-media-bg:      var(--pb2b-card-image-bg);
	--card-ink:           var(--pb2b-card-text);
	--card-muted:         var(--pb2b-card-muted);
	--card-primary:       var(--pb2b-card-primary);
	--card-primary-2:     var(--pb2b-card-primary-strong);
	--card-shadow:        var(--pb2b-card-shadow);
	--card-shadow-hover:  var(--pb2b-card-shadow-hover);
}

/* ======================================================================
 * 2) KAFELEK — kolory z tokenów + równa wysokość (CTA przyklejone do dołu)
 * ====================================================================== */
.pb2b-card {
	background: var(--pb2b-card-bg);
	border-color: var(--pb2b-card-border);
	box-shadow: var(--pb2b-card-shadow);
	color: var(--pb2b-card-text);
}
.pb2b-card:hover {
	border-color: var(--pb2b-card-primary);
	box-shadow: var(--pb2b-card-shadow-hover);
}
.pb2b-card-image,
.pb2b-card-media { background: var(--pb2b-card-image-bg); }

.pb2b-card-title { color: var(--pb2b-card-text); }
.pb2b-card-title:hover { color: var(--pb2b-card-primary-strong); }
.pb2b-card-sku { color: var(--pb2b-card-muted); }
.pb2b-card-sku span { color: var(--pb2b-card-text-soft); }
.pb2b-card-sku-empty { color: var(--pb2b-card-muted); }
.pb2b-card-pack,
.pb2b-card-price-old { color: var(--pb2b-card-muted); }
.pb2b-card-price-value { color: var(--pb2b-card-text); }
.pb2b-card-price-suffix { color: var(--pb2b-card-muted); }

/* Cena „na zapytanie” / „dostępne po zalogowaniu” — czytelny pill, nigdy puste
   miejsce ani „0 zł”. Stała wysokość → karta się nie rozjeżdża. */
.pb2b-card-price-na,
.pb2b-card-price-locked {
	color: var(--pb2b-card-primary-strong);
	background: var(--pb2b-card-primary-soft);
	border-color: transparent;
}

/* MOQ — zawsze ten sam chip w tym samym miejscu (cena lewo / MOQ prawo). */
.pb2b-card-moq {
	color: var(--pb2b-card-pill-text);
	background: var(--pb2b-card-pill-bg);
	border-color: var(--pb2b-card-border);
}
.pb2b-card-moq strong { color: var(--pb2b-card-primary-strong); }
.pb2b-card-moq-empty {
	color: var(--pb2b-card-muted);
	background: var(--pb2b-card-pill-bg);
	border-color: var(--pb2b-card-border);
}

/* Badge stanu (stock) — tło/obrys z tokenów; semantyka kolorów spójna w dark. */
.pb2b-card-stock {
	background: var(--pb2b-card-bg);
	border-color: var(--pb2b-card-border);
}
.pb2b-card-stock-in   { color: var(--pb2b-card-ok); }
.pb2b-card-stock-low,
.pb2b-card-stock-back { color: var(--pb2b-card-warn); }
.pb2b-card-stock-out  { color: var(--pb2b-card-danger); }

/* ======================================================================
 * 3) WISHLIST / SERDUSZKO — pełna widoczność, dobry kontrast, klik bez linka
 * (media ma overflow:visible w product-card.css; tu domykamy kolory). Serce
 * NIE jest ucięte (z-index nad zdjęciem), tło zależne od motywu, stan
 * aktywny/nieaktywny zawsze czytelny.
 * ====================================================================== */
.pb2b-card-fav,
.pb2b-row-fav {
	background: var(--pb2b-card-fav-bg);
	border-color: var(--pb2b-card-border);
	color: var(--pb2b-card-fav-idle);
}
.pb2b-card-fav:hover,
.pb2b-row-fav:hover { color: var(--pb2b-card-fav-active); border-color: var(--pb2b-card-fav-active-bd); }
.pb2b-card-fav.is-fav,
.pb2b-row-fav.is-fav { color: var(--pb2b-card-fav-active); border-color: var(--pb2b-card-fav-active-bd); }
.pb2b-card-fav .pb2b-card-heart,
.pb2b-row-fav .pb2b-card-heart { pointer-events: none; }   /* klik łapie zawsze przycisk, nie SVG */

/* ======================================================================
 * 4) PRZYCISKI KAFELKA — gwarantowany kontrast w obu motywach.
 * Logika (Do koszyka / Wybierz opcje / Zobacz produkt / Zapytaj o cenę) jest
 * w PHP — tu tylko wygląd. CTA „Do koszyka” = solidny gradient; reszta outline.
 * ====================================================================== */
.pb2b-card-btn-cart,
.pb2b-row-btn-cart {
	background: var(--pb2b-card-button-bg);
	color: var(--pb2b-card-button-text);
	border-color: transparent;
}
.pb2b-card-btn-cart:hover, .pb2b-card-btn-cart:focus,
.pb2b-row-btn-cart:hover, .pb2b-row-btn-cart:focus { color: var(--pb2b-card-button-text); }

.pb2b-card-btn-view,
.pb2b-card-btn-qv,
.pb2b-row-btn-view,
.pb2b-row-qv {
	background: var(--pb2b-card-ghost-bg);
	color: var(--pb2b-card-ghost-text);
	border-color: var(--pb2b-card-border);
}
.pb2b-card-btn-view:hover,
.pb2b-card-btn-qv:hover,
.pb2b-row-btn-view:hover,
.pb2b-row-qv:hover {
	background: var(--pb2b-card-bg-soft);
	color: var(--pb2b-card-primary-strong);
	border-color: var(--pb2b-card-primary);
}
.pb2b-card-btn-options,
.pb2b-row-btn-options {
	background: var(--pb2b-card-primary-soft);
	color: var(--pb2b-card-primary-strong);
	border-color: transparent;
}
.pb2b-card-btn-options:hover,
.pb2b-row-btn-options:hover {
	background: var(--pb2b-card-primary);
	color: var(--pb2b-card-button-text);
	border-color: var(--pb2b-card-primary);
}
.pb2b-card-btn:focus-visible,
.pb2b-row-btn:focus-visible,
.pb2b-row-fav:focus-visible,
.pb2b-row-qv:focus-visible { outline: none; box-shadow: var(--pb2b-card-focus); }

/* ======================================================================
 * 5) WIERSZ LISTY (.pb2b-row) — kolory z tokenów (działa też standalone,
 * gdzie dotąd wiersze bywały przezroczyste). Układ poziomy zostaje z
 * product-card.css; tu wyłącznie motyw.
 * ====================================================================== */
.pb2b-row { background: var(--pb2b-card-bg); border-color: var(--pb2b-card-border); box-shadow: var(--pb2b-card-shadow); color: var(--pb2b-card-text); }
.pb2b-row:hover { border-color: var(--pb2b-card-primary); box-shadow: var(--pb2b-card-shadow-hover); }
.pb2b-row-media { background: var(--pb2b-card-image-bg); }
.pb2b-row-title { color: var(--pb2b-card-text); }
.pb2b-row-title:hover { color: var(--pb2b-card-primary-strong); }
.pb2b-row-sku { color: var(--pb2b-card-muted); }
.pb2b-row-sku span { color: var(--pb2b-card-text); }
.pb2b-row-pack { color: var(--pb2b-card-muted); }
.pb2b-row-fav, .pb2b-row-qv { background: var(--pb2b-card-bg); border-color: var(--pb2b-card-border); color: var(--pb2b-card-muted); }

/* ======================================================================
 * 6) SIATKA WYNIKÓW — DETERMINISTYCZNA DRABINA KOLUMN (koniec konfliktów)
 * ----------------------------------------------------------------------
 * Zakres WYŁĄCZNIE `.pb2b-shop-results .pb2b-card-grid` (siatka wyników
 * sklepu) → NIE rusza siatek widżetów (ostatnio oglądane / najczęściej
 * kupowane / sekcje), które używają samego `.pb2b-card-grid`.
 *
 * STANDALONE (1 sidebar): 2 → 3(≥640) → 4(≥1024) → 5(≥1400).
 * < 360px: 1 kolumna (dopiero gdy 2 się nie mieszczą).
 * Wszystko z minmax(0,1fr) → brak poziomego scrolla, nic się nie ucina.
 * -------------------------------------------------------------------- */
.pb2b-shop-results { min-width: 0; }
.pb2b-shop-results .pb2b-card-grid {
	display: grid !important;
	grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	gap: 12px !important;
	align-items: stretch !important;
}
@media (min-width: 640px) {
	.pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
		gap: 16px !important;
	}
}
@media (min-width: 1024px) {
	.pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
		gap: 18px !important;
	}
}
@media (min-width: 1400px) {
	.pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;  /* PC: 5 w rzędzie */
		gap: 18px !important;
	}
}
@media (max-width: 359px) {
	.pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: 1fr !important;
		gap: 12px !important;
	}
}

/* ----------------------------------------------------------------------
 * 6a) PANEL KLIENTA (2 sidebary: nawigacja 260 + rail filtrów ~224) — drabina
 * przesunięta tak, by „Sklep w panelu” też miał 5 kart w rzędzie na PC.
 *   2 → 3(≥768) → 4(≥1200) → 5(≥1440). < 380px: trzymaj 2.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid {
	grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	gap: 12px !important;
}
@media (min-width: 768px) {
	.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
		gap: 14px !important;
	}
}
@media (min-width: 1200px) {
	.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
		gap: 16px !important;
	}
	/* Węższy rail filtrów daje kartom oddech przy 4–5 kolumnach. */
	.phoenix-b2b-panel .pb2b-shop .pb2b-shop-layout { grid-template-columns: 224px minmax(0, 1fr); }
}
/* UPDATE 1 (P4): próg 5 kolumn obniżony 1440 → 1280px, żeby Sklep B2B w panelu
 * dawał 5 kart także na 1366px i na 1920px @125–150% (CSS ~1280–1536px). */
@media (min-width: 1280px) {
	.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;  /* PC w panelu: 5 w rzędzie */
		gap: 16px !important;
	}
	/* Przy 5 kolumnach rail filtrów odrobinę węższy = karty mają oddech, brak scrolla. */
	.phoenix-b2b-panel .pb2b-shop .pb2b-shop-layout { grid-template-columns: 208px minmax(0, 1fr); }
}
@media (max-width: 380px) {
	.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
		gap: 10px !important;
	}
}

/* ----------------------------------------------------------------------
 * 6b) MOBILE — wymuś JEDNĄ kolumnę layoutu sklepu (filtry = szuflada).
 * BUGFIX v2.10.5 (znalezione w QA): w shop.css reguła
 *   `.pb2b-shop .pb2b-shop-layout { grid-template-columns: 260px 1fr }`
 * jest BAZOWA (poza @media, specyficzność 0-2-0) i nadpisywała mobilne
 *   `@media (max-width:880/900px){ .pb2b-shop-layout { 1fr } }` (0-1-0).
 * Skutek na telefonie: layout trzymał ~260px kolumnę na filtry (które i tak
 * są szufladą off-canvas), a `.pb2b-shop-main` z siatką gniótł się do reszty
 * → „2 kafelki" wychodziły mikroskopijne i rozjechane (zgłaszany chaos na
 * mobile; sprzyjał też mis-tapom otwierającym podstronę zamiast quick-view).
 * Jako OSTATNIA warstwa przywracamy 1 kolumnę do 900px (próg szuflady) —
 * z !important i wyższą specyficznością, więc pokonujemy regułę bazową.
 * -------------------------------------------------------------------- */
@media (max-width: 900px) {
	.pb2b-shop .pb2b-shop-layout,
	.phoenix-b2b-panel .pb2b-shop .pb2b-shop-layout {
		grid-template-columns: 1fr !important;
	}
}

/* ======================================================================
 * 7) PRZEŁĄCZNIK WIDOKU (grid / list) — ZAWSZE WIDOCZNY + mocny stan aktywny
 * ----------------------------------------------------------------------
 * Markup jest w shop.php, logika (localStorage + AJAX) w shop.js. Tu
 * gwarantujemy widoczność (na wypadek starej/zcache'owanej reguły
 * `display:none`) oraz czytelny aktywny stan w obu kontekstach i motywach.
 * -------------------------------------------------------------------- */
.pb2b-shop-view-toggle,
.phoenix-b2b-panel .pb2b-shop-view-toggle {
	display: inline-flex !important;
	visibility: visible !important;
	flex: 0 0 auto;
	align-items: stretch;
	overflow: hidden;
	border: 1px solid var(--pb2b-card-border-strong);
	border-radius: 12px;
	background: var(--pb2b-card-bg);
}
.pb2b-shop-view-btn,
.phoenix-b2b-panel .pb2b-shop-view-btn {
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--pb2b-card-muted);
	cursor: pointer;
	transition: background .15s ease, color .15s ease;
}
.pb2b-shop-view-btn + .pb2b-shop-view-btn,
.phoenix-b2b-panel .pb2b-shop-view-btn + .pb2b-shop-view-btn { border-left: 1px solid var(--pb2b-card-border); }
.pb2b-shop-view-btn:hover,
.phoenix-b2b-panel .pb2b-shop-view-btn:hover { color: var(--pb2b-card-text); background: var(--pb2b-card-bg-soft); }
.pb2b-shop-view-btn.is-active,
.phoenix-b2b-panel .pb2b-shop-view-btn.is-active {
	background: var(--pb2b-card-button-bg);
	color: var(--pb2b-card-button-text);
}
.pb2b-shop-view-btn:focus-visible,
.phoenix-b2b-panel .pb2b-shop-view-btn:focus-visible {
	outline: none;
	box-shadow: var(--pb2b-card-focus);
	position: relative;
	z-index: 1;
}

/* ======================================================================
 * 8) QUICK VIEW — POPUP, NIE PODSTRONA (mobile-safe, dark-safe)
 * ----------------------------------------------------------------------
 * Modal jest dzieckiem <body> (poza .phoenix-b2b-panel), dlatego dotąd był
 * zawsze biały w dark mode i potrafił być wyższy niż ekran. Tu:
 *   - pełny motyw light/dark (tokeny dziedziczone z bloku dark <body>/<html>),
 *   - dialog = kolumna flex; X przyklejony (sticky), treść scrolluje WEWNĄTRZ,
 *   - mobile: bottom-sheet z max-height: calc(100dvh - bezpieczne marginesy),
 *   - zamknięcie X / tło / ESC obsługuje shop.js (body dostaje lock scroll).
 * ====================================================================== */
.pb2b-qv-modal { z-index: 100050; }
.pb2b-qv-overlay { background: rgba(8, 6, 18, .62); }

/* Dialog: NIE scrolluje sam — scrolluje wnętrze, więc X zostaje na miejscu. */
.pb2b-qv-dialog {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--pb2b-card-bg);
	color: var(--pb2b-card-text);
	max-height: calc(100dvh - 48px);
	border: 1px solid var(--pb2b-card-border);
}
.pb2b-qv-modal-content {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
}
.pb2b-qv-close {
	background: var(--pb2b-card-bg) !important;
	color: var(--pb2b-card-text) !important;
	border: 1px solid var(--pb2b-card-border) !important;
}
.pb2b-qv-close:hover { background: var(--pb2b-card-primary) !important; color: #fff !important; }

/* Treść QV — kolory z tokenów (light/dark) zamiast hardkodów. */
.pb2b-qv-media { background: var(--pb2b-card-image-bg); }
.pb2b-qv-title { color: var(--pb2b-card-text); }
.pb2b-qv-meta { color: var(--pb2b-card-muted); }
.pb2b-qv-meta strong,
.pb2b-qv-attr-value,
.pb2b-qv-cats-value { color: var(--pb2b-card-text); }
.pb2b-qv-price-value { color: var(--pb2b-card-text); }
.pb2b-qv-price-old,
.pb2b-qv-price-suffix,
.pb2b-qv-attr-label,
.pb2b-qv-cats,
.pb2b-qv-stock { color: var(--pb2b-card-muted); }
.pb2b-qv-desc { color: var(--pb2b-card-text-soft); }
.pb2b-qv-price-na,
.pb2b-qv-price-locked { color: var(--pb2b-card-primary-strong); background: var(--pb2b-card-primary-soft); border-color: transparent; }
.pb2b-qv-attrs,
.pb2b-qv-variations { border-top-color: var(--pb2b-card-border); }
.pb2b-qv-moq { color: var(--pb2b-card-pill-text); }
.pb2b-qv-moq strong { color: var(--pb2b-card-primary-strong); }

/* Selektory / ilość / miniatury — czytelne pola w obu motywach. */
.pb2b-qv-select,
.pb2b-qv-qty,
.pb2b-qv-thumb {
	background: var(--pb2b-card-bg-soft);
	color: var(--pb2b-card-text);
	border-color: var(--pb2b-card-border);
}
.pb2b-qv-select { color: var(--pb2b-card-text); }
.pb2b-qv-variation-label { color: var(--pb2b-card-muted); }
.pb2b-qv-select-wrap::after { border-color: var(--pb2b-card-muted); }
.pb2b-qv-qty-btn { color: var(--pb2b-card-text); }
.pb2b-qv-qty-btn:hover { background: var(--pb2b-card-primary-soft); color: var(--pb2b-card-primary-strong); }
.pb2b-qv-qty-input { color: var(--pb2b-card-text); border-color: var(--pb2b-card-border); }
.pb2b-qv-badge { background: var(--pb2b-card-text); color: var(--pb2b-card-bg); }

/* Przyciski w modalu. */
.pb2b-qv-btn-cart { background: var(--pb2b-card-button-bg); color: var(--pb2b-card-button-text); }
.pb2b-qv-btn-cart:hover { color: var(--pb2b-card-button-text); }
.pb2b-qv-btn-view,
.pb2b-qv-btn-options { background: var(--pb2b-card-ghost-bg); color: var(--pb2b-card-ghost-text); border-color: var(--pb2b-card-border); }
.pb2b-qv-btn-view:hover,
.pb2b-qv-btn-options:hover { background: var(--pb2b-card-bg-soft); color: var(--pb2b-card-primary-strong); border-color: var(--pb2b-card-primary); }
.pb2b-qv-loading,
.pb2b-qv-empty { color: var(--pb2b-card-muted); }

/* „Zapisz do obejrzenia później” w modalu — czytelny w dark. */
.pb2b-qv-save { background: var(--pb2b-card-bg-soft); color: var(--pb2b-card-muted); border-color: var(--pb2b-card-border); }
.pb2b-qv-save.is-fav { color: var(--pb2b-card-fav-active); border-color: var(--pb2b-card-fav-active-bd); background: var(--pb2b-card-primary-soft); }

/* ----------------------------------------------------------------------
 * 8a) QUICK VIEW — MOBILE: bottom-sheet pełnoekranowy, X zawsze widoczny.
 * -------------------------------------------------------------------- */
@media (max-width: 767px) {
	.pb2b-qv-modal.is-open {
		display: flex;
		align-items: flex-end;        /* arkusz wjeżdża od dołu */
		justify-content: center;
		padding: 0;
	}
	.pb2b-qv-dialog {
		width: 100%;
		max-width: none;
		max-height: calc(100dvh - max(12px, env(safe-area-inset-top)));
		border-radius: 22px 22px 0 0;
		border-bottom: 0;
	}
	/* X przyklejony do górnej krawędzi arkusza (nie ucieka przy scrollu treści). */
	.pb2b-qv-close {
		position: sticky;
		top: 10px;
		left: auto;
		margin: 10px 10px -44px auto;  /* „pływa” nad treścią, nie zajmuje miejsca */
		z-index: 6;
	}
	.pb2b-qv { grid-template-columns: 1fr; }
	.pb2b-qv-info { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
}

/* ======================================================================
 * 9) DEFENSYWA — usuń elementy rozpychające kafelek (kalkulator zysku itp.)
 * gdyby wróciły z innego wywołania karty/quick view.
 * ====================================================================== */
.pb2b-card-calc,
.pb2b-card [data-pb2b-calc],
.pb2b-row [data-pb2b-calc],
.pb2b-card-profit,
.pb2b-card-margin { display: none !important; }

/* ======================================================================
 * 10) LEGACY FALLBACK — gdyby admin wyłączył nowy kafelek (shop_use_new_card
 * = 'no'), stary `.pb2b-shop-card` przynajmniej nie świeci białym tłem w dark
 * mode (spójność motywu). Nowy kafelek pozostaje domyślny i zalecany.
 * ====================================================================== */
html[data-pb2b-theme="dark"] .pb2b-shop-card,
body.pb2b-theme-dark .pb2b-shop-card,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-card {
	background: var(--pb2b-bg-2, #111827);
	border-color: var(--pb2b-border, rgba(255,255,255,.10));
	color: var(--pb2b-text, #f5f7fb);
}

/* ======================================================================
 * 11) v2.10.6 — MOQ ZAWSZE POD CENĄ (brief D) + finalizacja rytmu kafelka.
 * ----------------------------------------------------------------------
 * DLACZEGO: product-card.css układał `.pb2b-card-pricing` POZIOMO
 * (display:flex; justify-content:space-between) z MOQ po prawej, a w
 * `.pb2b-shop-results` dokładał `margin-left:auto` na MOQ. Efekt: „latające"
 * MOQ obok ceny / przyklejone do prawej krawędzi / w połowie pustej karty.
 * Brief wymaga: cena (lub „Zapytaj o cenę" / „Dostępne po zalogowaniu"),
 * a BEZPOŚREDNIO POD nią MOQ. Ta warstwa ładuje się PO product-card.css i
 * panel-v3-12 (ta sama specyficzność, późniejszy load → wygrywa) i wymusza
 * pionowy stack. Markup BEZ zmian — MOQ jest już osobnym elementem w
 * `.pb2b-card-pricing`, więc samo przestawienie osi załatwia sprawę.
 * ====================================================================== */
.pb2b-card .pb2b-card-pricing,
.pb2b-card-grid .pb2b-card-pricing,
.pb2b-shop-results .pb2b-card-pricing,
.phoenix-b2b-panel .pb2b-card-grid .pb2b-card-pricing,
.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-pricing {
	display: flex;
	flex-direction: column;      /* cena na górze, MOQ pod spodem */
	align-items: flex-start;     /* chip MOQ przy lewej, nierozciągnięty  */
	justify-content: flex-start;
	gap: 6px;
	flex-wrap: nowrap;
}
/* Reset starego „MOQ do prawej" (shop-results / grid). */
.pb2b-shop-results .pb2b-card-moq,
.pb2b-card-grid .pb2b-card-moq,
.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-moq { margin-left: 0; }
/* Cena / status zajmują własny wiersz; MOQ trafia w nowy, niżej. */
.pb2b-card .pb2b-card-price,
.pb2b-card .pb2b-card-price-na,
.pb2b-card .pb2b-card-price-locked { width: auto; max-width: 100%; }
.pb2b-card .pb2b-card-price-old { width: 100%; }
.pb2b-card .pb2b-card-moq { margin: 0; align-self: flex-start; }

/* ======================================================================
 * 12) v2.10.6 — POZIOMY SLIDER PRODUKTÓW (brief H) — „jak Allegro".
 * ----------------------------------------------------------------------
 * Sekcje rekomendacji: „Podobne produkty" + „Polecane produkty hurtowe" na
 * karcie produktu (.pb2b-rail) oraz „Ostatnio oglądane" / „Najczęściej
 * kupowane" w panelu (.pb2b-recent / .pb2b-most-purchased) przestają być
 * pionową siatką, a stają się poziomym scroll-snapem zbudowanym z TYCH
 * SAMYCH finalnych kafli `.pb2b-card`. Scroll jest WEWNĄTRZ siatki (overflow
 * na samym .pb2b-card-grid) → cała strona NIE dostaje poziomego paska.
 *   mobile: ~2 kafle + zajawka 3-go; tablet: ~3 + zajawka; PC: ~5 widocznych.
 * ZAKRES: wyłącznie te sekcje. Główny grid sklepu (.pb2b-shop-results
 * .pb2b-card-grid) pozostaje deterministyczną siatką z sekcji 6 — NIETKNIĘTY.
 * ====================================================================== */
.pb2b-rail .pb2b-card-grid,
.pb2b-recent .pb2b-card-grid,
.pb2b-most-purchased .pb2b-card-grid {
	display: flex !important;            /* bije bazowy display:grid kafli */
	grid-template-columns: none !important;
	flex-wrap: nowrap !important;
	gap: 12px !important;
	min-width: 0;
	margin: 0;
	padding: 4px 2px 14px;               /* dół: miejsce na cień karty + pasek */
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scroll-padding-left: 2px;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-x: contain;
	scrollbar-width: thin;
	scrollbar-color: var(--pb2b-card-border-strong) transparent;
}
.pb2b-rail .pb2b-card-grid > .pb2b-card,
.pb2b-recent .pb2b-card-grid > .pb2b-card,
.pb2b-most-purchased .pb2b-card-grid > .pb2b-card {
	scroll-snap-align: start;
	flex: 0 0 auto;
	/* v2.12.2 — 2 PEŁNE kafle na mobile (koniec „zajawki 3-go" + ściśniętych
	   kart z połamanymi przyciskami). */
	width: calc((100% - 12px) / 2);
	min-width: 150px;
	max-width: 320px;
	margin: 0;
}
@media (min-width: 641px) {
	.pb2b-rail .pb2b-card-grid > .pb2b-card,
	.pb2b-recent .pb2b-card-grid > .pb2b-card,
	.pb2b-most-purchased .pb2b-card-grid > .pb2b-card { width: calc((100% - 24px) / 3); }    /* 3 pełne */
}
@media (min-width: 1024px) {
	.pb2b-rail .pb2b-card-grid > .pb2b-card,
	.pb2b-recent .pb2b-card-grid > .pb2b-card,
	.pb2b-most-purchased .pb2b-card-grid > .pb2b-card { width: calc((100% - 48px) / 5); }    /* PC: 5 pełnych */
}
/* Pasek przewijania raila — subtelny, ale WIDOCZNY (oba motywy z tokenów). */
.pb2b-rail .pb2b-card-grid::-webkit-scrollbar,
.pb2b-recent .pb2b-card-grid::-webkit-scrollbar,
.pb2b-most-purchased .pb2b-card-grid::-webkit-scrollbar { height: 8px; }
.pb2b-rail .pb2b-card-grid::-webkit-scrollbar-track,
.pb2b-recent .pb2b-card-grid::-webkit-scrollbar-track,
.pb2b-most-purchased .pb2b-card-grid::-webkit-scrollbar-track { background: transparent; }
.pb2b-rail .pb2b-card-grid::-webkit-scrollbar-thumb,
.pb2b-recent .pb2b-card-grid::-webkit-scrollbar-thumb,
.pb2b-most-purchased .pb2b-card-grid::-webkit-scrollbar-thumb { background: var(--pb2b-card-border-strong); border-radius: 999px; }
/* Sekcja raila nie rozpycha strony w poziomie (scroll tylko w torze). */
.pb2b-rail,
.pb2b-recent,
.pb2b-most-purchased { min-width: 0; max-width: 100%; }

/* ======================================================================
 * 13) v2.10.7 — KANONICZNA WARSTWA TOKENÓW KARTY (nazwy z briefu #4).
 * ----------------------------------------------------------------------
 * Brief wymaga DOKŁADNIE tych nazw zmiennych. Definiujemy je jako aliasy
 * istniejącego, sprawdzonego systemu `--pb2b-card-*` (light/dark/panel
 * ustawiany w sekcjach 1/1a/1b). Dzięki temu:
 *   - panel-v3.css (po poprawce v2.10.7) może je czytać: kafelek w panelu
 *     bierze tło/obrys/tekst z tej JEDNEJ warstwy,
 *   - kolory są spójne w Sklepie B2B, panelu, quick view i railach,
 *   - alias dziedziczy kontekst (dark/panel) bo `--pb2b-card-*` jest już
 *     nadpisane per-kontekst wyżej (custom property = leniwa ewaluacja).
 * To jest „jedno źródło prawdy" kolorów karty wymagane przez brief.
 * ====================================================================== */
.pb2b-card-grid,
.pb2b-card,
.pb2b-list,
.pb2b-row,
.pb2b-shop-results,
.pb2b-qv-modal,
.phoenix-b2b-panel .pb2b-card-grid,
.phoenix-b2b-panel .pb2b-card,
.phoenix-b2b-panel .pb2b-list,
.phoenix-b2b-panel .pb2b-row {
	--pb2b-product-card-bg:         var(--pb2b-card-bg);
	--pb2b-product-card-border:     var(--pb2b-card-border);
	--pb2b-product-card-text:       var(--pb2b-card-text);
	--pb2b-product-card-muted:      var(--pb2b-card-muted);
	--pb2b-product-card-price:      var(--pb2b-card-text);
	--pb2b-product-card-sku:        var(--pb2b-card-muted);
	--pb2b-product-card-image-bg:   var(--pb2b-card-image-bg);
	--pb2b-product-card-cta-bg:     var(--pb2b-card-button-bg);
	--pb2b-product-card-cta-text:   var(--pb2b-card-button-text);
	--pb2b-product-card-icon-bg:    var(--pb2b-card-fav-bg);
	--pb2b-product-card-icon-text:  var(--pb2b-card-muted);
	--pb2b-product-card-moq-bg:     var(--pb2b-card-pill-bg);
	--pb2b-product-card-moq-text:   var(--pb2b-card-pill-text);
}

/* ----------------------------------------------------------------------
 * 13a) EGZEKWOWANIE POWIERZCHNI KARTY — warstwa ładowana JAKO OSTATNIA.
 * To „pas + szelki": nawet gdyby jakaś przyszła reguła próbowała zabielić
 * kartę, ta warstwa (z tokenów, więc i tak poprawna w dark) trzyma spójny
 * wygląd. W panelu reguła (0,3,0) z panel-v3.css jest już naprawiona na
 * tokeny; tutaj pilnujemy sklepu standalone i modalu quick view.
 * -------------------------------------------------------------------- */
.pb2b-card {
	background: var(--pb2b-product-card-bg) !important;
	border-color: var(--pb2b-product-card-border) !important;
}
.pb2b-card .pb2b-card-title { color: var(--pb2b-product-card-text); }
.pb2b-card .pb2b-card-sku { color: var(--pb2b-product-card-sku); }
.pb2b-card .pb2b-card-price-value { color: var(--pb2b-product-card-price); }
/* WooCommerce wstrzykuje własny <span class="amount"> z kolorem motywu —
 * wymuszamy dziedziczenie, żeby cena była widoczna w dark mode. */
.pb2b-card .pb2b-card-price-value .woocommerce-Price-amount,
.pb2b-card .pb2b-card-price-value .amount,
.pb2b-card .pb2b-card-price-value bdi,
.pb2b-card .pb2b-card-price .woocommerce-Price-amount,
.pb2b-card .pb2b-card-price .amount { color: inherit !important; }

/* ======================================================================
 * 14) v2.10.7 — SKLEP STANDALONE /sklep W DARK MODE (poza panelem).
 * ----------------------------------------------------------------------
 * shop.css remapuje --s-* na --pb2b-* TYLKO pod `.phoenix-b2b-panel`.
 * Na samodzielnej stronie /sklep panel-tokenów nie ma w ogóle, więc
 * powłoka sklepu (toolbar, pola, przyciski widoku) zostawała biała mimo
 * data-pb2b-theme="dark". Tutaj nadajemy --s-* WARTOŚCIAMI WPROST
 * (spójnymi z paletą kart z sekcji 1a), aktywowane motywem na <html>/<body>
 * przez boot w szablonie b2b-shop-page.php. Zakres: tylko `.pb2b-shop`.
 * ====================================================================== */
html[data-pb2b-theme="dark"] .pb2b-shop,
body.pb2b-theme-dark .pb2b-shop {
	--s-bg:            #111827;
	--s-bg-2:          #151b2e;
	--s-bg-3:          #1b2237;
	--s-text:          #f5f7fb;
	--s-text-soft:     #cbd5e1;
	--s-muted:         #94a3b8;
	--s-border:        rgba(255, 255, 255, .10);
	--s-border-strong: rgba(255, 255, 255, .16);
	--s-primary:       #a855f7;
	--s-primary-ink:   #ffffff;
	--s-success:       #4ade80;
	--s-warning:       #fbbf24;
	--s-danger:        #f87171;
	--s-shadow:        0 1px 2px rgba(0, 0, 0, .45);
	--s-shadow-lg:     0 14px 34px rgba(0, 0, 0, .45);
}
/* Tło całej powłoki sklepu w dark (żeby nie prześwitywał biały motyw). */
html[data-pb2b-theme="dark"] .pb2b-shop-shell,
body.pb2b-theme-dark .pb2b-shop-shell { background: var(--s-bg); color: var(--s-text); }

/* ======================================================================
 * 15) v2.10.7 — ALIASY KLAS RAILA Z BRIEFU (#7).
 * Brief prosi o nazwy .pb2b-product-rail / -track / -card. Mapujemy je na
 * zachowanie raila z sekcji 12, żeby działały gdy markup ich użyje.
 * ====================================================================== */
.pb2b-product-rail { min-width: 0; max-width: 100%; }
.pb2b-product-rail .pb2b-product-rail-track,
.pb2b-product-rail-track {
	display: flex; flex-wrap: nowrap; gap: 12px;
	overflow-x: auto; overflow-y: hidden;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-x: contain;
	padding: 4px 2px 14px; margin: 0;
	scrollbar-width: thin;
	scrollbar-color: var(--pb2b-card-border-strong) transparent;
}
.pb2b-product-rail-track > .pb2b-card,
.pb2b-product-rail-track > .pb2b-product-rail-card {
	scroll-snap-align: start; flex: 0 0 auto;
	/* v2.12.2 — 2 PEŁNE kafle na mobile (spójnie z pozostałymi railami). */
	width: calc((100% - 12px) / 2); min-width: 150px; max-width: 320px; margin: 0;
}
@media (min-width: 641px) {
	.pb2b-product-rail-track > .pb2b-card,
	.pb2b-product-rail-track > .pb2b-product-rail-card { width: calc((100% - 24px) / 3); }
}
@media (min-width: 1024px) {
	.pb2b-product-rail-track > .pb2b-card,
	.pb2b-product-rail-track > .pb2b-product-rail-card { width: calc((100% - 48px) / 5); }
}

/* ======================================================================
 * 16) v2.10.7 — CHROME SKLEPU W DARK MODE (powłoka, nie kafle).
 * ----------------------------------------------------------------------
 * shop.css i jego sekcja „premium" (.pb2b-shop ...) koduje WPROST #fff /
 * #16161d / #e8e8ef dla: pola wyszukiwania, selecta sortowania, przycisku
 * Filtry, panelu/arkusza filtrów, nagłówka filtrów, licznika. W dark mode
 * dawało to białe pola i biały arkusz filtrów (zarówno standalone /sklep,
 * jak i w panelu — bo panelowe override'y ustawiają tylko layout, nie tło).
 * Tu nadpisujemy WYŁĄCZNIE kolory i WYŁĄCZNIE w dark (gate na <html>/<body>),
 * z tokenów --s-* (sekcja 14 = standalone dark; shop.css = panel dark).
 * Specyficzność (0,3,1) > (0,2,0) → wygrywa bez !important; light NIETKNIĘTY.
 * ====================================================================== */
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-search-input,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-search-input,
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-orderby,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-orderby,
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-filter-toggle,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-filter-toggle {
	background-color: var(--s-bg);
	color: var(--s-text);
	border-color: var(--s-border-strong);
}
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-search-input::placeholder,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-search-input::placeholder { color: var(--s-muted); }

html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-filters,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-filters {
	background: var(--s-bg);
	border-color: var(--s-border);
}
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-filters-head,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-filters-head {
	color: var(--s-text);
	border-bottom-color: var(--s-border);
}
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-filter-label,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-filter-label,
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-count,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-count { color: var(--s-muted); }

/* Arkusz filtrów (mobile bottom-sheet) i overlay — czytelne w dark. */
html[data-pb2b-theme="dark"] .pb2b-shop .pb2b-shop-filters-apply,
body.pb2b-theme-dark   .pb2b-shop .pb2b-shop-filters-apply { background: var(--s-bg-2); }

/* ======================================================================
 * 17) v2.10.8 — QC FIX: PANEL PRODUCT VIEW (sekcja-product) = SLIDER.
 * ----------------------------------------------------------------------
 * Widok produktu w panelu (sections/section-product.php) renderuje
 * „Podobne/Polecane" w `.pb2b-pview-related`, które panel-v3-5.css ustawiał
 * jako PIONOWĄ siatkę (repeat(4,...)). Brief #7 wymaga POZIOMEGO slidera
 * wszędzie — tu doprowadzamy panelowy widok produktu do tego samego raila
 * (te same kafle, ten sam scroll-snap). `!important` bije (0,3,0) z v3-5.
 * ====================================================================== */
.pb2b-pview-related .pb2b-card-grid {
	display: flex !important;
	grid-template-columns: none !important;
	flex-wrap: nowrap !important;
	gap: 12px !important;
	min-width: 0;
	margin: 0;
	padding: 4px 2px 14px;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-x: contain;
	scrollbar-width: thin;
	scrollbar-color: var(--pb2b-card-border-strong) transparent;
}
.pb2b-pview-related .pb2b-card-grid > .pb2b-card {
	scroll-snap-align: start;
	flex: 0 0 auto;
	/* v2.12.2 — KONIEC „wystającego trzeciego kafelka": 43% dawało ~2,3 kafla
	   (dwa ściśnięte + wystający trzeci, który łamał przyciski). Teraz 2 PEŁNE
	   kafle na mobile z czystym snapem. */
	width: calc((100% - 12px) / 2);
	min-width: 150px;
	max-width: 320px;
	margin: 0;
}
@media (min-width: 641px) {
	.pb2b-pview-related .pb2b-card-grid > .pb2b-card { width: calc((100% - 24px) / 3); } /* 3 pełne */
}
@media (min-width: 1024px) {
	.pb2b-pview-related .pb2b-card-grid > .pb2b-card { width: calc((100% - 48px) / 5); } /* 5 pełnych */
}
.pb2b-pview-related .pb2b-card-grid::-webkit-scrollbar { height: 8px; }
.pb2b-pview-related .pb2b-card-grid::-webkit-scrollbar-track { background: transparent; }
.pb2b-pview-related .pb2b-card-grid::-webkit-scrollbar-thumb { background: var(--pb2b-card-border-strong); border-radius: 999px; }
.pb2b-pview-related { min-width: 0; max-width: 100%; }

/* ======================================================================
 * 18) v2.11.1 — STEPPER ILOŚCI W WIDOKU LISTY (.pb2b-row-qty)
 * ----------------------------------------------------------------------
 * Brief #2: „ilość +/– jeśli zalogowany i można kupić”. Stepper renderuje
 * product-row.php (tylko gdy can_buy), obsługę robi shop.js. Tu wyłącznie
 * wygląd — z tokenów karty, więc poprawny w light i dark, standalone i panel.
 * ====================================================================== */
.pb2b-row-qty {
	display: inline-flex;
	align-items: stretch;
	flex: 0 0 auto;
	border: 1px solid var(--pb2b-card-border-strong);
	border-radius: 10px;
	overflow: hidden;
	background: var(--pb2b-card-bg);
}
.pb2b-row-qty-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	min-height: 38px;
	padding: 0;
	border: 0;
	background: var(--pb2b-card-bg);
	color: var(--pb2b-card-text);
	cursor: pointer;
	transition: background .15s ease, color .15s ease;
}
.pb2b-row-qty-btn:hover { background: var(--pb2b-card-primary-soft); color: var(--pb2b-card-primary-strong); }
.pb2b-row-qty-input {
	width: 44px;
	min-width: 0;
	border: 0;
	border-left: 1px solid var(--pb2b-card-border);
	border-right: 1px solid var(--pb2b-card-border);
	background: var(--pb2b-card-bg);
	color: var(--pb2b-card-text);
	text-align: center;
	font-size: 14px;
	font-weight: 600;
	-moz-appearance: textfield;
	appearance: textfield;
}
.pb2b-row-qty-input::-webkit-outer-spin-button,
.pb2b-row-qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pb2b-row-qty-input:focus-visible { outline: none; box-shadow: var(--pb2b-card-focus); position: relative; z-index: 1; }
.pb2b-row-actions { flex-wrap: wrap; row-gap: 8px; }
@media (max-width: 560px) {
	/* Na mobile stepper + CTA dzielą pełną szerokość wiersza akcji. */
	.pb2b-row-qty { flex: 0 0 auto; }
	.pb2b-row-actions .pb2b-row-btn-cart { flex: 1 1 120px; }
}

/* ======================================================================
 * 19) v2.11.1 — MODAL WYBORU KATEGORII (.pb2b-catpick) — CZYTELNY W DARK/LIGHT
 * ----------------------------------------------------------------------
 * ROOT CAUSE (potwierdzone w QA): panel-v3-5.js dopina picker do <body>
 *   document.body.appendChild(wrap)  →  .pb2b-catpick jest POZA .phoenix-b2b-panel,
 * a panel-v3-5.css koduje jego tło/tekst tokenami --pb2b-bg-*/--pb2b-text/…,
 * które istnieją WYŁĄCZNIE w .phoenix-b2b-panel (panel-v3-tokens.css). Poza
 * panelem te zmienne są NIEZDEFINIOWANE → `background: var(--pb2b-bg-1)` bez
 * wartości = brak tła → „modal przezroczysty, tekst miesza się z tłem,
 * przyciski Wszystkie/Zastosuj nieczytelne”. Identyczny mechanizm jak przy
 * modalu quick-view (rozwiązany w sekcji 1a/8).
 *
 * FIX: definiujemy komplet tokenów WPROST na .pb2b-catpick (light = domyślny)
 * + pełny override dla dark (gate na <html>/<body>, które boot panelu ustawia
 * niezależnie od .phoenix-b2b-panel). Wartości 1:1 z panel-v3-tokens.css, więc
 * picker wygląda identycznie jak panel. Markup i logika BEZ zmian.
 * ====================================================================== */
.pb2b-catpick {
	--pb2b-bg-0:           #EEF1F8;
	--pb2b-bg-1:           #FFFFFF;
	--pb2b-bg-2:           #FFFFFF;
	--pb2b-bg-3:           #F1F4FB;
	--pb2b-bg-4:           #E7ECF7;
	--pb2b-text:           #0F172A;
	--pb2b-text-strong:    #0B1220;
	--pb2b-text-soft:      #334155;
	--pb2b-text-muted:     #475569;
	--pb2b-border:         rgba(15, 23, 42, 0.10);
	--pb2b-border-strong:  rgba(15, 23, 42, 0.20);
	--pb2b-primary:        #7C3AED;
	--pb2b-primary-strong: #6D28D9;
	--pb2b-primary-soft:   rgba(124, 58, 237, 0.10);
	--pb2b-primary-contrast: #FFFFFF;
	--pb2b-accent-grad:    linear-gradient(135deg, #A855F7 0%, #7C3AED 50%, #3B82F6 100%);
	--pb2b-radius-sm:      10px;
	--pb2b-shadow-focus:   0 0 0 4px rgba(124, 58, 237, 0.16);
}
html[data-pb2b-theme="dark"] .pb2b-catpick,
body.pb2b-theme-dark .pb2b-catpick {
	--pb2b-bg-0:           #070B18;
	--pb2b-bg-1:           #0B1020;
	--pb2b-bg-2:           #111827;
	--pb2b-bg-3:           #151B2E;
	--pb2b-bg-4:           #1B2237;
	--pb2b-text:           #F8FAFC;
	--pb2b-text-strong:    #FFFFFF;
	--pb2b-text-soft:      #CBD5E1;
	--pb2b-text-muted:     #94A3B8;
	--pb2b-border:         rgba(255, 255, 255, 0.08);
	--pb2b-border-strong:  rgba(255, 255, 255, 0.14);
	--pb2b-primary:        #A855F7;
	--pb2b-primary-strong: #C084FC;
	--pb2b-primary-soft:   rgba(168, 85, 247, 0.18);
	--pb2b-primary-contrast: #FFFFFF;
	--pb2b-shadow-focus:   0 0 0 4px rgba(124, 58, 237, 0.18);
}
/* Pas + szelki: nawet bez tokenów sheet i pozycje mają solidne, nieprzezroczyste
 * tło (fallback wartością wprost), więc tekst nigdy nie zlewa się z tłem. */
.pb2b-catpick-sheet { background: var(--pb2b-bg-1, #fff); }
.pb2b-catpick-item  { background: var(--pb2b-bg-2, #fff); }
html[data-pb2b-theme="dark"] .pb2b-catpick-sheet,
body.pb2b-theme-dark .pb2b-catpick-sheet { background: var(--pb2b-bg-1, #0B1020); }
html[data-pb2b-theme="dark"] .pb2b-catpick-item,
body.pb2b-theme-dark .pb2b-catpick-item { background: var(--pb2b-bg-2, #111827); }

/* ======================================================================
 * 20) v2.11.1 — TWARDA WIDOCZNOŚĆ CENY / SKU / ETYKIET (anty „niewidoczny tekst”)
 * ----------------------------------------------------------------------
 * Brief #8 zabrania: „cena niewidoczna / SKU niewidoczne / placeholder
 * niewidoczny”. Motyw sklepu (WooCommerce/theme) potrafi nadać .amount własny
 * kolor (czasem biały) z wyższą wagą. Domykamy to tokenem karty z !important —
 * cena, SKU i sufiks są ZAWSZE czytelne na tle karty, w obu motywach.
 * ====================================================================== */
.pb2b-card .pb2b-card-price-value,
.pb2b-card .pb2b-card-price-value bdi,
.pb2b-card .pb2b-card-price-value .amount,
.pb2b-card .pb2b-card-price-value .woocommerce-Price-amount,
.pb2b-row .pb2b-card-price-value,
.pb2b-row .pb2b-card-price-value bdi,
.pb2b-row .pb2b-card-price-value .amount,
.pb2b-qv .pb2b-qv-price-value,
.pb2b-qv .pb2b-qv-price-value bdi,
.pb2b-qv .pb2b-qv-price-value .amount { color: var(--pb2b-card-text) !important; }
.pb2b-card .pb2b-card-sku span,
.pb2b-row .pb2b-row-sku span { color: var(--pb2b-card-text-soft); }
.pb2b-card .pb2b-card-price-suffix,
.pb2b-row .pb2b-card-price-suffix { color: var(--pb2b-card-muted); }
/* Placeholder pól sklepu — nigdy „niewidoczny” (kontrast z muted tokenem). */
.pb2b-shop .pb2b-shop-search-input::placeholder,
.pb2b-shop .pb2b-shop-input::placeholder { color: var(--pb2b-card-muted); opacity: 1; }

/* ======================================================================
 * 21) ETAP 2 (v2.12.9) — REMEDIACJA WYGLĄDU PANELU KLIENTA
 * ----------------------------------------------------------------------
 * Ta warstwa jest CELOWO na końcu pliku, który w panelu i w sklepie ładuje
 * się JAKO OSTATNI (po frontend.css, panel-bundle.css, shop*.css,
 * product-card.css i całym łańcuchu panel-v3*). Dzięki temu poprawki realnie
 * docierają do przeglądarki i wygrywają kaskadę bez dodatkowego pliku i bez
 * zmian w enqueue (zero regresji wydajności).
 *
 * Zakres = WYŁĄCZNIE warstwa wizualna panelu klienta (.phoenix-b2b-panel):
 * kafelki, dashboard, podobne/polecane, ostatnio oglądane, najczęściej
 * kupowane, katalog/szybkie zamówienia (compact), mobile/PWA, kosmetyka CSV.
 * Logika (koszyk, listy, wiadomości, REST, cache, PWA, Action Scheduler) —
 * NIETKNIĘTA. Wzorcem jakościowym jest kafelek „Sklep B2B”.
 * ====================================================================== */

/* ----------------------------------------------------------------------
 * 21.1) ZDJĘCIE PRODUKTU WIDOCZNE W DARK MODE (brief #2/#7, najwyższy prio)
 * Token --pb2b-card-image-bg jest jedynym źródłem tła płyty pod zdjęciem
 * (.pb2b-card-media / .pb2b-row-media / .pb2b-qv-media / product-card). W
 * panelu w dark mode wygrywał ciemny token (var(--pb2b-bg-3) / #0e1422) i
 * zdjęcia znikały. Wymuszamy JASNĄ płytę w panelu w dark mode — wyższą
 * specyficznością i późniejszą kolejnością niż bloki z sekcji 1/1a/1b.
 * Zakaz z briefu: żadnego filter / opacity / overlay / mix-blend-mode na
 * samym zdjęciu — egzekwujemy reset, gdyby motyw je nałożył.
 * -------------------------------------------------------------------- */
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-card,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-card-grid,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-list,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-row,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-results,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-card,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-card-grid,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-list,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-row,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-results,
body.pb2b-theme-dark .phoenix-b2b-panel .pb2b-card,
body.pb2b-theme-dark .phoenix-b2b-panel .pb2b-card-grid,
body.pb2b-theme-dark .phoenix-b2b-panel .pb2b-list,
body.pb2b-theme-dark .phoenix-b2b-panel .pb2b-row,
body.pb2b-theme-dark .phoenix-b2b-panel .pb2b-shop-results {
	--pb2b-card-image-bg: #eef0f4;
}
/* Twarda płyta na samych mediach + reset ewentualnego przyciemnienia zdjęcia. */
.phoenix-b2b-panel .pb2b-card-media,
.phoenix-b2b-panel .pb2b-row-media,
.phoenix-b2b-panel .pb2b-qv-media { background: var(--pb2b-card-image-bg); }
.phoenix-b2b-panel .pb2b-card-image img,
.phoenix-b2b-panel .pb2b-card-media img,
.phoenix-b2b-panel .pb2b-row-media img,
.phoenix-b2b-panel .pb2b-qv-media img {
	filter: none !important;
	opacity: 1 !important;
	mix-blend-mode: normal !important;
}

/* ----------------------------------------------------------------------
 * 21.2) SERDUSZKO NIGDY UCIĘTE (brief #2/#8)
 * .pb2b-card ma overflow:hidden (zaokrąglenie rogów), więc media MUSI mieć
 * overflow:visible, a serce bezpieczny inset wewnątrz marginesu media —
 * także w wariancie compact (raile/related na mobile).
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-card-media { overflow: visible; }
.phoenix-b2b-panel .pb2b-card-fav {
	width: 36px; height: 36px;
	top: 10px; right: 10px;
	z-index: 3;
}
.phoenix-b2b-panel .pb2b-card-fav .pb2b-card-heart { width: 18px; height: 18px; }
@media (max-width: 719px) {
	.phoenix-b2b-panel .pb2b-card-fav { width: 32px; height: 32px; top: 8px; right: 8px; }
	.phoenix-b2b-panel .pb2b-card-fav .pb2b-card-heart { width: 16px; height: 16px; }
}

/* ----------------------------------------------------------------------
 * 21.3) CTA — TEKST NIGDY UCIĘTY („Do koszy…”), PRZYCISKI NIE ŁAMIĄ LAYOUTU
 * (brief #2/#4). Bazowo product-card.css zaciska span (white-space:nowrap +
 * text-overflow:ellipsis) → „Dodaj/Do koszyka” skracało się do „Do koszy…”
 * tam, gdzie kafelek nie był w .pb2b-shop-results (raile, dashboard,
 * podobne). Odcinamy zacisk: etykieta może zawinąć się czysto do 2 linii,
 * ale NIGDY nie jest ucinana wielokropkiem.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-card-btn > span,
.phoenix-b2b-panel .pb2b-card-btn-cart > span,
.phoenix-b2b-panel .pb2b-card-btn-qv-text {
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
	min-width: 0;
	line-height: 1.15;
}
/* Model „Sklep B2B” daje przyciskowi głównemu miejsce: rząd akcji to flex,
   przycisk główny rośnie, a „Podgląd” na desktopie zwija się do samej ikony.
   Przenosimy ten sam mechanizm na WSZYSTKIE pełne kafle panelu (parytet). */
.phoenix-b2b-panel .pb2b-card-actions-row {
	display: flex;
	gap: 8px;
	align-items: stretch;
}
.phoenix-b2b-panel .pb2b-card-actions-row > .pb2b-card-btn:first-child { flex: 1 1 auto; }
.phoenix-b2b-panel .pb2b-card-btn,
.phoenix-b2b-panel .pb2b-card-btn-cart,
.phoenix-b2b-panel .pb2b-card-btn-view,
.phoenix-b2b-panel .pb2b-card-btn-options {
	height: auto;
	min-height: 40px;       /* 2 linie etykiety nigdy nie są przycięte */
	min-width: 0;
}
@media (min-width: 1080px) {
	/* Gęsta siatka / raile na PC: „Podgląd” jako sama ikona oka → więcej
	   miejsca na CTA, etykieta „Do koszyka” mieści się w jednej linii. */
	.phoenix-b2b-panel .pb2b-card-btn-qv { width: 40px; flex: 0 0 40px; padding: 0; }
	.phoenix-b2b-panel .pb2b-card-btn-qv .pb2b-card-btn-qv-text { display: none; }
}

/* ----------------------------------------------------------------------
 * 21.4) CENA + MOQ ZAWSZE W TYM SAMYM MIEJSCU (brief #2/#3)
 * Wzór „Sklep B2B”: cena po lewej, MOQ jako chip dosunięty do prawej,
 * stała min-wysokość rzędu. Doprowadzamy do tego raile/podobne/dashboard,
 * które bez tego miały MOQ raz obok, raz pod ceną.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-card .pb2b-card-pricing {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px 10px;
	flex-wrap: wrap;
	min-height: 36px;
	padding-top: 6px;
}
.phoenix-b2b-panel .pb2b-card .pb2b-card-moq { margin-left: auto; }

/* ----------------------------------------------------------------------
 * 21.5) PODOBNE/POLECANE NA PRODUKCIE — 2 PEŁNE KAFLE + SNAP (brief #4)
 * Sekcja 18 (.pb2b-pview-related) już robi poziomy rail. Tu domykamy
 * gwarancję: brak „prawie trzeciego kafelka”, twardy snap, kontener nie
 * rozpycha strony.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .pb2b-pview-related { min-width: 0; max-width: 100%; }
.phoenix-b2b-panel .pb2b-pview-related .pb2b-card-grid {
	scroll-padding-left: 2px;
	overscroll-behavior-x: contain;
}
.phoenix-b2b-panel .pb2b-pview-related .pb2b-card-grid > .pb2b-card {
	scroll-snap-align: start;
	scroll-snap-stop: always;
}

/* ----------------------------------------------------------------------
 * 21.6) KATALOG B2B / SZYBKIE ZAMÓWIENIA — COMPACT (brief #5)
 * Widoki tabelaryczne (.phoenix-b2b-qo-table). Cel: więcej produktów na
 * ekran przy zachowaniu „dodaj do koszyka”. Mniejsza miniatura, ciaśniejsze
 * rzędy, compact stepper. Mobilne „kafelkowanie” tabeli (data-label) zostaje
 * z bazowej warstwy — tu tylko zagęszczamy i pilnujemy szerokości.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .phoenix-b2b-qo-table { width: 100%; max-width: 100%; }
.phoenix-b2b-panel .phoenix-b2b-qo-table .pb2b-qo-col-thumb img {
	width: 42px; height: 42px;
	object-fit: contain;
	background: var(--pb2b-card-image-bg);
	border-radius: 8px;
}
.phoenix-b2b-panel .phoenix-b2b-qo-table tbody td,
.phoenix-b2b-panel .phoenix-b2b-qo-table tbody th { padding-top: 6px; padding-bottom: 6px; }
.phoenix-b2b-panel .phoenix-b2b-qo-table .pb2b-qo-col-name { line-height: 1.25; }
/* Compact stepper ilości — mniejszy, ale klikalny (≥32px target). */
.phoenix-b2b-panel .phoenix-b2b-qo-table .pb2b-qo-step {
	width: 32px; height: 32px;
	min-width: 32px;
	padding: 0;
}
.phoenix-b2b-panel .phoenix-b2b-qo-table .pb2b-qo-qty {
	width: 52px;
	max-width: 64px;
	text-align: center;
}

/* ----------------------------------------------------------------------
 * 21.7) MOBILE / PWA — BRAK POZIOMEGO SCROLLA U ŹRÓDŁA (brief #6)
 * Nie globalne overflow-x:hidden — pilnujemy elementów, które realnie
 * rozpychają: grid/flex/tabela/input/button/obraz. Każdy z nich nie może
 * przekroczyć szerokości panelu.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel { max-width: 100%; }
.phoenix-b2b-panel img,
.phoenix-b2b-panel table,
.phoenix-b2b-panel pre,
.phoenix-b2b-panel code { max-width: 100%; }
.phoenix-b2b-panel input,
.phoenix-b2b-panel select,
.phoenix-b2b-panel textarea,
.phoenix-b2b-panel button { max-width: 100%; }
/* Elementy siatek/flexów muszą móc się kurczyć (min-width:0), inaczej długie
   SKU/nazwa rozpychają tor poziomy. */
.phoenix-b2b-panel .pb2b-card,
.phoenix-b2b-panel .pb2b-row,
.phoenix-b2b-panel .pb2b-card-body,
.phoenix-b2b-panel .pb2b-card-title,
.phoenix-b2b-panel .pb2b-card-pricing { min-width: 0; }
@media (max-width: 767px) {
	/* iOS: focus na input <16px wymusza auto-zoom strony. 16px to wyłącza,
	   bez agresywnego user-scalable=no (dostępność zachowana). */
	.phoenix-b2b-panel input:not([type="checkbox"]):not([type="radio"]),
	.phoenix-b2b-panel select,
	.phoenix-b2b-panel textarea { font-size: 16px; }
}

/* ----------------------------------------------------------------------
 * 21.8) IMPORT CSV / CENNIK CSV — TYLKO KOSMETYKA (brief #7)
 * Spójny card layout, pola i przyciski równe, komunikaty czytelne, brak
 * poziomego scrolla. Logika CSV — nietknięta.
 * -------------------------------------------------------------------- */
.phoenix-b2b-panel .phoenix-b2b-csv-import.pb2b-card,
.phoenix-b2b-panel .phoenix-b2b-csv-export.pb2b-card { max-width: 100%; }
.phoenix-b2b-panel .phoenix-b2b-csv-form,
.phoenix-b2b-panel .phoenix-b2b-csv-form .pb2b-field {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: center;
	max-width: 100%;
}
.phoenix-b2b-panel .phoenix-b2b-csv-form input,
.phoenix-b2b-panel .phoenix-b2b-csv-form select,
.phoenix-b2b-panel .phoenix-b2b-csv-form button { max-width: 100%; }
/* Komunikaty / statystyki / błędy — zawijają, czytelne, nie rozpychają. */
.phoenix-b2b-panel .phoenix-b2b-csv-result,
.phoenix-b2b-panel .phoenix-b2b-csv-stats,
.phoenix-b2b-panel .phoenix-b2b-csv-errors {
	max-width: 100%;
	overflow-wrap: anywhere;
	word-break: break-word;
}
.phoenix-b2b-panel .phoenix-b2b-csv-paste textarea {
	width: 100%;
	max-width: 100%;
	box-sizing: border-box;
}
/* Ewentualna tabela podglądu CSV scrolluje WEWNĄTRZ karty, nie całą stroną. */
.phoenix-b2b-panel .phoenix-b2b-csv-result table,
.phoenix-b2b-panel .phoenix-b2b-csv-export table { display: block; max-width: 100%; overflow-x: auto; }

/* ====================================================================== */
/* KONIEC ETAP 2 (v2.12.9) */

/* ======================================================================
 * 22) v2.12.11 — UJEDNOLICENIE ETYKIET KAFELKA: „MOQ" → OPIS + JEDEN
 *     UKŁAD CENA / MINIMALNE ZAMÓWIENIE / W KARTONIE (brief #3/#4/#5).
 * ----------------------------------------------------------------------
 * PHP nie pokazuje już skrótu „MOQ" (klient mógł nie wiedzieć, co to). W
 * każdym KAFELKU (.pb2b-card) i w każdym kontekście (Sklep B2B, Dashboard,
 * Ostatnio oglądane, Najczęściej kupowane, Podobne/Polecane na produkcie)
 * obowiązuje DOKŁADNIE ten sam, pionowy układ:
 *
 *     [cena]                      (np. 24,60 zł netto)
 *     Minimalne zamówienie: 10 szt.
 *     W kartonie: 50 szt.
 *
 * Dawniej MOQ był chipem dosuniętym do prawej obok ceny (.pb2b-card-pricing
 * = flex row + margin-left:auto). Dłuższa etykieta opisowa by się tam nie
 * zmieściła i łamała layout, więc przestawiamy `.pb2b-card-pricing` na
 * pionowy stos i zamieniamy chipy na pełnowymiarowe, czytelne WIERSZE
 * (etykieta wyszarzona + wartość pogrubiona). Ta warstwa jest ostatnia w
 * kaskadzie (ładowana po panel-bundle i product-card), więc wygrywa w
 * Sklepie B2B i w panelu jednocześnie — koniec rozjazdu „raz obok, raz pod".
 * ====================================================================== */

/* 22.1) Stos pionowy: cena → minimalne zamówienie → w kartonie. Bije
 *       wcześniejszą regułę panelu (flex row + space-between) tą samą
 *       specyficznością, ale później w pliku + !important na osi. */
.pb2b-card .pb2b-card-pricing,
.pb2b-card-grid .pb2b-card-pricing,
.pb2b-shop-results .pb2b-card-pricing,
.phoenix-b2b-panel .pb2b-card .pb2b-card-pricing {
	display: flex !important;
	flex-direction: column !important;
	align-items: stretch !important;
	justify-content: flex-start !important;
	flex-wrap: nowrap !important;
	gap: 3px !important;
	min-height: 0;
	min-width: 0;
	padding-top: 2px;
}

/* Linia ceny zostaje pierwsza, do lewej, bez doklejania do prawej. */
.pb2b-card .pb2b-card-price,
.pb2b-card .pb2b-card-price-na,
.pb2b-card .pb2b-card-price-locked {
	align-self: flex-start;
	margin: 0 0 1px;
}

/* 22.2) Etykieta + wartość jako WIERSZ (nie pill). Kasujemy tło/obrys/pad
 *       chipu oraz dawne margin-left:auto. Działa dla minimalnego
 *       zamówienia (.pb2b-card-moq) i kartonu (.pb2b-card-pack). */
.pb2b-card .pb2b-card-metarow,
.phoenix-b2b-panel .pb2b-card .pb2b-card-metarow,
.pb2b-card .pb2b-card-moq.pb2b-card-metarow,
.phoenix-b2b-panel .pb2b-card .pb2b-card-moq.pb2b-card-metarow {
	display: flex !important;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 2px 6px;
	width: 100%;
	margin: 0 !important;
	margin-left: 0 !important;
	padding: 0 !important;
	background: none !important;
	border: 0 !important;
	border-radius: 0 !important;
	min-width: 0;
	max-width: 100%;
	min-height: 0;
	font-size: 12.5px;
	line-height: 1.3;
	white-space: normal;
	align-self: stretch;
}
.pb2b-card-metarow .pb2b-meta-k {
	color: var(--pb2b-card-muted);
	font-weight: 500;
}
.pb2b-card-metarow .pb2b-meta-v {
	color: var(--pb2b-card-text);
	font-weight: 700;
}
/* Brak wartości („—") — wyszarzona, lżejsza, ale ten sam wiersz/wysokość. */
.pb2b-card-moq-empty.pb2b-card-metarow .pb2b-meta-v {
	color: var(--pb2b-card-muted);
	font-weight: 600;
}

/* 22.3) Responsywna etykieta: pełna „Minimalne zamówienie:" na desktop,
 *       krótsza „Min. zamówienie:" na wąskim mobile (oba renderowane w PHP,
 *       przełączane tu — zero JS). Próg 480px = 2 kolumny na telefonie.
 *       v2.12.59 — short ma inline `display:none` (bulletproof bez CSS), więc
 *       mobilne przełączenie MUSI być `!important`, by je nadpisać. */
.pb2b-meta-k-short { display: none; }
@media (max-width: 480px) {
	.pb2b-meta-k-full  { display: none !important; }
	.pb2b-meta-k-short { display: inline !important; }
}

/* 22.4) Widok LISTY/KATALOGU (.pb2b-row) — te same etykiety, ale compact,
 *       w jednej linii w pasku meta (stan • min. zamówienie • w kartonie). */
.pb2b-row .pb2b-row-metachip,
.phoenix-b2b-panel .pb2b-row .pb2b-row-metachip {
	display: inline-flex;
	align-items: baseline;
	gap: 3px;
	background: none !important;
	border: 0 !important;
	border-radius: 0 !important;
	padding: 0 !important;
	margin: 0;
	font-size: 12px;
	line-height: 1.3;
	white-space: nowrap;
	max-width: 100%;
}
.pb2b-row-metachip .pb2b-meta-k { color: var(--pb2b-card-muted); font-weight: 500; }
.pb2b-row-metachip .pb2b-meta-v { color: var(--pb2b-card-text); font-weight: 600; }

/* 22.5) Konteksty szczegółowe (quick-view, widok produktu w panelu,
 *       podstrona produktu) — dłuższe etykiety nie mogą wyjść poza chip
 *       ani rozpychać wiersza meta. Zostają chipami, ale zawijają. */
.pb2b-qv-moq,
.pb2b-pview-chip,
.pb2b-pp-chip {
	max-width: 100%;
	white-space: normal;
	overflow-wrap: anywhere;
}

/* 22.6) GWARANCJA BRAKU ROZPYCHANIA — dłuższy tekst etykiety NIGDY nie tworzy
 *       poziomego scrolla. Wiersze meta muszą móc się zawinąć/skurczyć. */
.pb2b-card .pb2b-card-body,
.pb2b-card .pb2b-card-pricing,
.pb2b-card .pb2b-card-metarow,
.pb2b-card .pb2b-card-moq,
.pb2b-card .pb2b-card-pack { min-width: 0; max-width: 100%; }
.pb2b-card-metarow .pb2b-meta-k,
.pb2b-card-metarow .pb2b-meta-v { overflow-wrap: anywhere; }

/* ====================================================================== */
/* KONIEC v2.12.11 — UJEDNOLICENIE ETYKIET KAFELKA */

/* ======================================================================
 * 23) v2.12.12 — ETAP 1: UJEDNOLICENIE KAFELKÓW PANELU KLIENTA
 * ----------------------------------------------------------------------
 * Ta sekcja ładuje się JAKO OSTATNIA warstwa listingu (pb2b-listing.css
 * zależy od panel-v3-13), więc wygrywa kaskadę bez nowej wojny !important.
 * Zakres: tylko kafelek `.pb2b-card` i jego siatki w panelu. Zero zmian
 * w innych komponentach, zero nowego, trzeciego systemu kafli.
 *
 * Brief (sekcje 2–7):
 *  - jeden system: Dashboard / Ostatnio oglądane / Najczęściej kupowane /
 *    Ulubione = TA SAMA pionowa siatka co Sklep B2B (drabina 2→3→4→5),
 *    a nie poziomy rail (decyzja z briefu sekcja 3: siatka 2 kol. na mobile);
 *  - równy „pas ceny" (cena / „Zapytaj o cenę" / „Cena po zalogowaniu");
 *  - jedna reguła tytułu (2 linie, stała min. wysokość);
 *  - CTA „Zapytaj o cenę" (produkt bez ceny — logika w product-card.php).
 *  Podstrona produktu (.pb2b-pview-related) ZOSTAJE czystym railem 2 pełnych
 *  kafli (sekcja 17) — brief dopuszcza scroll-snap bez „3-go" kafelka.
 * ====================================================================== */

/* 23.1) WIDŻETY → SIATKA (koniec raila dla recent/most/favorites). */
.pb2b-recent .pb2b-card-grid,
.pb2b-most-purchased .pb2b-card-grid,
.pb2b-favorites .pb2b-card-grid,
.pb2b-favorites-grid {
	display: grid !important;
	grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	gap: 12px !important;
	align-items: stretch !important;
	overflow-x: visible !important;
	overflow-y: visible !important;
	scroll-snap-type: none !important;
	padding: 0 !important;
	margin: 0 !important;
}
.pb2b-recent .pb2b-card-grid > .pb2b-card,
.pb2b-most-purchased .pb2b-card-grid > .pb2b-card,
.pb2b-favorites .pb2b-card-grid > .pb2b-card,
.pb2b-favorites-grid > .pb2b-card {
	width: auto !important;
	min-width: 0 !important;
	max-width: none !important;
	scroll-snap-align: none !important;
	margin: 0 !important;
}
@media (min-width: 768px) {
	.pb2b-recent .pb2b-card-grid,
	.pb2b-most-purchased .pb2b-card-grid,
	.pb2b-favorites .pb2b-card-grid,
	.pb2b-favorites-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; gap: 14px !important; }
}
@media (min-width: 1200px) {
	.pb2b-recent .pb2b-card-grid,
	.pb2b-most-purchased .pb2b-card-grid,
	.pb2b-favorites .pb2b-card-grid,
	.pb2b-favorites-grid { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; gap: 16px !important; }
}
@media (min-width: 1440px) {
	.pb2b-recent .pb2b-card-grid,
	.pb2b-most-purchased .pb2b-card-grid,
	.pb2b-favorites .pb2b-card-grid,
	.pb2b-favorites-grid { grid-template-columns: repeat(5, minmax(0, 1fr)) !important; gap: 16px !important; }
}
@media (max-width: 380px) {
	.pb2b-recent .pb2b-card-grid,
	.pb2b-most-purchased .pb2b-card-grid,
	.pb2b-favorites .pb2b-card-grid,
	.pb2b-favorites-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 10px !important; }
}

/* 23.2) RÓWNY PAS CENY — cena / „Zapytaj o cenę" / „Cena po zalogowaniu"
 *       zajmują tę samą wysokość → „Min. zamówienie" i „W kartonie" startują
 *       równo w sąsiednich kartach, niezależnie od wariantu ceny. */
.pb2b-card .pb2b-card-pricing > .pb2b-card-price,
.pb2b-card .pb2b-card-pricing > .pb2b-card-price-na,
.pb2b-card .pb2b-card-pricing > .pb2b-card-price-locked {
	min-height: 30px;
	align-items: center;
	align-self: flex-start;
	margin: 0 0 2px;
}
@media (max-width: 600px) {
	.pb2b-card .pb2b-card-pricing > .pb2b-card-price,
	.pb2b-card .pb2b-card-pricing > .pb2b-card-price-na,
	.pb2b-card .pb2b-card-pricing > .pb2b-card-price-locked { min-height: 28px; }
}

/* 23.3) TYTUŁ — JEDNA reguła (2 linie + stała min. wysokość) we wszystkich
 *       kontekstach panelu (równy rytm karty niezależnie od długości nazwy). */
.pb2b-card .pb2b-card-title,
.phoenix-b2b-panel .pb2b-card-grid .pb2b-card-title,
.phoenix-b2b-panel .pb2b-card-grid:not(.pb2b-card-grid-compact) .pb2b-card-title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-height: 2.66em;
}

/* 23.4) CTA „Zapytaj o cenę" — akcent; wymiary z bazowego .pb2b-card-btn /
 *       .pb2b-row-btn. Czytelne w light i dark. */
.pb2b-card-btn-ask,
.pb2b-row-btn-ask {
	color: #6d28d9;
	background: rgba(124, 58, 237, .10);
	border: 1px solid rgba(124, 58, 237, .26);
}
.pb2b-card-btn-ask:hover,
.pb2b-row-btn-ask:hover {
	background: rgba(124, 58, 237, .16);
	color: #5b21b6;
}
html[data-pb2b-theme="dark"] .pb2b-card-btn-ask,
body.pb2b-theme-dark .pb2b-card-btn-ask,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-card-btn-ask,
html[data-pb2b-theme="dark"] .pb2b-row-btn-ask,
body.pb2b-theme-dark .pb2b-row-btn-ask,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-row-btn-ask {
	color: #c4b5fd;
	background: rgba(139, 92, 246, .16);
	border-color: rgba(139, 92, 246, .38);
}
/* ====================================================================== */
/* KONIEC v2.12.12 — ETAP 1 UJEDNOLICENIE KAFELKÓW */

/* ======================================================================
 * UPDATE 1 (2.12.54) — warstwa FINALNA shop/ulubione/filtry.
 * Ładowana po panel-bundle.css + całym łańcuchu panel-v3 → wygrywa kaskadę.
 * Zakres: P8 (Ulubione 5 kol PC), P3 (czytelne filtry w dark mode).
 * ====================================================================== */

/* --- P8: ULUBIONE = 5 kafli w rzędzie na PC (≥1280px) ---------------- */
/* Bundle (≥1200px) trzyma repeat(4) dla .pb2b-favorites-grid; tu podnosimy
 * do 5 od 1280px (spójnie ze Sklepem B2B). Tablet/mobile bez zmian. */
@media (min-width: 1280px) {
	.phoenix-b2b-panel .pb2b-favorites-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
		gap: 16px !important;
	}
}
/* Uwaga: „Ostatnio oglądane" (.pb2b-recent) to poziomy rail scroll-snap,
 * który już pokazuje 5 pełnych kart na PC (≥1024px) — NIE zmieniamy go na
 * siatkę, aby nie wracał poziomy scroll strony. */

/* --- P3: FILTRY SKLEPU — czytelne w DARK MODE ----------------------- */
/* Filtry używają tokenów sklepu (--s-*), a override dark w sekcji 16 kluczuje
 * tylko na html[data-pb2b-theme="dark"]/body.pb2b-theme-dark. Dokładamy ZAKRES
 * panelu .phoenix-b2b-panel[data-pb2b-theme="dark"] i jawne, jasne kolory dla
 * etykiet, checkboxów, selectów, inputów i placeholderów. */
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-filter-label,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-filter-label {
	color: var(--pb2b-text-soft, #c9cedb) !important;
}
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-check,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-check span,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-check,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-check span {
	color: var(--pb2b-text, #eef1f7) !important;
}
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-select,
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-input,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-select,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-input {
	color: var(--pb2b-text, #eef1f7) !important;
	background: var(--pb2b-bg-3, #161c2c) !important;
	border-color: var(--pb2b-border-strong, rgba(255,255,255,.18)) !important;
}
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-input::placeholder,
html[data-pb2b-theme="dark"] .phoenix-b2b-panel .pb2b-shop-input::placeholder {
	color: var(--pb2b-text-muted, #99a1b3) !important;
	opacity: 1;
}
/* Strzałka selecta widoczna na ciemnym tle. */
.phoenix-b2b-panel[data-pb2b-theme="dark"] .pb2b-shop-select {
	color-scheme: dark;
}
/* KONIEC UPDATE 1 — shop/ulubione/filtry */

/* ======================================================================
 * UPDATE 2 (2.12.55) — QUICK VIEW: stepper +/- SAMOWYSTARCZALNY.
 * Modal .pb2b-qv-modal renderuje się POZA .phoenix-b2b-panel, więc NIE polegamy
 * na tokenach --pb2b-card-*. Jawne tło/border/kolor ikon i inputa, !important
 * (bije product-card.css: .pb2b-qv-qty bg #fff, input bez tła). Dark = pod
 * html[data-pb2b-theme="dark"] / body.pb2b-theme-dark (mirror z theme-toggle.js).
 * ====================================================================== */
.pb2b-qv-qty {
	display: inline-flex !important;
	align-items: center !important;
	height: 44px !important;
	border: 1px solid #d7d9e3 !important;
	border-radius: 999px !important;
	background: #f1f3f8 !important;
	overflow: hidden !important;
}
.pb2b-qv-qty-btn {
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: 42px !important;
	height: 44px !important;
	padding: 0 !important;
	border: 0 !important;
	background: transparent !important;
	color: #15151d !important;
	cursor: pointer !important;
}
.pb2b-qv-qty-btn svg { width: 16px !important; height: 16px !important; stroke: currentColor !important; fill: none !important; opacity: 1 !important; visibility: visible !important; }
.pb2b-qv-qty-btn:hover { background: rgba(124,58,237,.10) !important; color: #6d28d9 !important; }
.pb2b-qv-qty-input {
	width: 54px !important;
	height: 44px !important;
	text-align: center !important;
	border: 0 !important;
	border-left: 1px solid #e2e3ec !important;
	border-right: 1px solid #e2e3ec !important;
	background: transparent !important;
	color: #15151d !important;
	font-size: 15px !important;
	font-weight: 800 !important;
	-moz-appearance: textfield;
}
.pb2b-qv-qty-input:focus { outline: none !important; box-shadow: none !important; }
.pb2b-qv-qty-input::-webkit-outer-spin-button,
.pb2b-qv-qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* DARK — input ciemny/przezroczysty, ikony jasne, brak białego pola. */
html[data-pb2b-theme="dark"] .pb2b-qv-qty,
body.pb2b-theme-dark .pb2b-qv-qty {
	background: #141a2a !important;
	border-color: rgba(255, 255, 255, .14) !important;
}
html[data-pb2b-theme="dark"] .pb2b-qv-qty-btn,
body.pb2b-theme-dark .pb2b-qv-qty-btn { color: #f3f5fb !important; }
html[data-pb2b-theme="dark"] .pb2b-qv-qty-btn:hover,
body.pb2b-theme-dark .pb2b-qv-qty-btn:hover { background: rgba(139, 92, 246, .20) !important; color: #c4b5fd !important; }
html[data-pb2b-theme="dark"] .pb2b-qv-qty-input,
body.pb2b-theme-dark .pb2b-qv-qty-input {
	color: #f3f5fb !important;
	background: transparent !important;
	border-left-color: rgba(255, 255, 255, .12) !important;
	border-right-color: rgba(255, 255, 255, .12) !important;
}
/* KONIEC UPDATE 2 — quick view stepper */

/* ======================================================================
 * UPDATE 4 (2.12.57) — P4 HARTOWANIE: 5 kolumn na REALNYM selektorze siatki.
 * Raport 2.12.53 (sekcja 5.4 pkt 2) wskazał, że dotychczasowe poprawki 5-kol
 * celowały w `.pb2b-shop-results .pb2b-card-grid`, podczas gdy w żywym DOM o
 * wyniku decyduje też reguła Systemu 1 `.pb2b-shop .pb2b-card-grid` (bundle
 * 4434–4451, twardo repeat(4) @≥1200px, !important). Tu domykamy sprawę: ten
 * sam, niższy próg (1280px) NA OBU selektorach, w panelu i poza nim, więc
 * żadna wcześniejsza warstwa repeat(4) nie wygrywa. Ładowane na końcu
 * pb2b-listing.css → ostatnia warstwa kaskady.
 * ====================================================================== */
@media (min-width: 1280px) {
	/* Panel klienta — sekcja „Sklep B2B". Oba selektory = pewność trafienia. */
	.phoenix-b2b-panel .pb2b-shop .pb2b-card-grid,
	.phoenix-b2b-panel .pb2b-shop-results .pb2b-card-grid,
	.phoenix-b2b-panel .pb2b-shop .pb2b-card-grid.pb2b-shop-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
		gap: 16px !important;
	}
	/* Sklep B2B jako samodzielny shortcode [phoenix_b2b_shop] (poza panelem):
	 * obniżamy próg 5 kolumn z 1400px do 1280px, by 1920px@150% (CSS ~1280px)
	 * też dawało 5 kart — zgodnie z P4. */
	.pb2b-shop .pb2b-card-grid,
	.pb2b-shop-results .pb2b-card-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
		gap: 18px !important;
	}
}
/* Ulubione / siatka kafli produktowych w panelu — spójnie 5 kolumn @≥1280px,
 * na wypadek gdyby render emitował tylko `.pb2b-card-grid` bez `-results`. */
@media (min-width: 1280px) {
	.phoenix-b2b-panel .pb2b-favorites-grid,
	.phoenix-b2b-panel .pb2b-shop-grid.pb2b-card-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
		gap: 16px !important;
	}
}
/* Bez poziomego scrolla: każda komórka siatki musi móc się kurczyć (min-width:0),
 * inaczej długie nazwy/SKU rozpychają kolumny i wraca scroll strony (P15). */
.phoenix-b2b-panel .pb2b-card-grid > * { min-width: 0 !important; }
/* KONIEC UPDATE 4 — P4 siatki 5 kolumn na realnym selektorze */
