/*
Theme Name: ALPHASCIENCE
Theme URI: https://alphascience.com.pl
Author: DIGIWOLF Piotr Dejneka
Author URI: https://piotrdejneka.com
Description: Lekki motyw dedykowany sklepowi ALPHASCIENCE. Bez webfontow, bez frameworkow i bez kroku budowania. Rdzen wspolny plus moduly wpinane tylko tam, gdzie sa potrzebne. Sciezka zakupowa ma wlasna powloke. Pelne wsparcie WooCommerce, Elementor wylacznie do tresci stron.
Version: 2.9.0
Requires at least: 6.5
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: alphascience
Domain Path: /languages
Tags: e-commerce, custom-logo, custom-menu, translation-ready, threaded-comments
*/

/* ---------- kroje ----------
 *
 * Jost (naglowki) i Inter (tekst) serwowane z WLASNEGO serwera. Wersja
 * zmienna: jeden plik na rodzine i podzbior zamiast siedmiu statycznych.
 * Zmierzone na plikach Google: zmienne 173,3 KB, statyczne dla tych samych
 * wag 650,5 KB. Google NIE przycina osi wag przy zapytaniu o waski zakres -
 * sprawdzone, plik dla wght@300..500 wazy tyle samo co dla 100..900.
 *
 * Dlaczego lokalnie, a nie z fonts.gstatic.com: polaczenie do Google przekazuje
 * adres IP klientki bez podstawy prawnej i doklada obcy host na sciezce
 * krytycznej. Makiety wczytywaly kroje z Google - w sklepie tego nie robimy.
 *
 * PODZIAL PODZBIOROW JEST ISTOTNY DLA POLSZCZYZNY i zostal sprawdzony
 * w tablicy znakow kazdego pliku, a nie zalozony:
 *   latin      -> o z kreska (U+00F3)
 *   latin-ext  -> a, c, e, l, n, s, z z ogonkami i kreskami
 * Polski tekst potrzebuje OBU plikow, wiec oba laduja sie na kazdej stronie.
 *
 * Zakres font-weight to 100 900, bo tyle naprawde zawiera plik. Dzieki temu
 * <b> i <strong> dostaja PRAWDZIWE pogrubienie zamiast dorabianego przez
 * przegladarke - w makietach bylo syntetyczne, bo Google dostarczal wtedy
 * tylko wagi 300-500.
 *
 * Licencje: OFL, pelne teksty w assets/fonts/LICENCJA-*.txt.
 */
@font-face {
	font-family: "Jost";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("assets/fonts/jost-latin-ext.woff2") format("woff2");
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: "Jost";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("assets/fonts/jost-latin.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: "Inter";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("assets/fonts/inter-latin-ext.woff2") format("woff2");
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: "Inter";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("assets/fonts/inter-latin.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- tokeny ----------
 *
 * Zestaw przeniesiony 1:1 z makiet zatwierdzonych przez Klientke. Wszystkie
 * szesc plikow makiet ma DOKLADNIE te same wartosci - sprawdzone, zero
 * rozjazdow - wiec to jest system, a nie zbior przypadkowych kolorow.
 *
 * Jesli cos ma sie zmienic, zmienia sie TUTAJ i w makietach naraz. Wpisanie
 * wartosci wprost w regule konczy tak, ze po roku nikt nie wie, ktora jest
 * obowiazujaca.
 */
:root {
	/* --- kolory --- */
	--ink: #0d0d0d;
	--ink-soft: #3c3c3c;

	/*
	 * --muted i --cerulean sa o wlos ciemniejsze od wartosci wyjsciowych
	 * z brand booka (#6e6e73 i #0076a8). Tamte dawaly 4,37:1 i 4,36:1 na
	 * porcelanie, czyli tuz pod progiem WCAG AA 4,5:1 - a wlasnie na porcelanie
	 * stoi wiekszosc tekstu pomocniczego. Teraz 4,57:1 i 4,55:1.
	 */
	--muted: #6b6b70;

	/* --line i --line-strong sluza WYLACZNIE do dekoracji. Granica kontrolki
	   (pole, przycisk obrysowy) musi miec 3:1 wzgledem tla - WCAG 1.4.11 -
	   i do tego jest osobny --line-control. */
	--line: #e7e4df;
	--line-strong: #c9c4bc;
	--line-control: #8a857b;

	--bg: #ffffff;
	--porcelain: #f0eee9;   /* Soft Porcelain */
	--blush: #eec8b9;       /* Blush Sand */
	--sienna: #8b4720;      /* Burnt Sienna */
	/* WYCOFANY 10.08.2026 - patrz docs/MAKIETA.md. Klientka poprosila o jeden
	   odcien niebieskiego, ten ciemniejszy, takze w tresci. Token zostaje,
	   zeby nie wrocil przez przypadek jako "ten drugi niebieski". */
	--cerulean: #0073a3;    /* Deep Cerulean - nieuzywany */
	--navy: #002855;

	/* KOLOR AKCJI - wylacznie sciezka zakupowa.
	   Zyczenie Klientki z 10.08.2026: przyciski prowadzace do zakupu maja
	   miec wlasny, kontrastowy kolor NIEUZYWANY nigdzie indziej. Dziala to
	   tylko dopoki nie pojawia sie przy niczym innym - stad osobna regula
	   dla nich, a nie zmiana wygladu wszystkich przyciskow.
	   4,79:1 z bialym tekstem. */
	--akcja: #2b8159;
	--akcja-ciemna: #25734f;

	/*
	 * Bialy tekst wolno klasc na: cerulean (5,27:1), ink (19,44:1),
	 * navy (14,64:1), sienna (6,95:1).
	 *
	 * NA BLUSH NIGDY - bialy daje tam 1,54:1. Blush wymaga tekstu --ink,
	 * ktory daje 12,58:1. Policzone, nie oszacowane.
	 */

	/* --- typografia --- */
	/* Nazwy zapasowe te same co w makietach - gdyby plik kroju nie doszedl,
	   uklad ma sie oprzec na czyms o zblizonych proporcjach. */
	/*
	 * NAZWA Z PRZEDROSTKIEM "font-" NIE JEST OZDOBNA. Token nazywal sie
	 * --display i na stronie glownej przegrywal z Elementorem: jego pojemniki
	 * ustawiaja wlasne --display:flex (".e-con{--display:flex;display:var(--display)}"),
	 * a zmienne dziedzicza sie w dol. Kazdy naglowek wewnatrz pojemnika
	 * dostawal wiec font-family:flex - wartosc niepoprawna - i lecial na
	 * kroju zastepczym przegladarki zamiast na Joscie.
	 */
	--font-display: "Jost", "Futura", "Century Gothic", system-ui, sans-serif;
	--text: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
		"Helvetica Neue", Arial, "Noto Sans", sans-serif;
	--track: 0.25em;        /* brand book: SPACING 250 */

	/*
	 * Rozstrzelenie POZA --track nie jest skala i nie udajemy, ze jest.
	 * Makiety uzywaja trzynastu wartosci od .01em do .2em, a sprowadzenie ich
	 * do szesciu krokow przesunelo 155 z 248 wystapien o ponad pol piksela
	 * na dziesieciu znakach. Rozstrzelenie niesie tu znaczenie - wersaliki
	 * dostaja duze, przyciski male - wiec rozstrzyga sie je przy skladaniu
	 * konkretnego elementu, a nie hurtem.
	 *
	 * Ponizsze trzy pokrywaja wartosci najczestsze i sa DOKLADNE, nie zaokraglone.
	 */
	--track-ui: .04em;      /* przyciski, etykiety kontrolek */
	--track-label: .12em;   /* male wersaliki */
	--track-eyebrow: .16em; /* nadtytuly sekcji */

	/* --- skala rozmiarow ---
	 *
	 * Drabina geometryczna, iloraz ~1.085. Zbudowana Z makiet, nie wymyslona:
	 * 39 roznych rozmiarow z szesciu plikow sprowadza sie do dwunastu krokow,
	 * przy czym 95 procent wystapien przesuwa sie o MNIEJ NIZ POL PIKSELA.
	 * Reszta to pojedyncze uzycia, czyli rozjazd, a nie zamysl.
	 *
	 * --t-7 to podstawa (1rem = 16px). Wyzej naglowki, nizej tekst pomocniczy.
	 */
	--t-1: .60rem;
	--t-2: .66rem;
	--t-3: .72rem;
	--t-4: .78rem;
	--t-5: .85rem;
	--t-6: .92rem;
	--t-7: 1rem;
	--t-8: 1.15rem;
	--t-9: 1.35rem;
	--t-10: 1.6rem;
	--t-11: 2.4rem;
	--t-12: 3.4rem;

	/* Kroki plynne - te akurat byly juz spojne we wszystkich szesciu makietach,
	   wiec ida 1:1, bez ruszania. */
	--t-display: clamp(2rem, 7vw, 4.2rem);
	--t-h1: clamp(1.75rem, 4.4vw, 2.9rem);
	--t-h2: clamp(1.25rem, 3vw, 1.75rem);
	--t-h3: clamp(1.15rem, 2.4vw, 1.5rem);
	--t-lead: clamp(1rem, 1.5vw, 1.1rem);

	/* --- interlinia --- */
	--lh-flat: 1;           /* liczby, plakietki, jednowierszowe etykiety */
	--lh-tight: 1.15;       /* naglowki */
	--lh-snug: 1.3;
	--lh-text: 1.45;
	--lh-body: 1.65;        /* tekst ciagly */

	/* --- wagi ---
	   Makiety uzywaja DOKLADNIE trzech. Czwarta pojawi sie tylko wtedy,
	   gdy ktos swiadomie ja doda, a nie przez pomylke. */
	--w-light: 300;
	--w-regular: 400;
	--w-medium: 500;

	/* --- skala odstepow: jedna, uzywana wszedzie --- */
	--s1: .5rem;
	--s2: .75rem;
	--s3: 1.25rem;
	--s4: 2rem;
	--s5: 3rem;
	--s6: clamp(2.25rem, 7vw, 5.5rem);   /* odstep wewnatrz sekcji */
	--sec: clamp(3rem, 9vw, 8rem);   /* odstep miedzy sekcjami */

	/* --- uklad --- */
	--maxw: 1280px;
	--pad: clamp(1.25rem, 5vw, 3.5rem);
	--radius: 2px;
	--head-h: 104px;        /* wysokosc naglowka, do przesuniec przy kotwicach */

	/*
	 * Wysokosc przyklejonego paska zakupu. Zero, dopoki pasek nie wjedzie -
	 * mierzy go i podstawia skrypt karty produktu.
	 *
	 * DEFINICJA MUSI TU BYC, nawet gdy zawsze byloby to zero. Sticky spis
	 * tresci i kolumna zakupowa licza swoje "top" przez
	 * calc(var(--head-h) + var(--pasek-h) + var(--s3)); brak zmiennej robi
	 * z calc() wartosc nieprawidlowa, top schodzi do "auto" i przyklejanie
	 * NIE DZIALA W OGOLE. Tak wlasnie przestal plywac spis "Na tej stronie".
	 */
	--pasek-h: 0px;
	--pasek-dol-h: 0px;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

/*
 * Atrybut hidden musi wygrywac z kazdym display z tego arkusza.
 *
 * W arkuszu przegladarki hidden to zwykle display:none o najnizszym mozliwym
 * pierwszenstwie - KAZDA nasza regula z display go pokonuje. Szuflada
 * (.drawer) i wysuwany koszyk (.koszyk) sa domyslnie ukryte wlasnie tym
 * atrybutem, wiec bez tej reguly pojawilyby sie na stale, gdy tylko dostana
 * display:flex albo display:grid.
 *
 * Ta sama pulapka zlapala nas juz trzy razy przy makietach: materialy do
 * pobrania widoczne dla oczekujacych kont, rozjechany wariant zalogowanego
 * i przycisk "Usun filtr" widoczny zawsze. Za kazdym razem test sprawdzal
 * ATRYBUT zamiast wyliczonego display.
 */
[hidden] { display: none !important; }

/* Zaznaczenie i podswietlenie z przegladarki.
   Na zrzutach z telefonu Klientki (10.08.2026) czesc napisow miala pomaranczowe
   albo ciemnozielone tlo - to nie nasze style, tylko wlasne podswietlenie
   przegladarki: zaznaczenie tekstu i trafienie z wyszukiwania na stronie.
   Domyslne barwy systemu potrafia byc jaskrawe i nieczytelne, a na ciemnych
   sekcjach dawaly czarny tekst na ciemnym tle. Ustawiamy je same. */
::selection{background:var(--blush);color:var(--ink)}
::target-text{background:var(--blush);color:var(--ink)}
.on-dark ::selection,.section--ink ::selection,.section--navy ::selection{background:var(--blush);color:var(--ink)}


/* Otwarty panel blokuje przewijanie tla - inaczej palec przewija strone
   pod szuflada zamiast jej zawartosci. Klase ustawia main.js. */
html.has-panel { overflow: hidden; }
body {
	/*
	 * STRONY NIE DA SIE PRZESUNAC W BOK.
	 *
	 * Zglosone z telefonu: przy przewijaniu palcem strona uciekala na boki.
	 * Zrodel jest kilka i wszystkie sa poza naszym ukladem - dojechanie
	 * palcem do konca pasa kafelkow, wysunieta szuflada menu stojaca poza
	 * kadrem, wtyczka dokladajaca szerszy element. Zamiast lapac je po kolei,
	 * ucinamy ruch w poziomie na calej stronie.
	 *
	 * clip, a NIE hidden: "hidden" robi z <body> kontener przewijania i
	 * zabiera dzialanie przyklejonemu naglowkowi oraz spisowi tresci.
	 * "clip" tylko przycina i nie tworzy kontenera - pozycja sticky dziala
	 * dalej. Przegladarki bez obslugi clip (starsze) po prostu jej nie
	 * zastosuja i zostana przy dotychczasowym zachowaniu.
	 */
	overflow-x: clip;
	margin: 0;
	font-family: var(--text);
	font-size: 16px;
	line-height: var(--lh-body);
	color: var(--ink);
	background: var(--bg);
	-webkit-font-smoothing: antialiased;
}
/* display:block przy obrazkach jest z makiet i nie jest kosmetyka: obrazek
   liniowy stoi na linii tekstu, wiec przegladarka zostawia pod nim miejsce
   na ogonki liter. Banery sekcji byly przez to o 8 px wyzsze niz w projekcie,
   a pod kazdym zdjeciem w kafelku zostawal cienki pasek tla. */
img, video, svg { max-width: 100%; height: auto; display: block; }

/*
 * Odnosniki i przyciski wedlug makiet.
 *
 * a{color:inherit;text-decoration:none} - w projekcie podkreslenie i kolor
 * niesie KLASA (.link-u, .link-w), a nie sam znacznik. Odnosnik w belce,
 * w menu i w kafelku produktu ma wygladac inaczej niz odnosnik w zdaniu.
 *
 * button - bez tej reguly przegladarka maluje wlasne pudelko z ramka
 * i szarym tlem. Zlapane od razu po wdrozeniu powloki: pozycje "Produkty"
 * i "Kontakt" w rzedzie nawigacji wygladaly jak przyciski formularza,
 * a ikony w belce jak klawisze.
 *
 * input[type=submit] chodzi w parze z button, bo WordPress wysyla formularze
 * wlasnie takim polem - i tylko taki przycisk stoi pod formularzem opinii.
 * Bez niego .btn--kup dostawal blady lawendowy prostokat od przegladarki
 * zamiast zieleni sciezki zakupowej.
 */
a { color: inherit; text-decoration: none; }
button,
input[type="submit"] { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul { margin: 0; padding: 0; list-style: none; }
blockquote, figure { margin: 0; }
/*
 * Naglowki wedlug makiet: kroj naglowkowy, waga LEKKA (300), ciasna interlinia.
 *
 * Waga 300 nie jest pomylka - Jost w tej wadze jest czytelny w duzych stopniach
 * i tak wyglada projekt zatwierdzony przez Klientke. WCAG nie stawia wymagan
 * wobec grubosci pisma, a kontrast --ink na bieli to 19,44:1.
 *
 * text-wrap: balance rozklada wyrazy rowno miedzy wiersze, zeby w naglowku
 * nie zostawal jeden wyraz w ostatnim wierszu.
 */
h1, h2, h3, h4 {
	font-family: var(--font-display);
	font-weight: var(--w-light);
	line-height: var(--lh-tight);
	margin: 0;
	text-wrap: balance;
}
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); }
h4 { font-size: var(--t-8); }

/*
 * Zero marginesu przy naglowkach i akapitach - odstepy daje UKLAD (gap
 * w siatce, margin-top w komponencie), a nie znacznik. Tak liczy je makieta
 * i tylko wtedy odstep miedzy naglowkiem a tekstem jest wszedzie taki sam.
 * Tresc redakcyjna (wpisy, opisy) odzyskuje marginesy w swoim komponencie.
 */
p { margin: 0; }
:focus-visible { outline: 2px solid var(--navy); outline-offset: 3px; }

/* ---------- ikony ----------
 *
 * Rozmiary i grubosc kreski ustawia TEN arkusz, a nie atrybuty na <svg> -
 * dzieki temu ikona skaluje sie razem z tekstem obok i nie trzeba jej
 * przerysowywac przy kazdym uzyciu.
 *
 * Makiety uzywaly jedenastu rozmiarow od 11 do 26 px i siedmiu grubosci kreski
 * od 1.3 do 2.2 - ten sam rozjazd co przy typografii. Piec krokow pokrywa
 * wszystko, a najwiekszy przesuw to 2 px na dwoch wartosciach uzytych raz.
 */
:root {
	--i-xs: 12px;
	--i-sm: 14px;
	--i-md: 17px;
	--i-lg: 20px;
	--i-xl: 24px;

	/* Kreska nie skaluje sie z ikona: przy 12 px ta sama wartosc daje cienszy
	   slad niz przy 24 px, dlatego male ikony dostaja grubsza. */
	--i-kreska: 1.4;
	--i-kreska-gruba: 2;
}

.ikona {
	width: var(--i-md);
	height: var(--i-md);
	flex: none;              /* w rzedzie flex ikona nie moze sie sciskac */
	fill: none;
	stroke: currentColor;    /* ikona przejmuje kolor tekstu obok */
	stroke-width: var(--i-kreska);
	vertical-align: middle;
}

.ikona--xs { width: var(--i-xs); height: var(--i-xs); stroke-width: var(--i-kreska-gruba); }
.ikona--sm { width: var(--i-sm); height: var(--i-sm); }
.ikona--lg { width: var(--i-lg); height: var(--i-lg); }
.ikona--xl { width: var(--i-xl); height: var(--i-xl); }

/* Gwiazdki ocen i znaki serwisow spolecznosciowych sa plama, nie konturem. */
.ikona--wypelniona { fill: currentColor; stroke: none; }


/* =====================================================================
   POWLOKA - przeniesiona z makiet 27.08.2026
   =====================================================================
   Reguly ponizej pochodza WPROST z arkusza makiet zatwierdzonych przez
   Klientke. Nie sa przepisywane wlasnymi slowami: przez okolo trzydziesci
   tur poprawek dopracowalismy w nich drobiazgi, ktorych nie da sie odtworzyc
   z pamieci, a kazdy z nich Klientka zauwazyla. Szablony motywu wypuszczaja
   wiec klasy z makiet, a nie odwrotnie.

   Zrodlo: docs/makiety/strona-glowna.html. Przy kazdej zmianie wygladu
   powloki poprawiamy OBA miejsca albo zadne - makieta zostaje punktem
   odniesienia do konca wdrozenia.
   ===================================================================== */

/* ---------- most do WordPressa ----------
   Klasy, ktorych makieta nie zna, bo generuje je rdzen albo WooCommerce.
   Zostaja z poprzedniej wersji arkusza. */
/* RYTM PIONOWY TAKI SAM JAK NA STRONACH Z SEKCJI. Zwykly szablon (konto,
   materialy, wniosek B2B, wyniki wyszukiwania) mial 48 px odstepu, a kazda
   strona zlozona z widzetow zaczyna sie sekcja z odstepem --s6 (88 px). Ta
   sama witryna oddychala wiec dwoma rytmami zaleznie od tego, czym strona
   zostala zbudowana - najbardziej bilo to po oczach na logowaniu, gdzie
   naglowek "Moje konto" siedzial tuz pod nawigacja. Audyt 02.09.2026. */
.site-main { padding-block: var(--s6); min-height: 50vh; }
/* SCIEZKA ZAKUPOWA ZOSTAJE CIASNA. Koszyk i kasa maja skrocona powloke po to,
   zeby droga do zaplaty byla krotka; 88 px u gory zepchneloby podsumowanie
   ponizej krawedzi ekranu. */
.shell-checkout .site-main { padding-block: clamp(1.5rem, 4vw, 3rem); }
/* Widok zlozony z sekcji z makiety: marginesami zajmuja sie one same (.wrap
   w srodku), a tlem maja siegac krawedzi okna. Gorny odstep tez znika -
   pierwsze sa okruszki, ktore niosa wlasny. */
.site-main--pelna { padding-block: 0; min-height: 50vh; }

/* .container zostaje jako alias .wrap - uzywaja go szablony spoza powloki,
   ktore przepiszemy przy swoich etapach. */
.container,
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--pad); }

.skip-link {
	position: absolute; left: -9999px; top: 0; z-index: 999;
	background: var(--ink); color: #fff; padding: .6rem 1rem;
}
.skip-link:focus { left: 0; }

/*
 * Tresc wylacznie dla czytnikow ekranu.
 *
 * Definicja MUSI byc w motywie. Klase generuje rdzen WordPressa, WooCommerce
 * (opisy przyciskow "Dodaj do koszyka") oraz nasze wtyczki, ale arkusz, ktory ja
 * definiuje - woocommerce.css - jest wczytywany TYLKO na stronach sklepu
 * (alpha_wc_scope_assets). Poza nimi arkuszem jest sam motyw i bez tej reguly
 * tekst pomocniczy renderowalby sie widocznie posrodku tresci.
 *
 * .sr to ta sama rzecz w jezyku makiet - jedna regula obsluguje obie nazwy.
 *
 * Nie uzywamy display:none - to usuneloby tresc rowniez z czytnika ekranu,
 * czyli dokladnie z miejsca, dla ktorego jest przeznaczona.
 */
/*
 * Stan koszyka NIE moze byc elementem ukladu przycisku.
 *
 * .iconbtn to siatka z place-items:center i jednym oczekiwanym dzieckiem -
 * ikona. Docket podmienia stan koszyka bez przeladowania strony, wiec musi
 * miec wlasny, staly element do wymiany; ten element wchodzil jednak do
 * siatki jako DRUGI wiersz. Efekt: przycisk mial wiersze 32 px i 12 px,
 * a ikona koszyka siedziala 6 px nad srodkiem - obok lupki i konta, ktore
 * stoja dokladnie po srodku. Zmierzone, nie oszacowane.
 *
 * Wyjmujemy go z ukladu i rozciagamy na caly przycisk: plakietka z liczba
 * jest wzgledem niego pozycjonowana tak samo jak wczesniej wzgledem
 * przycisku, a tekst dla czytnika ekranu i tak jest poza obiegiem.
 */
.header__cart-state {
	position: absolute; inset: 0;
	pointer-events: none;
}

.screen-reader-text,
.sr {
	position: absolute !important;
	width: 1px; height: 1px;
	margin: -1px; padding: 0; border: 0;
	overflow: hidden; word-wrap: normal !important;
	clip-path: inset(50%);
}

/* Gdy taki tekst jest odnosnikiem (np. "przejdz do tresci"), po otrzymaniu
   ogniska musi stac sie widoczny - inaczej nawigacja klawiatura gubi sie. */
.screen-reader-text:focus,
.sr:focus {
	position: static !important;
	width: auto; height: auto;
	margin: 0; padding: .6rem 1rem;
	clip-path: none;
	background: var(--ink); color: #fff;
}

/* ---------- układ ---------- */
.wrap{max-width:var(--maxw);margin-inline:auto;padding-inline:var(--pad)}
.section{padding-block:var(--sec)}
/* sekcja na tym samym tle co poprzednia - odstep liczy sie raz */
.section--sklejona{padding-block-start:0}
.section--soft{background:var(--porcelain)}
/* Skin Longevity: makro skóry pod mocną czarną nakładką plus deseń
   koncentrycznych okręgów - ten sam motyw, co na opakowaniach marki.
   Nakładka jest po to, żeby biały tekst trzymał kontrast, a nie dla efektu. */
.section--ink{position:relative;background:var(--ink);color:#fff;overflow:hidden;isolation:isolate}
/* Zdjecie w tle usuniete (13.08.2026) - zostaje samo ciemne tlo z siatka
   koncentrycznych linii. Nakladka przyciemniajaca tez znika: byla po to,
   zeby tekst dalo sie czytac na fotografii. */
.section--ink::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:repeating-radial-gradient(circle at 22% 46%, rgba(255,255,255,.07) 0 1px, transparent 1px 54px);
}
@media(max-width:899px){
  .section--ink::after{
    background:repeating-radial-gradient(circle at 70% 22%, rgba(255,255,255,.06) 0 1px, transparent 1px 46px);
  }
}
.section--navy{background:var(--navy);color:#fff}

/* Pas domykajacy strone i jego siatka. W rdzeniu, a nie w arkuszu strony
   glownej, bo ten sam komponent sklada trzy rozne rzeczy: widzet "Pas
   z wezwaniem" na stronach tresciowych, widzet B2B na glownej i wniosek
   o konto profesjonalne z wtyczki Vetted. Trzy linie w rdzeniu sa tansze
   niz 21 KB arkusza glownej wozone przez regulamin. */
.section--pas{padding-block:var(--s6)}
.b2b{display:grid;gap:var(--s4);align-items:center}
@media(min-width:900px){.b2b{grid-template-columns:minmax(0,1fr) minmax(0,auto);gap:var(--s5)}}
/* Kotwica zatrzymuje sie pod naglowkiem I pod paskiem zakupu - inaczej
   klikniecie w spis tresci chowa naglowek sekcji za paskiem. */
[id]{scroll-margin-top:calc(var(--head-h) + var(--pasek-h))}

/* ---------- typografia użytkowa ---------- */
.eyebrow{
  display:block;font-family:var(--font-display);font-size:.68rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);font-weight:400;
}
.eyebrow--accent{color:var(--navy)}
.eyebrow--blush{color:var(--blush)}
.h-l{font-size:clamp(1.75rem,4.4vw,2.9rem);letter-spacing:.06em;text-transform:uppercase}
.h-m{font-size:clamp(1.15rem,2.4vw,1.5rem);letter-spacing:.08em;text-transform:uppercase}
.lead{font-size:clamp(1rem,1.5vw,1.1rem);color:var(--ink-soft);max-width:60ch;text-wrap:pretty}
/* Jasniejszy lead na ciemnym tle - regula zywa, ktora poszla razem
   z martwym .note. */
.on-dark .lead{color:rgba(255,255,255,.72)}

/* nagłówek sekcji – jeden komponent, jeden rytm */
.sec-head{display:grid;gap:var(--s3);margin-bottom:var(--s6)}
.sec-head__title>*+*{margin-top:var(--s2)}
/* Strzalki i odnosnik stoja obok siebie, wiec potrzebuja odstepu:
   bez niego "Wszystkie artykuly" wchodzilo na przycisk przewijania. */
.sec-head__aside{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
/* Odnosnik "wszystkie" stoi POD pasem, na srodku - tak jak w makiecie.
   W naglowku konkurowalby o miejsce ze strzalkami przewijania, a na telefonie
   spychal je do drugiego wiersza. */
.sekcja-wiecej{margin-top:var(--s4);display:flex;justify-content:center}
@media(min-width:860px){
  .sec-head{grid-template-columns:minmax(0,1fr) minmax(0,auto);gap:var(--s5);align-items:end}
  .sec-head--split{grid-template-columns:minmax(0,1fr) minmax(0,26rem)}
  .sec-head__aside{justify-content:flex-end}
}
/* Reguly .sec-head--center usuniete 27.08.2026 razem z ostatnia
   wysrodkowana sekcja - wszystkie naglowki sa teraz do lewej. */

/* ---------- przyciski ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  min-height:54px;padding:.9rem 1.75rem;border-radius:var(--radius);
  font-family:var(--font-display);font-size:.78rem;letter-spacing:var(--track);line-height:1.3;
  text-transform:uppercase;text-align:center;text-wrap:balance;
  transition:background .25s,color .25s,border-color .25s;
}
/* [hidden] to w arkuszu przegladarki zwykle display:none, wiec wlasny
   display go pokonuje. Bez tej linii przycisk z atrybutem hidden
   zostaje widoczny - a wlasnie tak ukrywamy przyciski warunkowe. */
.btn[hidden]{display:none}
.btn--solid{background:var(--ink);color:#fff}
/* Wariant sciezki zakupowej. Osobna klasa, a nie nadpisanie .btn--solid:
   czarny przycisk ma na stronie mnostwo innych zadan (wyslij wniosek, zapisz
   sie, pokaz wyniki) i gdyby zzielenial, kolor przestalby cokolwiek znaczyc. */
.btn--akcja{background:var(--akcja);color:#fff;border-color:var(--akcja)}
.btn--akcja:hover,.btn--akcja:focus-visible{background:var(--akcja-ciemna);border-color:var(--akcja-ciemna)}
.btn--solid:hover{background:var(--navy)}
.btn--ghost{border:1px solid var(--ink);color:var(--ink)}
.btn--ghost:hover{background:var(--ink);color:#fff}
/* Przycisk na cala szerokosc rodzica - w makiecie uzywaja go formularz
   newslettera i "Przejdź do kasy" w wysuwanym koszyku. Klasa byla w znacznikach
   od poczatku, ale regula nigdy nie zostala przepisana z makiety, wiec przycisk
   w koszyku mial szerokosc napisu (204 zamiast 335 px) i wygladal jak jeden
   z dwoch, a nie jak glowna czynnosc panelu. */
.btn--full{width:100%}
.btn--light{background:#fff;color:var(--ink)}
.btn--light:hover{background:var(--blush)}
.btn-row{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}

/*
 * PIGULKA (.chip) - element sterujacy z powloki.
 *
 * Ta sama pigulka niesie dzialy bazy wiedzy i - docelowo - kroki doboru
 * pielegnacji na stronie glownej. Obramowanie jest w --line-control, a nie
 * w dekoracyjnym --line: w stanie niewybranym to jedyny znacznik granicy
 * elementu sterujacego (WCAG 1.4.11).
 *
 * Stan wybrany PRZELACZA sie, nie gasnie: przy animowanym tle ciemny tekst
 * stal przez 200 ms na jeszcze ciemnym, gasnacym tle - kontrast 1,00.
 * Stad w przejsciu tylko kolor obramowania.
 */
.chip{
	flex: 0 0 auto; display: inline-flex; align-items: center;
	border: 1px solid var(--line-control); border-radius: 99px;
	padding: .8rem 1.25rem; min-height: 46px;
	font-family: var(--font-display); font-size: .74rem; letter-spacing: .1em; text-transform: uppercase;
	transition: border-color .2s;
}
.chip:hover{ border-color: var(--ink) }
.chip[aria-selected="true"],
.chip[aria-current="page"]{ background: var(--ink); color: #fff; border-color: var(--ink) }
/* Na telefonie przycisk i odnosnik ida jeden pod drugim i sa wysrodkowane.
   W rzedzie "Kup pojedynczo" wisial przy lewej krawedzi, pod szerokim
   przyciskiem, i wygladal na zgubiony. */
@media(max-width:619px){
  .finder__akcje{flex-direction:column;align-items:center;text-align:center}
  .finder__akcje .btn{width:100%}
  .finder__wszystkie{text-align:center}
}
@media(max-width:400px){.btn-row .btn{width:100%}}
.link-u{
  display:inline-block;font-family:var(--font-display);font-size:.72rem;letter-spacing:var(--track);
  text-transform:uppercase;border-bottom:1px solid currentColor;padding-block:.55rem .35rem;
}
.link-u:hover{color:var(--navy)}

/* Pasmo dotyku 44 px dla elementow, ktorych pudelko jest nizsze. Powiekszenie
   samego pudelka przesunuloby uklad, wiec zamiast tego niewidoczna warstwa.
   Logo ma 33 px, samodzielny odnosnik .link-u 34 px - oba ponizej progu. */
.logo{position:relative}
.logo::after,
.link-u::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}
.link-u{position:relative}

/* Pasmo dotyku dla paska gornego i rozwijanych pozycji belki - oba maja
   wysokosc samego tekstu. .logo i .link-u dostaja je wyzej, osobno. */
.topbar a,.nav__toggle{position:relative}
.topbar a::after,.nav__toggle::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}


/* Link W ZDANIU. Nie myli sie z .link-u, ktory jest samodzielnym wezwaniem
   do dzialania: wersaliki, Jost, wlasny odstep i pasmo dotyku 44 px.
   Wstawiony w akapit dawal "MOZESZ TEZ NAPISAC DO NAS" innym krojem posrodku
   zdania, a jego pasmo 44 px nachodzilo na sasiednie linijki i kradlo
   klikniecia. Ten dziedziczy typografie zdania i nie ma pasma - WCAG 2.5.8
   wprost wylacza linki osadzone w tekscie z wymogu wielkosci pola. */
.link-w{
  color:inherit;text-decoration:underline;
  text-underline-offset:3px;text-decoration-thickness:1px;
  transition:color .2s;
}
.link-w:hover{color:var(--navy)}
.on-dark .link-u:hover{color:var(--blush)}

/* Pole dotyku 44 px dla linkow tekstowych. Grupa docelowa to 35-50+, a
   specyfikacja mowi o duzych polach - ale samo powiekszenie odstepow
   odsunieloby podkreslenie od tekstu i zepsulo typografie. Warstwa ::after
   powieksza obszar klikalny, nie ruszajac ani piksela wygladu.
   Elementy dekoracyjne dostaja pointer-events:none, zeby nie przykrywac
   sasiednich linkow. */


/* =====================================================================
   NAGŁÓWEK
   ===================================================================== */
/* Plakietka makiety wchodzi NAD pasek zakupu. Na telefonie pasek stoi
   u dolu ekranu i plakietka zaslaniala mu przycisk "Do koszyka" - zmienna
   ustawia skrypt paska, wiec na stronach bez niego zostaje zerem. */
.ribbon{
  position:fixed;right:0;bottom:var(--pasek-dol-h,0px);z-index:80;background:var(--ink-soft);color:#fff;
  font-family:var(--font-display);font-size:.58rem;letter-spacing:.18em;text-transform:uppercase;
  padding:.4rem .7rem;opacity:.85;
}
.topbar{background:var(--ink);color:#fff}
/* Trzy osobne informacje rozlozone rowno. Wczesniej dwie z nich byly sklejone
   w jeden akapit i lądowaly razem przy prawej krawedzi, a srodek belki stal
   pusty. Na waskim ekranie zostaje sama darmowa dostawa. */
.topbar .wrap{display:flex;align-items:center;justify-content:center;gap:var(--s4);min-height:44px}
.topbar p{letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-display);font-size:.65rem}
.topbar__side{display:none}
.topbar__more{display:none}
@media(min-width:560px){.topbar__more{display:block}}
@media(min-width:920px){
  .topbar .wrap{display:grid;grid-template-columns:1fr auto 1fr;justify-content:initial}
  .topbar__side{display:block;justify-self:start}
  .topbar__more{justify-self:end}
}

.header{position:sticky;top:0;z-index:70;background:rgba(255,255,255,.94);backdrop-filter:saturate(160%) blur(12px);border-bottom:1px solid var(--line)}
.header__bar{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;min-height:64px;gap:var(--s1)}
.header__left,.header__right{display:flex;align-items:center}
.header__right{justify-content:flex-end}
.iconbtn{width:44px;height:44px;display:grid;place-items:center;border-radius:var(--radius);position:relative;flex:0 0 auto;transition:background .2s}
.iconbtn:hover{background:var(--porcelain)}
.iconbtn svg{width:20px;height:20px;stroke:currentColor;stroke-width:1.3;fill:none}
.iconbtn--wide{display:none}
@media(min-width:520px){.iconbtn--wide{display:grid}}
.badge{
  position:absolute;top:5px;right:5px;min-width:18px;height:18px;border-radius:99px;
  background:var(--navy);color:#fff;font-size:.6rem;display:grid;place-items:center;
  font-family:var(--text);font-weight:500;
}

.badge[hidden]{display:none}

.logo{text-align:center;line-height:1;display:block}

/* =====================================================================
   WYSZUKIWARKA W NAGLOWKU
   ===================================================================== */
/* Pole zajmuje miejsce logo. Ikony po prawej zostaja - koszyk i konto sa
   potrzebne takze w trakcie szukania. */
.header__bar[data-szukanie="true"]{grid-template-columns:1fr auto}
.header__bar[data-szukanie="true"] .logo,
.header__bar[data-szukanie="true"] #szukajBtn,
.header__bar[data-szukanie="true"] .header__left{display:none}

.szukajka{
  display:flex;align-items:center;gap:.5rem;
  border-bottom:1px solid var(--line-control);padding-block:.25rem;
}
/* KONIECZNE. Atrybut hidden daje display:none tylko z arkusza przegladarki,
   a kazda wlasna deklaracja display go bije. Bez tej linijki pole wisi w belce
   od zaladowania strony i obok lupy w naglowku widac druga, te z pola. */
.szukajka[hidden]{display:none}
.szukajka__lupa{width:20px;height:20px;flex:0 0 auto;stroke:var(--muted);stroke-width:1.5;fill:none}
/*
 * Selektor z typem pola, a nie samo ".szukajka input".
 *
 * Ogolna regula formularzy nizej w arkuszu ma DOKLADNIE TE SAMA wage
 * (input[type="search"] to jedna klasa i jeden element, tak samo jak
 * .szukajka input), wiec przy rownej wadze wygrywala kolejnoscia: pole
 * w belce dostawalo ramke, biale tlo, zaokraglenie i wlasne wciecie.
 * Na makiecie pole jest niewidoczne - kreske rysuje caly formularz.
 *
 * padding:revert oddaje wciecie arkuszowi przegladarki, czyli dokladnie
 * temu, co ma makieta. Wpisana liczba trafialaby tylko w jedna przegladarke.
 */
.szukajka input[type="search"]{
  flex:1 1 auto;min-width:0;min-height:48px;
  border:none;border-radius:0;background:none;padding:revert;
  font-family:var(--text);font-size:1rem;color:var(--ink);
}
.szukajka input::placeholder{color:var(--muted)}
.szukajka input:focus-visible{outline:none}
.szukajka:focus-within{border-bottom-color:var(--ink)}

/* --- panel z podpowiedziami --- */
.szukajka__panel{
  position:absolute;top:100%;left:0;right:0;z-index:80;
  background:#fff;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  box-shadow:0 18px 40px rgba(13,13,13,.10);
  visibility:hidden;opacity:0;transition:opacity .18s,visibility 0s .18s;
}
.szukajka__panel.jest-otwarte{visibility:visible;opacity:1;transition:opacity .18s,visibility 0s}
.szukajka__wnetrze{max-width:var(--maxw);margin-inline:auto;padding:var(--s3) var(--pad) var(--s4)}
.szukajka__grupa + .szukajka__grupa{margin-top:var(--s4)}
.szukajka__tytul{
  font-family:var(--font-display);font-size:.63rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);
  padding-bottom:.5rem;border-bottom:1px solid var(--line);margin-bottom:var(--s1);
}
/* Podswietlenie musi miec oddech. Bez odstepow poziomych tlo przylegalo
   wprost do miniatury i do ceny, przez co wygladalo jak przypadkowy pasek,
   a nie jak wskazana pozycja.
   Ujemny margines o te sama wartosc sprawia, ze tekst nadal stoi w jednej
   linii z naglowkiem grupy, a rozjezdza sie tylko samo tlo. */
.szukajka__poz{
  display:flex;align-items:center;gap:var(--s2);min-height:56px;
  padding:.5rem var(--s2);
  margin-inline:calc(var(--s2) * -1);
  border-radius:var(--radius);
  transition:background .18s;
}
.szukajka__poz:hover{background:var(--porcelain)}
.szukajka__foto{width:48px;height:48px;flex:0 0 auto;background:var(--porcelain);overflow:hidden}
.szukajka__foto img{width:100%;height:100%;object-fit:cover}
/* display:block, bo to elementy liniowe - bez tego nazwa i opis sklejaja sie
   w jedna linijke ("MELA BRIGHT [C+]Serum 30 ml"). */
.szukajka__nazwa{display:block;font-family:var(--font-display);font-size:.92rem;letter-spacing:.03em}
.szukajka__opis{display:block;font-size:.78rem;color:var(--muted);margin-top:.1rem}
.szukajka__poz > span:not([class]){flex:1 1 auto;min-width:0}
.szukajka__cena{margin-left:auto;font-family:var(--font-display);font-size:.92rem;white-space:nowrap}
/* Produkt z ukryta cena zostaje w wynikach, znika sama cena - tak samo
   jak w katalogu (decyzja Klienta z 03.08.2026). */
.szukajka__zaloguj{margin-left:auto;font-size:.75rem;color:var(--navy);white-space:nowrap}

.szukajka__pusto{padding-block:var(--s2)}
.szukajka__pusto p{margin-bottom:.4rem}
.szukajka__rada{font-size:.85rem;color:var(--muted)}

/* Pozycja wskazana strzalkami - ten sam wyglad co najechanie myszka,
   zeby obie drogi wygladaly tak samo. */
.szukajka__poz:focus-visible{outline:2px solid var(--navy);outline-offset:-2px;background:var(--porcelain)}
/* Oryginalny plik logo od producenta (ALPHASCIENCE_BLACK.png).
   Brand book zabrania przerysowywania i zmiany proporcji, więc lockup
   wstawiamy jako obraz, a nie jako tekst.
   UWAGA: brand book podaje minimalną szerokość 200 px. Poniżej ~380 px
   ekranu logo nie zmieści się obok ikon w tej szerokości - do wersji
   mobilnej potrzebujemy od Klienta pliku z samym monogramem. */
.logo__img{width:clamp(170px,48vw,230px);height:auto}
.footer .logo__img{filter:invert(1)}

/* LOGO NA SRODKU BELKI (zyczenie Klientki z 27.08.2026).
   Belka to siatka 1fr auto 1fr, ale "1fr" dzieli tylko WOLNE miejsce - przy
   jednej ikonie po lewej i dwoch po prawej boczne sciezki wychodzily rozne
   (51 i 88 px), wiec logo stalo 18 px od srodka. Sciezki dostaja wiec rowna,
   sztywna szerokosc, a logo bierze to, co zostanie.

   Dwie wartosci, bo po prawej stronie zmienia sie liczba ikon: ponizej 520 px
   sa dwie (szukaj, koszyk), powyzej dochodzi konto.

   KOSZT: na telefonie logo schodzi ze 180 do okolo 159 px. Brand book podaje
   minimalna szerokosc 200 px, ktorej i tak nie spelnialismy - wlasciwym
   rozwiazaniem jest plik z samym monogramem do wersji mobilnej. */
@media(max-width:999px){
  .header__bar{grid-template-columns:88px minmax(0,1fr) 88px;gap:0}
  /* margin-inline:auto - obrazek jest blokiem, wiec text-align rodzica go
     nie centruje. Powyzej ~700 px sciezka robi sie szersza niz logo
     i bez tego znak przykleja sie do jej lewej krawedzi.

     calc(100% - 24px): logo NIE dotyka krawedzi swojej sciezki, tylko
     zostawia po 12 px z kazdej strony. Bez tego przyklejalo sie do lupki
     - do niej bylo 12 px, a do koszyka 24 px, wiec ikona wygladala na
     przysunieta do znaku. Teraz oba odstepy wychodza po 24 px.

     Probowalem najpierw przesunac sam znaczek lupki wewnatrz przycisku.
     Odstepy sie zgadzaly, ale tlo najechania rysuje sie na CALYM pudelku
     przycisku - ikona przestawala byc w nim na srodku i najechanie
     wygladalo na zepsute. */
  .logo__img{width:min(calc(100% - 24px),230px);margin-inline:auto}
}
@media(min-width:520px) and (max-width:999px){
  .header__bar{grid-template-columns:132px minmax(0,1fr) 132px}
}

/* Ponizej 360 px sciezka logo ma juz tylko okolo 104 px - odjecie z niej
   kolejnych 24 px zrobiloby ze znaku plamke. Na najwezszych ekranach logo
   wypelnia sciezke jak dotad, kosztem nierownych odstepow przy lupce. */
@media(max-width:359px){
  .logo__img{width:min(100%,230px)}
}

.nav{display:none}
@media(min-width:1000px){
  .nav{display:block;border-top:1px solid var(--line)}
  .nav__row{display:flex;justify-content:center;gap:2.1rem;min-height:50px;align-items:center}
  .nav a{
    font-family:var(--font-display);font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
    padding-block:.35rem;border-bottom:1px solid transparent;transition:border-color .2s,color .2s;
  }
  /* Odnosnik ma 31 px wysokosci i tyle musi miec, bo podkreslenie na hover
     rysuje sie tuz pod tekstem - powiekszenie pudelka odsunieloby je od slowa.
     Obszar klikniecia powiekszamy wiec warstwa, ktorej nie widac. Wiersz ma
     50 px, wiec pasmo 44 px miesci sie w nim bez dotykania sasiadow. */
  .nav a{position:relative}
  .nav a::after{
    content:"";position:absolute;left:-.4rem;right:-.4rem;top:50%;translate:0 -50%;height:44px;
  }
  .nav a:hover{border-bottom-color:var(--ink)}
  .nav a.is-accent{color:var(--ink)}
  .nav a.is-accent:hover{border-bottom-color:var(--ink)}
  .header__burger{display:none}

  /* --- Produkty z kategoriami --- */
  /* Rozwijane przyciskiem, nie najechaniem myszka: menu otwierane hoverem jest
     nieosiagalne z klawiatury i znika, gdy kursor przypadkiem zjedzie w bok. */
  .nav__item{position:relative;display:flex;align-items:center}
  .nav__toggle{
    display:inline-flex;align-items:center;gap:.35rem;
    font-family:var(--font-display);font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
    padding-block:.35rem;border-bottom:1px solid transparent;color:inherit;
    transition:border-color .2s,color .2s;
  }
  /* TEN SAM NIEWIDOCZNY PASEK DOTYKU CO PRZY ODNOSNIKACH.
     Przycisk rozwijajacy ma te same 31 px wysokosci co odnosnik obok i te
     sama potrzebe - a przy przebudowie menu zostal bez paska: "Produkty"
     i "Kontakt" mialy 31 px celu, reszta rzedu 44 px. Wyszlo w audycie
     z 01.09.2026. */
  .nav__toggle::after{
    content:"";position:absolute;left:-.4rem;right:-.4rem;top:50%;translate:0 -50%;height:44px;
  }
  .nav__toggle:hover{border-bottom-color:var(--ink)}
  .nav__strzalka{width:13px;height:13px;stroke:currentColor;stroke-width:1.6;fill:none;transition:rotate .2s}
  .nav__toggle[aria-expanded="true"] .nav__strzalka{rotate:180deg}

  /* --- mega menu --- */
  .nav{position:relative}
  .mega{
    position:absolute;top:100%;left:0;right:0;z-index:80;
    background:#fff;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
    box-shadow:0 18px 40px rgba(13,13,13,.10);
    /* visibility, nie display - zeby pozycje znikaly takze z kolejnosci
       tabulacji, a nie tylko z oczu (ta sama pulapka co przy szufladzie) */
    visibility:hidden;opacity:0;translate:0 -6px;
    transition:opacity .2s,translate .2s,visibility 0s .2s;
  }
  .nav__toggle[aria-expanded="true"] ~ .mega,
  .mega.jest-otwarte{
    visibility:visible;opacity:1;translate:0;
    transition:opacity .2s,translate .2s,visibility 0s;
  }
  /* Dwie kolumny odnosnikow o wlasnej szerokosci, a za nimi DWA kafelki
     tresci. Przy trzech kolumnach odnosnikow starczal jeden kafelek; po
     skroceniu menu do dwoch grup zostawalo po prawej pol szerokosci pustki. */
  .mega__grid{
    display:grid;grid-template-columns:repeat(2,minmax(0,190px)) repeat(2,minmax(0,1fr));
    gap:var(--s4);padding-block:var(--s4) var(--s5);align-items:start;
  }

  /* --- kontakt: kartka pod pozycja w belce ---
     Wczesniej byla to belka na cala szerokosc ekranu z trzema linijkami
     w rogu - panel wielkosci mega menu dla adresu i numeru. Teraz zwykla
     kartka zaczepiona pod slowem "Kontakt", z ikonami, zeby na pierwszy rzut
     oka bylo widac dane, a nie kolejne pozycje nawigacji.

     UWAGA na kolejnosc: ponizsze reguly maja te sama specyficznosc co
     ".nav a" (dwie klasy / klasa + element) i MUSZA stac za nimi. Postawione
     wyzej byly by po cichu kasowane i dane kontaktowe renderowaly by sie
     wersalikami jak pozycje menu. */
  .podmenu{
    position:absolute;top:calc(100% + .7rem);right:0;z-index:80;
    min-width:266px;padding:var(--s3);
    background:#fff;border:1px solid var(--line);
    box-shadow:0 18px 40px rgba(13,13,13,.10);
    visibility:hidden;opacity:0;translate:0 -6px;
    transition:opacity .2s,translate .2s,visibility 0s .2s;
  }
  .podmenu.jest-otwarte{
    visibility:visible;opacity:1;translate:0;
    transition:opacity .2s,translate .2s,visibility 0s;
  }
  .podmenu__lista{display:flex;flex-direction:column}
  .podmenu a,.podmenu__godziny{
    display:flex;align-items:center;gap:.65rem;min-height:40px;
    font-family:var(--text);font-size:.85rem;letter-spacing:0;text-transform:none;
    padding-block:0;border-bottom:none;color:var(--ink);white-space:nowrap;
  }
  /* Warstwa powiekszajaca klikniecie w belce nie ma tu czego powiekszac -
     wiersz sam ma 40 px - a rozciagnieta na 44 px zachodzilaby na sasiada. */
  .podmenu a::after{content:none}
  .podmenu a:hover{color:var(--navy);border-bottom:none}
  .podmenu__godziny{color:var(--muted);font-size:.78rem;min-height:34px;margin-top:.15rem}
  .podmenu svg{width:16px;height:16px;flex:none;stroke:var(--muted);stroke-width:1.4;fill:none}
  .mega__tytul{
    font-family:var(--font-display);font-size:.68rem;letter-spacing:var(--track);
    text-transform:uppercase;color:var(--muted);margin-bottom:var(--s2);
    padding-bottom:.5rem;border-bottom:1px solid var(--line);
  }
  .mega__kol ul{display:flex;flex-direction:column}
  .mega a{
    display:flex;align-items:center;min-height:44px;
    font-family:var(--text);font-size:.86rem;letter-spacing:0;text-transform:none;
    padding-block:0;border-bottom:none;
  }
  .mega a:hover{color:var(--navy);border-bottom:none}

  /* Selektor musi byc mocniejszy niz .mega a - inaczej kafelek dziedziczy
     display:flex i align-items:center, przez co zdjecie kurczy sie do paska,
     a napisy wchodza na siebie. */
  .mega a.mega__promo{
    display:block;min-height:0;background:var(--porcelain);padding:var(--s3);
  }
  .mega a.mega__promo:hover{color:inherit}
  .mega__promo-foto{display:block;aspect-ratio:4/3;overflow:hidden;margin-bottom:var(--s2)}
  .mega__promo-foto img{width:100%;height:100%;object-fit:cover;transition:scale .35s}
  .mega__promo:hover .mega__promo-foto img{scale:1.03}
  .mega__promo-nadtytul{
    display:block;font-family:var(--font-display);font-size:.63rem;
    letter-spacing:var(--track);text-transform:uppercase;color:var(--muted);
  }
  .mega__promo-tytul{
    display:block;font-family:var(--font-display);font-size:1.05rem;margin-block:.2rem .3rem;
  }
  .mega__promo-opis{display:block;font-size:.8rem;color:var(--muted);line-height:1.45}
}


/* Szuflada jest chowana transformem, ale sam transform nie zdejmuje jej
   z kolejnosci tabulacji - linki zostawaly fokusowalne przy zamknietym menu
   i fokus znikal poza ekranem na dziesiec nacisniec Tab. Dokladane
   visibility:hidden usuwa je tez z drzewa dostepnosci, a opoznienie
   przejscia (0s .32s) trzyma szuflade widoczna na czas wyjazdu. */
.drawer{
  position:fixed;inset:0 20% 0 0;min-width:300px;max-width:380px;background:#fff;z-index:90;
  transform:translateX(-102%);visibility:hidden;
  transition:transform .32s cubic-bezier(.4,0,.2,1),visibility 0s .32s;
  padding:var(--s3);overflow:auto;
}
.drawer[data-open="true"]{
  transform:none;visibility:visible;
  transition:transform .32s cubic-bezier(.4,0,.2,1),visibility 0s;
}
.drawer__head{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--s4)}
.drawer a{display:block;padding:.9rem 0;border-bottom:1px solid var(--line);font-family:var(--font-display);letter-spacing:.14em;text-transform:uppercase;font-size:.82rem}

/* Ponizsze reguly MUSZA stac za .drawer a. Maja te sama specyficznosc
   (jedna klasa + element), wiec o wyniku decyduje kolejnosc w pliku.
   Postawione wyzej byly po cichu kasowane i cala szuflada renderowala sie
   jednym krojem wersalikow, bez zadnej hierarchii. */
/* --- rozwijana grupa w szufladzie --- */
.drawer__toggle{
  display:flex;align-items:center;justify-content:space-between;width:100%;
  padding:.9rem 0;border-bottom:1px solid var(--line);
  font-family:var(--font-display);letter-spacing:.14em;text-transform:uppercase;font-size:.82rem;
  color:inherit;text-align:left;
}
.drawer__strzalka{width:16px;height:16px;stroke:currentColor;stroke-width:1.6;fill:none;transition:rotate .2s}
.drawer__toggle[aria-expanded="true"] .drawer__strzalka{rotate:180deg}
.drawer__grupa{padding-block:var(--s2);border-bottom:1px solid var(--line)}
.drawer__tytul{
  font-family:var(--font-display);font-size:.63rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);margin-block:var(--s3) .15rem;
}
.drawer__tytul:first-child{margin-top:0}
/* Pozycje w grupie sa nizszego rzedu, wiec bez wersalikow i bez kreski pod
   kazda - inaczej zwiniete menu wyglada jak druga nawigacja, nie jak podpunkty. */
/* Rozmiar mniejszy od pozycji nadrzednej i lagodniejszy kolor. Wczesniej
   podpunkty mialy 14,4 px przy 13,1 px pozycji nadrzednej, wiec poziom nizszy
   dominowal nad wyzszym. Pole dotyku zostaje pelne 44 px. */
.drawer__grupa a{
  padding:0 0 0 var(--s2);border-bottom:none;
  font-family:var(--text);letter-spacing:0;text-transform:none;font-size:.85rem;
  color:var(--ink-soft);min-height:44px;display:flex;align-items:center;
}
.drawer__grupa a:hover{color:var(--navy)}
/* Kontakt w szufladzie to DANE, nie kolejne pozycje menu - stad porcelanowe
   tlo, ikony i brak wersalikow. Bez tego trzy linijki wygladaly jak trzy
   nastepne odnosniki nawigacji. */
.drawer__grupa--kontakt{background:var(--porcelain);padding:var(--s2) var(--s3)}
.drawer__kontakt{display:flex;flex-direction:column}
.drawer__kontakt a,.drawer__kontakt-godziny{
  display:flex;align-items:center;gap:.65rem;min-height:44px;
  padding:0;border-bottom:none;
  font-family:var(--text);letter-spacing:0;text-transform:none;font-size:.85rem;
  color:var(--ink);
}
/* Godziny to przypis do danych kontaktowych, nie kolejna pozycja menu -
   drobniej i jasniej, zeby nie udawaly odnosnika. */
.drawer__kontakt-godziny{font-size:.78rem;color:var(--muted);min-height:36px}
.drawer__kontakt svg{width:17px;height:17px;flex:none;stroke:var(--muted);stroke-width:1.4;fill:none}

/* --- konto i kontakt --- */
/* Godziny to przypis do danych kontaktowych, nie kolejna pozycja menu:
   drobniej, jasniej i wciete do kolumny tekstu, zeby wyrownaly sie z numerem
   i adresem zamiast zaczynac od krawedzi.
   Jasniejszy szary niz --muted, ale nadal 4,64:1 na bieli - to tekst
   informacyjny, wiec 4,5:1 obowiazuje go tak samo jak reszte. */
.drawer .is-accent{color:var(--ink)}
.scrim{position:fixed;inset:0;background:rgba(13,13,13,.4);z-index:85;opacity:0;pointer-events:none;transition:opacity .3s}

/* =====================================================================
   MINI-KOSZYK
   ===================================================================== */
.koszyk{
  position:fixed;top:0;right:0;bottom:0;z-index:90;
  width:min(420px, 100%);background:#fff;display:flex;flex-direction:column;
  transform:translateX(102%);visibility:hidden;
  transition:transform .32s cubic-bezier(.4,0,.2,1),visibility 0s .32s;
}
.koszyk[data-open="true"]{
  transform:none;visibility:visible;
  transition:transform .32s cubic-bezier(.4,0,.2,1),visibility 0s;
}
.koszyk__head{
  display:flex;justify-content:space-between;align-items:center;
  padding:var(--s3);border-bottom:1px solid var(--line);flex:0 0 auto;
}
/*
 * PRZEZROCZYSTE OPAKOWANIE. Makieta ma pasek postepu, liste i stopke wprost
 * w panelu; u nas obejmuje je jeszcze ".koszyk__body", bo to ONO jest
 * fragmentem podmienianym po kazdej zmianie koszyka. Bez tych trzech linii
 * lancuch ukladu urywal sie na nim: lista nie miala sie gdzie przewijac,
 * wiec przy czterech pozycjach rosla poza ekran i SPYCHALA STOPKE
 * z "Przejdź do kasy" poza widok.
 *
 * min-height:0 jest tu tak samo wazne jak flex - bez niego element w kolumnie
 * nie kurczy sie ponizej wysokosci swojej tresci i przewijanie znowu nie ma
 * gdzie sie wydarzyc.
 */
.koszyk__body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.koszyk__cofnij{flex:0 0 auto}
/* Podpis panelu jest <h2>, a wyglada jak nadtytul z makiety - stad wlasna
   regula zamiast domyslnego stopnia naglowka. */
.koszyk__head h2{font-family:var(--font-display);font-size:.72rem;letter-spacing:var(--track);text-transform:uppercase;font-weight:400}
.koszyk__licznik{color:var(--muted)}

/* --- pasek progu darmowej dostawy --- */
.koszyk__prog{padding:var(--s3) var(--s3) var(--s2);flex:0 0 auto}
/* Przy odbiorze osobistym i w pustym koszyku pasek nie ma tresci - bez tego
   zostawialby po sobie 32 px pustego marginesu. */
.koszyk__prog:empty{display:none}
.koszyk__prog p{font-size:.85rem;margin-bottom:.5rem}
.koszyk__prog b{font-family:var(--font-display);letter-spacing:.03em}
.koszyk__pasek{height:4px;background:var(--line);overflow:hidden}
.koszyk__pasek span{
  display:block;height:100%;background:var(--navy);
  transition:width .35s cubic-bezier(.4,0,.2,1);
}
/* JEDYNE miejsce, w ktorym zostaje braz (decyzja Klientki z 10.08.2026).
   Niesie tu stan - "prog darmowej dostawy osiagniety" - a nie dekoracje,
   i wyroznia sie na tle pozostalych komunikatow w koszyku. Na bialym tle
   panelu ma 6,95:1, wiec z zapasem przechodzi prog WCAG AA.
   Wszedzie indziej braz zszedl: histogram ocen, nadtytuly, gwiazdki. */
.koszyk__prog--osiagniety .koszyk__pasek span{background:var(--sienna)}
.koszyk__prog--osiagniety p{color:var(--sienna)}
.koszyk__prog--osiagniety p{display:flex;align-items:center;gap:.4rem}
.koszyk__ptaszek{width:16px;height:16px;flex:0 0 auto;stroke:currentColor;stroke-width:2;fill:none}

/* Adnotacja przy karcie podarunkowej - musi byc widoczna od razu, inaczej
   klientka nie zrozumie, czemu pasek nie drgnal po jej dodaniu. */
.koszyk__adnotacja{
  font-size:.72rem;color:var(--muted);margin-top:.5rem;
  padding-left:.6rem;border-left:2px solid var(--line-strong);
}
.koszyk__jednostkowa{font-size:.75rem;color:var(--muted);text-align:right;margin-top:.15rem}

/* --- pozycje --- */
.koszyk__tresc{flex:1 1 auto;overflow-y:auto;padding:0 var(--s3)}
.koszyk__poz{
  display:grid;grid-template-columns:72px 1fr auto;gap:var(--s2);
  padding-block:var(--s3);border-bottom:1px solid var(--line);align-items:start;
}
.koszyk__foto{background:var(--porcelain);aspect-ratio:1;overflow:hidden}
.koszyk__foto img{width:100%;height:100%;object-fit:cover}
.koszyk__nazwa{font-family:var(--font-display);font-size:.9rem;letter-spacing:.04em}
.koszyk__wariant{font-size:.78rem;color:var(--muted);margin-top:.15rem}
.koszyk__cena{font-family:var(--font-display);font-size:.95rem;text-align:right;white-space:nowrap}

/* Stepnik ilosci: dwa pola po 44 px, bo to najczestsza droga do dobicia
   koszyka do progu darmowej dostawy. */
.koszyk__ilosc{display:flex;align-items:center;gap:.25rem;margin-top:.6rem}
.koszyk__ilosc button{
  width:44px;height:44px;display:grid;place-items:center;
  border:1px solid var(--line-control);border-radius:var(--radius);
  font-size:1rem;line-height:1;color:var(--ink);transition:background .2s,border-color .2s;
}
.koszyk__ilosc button:hover{background:var(--porcelain);border-color:var(--ink)}
.koszyk__ilosc button[disabled]{opacity:.4;cursor:not-allowed}
.koszyk__ilosc output{min-width:2.2rem;text-align:center;font-size:.9rem}
.koszyk__usun{
  /* min-width, bo samo slowo "Usun" ma 43 px - o jeden za malo. Tekst zostaje
     dosuniety do prawej, wiec pudelko rosnie w lewo i nic sie nie przesuwa. */
  display:block;margin-top:.6rem;margin-left:auto;min-height:44px;min-width:44px;text-align:right;
  font-size:.78rem;color:var(--muted);text-decoration:underline;
  text-underline-offset:3px;transition:color .2s;
}
.koszyk__usun:hover{color:var(--ink)}
/* Odnosnik usuwania nosi tez klasy WooCommerce (to one uruchamiaja usuwanie
   bez przeladowania strony), a razem z nimi przychodzi styl krzyzyka: pismo
   1,5 raza wieksze, okragle tlo i pozycja bezwzgledna. Zdejmujemy go tutaj -
   selektor z trzema klasami wygrywa z "a.remove" ze sklepu. */
.koszyk .koszyk__usun.remove,
.woocommerce .koszyk__usun.remove{
  position:static;width:auto;height:auto;line-height:inherit;border-radius:0;
  background:none;font-size:.78rem;font-weight:400;text-decoration:underline;
  /* Kolor z !important, bo sklep tez pisze go z !important - a czerwien
     krzyzyka woła w wysuwanym koszyku glosniej niz "Przejdz do kasy". */
  color:var(--muted)!important;
}
.koszyk .koszyk__usun.remove:hover,
.woocommerce .koszyk__usun.remove:hover{background:none;color:var(--ink)!important}

/* --- cofniecie usuniecia ---
   Makieta zostawila ten pasek bez stylu - rysowal go skrypt, ktory dopiero
   pokazywal, ze taka funkcja ma byc. Ubieramy go w to samo, co reszta
   panelu: porcelanowe tlo, drobne pismo i podkreslone "Cofnij". */
.koszyk__cofnij{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  margin:0 var(--s3);padding:.7rem .9rem;background:var(--porcelain);font-size:.82rem;
}
.koszyk__cofnij span{color:var(--muted)}
/* 44 px wysokosci celu daje NIEWIDOCZNE PASMO ::after, a nie ujemne marginesy:
   przy marginesach podkreslenie odnosnika wychodzilo poza tlo paska i wisialo
   pod nim jak kreska nie wiadomo czego. Ten sam wzorzec co przy okruszkach
   i menu prawnym w stopce. */
.koszyk__cofnij-akcja{
  position:relative;flex:0 0 auto;display:inline-block;padding-inline:.2rem;
  font-family:var(--font-display);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink);border-bottom:1px solid var(--ink);
}
.koszyk__cofnij-akcja::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}
.koszyk__cofnij-akcja:hover{color:var(--navy);border-bottom-color:var(--navy)}


/* --- pusty koszyk --- */
.koszyk__pusto{padding-block:var(--s5);text-align:center}
.koszyk__pusto p{color:var(--muted);margin-bottom:var(--s3)}

/* --- stopka --- */
/* Na telefonie stopka zostaje w zasiegu kciuka, a lista przewija sie nad nia. */
.koszyk__stopka{
  flex:0 0 auto;padding:var(--s3);border-top:1px solid var(--line);background:#fff;
}
.koszyk__suma{display:flex;justify-content:space-between;align-items:baseline;font-size:.9rem}
.koszyk__suma b{font-family:var(--font-display);font-size:1.15rem;letter-spacing:.03em}
.koszyk__uwaga{font-size:.78rem;color:var(--muted);margin-block:.35rem var(--s2)}
.koszyk__pelny{text-align:center;margin-top:var(--s2)}
.scrim[data-open="true"]{opacity:1;pointer-events:auto}



/* --- okruszki ---
   Regula siedzi w POWLOCE, a nie przy pojedynczej makiecie. Powstala
   przy karcie produktu i trzy razy z rzedu zapominalismy jej przeniesc
   przy budowie kolejnej strony ze sciezka nawigacji - za kazdym razem
   audyt wylapywal okruszki o wysokosci 20 px zamiast 44. */
.okruszki{padding-block:var(--s3) 0;font-size:.78rem;color:var(--muted)}
/* Okruszki i naglowek strony to jeden blok. Kazdy z nich mial wlasny
   odstep, wiec na styku sumowaly sie dwa i naglowek odjezdzal w dol.
   Odstep jest teraz jeden i taki sam na wszystkich makietach.
   Uwaga: to samo miejsce w arkuszu co reguly ponizej - dlatego bloki
   docelowe ustawiaja WYLACZNIE padding-block-end, zeby o gornym
   odstepie nie decydowala kolejnosc regul. */
.okruszki + *{padding-block-start:var(--s3)}
.okruszki .wrap{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center}
/* Makieta pisala ukosniki jako osobne <span aria-hidden>. Tu sciezke buduje
   WooCommerce i wstawia <li>, wiec ukosnik rysuje arkusz - a przy okazji
   nigdy nie trafi do czytnika ekranu ani do schowka. */
/* Reset elementow obejmuje <ul>, a WooCommerce buduje okruszki na <ol> -
   zostawaly wiec domyslne marginesy przegladarki i pasek mial 76 px zamiast
   64 px z makiety. */
.okruszki ol{margin-block:0;list-style:none}
.okruszki li{display:inline-flex;align-items:center;gap:.4rem}
.okruszki li + li::before{content:"/";color:var(--muted)}
/* --line-strong ma 1,73:1 - jako znak w tekscie byl praktycznie niewidoczny. */
.okruszki span[aria-hidden]{color:var(--muted)}
/* Wysokosc byla juz na 44 px, ale krotkie nazwy ("Serum") dawaly 38 px
   szerokosci. Ujemny margines cofa to, co dodaje padding, wiec obszar
   klikniecia rosnie, a odstepy wokol ukosnikow zostaja bez zmian. */
.okruszki a{min-height:44px;display:inline-flex;align-items:center;
            padding-inline:.4rem;margin-inline:-.4rem}
.okruszki a:hover{color:var(--ink)}

/* =====================================================================
   STOPKA
   ===================================================================== */
.footer{background:var(--ink);color:rgba(255,255,255,.72);padding-block:var(--s6) var(--s4);font-size:.85rem}
.footer a:hover{color:#fff}
.footer__grid{display:grid;gap:var(--s5)}
/* minmax(0,…) w obu progach: sciezka grida domyslnie nie kurczy sie ponizej
   swojej tresci, wiec przy powiekszonym tekscie stopka wypychala cala
   strone w bok. Widac to dopiero przy powiekszeniu do 200%. */
@media(min-width:560px){.footer__grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5) var(--s4)}}
/*
 * Trzy kolumny na waskich laptopach, szesc dopiero od 1200 px (zyczenie
 * Klientki z 28.08.2026).
 *
 * Szesc kolumn wchodzilo wczesniej juz od 900 px i przy tej szerokosci na
 * kolumne zostawalo 87 px - dziesiec odnosnikow lamalo sie na dwa wiersze,
 * a "Panel profesjonalisty" na trzy. Przy trzech kolumnach kazda ma ponad
 * 240 px i nie lamie sie nic.
 */
@media(min-width:900px){
  .footer__grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s5) var(--s4)}
}
@media(min-width:1200px){
  /*
   * Kolumna kontaktu nie schodzi ponizej min-content, czyli ponizej dlugosci
   * adresu e-mail. To jedno slowo, ktorego nie da sie zlamac sensownie:
   * "sklep@alphascience.com.pl" potrzebuje 179 px, a przy rownym podziale
   * dostawal 168 px i schodzil do drugiego wiersza (zyczenie Klientki
   * z 28.08.2026, zeby mieszcil sie w jednej linii).
   *
   * Kolumna marki oddaje na to szerokosc: 1,5fr -> 1,4fr. Reszta bez zmian.
   * min-content zamiast wpisanej liczby, bo adres moze sie kiedys zmienic -
   * wtedy kolumna dopasuje sie sama, zamiast lamac sie po cichu.
   */
  .footer__grid{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr)) minmax(min-content,1.2fr);gap:var(--s4)}
  .footer__brand{grid-row:span 1}
}
.footer h2{font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:#fff;margin-bottom:var(--s2);font-weight:400}
/* Listy linkow w stopce stoja w pionie, wiec zamiast warstwy ::after
   (pasma sasiadow zachodzilyby na siebie) dostaja realne 44 px wysokosci.
   :not(.social) jest konieczne - ikony spolecznosciowe centruja ikonke
   przez display:grid i place-items, a display:flex z tej reguly to psul. */
.footer ul:not(.social):not(.footer__prawne-lista) li a{display:flex;align-items:center;min-height:44px}
.footer__about{margin-top:var(--s3);max-width:34ch;color:rgba(255,255,255,.6)}
/* Adres e-mail to jeden dlugi ciag bez spacji - przy powiekszonym tekscie
   nie mial gdzie sie zlamac i wypychal cala stopke poza ekran. */
/*
 * Adres e-mail bez lamania. Przegladarka chetnie dzieli go po malpie i po
 * kropkach, wiec sama minimalna szerokosc kolumny tego nie zalatwiala:
 * min-content wypadalo na najdluzszym KAWALKU adresu, a nie na calym.
 * Z nowrap min-content to caly adres i kolumna nie zejdzie ponizej niego.
 */
.contact a[href^="mailto:"]{white-space:nowrap}
.contact li{min-height:44px;display:flex;align-items:center;color:rgba(255,255,255,.72);
            overflow-wrap:anywhere}
.contact li a{align-self:stretch;display:flex;align-items:center}

/* media społecznościowe */
.social{display:flex;gap:var(--s2);margin-top:var(--s4)}
.social a{
  width:44px;height:44px;display:grid;place-items:center;border:1px solid rgba(255,255,255,.25);
  border-radius:99px;color:rgba(255,255,255,.8);transition:background .2s,color .2s,border-color .2s;
}
.social a:hover{background:#fff;color:var(--ink);border-color:#fff}
.social svg{width:19px;height:19px;stroke:currentColor;stroke-width:1.4;fill:none}

/* płatności i dostawa */
.footer__badges{
  margin-top:var(--s6);padding-top:var(--s4);border-top:1px solid rgba(255,255,255,.15);
  display:grid;gap:var(--s4);
}
@media(min-width:700px){.footer__badges{grid-template-columns:auto auto;justify-content:space-between;gap:var(--s5)}}
.badge-set{display:grid;gap:var(--s2)}
.badge-set__label{font-family:var(--font-display);font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.pays{display:flex;gap:var(--s1);flex-wrap:wrap}
.pays span{border:1px solid rgba(255,255,255,.25);padding:.4rem .7rem;font-size:.6rem;letter-spacing:.12em;font-family:var(--font-display);text-transform:uppercase;color:rgba(255,255,255,.75)}
.footer__bottom{
  margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid rgba(255,255,255,.15);
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);justify-content:space-between;font-size:.73rem;color:rgba(255,255,255,.55);
}
/* Odnosnik podkreslony ("Zobacz koszyk", "Edytuj koszyk") stoi samodzielnie
   w wierszu, a ma tylko 34 px wysokosci - za malo na kciuk. Cel dotyku
   powieksza NIEWIDOCZNE PASMO, wiec wiersz zostaje niski, a klikniecie
   lapie sie z zapasem. Ten sam wzorzec co przy okruszkach. */
.link-u{position:relative;display:inline-block}
.link-u::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}

/* Menu prawne w wierszu, a nie kolumna.
   Bez tej reguly lapala je ogolna regula stopki, ktora robi z kazdego
   odnosnika blok o wysokosci 44 px - w pasku na dole wygladalo to jak
   wypunktowana lista jedna pozycja pod druga.
   Pole dotyku zostaje: daje je niewidoczne pasmo ::after, tak samo jak
   przy okruszkach i pozycjach paska gornego. */
.footer__prawne-lista{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3)}
.footer__prawne-lista a{position:relative;display:inline-block}
.footer__prawne-lista a::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}

/* =====================================================================
   RUCH

   Zasady, ktorych tu pilnujemy:
   1. Animujemy wylacznie opacity i transform. Obie liczy kompozytor, wiec
      nie ruszaja ukladu i nie generuja przesuniec tresci (CLS).
      Nigdy height, top ani margin.
   2. Hero zostaje POZA animacja wejscia. To element LCP - start od
      opacity:0 wprost pogorszylby Largest Contentful Paint, a prog
      wydajnosci mamy w umowie.
   3. Stan poczatkowy siedzi pod klasa "js" (ustawiana w <head>), wiec bez
      JavaScriptu tresc jest po prostu widoczna.
   ===================================================================== */

.js .reveal{opacity:0;transform:translateY(12px)}
.js .reveal.is-in{
  opacity:1;transform:none;
  transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .5s cubic-bezier(.4,0,.2,1);
}

/* Kolejne elementy w siatce wchodza z opoznieniem 60 ms. Indeks --i
   ustawia skrypt, zeby nie pisac nth-child dla kazdej sekcji z osobna.
   Opoznienie jest zamkniete na 6 krokach - przy dluzszych listach dalsze
   kafelki zaczynaja sie zauwazalnie spozniac. */
.js .reveal-group > *{opacity:0;transform:translateY(12px)}
.js .reveal-group.is-in > *{
  opacity:1;transform:none;
  transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .5s cubic-bezier(.4,0,.2,1);
  transition-delay:calc(min(var(--i,0),6) * 60ms);
}

/* Naglowek po przewinieciu oddaje troche pionu. Zmieniamy min-height
   samego paska, a nie rozmiar logo - brand book zabrania schodzenia
   ponizej deklarowanej szerokosci znaku. */
.header__bar,.nav__row{transition:min-height .28s cubic-bezier(.4,0,.2,1)}
@media(min-width:1000px){
  .header[data-stuck="true"] .header__bar{min-height:52px}
  .header[data-stuck="true"] .nav__row{min-height:40px}
}

/* Zdjecie w hero dochodzi powoli przy wczytaniu. Sama skala, bez
   przewijania i bez paralaksy - obraz jest juz narysowany, wiec LCP na tym
   nie traci. */
.hero__media img{transition:transform 1.2s cubic-bezier(.4,0,.2,1)}
.js .hero__media img{transform:scale(1.04)}
.js .hero__media img.is-ready{transform:none}

/* Liczniki: cyfry o stalej szerokosci, zeby napis nie drgal przy zliczaniu. */
.count{font-variant-numeric:tabular-nums}

/* Kontener po skoku z linku pomijajacego nie musi rysowac obwodki. */
main:focus{outline:none}

@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important;scroll-behavior:auto!important}}

@media(max-width:899px){
  /* Wyszukiwarka na telefonie ma uzywac calej szerokosci.
     Domyslnie siedziala wysrodkowana w siatce naglowka i miala 186 px
     na ekranie 375 px - jedna trzecia szerokosci szla w nic. */
  .header__bar > .szukajka{ justify-self:stretch; width:100% }
}

/* Kolumna marki znika TYLKO w ukladzie jednokolumnowym, czyli ponizej 560 px
   (zyczenie Klientki z 28.08.2026).
   
   Powod jest ukladowy, nie estetyczny: przy jednej kolumnie marka stoi NAD
   odnosnikami i spycha je w dol - klientka na telefonie przewija znak
   i dwa zdania o marce, zanim dojdzie do czegokolwiek klikalnego. Od dwoch
   kolumn marka ma wlasna kolumne OBOK odnosnikow i nie zabiera im miejsca,
   wiec zostaje widoczna razem z opisem i ikonami.
   
   Chowamy cala kolumne, a nie jej zawartosc: pusty element siatki zostawialby
   48 px pustki na gorze stopki. */
@media(max-width:559px){
  .footer__brand{ display:none }
}




/* --- brakujace kawalki z makiety karty produktu (uzupelnione 28.08.2026) ---
   Wypadly z przenoszonych zakresow. Bez nich pytania i odpowiedzi renderowaly
   sie jako gole <details> przegladarki (sekcja miala 347 px zamiast 467),
   a naglowek bloku zakupowego bral rozmiar z .h-l zamiast wlasnego. */
.zakup h1{font-weight:400}

/* SZEROKOSC KOLUMNY, nie 780 px na srodku. Ograniczenie przyszlo z makiety
   karty produktu, gdzie pytania stoja w waskiej sekcji opisu - a tam i tak
   zdejmowala je regula ponizej. Na stronie glownej sekcja pytan ma pelna
   szerokosc kolumny, tak jak w makiecie strony glownej. */
.faq{border-top:1px solid var(--line-strong)}
.faq details{border-bottom:1px solid var(--line-strong)}
/* BLOK, NIE FLEX. Przy display:flex z rozsunieciem kazdy znacznik w tresci
   pytania - pogrubienie, znak zastrzezony - stawal sie osobnym polem i tekst
   rozjezdzal sie na cala szerokosc: "Czym NextGen   (R)   rozni sie...".
   Znacznik +/- ustawiony bezwzglednie znosi to raz, dla kazdego pytania. */
.faq summary{
  list-style:none;cursor:pointer;padding-block:var(--s3);display:block;position:relative;
  padding-right:2.5rem;font-family:var(--font-display);font-size:.95rem;letter-spacing:.04em;min-height:56px;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"+";color:var(--navy);font-size:1.25rem;line-height:1;
  position:absolute;right:0;top:50%;transform:translateY(-50%);
}
.faq details[open] summary::after{content:"–"}
.faq p{font-size:.9rem;color:var(--muted);padding-bottom:var(--s3);text-wrap:pretty}

.posts .post p.post__czytaj,
.rail .post p.post__czytaj{margin-top:auto;padding-top:var(--s2)}
.post__czytaj a{display:inline-flex;align-items:center;min-height:44px}

/* =====================================================================
   WPISY Z BLOGA I STRZALKI PASOW - przeniesione z makiety 28.08.2026
   =====================================================================
   Kafelek wpisu (.post) jest ten sam co w bazie wiedzy, a strzalki (.rail-nav)
   obsluguja kazdy pas przewijany w bok. Zrodlo: docs/makiety/karta-produktu.html
   - przy zmianie wygladu poprawiamy OBA miejsca albo zadne.
   ===================================================================== */
#zbloga .sec-head__aside{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.rail-nav{display:flex;gap:.5rem}
.rail-nav button{
  width:44px;height:44px;display:grid;place-items:center;
  border:1px solid var(--line-control);transition:background .2s,color .2s,opacity .2s;
}
.rail-nav button:hover:not(:disabled){background:var(--ink);color:#fff;border-color:var(--ink)}
.rail-nav button:disabled{opacity:.35;cursor:default}
.rail-nav svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.5}

/* Jedna kolumna tez musi byc minmax(0,1fr): przy samym display:grid kolumna
   nie moze zwezic sie ponizej zawartosci i kadr produktu rozpychal strone
   na telefonie o 2665 px. */
.posts{display:grid;gap:var(--s5);grid-template-columns:minmax(0,1fr)}
/* minmax(0,1fr), a nie samo 1fr: "1fr" znaczy minmax(auto,1fr), wiec kolumna
   nie moze zwezic sie ponizej wlasnej zawartosci. Wystarczyl jeden kadr
   produktu w wynikach wyszukiwania, zeby pierwsza kolumna urosla do 3000 px
   i wypchnela dwie pozostale do 100 px. */
@media(min-width:620px){.posts{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4)}}
@media(min-width:900px){.posts{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* KAFELEK TYLKO W SIATCE ALBO W PASIE.
   post_class() dokłada klasę "post" także do <article> pojedynczego wpisu -
   bez tego zawężenia reguły kafelka wchodziły w treść artykułu i lead
   dostawał 0,85 rem w kolorze --muted zamiast 1,05 rem w --ink-soft. */
.posts .post,
.rail .post{display:flex;flex-direction:column}
.post__media{aspect-ratio:16/10;background:#eceae6;overflow:hidden}
.post__media img{width:100%;height:100%;object-fit:cover;transition:transform .6s ease}
.post:hover .post__media img{transform:scale(1.035)}
.posts .post .eyebrow,
.rail .post .eyebrow{margin-top:var(--s3)}
/* Naglowki wpisow w tej samej konwencji co wyrozniony wpis i kafelki
   produktow: wersaliki w kroju naglowkowym. Zyczenie Klientki
   z 27.08.2026 - pierwszy wpis wygladal inaczej niz kolejne.
   Rozmiar zostaje kaflowy; hero jest wiekszy, bo jest hero. */
.posts .post h3,
.rail .post h3{
  font-family:var(--font-display);font-size:1rem;letter-spacing:.12em;
  text-transform:uppercase;font-weight:400;line-height:1.35;margin-top:var(--s1);
}
@media(min-width:800px){.posts .post h3,.rail .post h3{min-height:2.6em}}
/* Tytul w jednej linii ma 24 px wysokosci. "Czytaj" pod spodem ma pelne
   44 px, wiec wymog wielkosci pola jest spelniony, ale w tytul i tak sie
   celuje - dostaje wiec to samo niewidoczne pasmo co reszta odnosnikow.
   Pod tytulem stoi zajawka, nie odnosnik, wiec pasmo nie zachodzi na nic. */
.posts .post h3 a,
.rail .post h3 a{position:relative}
.posts .post h3 a::after,
.rail .post h3 a::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}
.posts .post p,
.rail .post p{font-size:.85rem;color:var(--muted);margin-top:var(--s1);text-wrap:pretty}

.wpis{height:100%}
/* Metadane stoja NAD tytulem, wiec przejmuja odstep, ktory na stronie glownej
   ma nadtytul. */
.wpis .wpis-meta{margin-top:var(--s3)}
.wpis h3{margin-top:var(--s1)}
/* Nazwa ma mniej niz 44 px wysokosci, a powiekszenie pudelka podnioslo by cala
   siatke - stad niewidoczne pasmo dotyku, tak samo jak w kafelkach produktow. */
.wpis h3 a{position:relative}
.wpis h3 a::after{content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px}
.wpis__zajawka{flex:1}
.wpis__czytaj{margin-top:auto;padding-top:var(--s2)}
.wpis__czytaj a{display:inline-flex;align-items:center;min-height:44px}
@media(max-width:619px){.wpis .wpis-meta{margin-top:var(--s2)}}

/* Metadane kafelka: dzial, data, czas czytania. NIE w arkuszu bazy wiedzy,
   bo ten sam kafelek stoi na stronie glownej i w wynikach wyszukiwania. */

.wpis-meta{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem .7rem;font-size:.78rem;color:var(--muted)}
/* Te same wartosci co .eyebrow w powloce - dzial na kafelku wyglada tak samo
   jak kategoria na stronie glownej. */
.wpis-meta__dzial{
  font-family:var(--font-display);font-size:.68rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);
}
/* Kropka rozdzielajaca rysowana PRZED elementem, a nie stojaca osobno.
   Jako samodzielny element zostawala sierota na koncu zawinietego wiersza. */
.wpis-meta > * + *::before{
  content:"";display:inline-block;vertical-align:middle;
  width:3px;height:3px;border-radius:99px;background:var(--line-control);
  margin-right:.55rem;translate:0 -1px;
}


/* =====================================================================
   KARTA PRODUKTU - przeniesiona z makiety 28.08.2026
   =====================================================================
   Kafelki produktow, zestawy, oceny i cytaty, galeria, blok zakupowy,
   harmonijka sekcji ze spisem tresci i przyklejony pasek zakupu.
   Zrodlo: docs/makiety/karta-produktu.html - przy zmianie wygladu
   poprawiamy OBA miejsca albo zadne.
   ===================================================================== */
.rail{
  display:grid;grid-auto-flow:column;grid-auto-columns:72%;gap:var(--s3);
  overflow-x:auto;scroll-snap-type:x proximity;padding-bottom:var(--s3);scrollbar-width:none;
  /* Gest nie ucieka na strone. Bez tego dojechanie palcem do konca pasa
     ciagnie za soba cala strone - i wyglada to, jakby plywala. Galeria
     miniatur miala to od poczatku, pasy nie. */
  overscroll-behavior-x:contain;
  margin-inline:calc(var(--pad)*-1);padding-inline:var(--pad);scroll-padding-inline:var(--pad);
}
.rail::-webkit-scrollbar{display:none}
.rail>*{scroll-snap-align:start}
@media(min-width:640px){.rail{grid-auto-columns:42%}}
@media(min-width:1000px){
  .rail{grid-auto-flow:row;grid-template-columns:repeat(3,1fr);overflow:visible;
        margin-inline:0;padding-inline:0;gap:var(--s6) var(--s4)}
  /* Przy dwoch pozycjach trzecia kolumna zostawala pusta i kafelki wisialy
     przy lewej krawedzi pod wysrodkowanym naglowkiem. Siatka idzie za liczba
     kafelkow, wiec dziala tez, gdy rekomendacji bedzie inna liczba. */
  .rail:has(> :nth-child(2):last-child){grid-template-columns:repeat(2,1fr)}
  .rail:has(> :first-child:last-child){grid-template-columns:minmax(0,420px);justify-content:center}
}
.card{display:flex;flex-direction:column;height:100%}
.card__media{position:relative;aspect-ratio:1/1;background:#fff;border:1px solid var(--line);overflow:hidden}
.card__media img{width:100%;height:100%;object-fit:cover;transition:transform .6s ease}
.card:hover .card__media img{transform:scale(1.035)}
.card__tag{
  position:absolute;top:var(--s2);left:var(--s2);z-index:2;background:#fff;color:var(--ink);
  font-family:var(--font-display);font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;padding:.35rem .6rem;
}
.card__tag--accent{background:var(--navy);color:#fff}



/* Stan wcisniety wieszamy na aria-pressed - jedno zrodlo prawdy dla oka
   i dla czytnika ekranu. Tak samo jak w module Docket\Wishlist. */


.card__body{padding-top:var(--s3);display:flex;flex-direction:column;gap:.4rem;flex:1}
.card__cat{font-family:var(--font-display);font-size:.62rem;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
/* Dlugie nazwy lamia sie w srodku wyrazu, gdy inaczej sie nie da:
   "ANTYOKSYDACYJNE" w kafelku o szerokosci 158 px (dwie kolumny na telefonie)
   wystawalo poza kafelek o 15 px. Lamanie w srodku wyrazu jest brzydsze niz
   przelamanie po spacji, ale ladniejsze niz napis wychodzacy poza ramke. */
.card__name{font-family:var(--font-display);font-size:1rem;letter-spacing:.12em;text-transform:uppercase;font-weight:400;overflow-wrap:anywhere}
.koszyk__nazwa{overflow-wrap:anywhere}
.card__desc{font-size:.82rem;color:var(--muted);text-wrap:pretty}
.stars{display:flex;align-items:center;gap:.4rem;font-size:.72rem;color:var(--muted);margin-top:auto;padding-top:var(--s2)}
.stars svg{width:13px;fill:var(--ink)}
/* margin-top:auto - stopka kafelka siada na jego dole. Bez tego cena
   i przycisk wisialy tuz pod opisem, a opisy maja rozna dlugosc:
   w jednym rzedzie dwie ceny stały na roznej wysokosci. */
/* flex-wrap, bo w sklepie cena bywa dluzsza niz w makiecie: zakres "od-do"
   przy wariantach albo kwota z dopiskiem podatkowym. Bez zawijania przycisk
   nie miescil sie w kafelku i wystawal poza siatke - strona dawala sie wtedy
   przewinac w bok. */
.card__foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s2);padding-top:var(--s2);margin-top:auto}
/* Kwota nigdy sie nie lamie. "349 zl" rozpadalo sie na "349" i "zl"
   w dwoch wierszach - zglosila to Klientka ze zdjecia z iPhone'a. */
.price,.price--stara{white-space:nowrap}
/* Na telefonie siatka ma DWIE kolumny, wiec kafelek ma 152 px. Cena obok
   przycisku "Do koszyka" nie miesci sie w tej szerokosci - lamaly sie oba.
   Pytamy o szerokosc KAFELKA, nie ekranu: ten sam kafelek stoi tez
   w przewijanej tasmie na stronie glownej, gdzie ma 335 px i lamac sie
   nie musi. Starsze przegladarki bez zapytan kontenerowych zachowuja sie
   jak dotad, a kwota i tak jest juz nierozdzielna. */
.card__body{container-type:inline-size}
@container (max-width:239px){
  /* Zawijanie, a nie kolumna: cena i przekreslona cena zostaja obok siebie
     w pierwszym wierszu, a przycisk schodzi pod nie na cala szerokosc.
     W kolumnie kafelek z promocja mial trzy wiersze zamiast dwoch i jego
     cena stala 30 px wyzej niz cena sasiada w tym samym rzedzie. */
  .card__foot{flex-wrap:wrap;justify-content:flex-start;gap:.55rem}
  .card__add,.card__zobacz{flex:1 0 100%}
}
.price{font-family:var(--font-display);font-size:1.05rem;letter-spacing:.06em}
/* Cene w kafelku rysuje sklep, wiec przychodzi w JEGO znacznikach: <del> ze
   stara kwota, <ins> z nowa (w tej kolejnosci), sufiks podatkowy i nota
   Omnibusa. Makieta ma odwrotnie - najpierw kwota do zaplaty, potem
   przekreslona. Ustawiamy kolejnosc wyswietlania zamiast skladac cene
   samodzielnie: inaczej stracilibysmy zakres "od-do" przy wariantach
   i zgodnosc not cenowych, ktorych wymaga dyrektywa Omnibus. */
.card__cena{font-family:var(--font-display);font-size:1.05rem;letter-spacing:.06em;white-space:nowrap}
/* Ukladem w wiersz rzadzi wspolna zasada dla cen (nizej) - ale tylko przy
   PRZECENIE. Poza nia cena zostaje zwyklym tekstem: zakres "od 219 zl do
   349 zl" rozbity na osobne pola siatki lamal sie w polowie, na "219 zl -"
   i "349 zl" w drugim wierszu. */
.card__cena--promo{white-space:normal}
.card__cena--promo ins,
.card__cena--promo del{white-space:nowrap}
.card__cena del{font-size:.76em}
/* Na telefonie cena odrobine wieksza (zyczenie Klientki z 27.08.2026).
   Kafelki sa tam wezsze, wiec ta sama liczba czytala sie drobniej niz
   na komputerze. Tylko w kafelku - w koszyku i na pasku zakupu cena
   ma wlasna skale i nie ma powodu jej ruszac. */
@media(max-width:899px){.card .price{font-size:1.18rem}}
/* "Do koszyka" w kolorze akcji, wypelnione. Wczesniej byl to przycisk
   z czarna ramka - taki sam jak kazdy inny na stronie, wiec nie odrozniał
   sie niczym od "Czytaj" czy "Zobacz wiecej". */
.card__add{
  /* W makiecie to <button>, u nas <a> - dodawanie do koszyka z listy robi
     skrypt sklepu, ktory nasluchuje na odnosniku. Odnosnik nie centruje
     napisu sam z siebie: gdy przycisk bral cala szerokosc kafelka (waskie
     kolumny na telefonie), "Do koszyka" stalo przy lewej krawedzi. */
  display:inline-flex;align-items:center;justify-content:center;text-align:center;
  background:var(--akcja);color:#fff;border:1px solid var(--akcja);
  min-height:44px;padding:0 1rem;border-radius:var(--radius);
  font-family:var(--font-display);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  transition:background .2s,border-color .2s;
}
.card__add:hover,.card__add:focus-visible{background:var(--akcja-ciemna);border-color:var(--akcja-ciemna)}
/* "Zobacz" zamiast "Do koszyka" tam, gdzie kafelek prowadzi na inna karte,
   a nie dodaje do koszyka. Przezroczysty, bo zielen jest zastrzezona dla
   sciezki zakupowej i nie ma udawac jej w miejscu, ktore tylko przenosi.
   Poza kolejnoscia tabulacji: nazwa produktu wyzej jest juz odnosnikiem
   w to samo miejsce. */
.card__zobacz{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 1rem;border:1px solid var(--ink);border-radius:var(--radius);
  color:var(--ink);background:transparent;
  font-family:var(--font-display);font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  transition:background .2s,color .2s;
}
.card__zobacz:hover{background:var(--ink);color:#fff}

/* zestawy */
.duos{display:grid;gap:var(--s4)}
@media(min-width:620px){.duos{grid-template-columns:repeat(2,1fr)}}
@media(min-width:900px){.duos{grid-template-columns:repeat(3,1fr)}}

/* =====================================================================

   ZESTAWY DUO
   =====================================================================
   Zestaw jest w sklepie OSOBNYM produktem, a nie doborem dwoch pozycji
   w locie - dlatego kafelek prowadzi na wlasna karte i ma wlasna cene.

   Uklad poziomy, nie kafelkowy: sekcja stoi tuz pod przyciskiem zakupu
   i ma nie konkurowac z nim wysokoscia. Zdjecie po lewej, nazwa i cena
   po prawej, dodanie do koszyka jako ikona. */
/* Ciasniej niz zwykla sekcja. To pasek dosprzedazy przy przycisku zakupu,
   a nie osobny rozdzial strony - przy odstepach .section (72 px na gore
   i na dol plus 56 px pod naglowkiem) zajmowal 721 px na telefonie i
   odpychal opis produktu poza zasieg. */
#zestawy{padding-block:var(--s4)}
#zestawy .sec-head{margin-bottom:var(--s3);gap:var(--s1)}
#zestawy .lead{font-size:.9rem}

.zestawy__lista{display:grid;gap:var(--s3);padding-left:0;list-style:none}
@media(min-width:900px){.zestawy__lista{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4)}}

/* Kafelek jest SIATKA, nie flexem: kolumna tresci ma sie rozciagac, a nie
   zostawiac pusty pas miedzy nazwa a przyciskiem. Poprzedni uklad wygladal
   niedokonczony wlasnie dlatego - krotka nazwa zostawiala 300 px pustki. */
/* Kolejnosc wg zyczenia Klientki (13.08.2026): najpierw nazwa, pod nia
   zdjecia, a na dole cena z odnosnikiem. Wczesniej zdjecia staly z lewej,
   a nazwa z prawej - na telefonie na nazwe zostawalo 150 px. */
.zestaw{
  position:relative;
  display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3);
  background:#fff;border:1px solid var(--line);
  transition:border-color .2s,box-shadow .2s;
}
.zestaw:hover{border-color:var(--line-control);box-shadow:0 6px 24px rgba(13,13,13,.06)}

/* Dwa kadry ze znakiem plus miedzy nimi. Zestaw czyta sie wtedy od razu jako
   "to i to", zanim ktokolwiek przeczyta nazwe. W sklepie stanie tu wlasne
   zdjecie zestawu - to podglad ukladu, nie grafika docelowa. */
/* Kadry dziela miedzy siebie szerokosc kafelka. Przy stalych 64 px stały
   przyklejone do lewej krawedzi, a obok nich zostawalo pol kartki pustki -
   na komputerze przy kafelku 518 px wygladalo to na brak zdjecia, a nie na
   uklad. */
.zestaw__media{display:flex;align-items:center;gap:.6rem}
.zestaw__foto{
  flex:1 1 0;max-width:200px;aspect-ratio:1/1;background:var(--porcelain);
  display:grid;place-items:center;overflow:hidden;
}
.zestaw__foto img{width:100%;height:100%;object-fit:contain;mix-blend-mode:multiply}
.zestaw__plus{
  font-family:var(--font-display);font-size:.95rem;font-weight:300;color:var(--muted);
  line-height:1;
}

.zestaw__nazwa{
  font-family:var(--font-display);font-size:.8rem;letter-spacing:.1em;
  text-transform:uppercase;font-weight:400;line-height:1.4;color:var(--muted);
}
/* Druga linia to konkret - co jest w srodku. Ona niesie tresc, wiec dostaje
   pelny kolor i wieksza wage niz rodzaj zestawu nad nia. */
.zestaw__sklad{display:block;color:var(--ink);letter-spacing:.06em;margin-top:.2rem}
.zestaw__nazwa a::after{content:"";position:absolute;inset:0}
/* Cena i "Zobacz" na przeciwnych koncach dolnego wiersza. */
.zestaw__stopka{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--s2);flex-wrap:wrap;margin-top:auto;padding-top:.2rem;
}
.zestaw__zobacz{
  font-family:var(--font-display);font-size:.68rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink);
  border-bottom:1px solid var(--ink);padding-bottom:.15rem;
}
.zestaw:hover .zestaw__zobacz{color:var(--navy);border-bottom-color:var(--navy)}
.zestaw__ceny{
  gap:.55rem;font-family:var(--font-display);font-size:1.15rem;letter-spacing:.04em;color:var(--ink);
}
.zestaw__ceny del{font-size:.75em}
/* Plakietka oszczednosci usunieta 10.08.2026. Promocje komunikuje wylacznie
   przekreslona stara cena obok nowej - zadnych "taniej o X zl" ani procentow
   przy cenie. */

/* Na telefonie zdjecia ida WYZEJ, na wlasny wiersz. Przy trzech kolumnach
   na 390 px na nazwe zostawalo 110 px, wiec lamala sie na cztery linie,
   plakietka schodzila na osobny wiersz, a przycisk na kolejny - kafelek
   robil sie na 420 px wysoki. Teraz: zdjecia, pod nimi tresc, a przycisk
   przy cenie w tym samym wierszu. */
@media(max-width:599px){
  .zestaw{grid-template-columns:minmax(0,1fr);row-gap:var(--s2)}
  .zestaw__media{grid-column:1}
  .zestaw__ceny{gap:.45rem}
}

/* =====================================================================

   OPIS - nazwa produktu i baner w podsekcji
   =====================================================================
   Nazwa skrocona w kazdej podsekcji: opis jest harmonijka, wiec czesto
   czyta sie jedna sekcje wyrwana z kontekstu - zwlaszcza po wejsciu
   z wyszukiwarki albo ze spisu tresci. */
/* Nazwa produktu w podsekcji opisu ma byc mniej wiecej tej samej wielkosci
   co tytul sekcji nad nia (1,15 rem) - w 0,63 rem byla szeptem, ktorego nie
   dalo sie powiazac z naglowkiem. */
.sekcja__produkt{
  font-family:var(--font-display);font-size:1rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink);font-weight:400;
}
/* Baner jest OPCJONALNY - sekcja bez niego wyglada tak samo jak dotad.
   Proporcja 4:1, docelowo plik 1600x400. Nie ustawiamy wysokosci na sztywno,
   zeby przy waskim ekranie pas nie zrobil sie paskiem kilku pikseli. */
.sekcja__baner{margin-top:var(--s3)}
.sekcja__baner img{
  width:100%;aspect-ratio:4/1;object-fit:cover;object-position:center;
  background:var(--porcelain);
}
@media(max-width:599px){.sekcja__baner img{aspect-ratio:5/2}}
.sekcja__baner figcaption{margin-top:.4rem;font-size:.76rem;color:var(--muted)}

/* =====================================================================

   OPINIE
   ===================================================================== */
.rating{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.rating__score{font-family:var(--font-display);font-size:2.4rem;font-weight:300;line-height:1}
.rating__stars{display:flex;gap:.15rem}
/* Gwiazdki na czarno, nie na brazowo. Braz mial zniknac ze strony
   (decyzja Klientki z 06.08.2026), a tu zostal - i akurat w miejscu,
   ktore rzuca sie w oczy najbardziej, bo jest duze i kolorowe. */
.rating__stars svg{width:16px;fill:var(--ink)}
.rating__meta{font-size:.74rem;color:var(--muted);line-height:1.4}
@media(min-width:860px){
  .rating{justify-content:flex-end}
  .rating__meta{max-width:15ch}
}

/* --- pas, ktory zostaje pasem na kazdej szerokosci ---
   Zwykly .rail na duzym ekranie przechodzi w siatke i przestaje sie przewijac.
   Klientka prosila, zeby opinie i bestsellery przewijaly sie w bok zawsze,
   wiec potrzebny jest wariant, ktory nie zamienia sie w siatke.
   Zrodlo: docs/makiety - przy zmianie poprawiamy OBA miejsca albo zadne.

   Pas MUSI byc osiagalny z klawiatury: bez tabindex osoba bez myszy nie
   doscignie dalszych kafelkow. Stad tabindex=0 razem z rola i nazwa
   w szablonie - inaczej czytnik oglosilby pusta grupe. */
.rail--zawsze{
  --rail-odstep:var(--s3);
  --rail-widocznych:1;
  display:grid;grid-auto-flow:column;grid-template-columns:none;
  grid-auto-columns:calc((100% - (var(--rail-widocznych) - 1) * var(--rail-odstep)) / var(--rail-widocznych));
  gap:var(--rail-odstep);
  overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;
  /* Gest nie ucieka na strone - tak samo jak w zwyklym pasie .rail. Pas
     opinii ma tylko te klase, wiec bez tej linii dojechanie palcem do konca
     ciagnelo za soba cala strone. */
  overscroll-behavior-x:contain;
  /* Zerujemy peldruk z .rail - czesc pasow ma obie klasy naraz. Bez tego
     kafelek liczony na 100% szerokosci konczyl sie 20 px przed krawiedzia
     kadru i wygladal na uciety, mimo ze mial byc jeden na ekran.

     scroll-padding TEZ musi zejsc do zera. Zostawione z .rail sprawialo, ze
     przewijanie zatrzymywalo sie 20 px przed koncem tasmy - ostatni kafelek
     nie dojezdzal do krawedzi i widac bylo z niego 94%, m.in. ucinalo
     przycisk zakupu. Zglosila to Klientka na bestsellerach. */
  margin-inline:0;padding-inline:0;scroll-padding-inline:0;
}
.rail--zawsze::-webkit-scrollbar{display:none}
.rail--zawsze>*{scroll-snap-align:start}
@media(min-width:640px){.rail--zawsze{--rail-widocznych:2;--rail-odstep:var(--s4)}}
@media(min-width:1000px){.rail--zawsze{--rail-widocznych:3}}
.rail--zawsze:focus-visible{outline:2px solid var(--ink);outline-offset:4px}

/* UKLADEM ZAJMUJE SIE .rail--zawsze - i tylko on.
   Stały tu jeszcze wlasne reguly siatki (repeat(2/3,1fr)) i robily dokladnie
   to, przed czym ostrzegal komentarz obok: stoja w arkuszu nizej niz pas,
   wiec wygrywaly z jego grid-template-columns:none. Skutek: pierwsze trzy
   opinie sciskaly sie do 150-200 px, a pozostale mialy pelne 368 px - i na
   stronie glownej, i pod karta produktu. W makiecie tych regul nie ma,
   a kazde uzycie .quotes jest pasem.
   Zrodlo: docs/makiety/strona-glowna.html */
.quote{
  background:#fff;padding:clamp(1.75rem,3.5vw,2.5rem);display:flex;flex-direction:column;gap:var(--s3);
  border-top:2px solid var(--ink);
}
.quote p{font-size:1rem;line-height:1.6;flex:1;text-wrap:pretty}
.quote footer{font-size:.76rem;color:var(--muted);border-top:1px solid var(--line);padding-top:var(--s3)}
.quote footer b{display:block;font-family:var(--font-display);letter-spacing:.12em;text-transform:uppercase;font-size:.7rem;color:var(--ink);font-weight:400;margin-bottom:.25rem}
.quote__prod{display:inline-flex;align-items:center;gap:.4rem}
.quote__prod::before{content:"";width:5px;height:5px;border-radius:99px;background:var(--navy)}
.quotes__foot{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s3);
  margin-top:var(--s4);
}
.quotes__note{font-size:.74rem;color:var(--muted);max-width:52ch}
.quotes__sterowanie{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}

/* =====================================================================

   OPINIE
   ===================================================================== */
/* Podpis pod opinia mial goly tekst i <span> obok siebie, wiec sklejalo sie
   w "Klientka, 47 latzakup potwierdzony". Nazwa idzie teraz w <b>, ktory
   regula ponizej stawia w osobnym wierszu, a potwierdzenie zakupu jest
   znacznikiem, a nie doklejonym slowem. */
.quote footer{display:flex;flex-direction:column;gap:.45rem;align-items:flex-start}
.znacznik{
  display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;color:var(--ink-soft);
  background:var(--porcelain);padding:.28rem .5rem;
}
.znacznik svg{width:12px;height:12px;fill:none;stroke:var(--navy);stroke-width:2.2;flex:0 0 auto}

/* --- podsumowanie ocen --- */
/* Reguly .oceny usuniete razem z rozkladem ocen - sekcja opinii ma teraz
   uklad ze strony glownej. */

/* --- formularz opinii --- */
.opinia-form{
  display:flex;flex-direction:column;gap:var(--s3);max-width:44rem;
  padding:var(--s4);background:var(--porcelain);margin-bottom:var(--s4);
}
.opinia-form[hidden]{display:none}
.opinia-form__stan{font-size:.8rem;color:var(--muted)}
.opinia-form__oceny{border:0;padding:0;margin:0}
.opinia-form__oceny legend{font-family:var(--font-display);font-size:.8rem;letter-spacing:var(--track);text-transform:uppercase;margin-bottom:.5rem}
/* Gwiazdki to ETYKIETY pieciu pol radio, a pola stoja w kodzie od 5 do 1.
   row-reverse odwraca je wizualnie z powrotem na 1-5, dzieki czemu
   "input:checked ~ label" trafia dokladnie w gwiazdki NA LEWO od wybranej. */
.gwiazdki{display:flex;flex-direction:row-reverse;justify-content:flex-end;
          align-items:center;gap:.15rem;flex-wrap:wrap-reverse}
/* Pole radio zostaje w drzewie i w tabulacji - znika tylko z widoku.
   display:none wyjeloby je z obslugi klawiatury i z czytnika ekranu. */
.gwiazdki input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.gwiazdka{width:44px;height:44px;display:grid;place-items:center;cursor:pointer}
.gwiazdka svg{width:22px;height:22px;fill:var(--line-control);transition:fill .15s,transform .15s}
.gwiazdki input:checked ~ .gwiazdka svg{fill:var(--ink)}
/* Podglad przy najechaniu: gaszimy stan wybrany i zapalamy to, nad czym stoi
   kursor. Regula musi byc PO regule zaznaczenia, bo obie waza tyle samo. */
.gwiazdki:hover input:checked ~ .gwiazdka svg{fill:var(--line-control)}
.gwiazdka:hover svg,.gwiazdka:hover ~ .gwiazdka svg{fill:var(--ink)}
.gwiazdka:hover svg{transform:scale(1.12)}
.gwiazdki input:focus-visible + .gwiazdka{outline:2px solid var(--navy);outline-offset:1px}
.gwiazdki__opis{margin-left:.5rem;font-size:.8rem;color:var(--muted)}

/* =====================================================================
   BANER ZGODY NA PLIKI COOKIES
   =====================================================================
   Znacznik wypisuje wtyczka Docket (Consents/Analityka.php) - tutaj, jak przy
   kazdym jej komponencie, jest wylacznie wyglad.

   PAS U DOLU, NIE OKNO NA SRODKU. Baner nie zaslania tresci i nie zabiera
   fokusu: prawo wymaga, zeby odmowa byla rownie latwa co zgoda, a nie zeby
   czytelnik zostal zatrzymany. Oba przyciski stoja obok siebie i wygladaja
   tak samo waznie - "Tylko niezbedne" nie jest szara pauza pod spodem. */
.zgody{
  position:fixed;inset-inline:0;bottom:0;z-index:60;
  display:grid;gap:var(--s3);align-items:start;
  padding:var(--s3) var(--pad);
  background:#fff;border-top:1px solid var(--line);
  box-shadow:0 -8px 30px rgba(13,13,13,.08);
}
@media(min-width:900px){
  .zgody{grid-template-columns:minmax(0,1fr) minmax(0,auto);gap:var(--s5);padding-block:var(--s4);align-items:center}
}
.zgody[hidden]{display:none}
.zgody__tresc{max-width:60ch}
.zgody__tytul{
  font-family:var(--font-display);font-size:.78rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);font-weight:400;margin:0 0 var(--s2);
}
.zgody__opis{font-size:.86rem;line-height:1.6;color:var(--ink-soft);margin:0}
.zgody__opis a{color:var(--ink);text-decoration:underline;text-underline-offset:3px}

.zgody__wybor{display:grid;gap:var(--s2);margin-top:var(--s3)}
.zgody__wybor[hidden]{display:none}
.zgody__pole{display:flex;gap:.6rem;align-items:flex-start;min-height:44px;font-size:.84rem;color:var(--ink-soft)}
.zgody__pole input{width:20px;height:20px;flex:0 0 auto;margin-top:.15rem;accent-color:var(--ink)}
.zgody__pole b{display:block;color:var(--ink);font-weight:500}

.zgody__akcje{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.zgody__akcje .btn{flex:0 0 auto}
/* "Ustawienia" to trzecia droga wyjscia z banera, wiec musi byc rownie latwa
   do trafienia palcem co dwie pozostale - sam napis mial 34 px wysokosci. */
.zgody__akcje .link-u{min-height:44px;display:inline-flex;align-items:center}
@media(max-width:560px){
  .zgody__akcje{flex-direction:column;align-items:stretch}
  .zgody__akcje .btn{width:100%}
  .zgody__akcje .link-u{align-self:flex-start}
}

/* Przycisk w stopce wyglada jak odnosnik - bo nim jest z punktu widzenia
   czytelnika. Element BUTTON, a nie A, poniewaz nigdzie nie prowadzi. */
.footer__zgody{background:none;border:0;padding:0;cursor:pointer;font:inherit}

/* Formularz wyszukiwania w tresci strony (wyniki, 404). Znacznik w
   searchform.php; tutaj sam uklad, bo pole i przycisk maja juz swoj wyglad
   z rdzenia. */
.szukaj-blok{display:flex;gap:var(--s2);align-items:stretch;max-width:34rem;margin-block:var(--s3) var(--s4)}
.szukaj-blok input[type="search"]{flex:1 1 auto;min-width:0}
.szukaj-blok .btn{flex:0 0 auto}
@media(max-width:480px){
  .szukaj-blok{flex-direction:column}
  .szukaj-blok .btn{width:100%}
}

.pole{display:flex;flex-direction:column;gap:.35rem}
.pole label{font-family:var(--font-display);font-size:.8rem;letter-spacing:var(--track);text-transform:uppercase}
.pole textarea,.pole input{
  font:inherit;padding:.7rem .8rem;border:1px solid var(--line-control);background:#fff;
  min-height:44px;width:100%;
}
.pole textarea{resize:vertical}
.pole textarea:focus-visible,.pole input:focus-visible{outline:2px solid var(--navy);outline-offset:1px}
.pole__wskazowka{font-size:.76rem;color:var(--muted)}

.opinia-form__stopka{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:center}
.opinia-form__info{font-size:.76rem;color:var(--muted);flex:1 1 16rem;text-wrap:pretty}
.opinia-form__komunikat:empty{display:none}
.opinia-form__komunikat{font-size:.85rem;color:var(--navy)}
/* Zgoda na zapamietanie danych to pole WordPressa, ktorego nie ma w makiecie.
   Zostaje - bez niego kazda kolejna opinia to ponowne wpisywanie imienia
   i adresu - ale w rozmiarze przypisu, a nie akapitu. */
.comment-form-cookies-consent{display:flex;align-items:flex-start;gap:.5rem}
.comment-form-cookies-consent input{width:18px;height:18px;margin-top:.15rem;flex:0 0 auto;accent-color:var(--navy)}
.comment-form-cookies-consent label{font-size:.8rem;color:var(--muted);line-height:1.45}

/* =====================================================================

   KARTA PRODUKTU
   ===================================================================== */
.okruszki{padding-block:var(--s3) 0;font-size:.78rem;color:var(--muted)}
/* Okruszki i naglowek strony to jeden blok. Kazdy z nich mial wlasny
   odstep, wiec na styku sumowaly sie dwa i naglowek odjezdzal w dol.
   Odstep jest teraz jeden i taki sam na wszystkich makietach.
   Uwaga: to samo miejsce w arkuszu co reguly ponizej - dlatego bloki
   docelowe ustawiaja WYLACZNIE padding-block-end, zeby o gornym
   odstepie nie decydowala kolejnosc regul. */
.okruszki + *{padding-block-start:var(--s3)}
.okruszki .wrap{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center}
/* --line-strong ma 1,73:1 - jako znak w tekscie byl praktycznie niewidoczny. */
.okruszki span[aria-hidden]{color:var(--muted)}
/* Wysokosc byla juz na 44 px, ale krotkie nazwy ("Serum") dawaly 38 px
   szerokosci. Ujemny margines cofa to, co dodaje padding, wiec obszar
   klikniecia rosnie, a odstepy wokol ukosnikow zostaja bez zmian. */
.okruszki a{min-height:44px;display:inline-flex;align-items:center;
            padding-inline:.4rem;margin-inline:-.4rem}
.okruszki a:hover{color:var(--ink)}

.karta__grid{display:grid;gap:var(--s4);padding-bottom:var(--s5)}
@media(min-width:900px){.karta__grid{grid-template-columns:1.05fr 1fr;gap:var(--s5);align-items:start}}

/* --- galeria --- */
.galeria__glowne{background:var(--porcelain);aspect-ratio:1;overflow:hidden}
.galeria__glowne img{width:100%;height:100%;object-fit:cover}
/* Miniatur jest teraz siedem (mozaika plus szesc zdjec) zamiast trzech,
   wiec na telefonie nie mieszcza sie w rzedzie - przy 360 px wypychaly
   dokument do 596 px. Tasma przewijana w poziomie zamiast lamania do
   drugiego rzedu: rzad zostaje jeden, a kciuk sam dosuwa kolejne. */
/* Miniatury BEZ przewijania w bok. Wczesniej byl pasek przewijany palcem -
   przy siedmiu kadrach dwa ostatnie chowaly sie za krawedzia, wiec nie bylo
   widac, ile ich w ogole jest, a pod spodem stal szary pasek przewijania.
   Teraz siatka zawija sie do drugiego rzedu: wszystkie kadry sa widoczne
   naraz, bez jednego gestu.

   auto-fill z minmax, a nie stala liczba kolumn - liczba zdjec jest inna
   przy kazdym produkcie i szerokosc galerii tez sie zmienia. */
/* Miniatury jako tasma na KAZDEJ szerokosci. Wczesniej byla to siatka, ktora
   zawijala sie do drugiego rzedu - i na telefonie, i na komputerze. Galeria
   rosla przez to w dol, a im nizej zjedzie zdjecie, tym dalej do ceny
   i przycisku zakupu. */
.galeria__mini{
  display:flex;gap:var(--s2);margin-top:var(--s2);
  overflow-x:auto;scroll-snap-type:x proximity;
  scrollbar-width:none;overscroll-behavior-x:contain;
}
/* Lapka zamiast strzalek - jedyny widoczny znak, ze tasme mozna chwycic.
   Kursor pokazuje sie tylko tam, gdzie faktycznie jest co przewijac: klase
   nadaje skrypt po zmierzeniu szerokosci. */
.galeria__mini.jest-czym-przewijac{cursor:grab}
.galeria__mini.ciagniemy{cursor:grabbing;scroll-snap-type:none;user-select:none}
.galeria__mini::-webkit-scrollbar{display:none}
.galeria__kciuk{flex:0 0 64px;scroll-snap-align:start}
@media(min-width:900px){.galeria__kciuk{flex-basis:76px}}
.galeria__kciuk{
  aspect-ratio:1/1;background:var(--porcelain);overflow:hidden;
  border:1px solid transparent;transition:border-color .2s;
}
.galeria__kciuk img{width:100%;height:100%;object-fit:cover}
.galeria__kciuk[aria-current="true"]{border-color:var(--ink)}
.galeria__kciuk:hover{border-color:var(--line-control)}

/* --- blok zakupowy --- */
@media(min-width:900px){.zakup{position:sticky;top:calc(var(--head-h) + var(--pasek-h) + var(--s3))}}
/* Reguly .zakup__pod i .zakup__oceny usuniete razem ze znacznikami - makieta
   robocza Klientki nie ma ani podtytulu, ani plakietki oceny nad cena.
   Sekcja opinii zostaje nizej na stronie i ma wlasne style. */
/* Kwote sklada WooCommerce, a nie my - stad krój i stopien na KONTENERZE,
   a nie na <b> z makiety, ktorego w kodzie sklepu nie ma. Wczesniej byla tu
   jeszcze regula ".zakup__cena span" dla dopisku "z VAT" z makiety; w znacznikach
   sklepu <span> jest rowniez sama kwota, wiec cena schodzila do 12 px i szarosci
   dopisku. Wyglad czesci skladowych ustawia wspolna zasada nizej. */
.zakup__cena{
  margin-top:var(--s2);
  font-family:var(--font-display);font-size:1.75rem;font-weight:400;letter-spacing:.02em;
  line-height:var(--lh-body);color:var(--ink);
}
.zakup__cena b{font-weight:400}

.warianty{display:flex;gap:.5rem;margin-top:var(--s3)}
.wariant{
  min-height:44px;padding:0 1.1rem;border:1px solid var(--line-control);
  border-radius:var(--radius);font-family:var(--font-display);font-size:.8rem;
  letter-spacing:.08em;transition:border-color .2s;
}
.wariant[aria-pressed="true"]{background:var(--ink);color:#fff;border-color:var(--ink)}
.wariant:hover{border-color:var(--ink)}

/* Lista atutow (EGCG, pH) usunieta razem ze znacznikami - te informacje
   sa w opisie nizej. */
.zakup__akcje{display:flex;gap:.6rem;margin-top:var(--s3)}
.zakup__akcje .btn{flex:1 1 auto}


.zakup__zaufanie{
  margin-top:var(--s3);padding-top:var(--s2);border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:.35rem var(--s3);font-size:.78rem;color:var(--muted);
}
.zakup__zaufanie li{padding-left:1rem;position:relative}
.zakup__zaufanie li::before{content:"\2713";position:absolute;left:0;color:var(--muted)}

/* --- opis --- */
.opis{background:var(--bg);padding-block:var(--s5)}
/* Bez dolnego marginesu, na kazdej szerokosci (zyczenie Klientki
   z 27.08.2026: "pomiedzy pytania a blog jest za duzo wolnego miejsca",
   potem "na desktopie tez"). Skladaly sie tu dwa odstepy: 48 px domkniecia
   opisu i odstep miedzysekcyjny, ktory wnosi sekcja bloga - razem 96 px
   na telefonie i 163 px na komputerze, po zwinietej harmonijce, ktorej
   wiersze stoja ciasno. Ostatni wiersz ma wlasna kreske, wiec blok i tak
   jest zamkniety, a przed blogiem zostaje zwykly rytm miedzy sekcjami. */
.opis{padding-bottom:0}
.opis__grid{display:grid;gap:var(--s4)}
@media(min-width:1000px){.opis__grid{grid-template-columns:220px minmax(0,1fr);gap:var(--s5)}}

/* Spis tresci tylko na komputerze - na telefonie sekcje sa zwiniete,
   wiec drugi spis bylby druga nawigacja do tego samego. */
.opis__spis{display:none}
@media(min-width:1000px){
  .opis__spis{display:block;position:sticky;top:calc(var(--head-h) + var(--pasek-h) + var(--s3));
              align-self:start;transition:top .28s cubic-bezier(.4,0,.2,1)}
  .opis__spis-tytul{
    font-family:var(--font-display);font-size:.63rem;letter-spacing:var(--track);
    text-transform:uppercase;color:var(--muted);margin-bottom:var(--s2);
  }
  .opis__spis a{
    display:flex;align-items:center;min-height:44px;font-size:.86rem;color:var(--muted);
    border-left:2px solid var(--line);padding-left:.75rem;transition:color .2s,border-color .2s;
  }
  .opis__spis a:hover{color:var(--ink)}
  .opis__spis a.jest-tu{color:var(--ink);border-left-color:var(--ink)}
}

.sekcja{border-top:1px solid var(--line)}
.sekcja:first-child{border-top:none}
.sekcja__tytul{margin:0}
.sekcja__przycisk{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  width:100%;min-height:64px;text-align:left;color:inherit;
  font-family:var(--font-display);font-size:1.15rem;font-weight:300;letter-spacing:.02em;
}
/* Pogrubienie w tytule sekcji i w spisie tresci. Tytul chodzi na wadze 300,
   wiec zwykle "bold" (700) bylby skokiem o cztery stopnie i wygladalby jak
   inny krój. 500 wystarczy, zeby wyroznic nazwe produktu. */
.sekcja__przycisk b,.opis__spis b{font-weight:500}
/* Etykieta jako JEDEN element ukladu - inaczej justify-content
   rozrzuca "Dlaczego" i <b>Novacell</b> na przeciwne konce belki. */
.sekcja__etykieta{min-width:0}
.sekcja__strzalka{width:18px;height:18px;flex:0 0 auto;stroke:currentColor;stroke-width:1.5;fill:none;transition:rotate .2s}
.sekcja__przycisk[aria-expanded="true"] .sekcja__strzalka{rotate:180deg}
/* Zwiniete przez display:none, wiec tresc wypada tez z kolejnosci tabulacji.
   Stan trzyma SEKCJA, nie przycisk. Przycisk siedzi w <h2>, wiec tresc nie jest
   jego rodzenstwem i selektor sasiadujacy nigdy by nie zadzialal - wszystkie
   sekcje zostawalyby zwiniete niezaleznie od aria-expanded. */
.sekcja__wnetrze{display:none;padding-bottom:var(--s4)}
.sekcja[data-otwarta="true"] .sekcja__wnetrze{display:block}
.sekcja__wnetrze .lead{max-width:none}
.sekcja__wnetrze > * + *{margin-top:var(--s2)}

/* Listy w opisie mialy zwykle kropki przegladarki. Ptaszek zamiast kropki
   niesie znaczenie ("to dostajesz", "to pasuje"), a nie jest ozdoba - dlatego
   ta sama forma co w pasku zaufania przy przycisku zakupu. Rysujemy go w CSS,
   wiec nie kosztuje ani jednego dodatkowego znaku w tresci. */
.lista{display:flex;flex-direction:column;gap:.55rem;padding-left:0;list-style:none}
.lista li{position:relative;padding-left:1.6rem}
.lista li::before{
  content:"";position:absolute;left:0;top:.42em;width:11px;height:7px;
  border-left:1.6px solid var(--navy);border-bottom:1.6px solid var(--navy);
  rotate:-45deg;
}
@media(min-width:700px){.lista--dwie{display:grid;grid-template-columns:1fr 1fr;gap:.55rem var(--s4)}}

/* Wariant dla listy przeciwwskazan i ostrzezen - ten sam uklad, inny znak. */
.lista--uwagi li::before{
  border:0;background:var(--ink-soft);width:6px;height:6px;border-radius:99px;
  top:.5em;rotate:none;
}

/* Skladniki i mechanizmy to najdluzsza tresc na karcie. Pionowa linia oddziela
   je od siebie mocniej niz sam odstep, a nazwa dostaje wlasny kolor akcentu -
   dzieki temu da sie przebiec wzrokiem po samych nazwach. */
/* Zwykla tresc, bez kreski i wciecia (zyczenie Klientki z 27.08.2026).
   Wczesniej kazda pozycja miala pionowa linijke po lewej, ktora pod kursorem
   zmieniala sie na granatowa - na komputerze wygladalo to jak podswietlanie
   akapitow, a nie jak lista skladnikow. Same odstepy oddzielaja tak samo.

   Naglowki w kroju tekstowym, nie naglowkowym - maja czytac sie jak poczatek
   zdania, a nie jak osobny tytul. Hierarchie trzyma waga i kolor: dt jest
   grubsze i pelnym atramentem, dd lzejsze i przygaszone. */
.mechanizmy{display:flex;flex-direction:column;gap:var(--s3)}
.mechanizmy dt{font-family:var(--text);font-size:1rem;font-weight:500;margin-bottom:.35rem}
.mechanizmy dd{margin:0;color:var(--ink-soft)}
/* Stezenie wyciagniete przed nazwe - to pierwsza rzecz, ktorej szuka sie
   w skladzie kosmetyku. */
/* TYLKO kolor. Wczesniej stezenie bylo osobnym pudelkiem z wlasnym marginesem,
   przez co "4 %" odrywalo sie wzrokowo od nazwy skladnika - a to jedna fraza:
   "4 % stabilizowanego EGCG". Co gorsza odstep robil sam margines, wiec
   w tresci nie bylo spacji: przy kopiowaniu i w czytniku ekranu wychodzilo
   "4 %stabilizowanego EGCG". Teraz odstep jest zwyklym znakiem, a niełamiąca
   spacja przed procentem pilnuje, zeby liczba i znak nie rozjechaly sie
   na dwie linie. */
.mechanizmy dt .stezenie{color:var(--navy)}

/* Nazwa w kafelku ma 23 px wysokosci. Powiekszenie pudelka podnioslo by
   wszystkie kafelki w calym serwisie, wiec zamiast tego warstwa dotyku.
   Pod spodem sa wylacznie teksty, wiec pasmo nie kradnie zadnych klikniec. */
.card__name a{position:relative}
.card__name a::after{
  content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px;
}

.badanie{margin-top:var(--s4);padding:var(--s3);background:var(--porcelain)}
.badanie__liczby{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
@media(min-width:700px){.badanie__liczby{grid-template-columns:repeat(4,1fr)}}
.badanie__poz b{display:block;font-family:var(--font-display);font-size:1.6rem;font-weight:300;color:var(--navy)}
.badanie__poz span{display:block;font-size:.78rem;color:var(--muted);margin-top:.15rem}
.badanie__zrodlo{margin-top:var(--s3);font-size:.78rem;color:var(--muted)}

/* ZNAK ZASTRZEZONY. Bez wlasnej reguly <sup> dziedziczy stopien pisma rodzica:
   w naglowku strony (R) rosl razem z nim do 39 px i przebijal linie. Wartosc
   w em, wiec skaluje sie z tekstem. Komponenty, ktore maja wlasny rozmiar
   (pasek faktow, dowody), wygrywaja waga selektora. */
main sup{font-size:.45em;vertical-align:super;line-height:0}
main .lead sup,main summary sup,main p sup{font-size:.55em}

/* --- zgoda przy polu wyboru ---
   Jeden komponent na caly sklep: newsletter na stronie glownej, zgody w kasie
   i oswiadczenie w formularzu zwrotow. Do 01.09.2026 stal w arkuszu strony
   glownej, wiec na stronie tresciowej nie bylo go czym pomalowac. */
.consent{display:flex;gap:var(--s2);align-items:flex-start;font-size:.74rem;color:var(--ink-soft);line-height:1.5}
.consent a{text-decoration:underline;text-underline-offset:2px}
/* KWADRAT WYSRODKOWANY NA PIERWSZYM WIERSZU TEKSTU, a nie odsuniety od gory
   na oko. Pole ma 22 px, wiersz przy tej wielkosci pisma - 1,5 em, czyli
   niecale 18 px; staly margines 3,2 px spychal kwadrat okolo 5 px ponizej
   srodka pierwszej linii i przy dwuwierszowej zgodzie widac to od razu.
   Rachunek w "em" trzyma sie tekstu: zmiana wielkosci pisma nie rozjezdza
   wyrownania. */
.consent input{
  margin-top:calc((1.5em - 22px) / 2);
  width:22px;height:22px;flex:0 0 auto;accent-color:var(--ink);
}
/* Cala etykieta jest polem kliknialnym pola wyboru, wiec obszar dotyku liczy
   sie z jej wysokosci - a nie z 22 px samego kwadratu. */
.consent{min-height:44px;padding-block:.35rem;cursor:pointer}

/* Kroki mialy numeracje przegladarki, ktora ginela przy tekscie. Numer
   w kolku czyta sie jak instrukcja, a nie jak kolejny akapit. Licznik CSS,
   wiec dopisanie kroku nie wymaga poprawiania numerow w tresci.

   NAZWA Z DOPISKIEM "UZYCIA" nie jest ozdobna. Do 01.09.2026 obie listy
   krokow - ta z karty produktu i ta z widzetow stron - nazywaly sie ".kroki".
   Na stronie tresciowej ladowaly oba arkusze, wiec numer z tej reguly zostawal
   pozycjonowany bezwzglednie, wypadal z siatki tamtej i tytul kroku wskakiwal
   obok wyjasnienia zamiast nad nim. Jedna klasa, dwa rozne komponenty - blad,
   ktorego nie widac w zadnym z nich osobno. */
.kroki-uzycia{display:flex;flex-direction:column;gap:var(--s2);padding-left:0;list-style:none;counter-reset:krok}
/* NIE flex. Element listy zawiera <b> i zwykly tekst obok siebie; przy
   display:flex kazdy z nich staje sie osobnym polem, a spacja miedzy nimi
   znika - wychodzilo "osuszskore twarzy". Blok zachowuje tekst jako tekst. */
.kroki-uzycia li{position:relative;padding-left:2.75rem;min-height:2rem;padding-top:.28rem}
.kroki-uzycia li::before{
  counter-increment:krok;content:counter(krok);
  position:absolute;left:0;top:0;width:2rem;height:2rem;
  display:grid;place-items:center;border:1px solid var(--line-control);border-radius:99px;
  font-family:var(--font-display);font-size:.85rem;color:var(--ink);
}
.uwaga{padding:var(--s2) var(--s3);border-left:2px solid var(--ink-soft);background:var(--porcelain);font-size:.9rem}
.podtytul{
  font-family:var(--font-display);font-size:.78rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);margin-top:var(--s4);margin-bottom:var(--s2);
}

/* Miejsca, ktorych Klient jeszcze nie uzupelnil - widoczne celowo, zeby
   nie zginely w makiecie. */
.brakuje{
  margin-top:var(--s3);padding:var(--s2);font-size:.83rem;
  border:1px dashed var(--line-control);color:var(--ink-soft);
}
/* Bez szarego tla - decyzja Klientki z 10.08.2026. Sekcja ma sie nie
   wyrozniac kolorem, bo to nadal ten sam opis produktu. Ze jest zamknieta
   dla gabinetow, mowi plakietka .hurt__znak w srodku - i to wystarczy. */
.sekcja--hurt{border-top-color:var(--line-strong)}
.hurt__znak{
  display:inline-block;font-family:var(--font-display);font-size:.63rem;letter-spacing:var(--track);
  text-transform:uppercase;color:var(--muted);
}

/* --- przyklejony pasek zakupu --- */
/* Na telefonie u dolu, w zasiegu kciuka; na komputerze pod naglowkiem.
   Pojawia sie dopiero, gdy glowny blok zakupowy zniknie z widoku. */
.pasek-zakupu{
  position:fixed;left:0;right:0;bottom:0;z-index:75;
  background:rgba(255,255,255,.97);backdrop-filter:saturate(160%) blur(12px);
  border-top:1px solid var(--line);
  transform:translateY(102%);visibility:hidden;
  transition:transform .28s cubic-bezier(.4,0,.2,1),visibility 0s .28s;
}
.pasek-zakupu[data-widoczny="true"]{
  transform:none;visibility:visible;
  transition:transform .28s cubic-bezier(.4,0,.2,1),visibility 0s;
}
.pasek-zakupu .wrap{display:flex;align-items:center;gap:var(--s2);min-height:68px;padding-block:.5rem}
.pasek-zakupu__foto{width:44px;height:44px;flex:0 0 auto;background:var(--porcelain);overflow:hidden}
.pasek-zakupu__foto img{width:100%;height:100%;object-fit:cover}
/* Nazwa i cena jedna pod druga, nie w jednej linii. Na 375 px caly ciag
   "Novacell [Cg] 349 zl - 30 ml" lamal sie w przypadkowym miejscu, a napis
   na przycisku rozpadal sie na dwa wiersze. */
.pasek-zakupu__nazwa{display:block;font-family:var(--font-display);font-size:.9rem;letter-spacing:.03em}
/* W pasku cena stoi pod nazwa, drobnym pismem - ale KOLEJNOSC i przekreslenie
   sa te same co wszedzie indziej (wspolna zasada nizej). Wczesniej pasek pokazywal
   "618 zl 556 zl" z podkreslona nowa kwota, bo tak sklada je sklep. */
.pasek-zakupu__cena{font-size:.83rem;color:var(--muted);gap:.35rem}
.pasek-zakupu .btn{margin-left:auto;min-height:48px;padding-inline:1.25rem;white-space:nowrap}
@media(max-width:420px){
  .pasek-zakupu .btn{padding-inline:.9rem;font-size:.62rem}
  .pasek-zakupu__foto{width:40px;height:40px}
}
/* Na telefonie pasek stoi u dolu i przykrywal ostatnie 38 px stopki. */
@media(max-width:999px){.footer{padding-bottom:calc(var(--s4) + 70px)}}
@media(min-width:900px){
  /* Pod naglowkiem, nie na nim: oba mialy top:0, a pasek wyzszy z-index,
     wiec przykrywal logo, wyszukiwarke i koszyk. */
  .pasek-zakupu{top:var(--head-h);bottom:auto;border-top:none;border-bottom:1px solid var(--line);
    transform:translateY(-102%);}
  .pasek-zakupu[data-widoczny="true"]{transform:none}
}

/* =====================================================================

/* ---------- galeria, stepnik i przycisk zakupu ----------
   Druga czesc arkusza karty produktu z makiety - powstala po pierwszej
   i lezy w niej nizej, za regulami powloki. */


/* ---------- galeria: mozaika ---------- */
/* min-width:0 na SAMEJ galerii, nie tylko na plytkach.
   Galeria jest elementem siatki ukladu karty produktu, a taki element ma
   min-width:auto - czyli nie schodzi ponizej szerokosci swojej zawartosci.
   Mozaika z czterema zdjeciami dawala 576 px i wypychala cala strone poza
   ekran. Zmierzone przy oknie 360 px: przed zmiana galeria miala 320 px
   i zero przelewu, po zmianie 576 px i dokument szerszy od okna. */
.galeria{min-width:0}
.galeria__glowne{position:relative;min-width:0}

/* WIDOCZNOSCIA STERUJE data-widok, a NIE sam atrybut hidden.
   Atrybut hidden to w arkuszu przegladarki display:none o najnizszym
   pierwszenstwie - regula ponizej (display:grid) bije go bez trudu.
   Skutek byl taki, ze mozaika nie znikala nigdy, a pod nia dochodzilo
   pojedyncze zdjecie. Atrybut zostaje, bo usuwa element z drzewa
   dostepnosci, ale o wyswietlaniu decyduje data-widok. */
.galeria[data-widok="pojedyncze"] .galeria__mozaika{display:none}
.galeria[data-widok="mozaika"] .galeria__pojedyncze{display:none}

/* Trzeci widok: kadr wideo. Ta sama zasada - o wyswietlaniu decyduje
   data-widok, a nie sam atrybut hidden. */
.galeria__wideo{width:100%;aspect-ratio:1/1;object-fit:cover;background:var(--porcelain)}
.galeria[data-widok="mozaika"] .galeria__wideo,
.galeria[data-widok="pojedyncze"] .galeria__wideo{display:none}
.galeria[data-widok="wideo"] .galeria__mozaika,
.galeria[data-widok="wideo"] .galeria__pojedyncze{display:none}
.galeria[data-widok="wideo"] .galeria__wideo{display:block}

/* Miniatura filmu: trojkat na przygaszonym kadrze. Bez znaczka nie da sie
   odroznic filmu od zdjecia, a klikniecie robi cos innego. */
.galeria__kciuk--wideo{position:relative}
.galeria__kciuk-graj{
  position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(13,13,13,.28);color:#fff;
}
.galeria__kciuk-graj svg{width:18px;height:18px;fill:currentColor;stroke:none}

.galeria__mozaika{
  display:grid;gap:2px;aspect-ratio:1;
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-template-rows:repeat(2,minmax(0,1fr));
}
/* Uklad zalezy od tego, ile zdjec ma produkt. Klientka poprosila
   o cztery - ale nie kazdy produkt tyle ma i wtedy puste pole w siatce
   wygladaloby na blad. */
.galeria__mozaika[data-plytek="3"]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}
.galeria__mozaika[data-plytek="3"] .galeria__plytka:first-child{grid-row:span 2}
.galeria__mozaika[data-plytek="2"]{grid-template-rows:minmax(0,1fr)}
.galeria__mozaika[data-plytek="1"]{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr)}

.galeria__plytka{
  position:relative;overflow:hidden;background:var(--porcelain);
  border:0;padding:0;cursor:pointer;
  /* min-width/min-height 0 sa TU KONIECZNE. Element siatki ma domyslnie
     min-width:auto, a w srodku siedzi zdjecie o wlasnej szerokosci 600 px -
     przez to mozaika nie schodzila ponizej 576 px i wypychala strone poza
     ekran na telefonie. Zmierzone: przy oknie 360 px dokument mial 576. */
  min-width:0;min-height:0;
}
.galeria__plytka img{
  width:100%;height:100%;max-width:100%;object-fit:cover;display:block;
  transition:opacity .5s ease,transform .5s ease;
}
.galeria__plytka:hover img{transform:scale(1.03)}
/* Klatka wymiany: zdjecie gasnie i wraca juz jako nastepne. */
.galeria__plytka.jest-wymiana img{opacity:0}

.galeria__pojedyncze{
  width:100%;aspect-ratio:1;object-fit:cover;background:var(--porcelain);
  transition:opacity .22s ease;
}
.galeria__pojedyncze.jest-wymiana{opacity:0}

/* Przycisk zatrzymania - dyskretny, ale osiagalny z klawiatury. */
/* Trzy poprawki naraz (10.08.2026), wszystkie tego samego przycisku:

   1. 44 px zamiast 36. Wszystkie pozostale przyciski w serwisie maja 44 -
      ten byl jedynym wyjatkiem i akurat on jest wymogiem dostepnosci.

   2. WIDOCZNY ZAWSZE, nie na najechanie myszka. Na telefonie najechania nie
      ma w ogole, wiec jedyny sposob zatrzymania przewijajacej sie galerii byl
      tam nieosiagalny. Przycisk wymagany przez WCAG 2.2.2 nie moze chowac sie
      za gestem, ktorego polowa odwiedzajacych nie wykona.

   3. ZNIKAL NA SLAJDACH ZE ZDJECIEM - a wlasnie wtedy galeria sie przewija.
      Przycisk byl widoczny dokladnie tam, gdzie nie byl potrzebny. */
.galeria__pauza{
  position:absolute;right:var(--s2);bottom:var(--s2);z-index:2;
  width:44px;height:44px;display:grid;place-items:center;
  border:0;border-radius:99px;cursor:pointer;
  background:rgba(255,255,255,.92);color:var(--ink);
  transition:background .2s;
}
.galeria__pauza:hover,.galeria__pauza:focus-visible{background:#fff}
/* Ktora ikona jest widoczna, decyduje STAN PRZYCISKU, a nie atrybut hidden
   przestawiany skryptem. Powod jest konkretny: wlasciwosc "hidden" istnieje
   na HTMLElement, ale nie na SVGElement - przypisanie svg.hidden = true
   zaklada zwykla wlasciwosc obiektu i nie tworzy atrybutu w drzewie, wiec
   selektor [hidden] nigdy jej nie widzi. W makiecie kosztowalo to pomiar. */
.galeria__pauza .galeria__ikonaGraj{display:none}
.galeria__pauza[aria-pressed="true"] .galeria__ikonaPauza{display:none}
.galeria__pauza[aria-pressed="true"] .galeria__ikonaGraj{display:block}
.galeria__pauza svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.6}

.galeria__kciuk--mozaika svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.3}
.galeria__kciuk--mozaika{display:grid;place-items:center}

/* Osoba, ktora prosila system o ograniczenie ruchu, nie dostaje samoczynnej
   zmiany w ogole - a nie tylko wolniejsza. */
@media(prefers-reduced-motion:reduce){
  .galeria__plytka img{transition:none}
}

/* Krotki opis pod naglowkiem. Wezszy niz reszta kolumny, zeby wiersz nie
   robil sie za dlugi do czytania.

   INTERLINIA 1,65, A NIE 1,45. W makiecie stalo tu var(--lh-text), ale sama
   makieta tej zmiennej nigdzie nie definiuje - deklaracja byla wiec nieważna
   i akapit dziedziczyl interlinie tekstu strony (1,65). Motyw ma --lh-text
   zdefiniowane, wiec ta sama regula dawala u nas ciasniejsze 1,45 i akapit
   mial 116 px zamiast 132 px. Bierzemy to, co Klientka widziala i zatwierdzila. */
.zakup__opis{
  max-width:46ch;margin:0 0 var(--s3);
  color:var(--ink-soft);font-size:1rem;line-height:var(--lh-body);
}

.zakup__akcje{display:flex;gap:var(--s2);align-items:stretch;flex-wrap:wrap}

.ilosc{display:flex;align-items:stretch;border:1px solid var(--line-control);flex:0 0 auto}
.ilosc button{
  width:44px;min-height:44px;flex:0 0 auto;background:none;border:0;cursor:pointer;color:var(--ink);
  font-size:1.1rem;line-height:1;
}
.ilosc button:hover{background:var(--porcelain)}
/* Selektor z rodzicem, bo motyw ma wspolna regule dla pol formularzy
   ("input[type=number]" i towarzystwo) ustawiajaca szerokosc 100%, ramke
   i padding. Selektor z atrybutem wazy wiecej niz sama klasa, wiec pole
   ilosci rozpychalo sie do 224 px zamiast 52 px i stepnik miał 298 px
   szerokosci zamiast 142 px z makiety. */
.ilosc .ilosc__pole{
  width:52px;min-height:0;padding:0;border:0;text-align:center;font:inherit;color:var(--ink);
  background:none;-moz-appearance:textfield;
}
/* Strzalki przegladarki sa male i niecelne palcem - mamy wlasne przyciski
   po 44 px, wiec systemowe tylko zabieraly miejsce. */
.ilosc__pole::-webkit-outer-spin-button,
.ilosc__pole::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* Zielony przycisk zakupu - wprost z makiety Klientki. Odcien dobrany tak,
   zeby bialy tekst mial 4,79:1, czyli powyzej progu WCAG AA 4,5:1.
   Odcien z makiety (#2f8f63) dawal 4,02:1 i by nie przeszedl. */
.btn--kup{
  flex:1 1 12rem;background:var(--akcja);color:#fff;border:0;
  min-height:52px;
}
.btn--kup:hover,.btn--kup:focus-visible{background:var(--akcja-ciemna)}

/* WooCommerce ma dla przycisku pod formularzem opinii wlasna regule
   z selektorem "#respond input#submit" - dwa identyfikatory, wiec zwykla
   klasa .btn--kup nie ma z nia szans i przycisk wychodzil blady, systemowy.
   Powtarzamy wiec wyglad przycisku zakupowego z tym samym punktem
   zaczepienia. Nie wyrzucamy calego arkusza sklepu, bo ustawia tez rzeczy,
   ktorych nie przepisalismy (komunikaty, tabele zamowien). */
#respond input#submit.btn--kup{
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--akcja);color:#fff;border:0;border-radius:var(--radius);
  min-height:52px;padding:.9rem 1.75rem;
  font-family:var(--font-display);font-size:.78rem;letter-spacing:var(--track);
  line-height:1.3;text-transform:uppercase;
}
#respond input#submit.btn--kup:hover,
#respond input#submit.btn--kup:focus-visible{background:var(--akcja-ciemna)}

.zakup__zaufanie li::before{content:"\2713 ";margin-right:.4rem}

/* ---------- ceny i przyciski w obrebie karty produktu ----------
   WooCommerce ma dla wszystkiego, co siedzi w "div.product", wlasne reguly
   z trzema klasami - a nasza karta jest jednym wielkim div.product. Kolorowal
   przez to KAZDA cene na stronie swoim oliwkowym odcieniem (#958e09)
   i powiekszal ja do 1,25em: ceny w kafelkach "Inni wybieraja" i w zestawach
   wychodzily zolte i za duze. Przywracamy wyglad z makiety. */
/* Znacznik "span" w selektorze nie jest ozdoba: regula WooCommerce brzmi
   "div.product span.price" i bez niego nasza wazy mniej, a wtedy cena zostaje
   oliwkowa mimo pozniejszego arkusza. */
.woocommerce div.product span.price,
.woocommerce div.product p.price{
  font-family:var(--font-display);font-size:1.05rem;letter-spacing:.06em;color:var(--ink);
}
/* Na telefonie cena w kafelku odrobine wieksza - zyczenie Klientki
   z 27.08.2026, przeniesione razem z reszta makiety. */
@media(max-width:899px){.woocommerce div.product .card span.price{font-size:1.18rem}}

/* Przycisk zakupu ma typografie z makiety: mniejszy stopien, szersze
   swiatlo miedzy literami i zwykla grubosc. WooCommerce pogrubia swoje
   przyciski do 700 i daje im wlasny padding - roznica byla widoczna
   w zestawieniu z paskiem zakupu. */
.woocommerce div.product .zakup__form button.single_add_to_cart_button,
.woocommerce div.product .pasek-zakupu .btn{
  font-size:.66rem;letter-spacing:.16em;font-weight:400;
}
.woocommerce div.product .zakup__form button.single_add_to_cart_button{padding:0 1rem}
/* Pasek zakupu powtarza przycisk ze sciezki zakupowej - w makiecie jest
   zielony, tak jak przycisk w bloku zakupowym. */
.woocommerce div.product .pasek-zakupu .btn--solid{
  background:var(--akcja);border-color:var(--akcja);padding:0 1.25rem;
}
.woocommerce div.product .pasek-zakupu .btn--solid:hover,
.woocommerce div.product .pasek-zakupu .btn--solid:focus-visible{
  background:var(--akcja-ciemna);border-color:var(--akcja-ciemna);
}

/* Wtyczka z historia cen (obowiazek z dyrektywy Omnibus) pisze zdanie
   o najnizszej cenie w JEDNEJ linii - ma na sztywno white-space:nowrap.
   W kafelku katalogu kolumna ma 234 px, wiec zdanie wystawalo poza kafelek,
   poza siatke i poza ekran: strone dalo sie przesunac w bok o 108 px.
   Pozwalamy mu sie zawinac; tresc zostaje bez zmian. */
.wc-price-history,
.wc-price-history *{white-space:normal}

/* ---------- most do WooCommerce na karcie produktu ----------
   Klasy, ktorych makieta nie zna, bo generuje je sklep albo nasz skrypt. */

/* =====================================================================
   CENY ZE SKLEPU - JEDNA ZASADA NA CALY SERWIS
   =====================================================================
   WooCommerce sklada kwote z wlasnych znacznikow i zawsze w tej samej
   kolejnosci: najpierw <del> ze stara cena, potem <ins> z nowa, dalej
   dopisek podatkowy i - przy obnizce - nota Omnibusa o najnizszej cenie
   z 30 dni. Makieta pisze odwrotnie: najpierw kwota DO ZAPLATY.

   Ustawiamy wiec KOLEJNOSC WYSWIETLANIA zamiast skladac cene samodzielnie.
   Gdybysmy pisali ja sami, wzielibysmy na siebie zakres "od-do" przy
   wariantach, ceny hurtowe i zgodnosc not cenowych wymaganych przy kazdej
   oglaszanej obnizce.

   Jedna zasada dla wszystkich miejsc, w ktorych cena wychodzi ze sklepu -
   kafelek na liscie, blok zakupowy, zestawy, pasek na dole i tasma
   "Inni wybieraja". Wczesniej kazde z nich mialo wlasne reguly i rozjezdzaly
   sie miedzy soba: w pasku stara cena stala przed nowa, a nowa byla
   podkreslona.

   Stopien pisma zostaje przy KAZDYM z tych miejsc osobno (cena w bloku
   zakupowym ma 28 px, w kafelku 17), dlatego czesci skladowe licza sie
   w "em" - wzgledem kwoty, obok ktorej stoja. */
.card__cena--promo,
.zakup__cena,
.zestaw__ceny,
.pasek-zakupu__cena,
.rail .price{display:flex;flex-wrap:wrap;align-items:baseline;gap:.4rem}

/* Kwota do zaplaty: pierwsza i bez podkreslenia, ktore <ins> ma z przegladarki. */
.card__cena--promo ins,
.woocommerce div.product .zakup__cena ins,
.woocommerce div.product .zestaw__ceny ins,
.woocommerce div.product .pasek-zakupu__cena ins,
.woocommerce div.product .rail .price ins,
.zakup__cena ins,
.zestaw__ceny ins,
.pasek-zakupu__cena ins,
.rail .price ins{order:1;text-decoration:none;background:none;color:inherit;font-weight:inherit}

/* Cena sprzed obnizki: druga, szara i przekreslona. */
.card__cena del,
.woocommerce div.product .zakup__cena del,
.woocommerce div.product .zestaw__ceny del,
.woocommerce div.product .pasek-zakupu__cena del,
.woocommerce div.product .rail .price del,
.zakup__cena del,
.zestaw__ceny del,
.pasek-zakupu__cena del,
.rail .price del{
  order:2;color:var(--muted);letter-spacing:normal;text-decoration:line-through;
}

/* Dopisek podatkowy - drobnym pismem tekstowym, nie wersalikami marki. */
.card__cena .woocommerce-price-suffix,
.zakup__cena .woocommerce-price-suffix,
.zestaw__ceny .woocommerce-price-suffix,
.pasek-zakupu__cena .woocommerce-price-suffix,
.rail .price .woocommerce-price-suffix{
  order:3;font-family:var(--text);font-size:.72rem;letter-spacing:normal;color:var(--muted);
}

/* Nota Omnibusa idzie do WLASNEGO wiersza pod kwota: prawo kaze ja pokazac
   przy kazdej oglaszanej obnizce, ale to przypis do ceny, a nie druga cena.
   W jednym wierszu z kwota zajmowala w kafelku tyle miejsca, co tytul. */
.card__cena .wc-price-history,
.zakup__cena .wc-price-history,
.zestaw__ceny .wc-price-history,
.pasek-zakupu__cena .wc-price-history,
.rail .price .wc-price-history{
  order:4;flex:1 0 100%;display:block;
  font-family:var(--text);font-size:.72rem;line-height:1.35;letter-spacing:normal;
  color:var(--muted);white-space:normal;font-weight:400;
}
/* W bloku zakupowym oba dopiski o stopien wieksze - stoja przy kwocie
   o 28 px i przy tamtej skali .72rem czytalo sie jak przypis do przypisu. */
.zakup__cena .woocommerce-price-suffix,
.zakup__cena .wc-price-history{font-size:.78rem}

/* Stara cena skaluje sie z kwota, obok ktorej stoi - stad "em", a nie "rem". */
.zakup__cena del{font-size:.57em}
.rail .price del{font-size:.76em}

/*
 * W PASKU ZOSTAJE SAMA KWOTA DO ZAPLATY - bez przekreslonej ceny i bez noty
 * Omnibusa. Nie jest to ukrywanie obnizki: pasek nie OGLASZA jej wcale, wiec
 * nie musi nosic noty. Cala historia ceny - stara kwota i najnizsza cena
 * z 30 dni - stoi w bloku zakupowym wyzej, na tej samej stronie.
 *
 * Powod jest praktyczny: pasek ma 68 px wysokosci i jedna linijke na cene.
 * Nota rozpychala go do trzech wierszy i zjadala miejsce przyciskowi
 * "Do koszyka", czyli jedynej rzeczy, po ktora ten pasek istnieje.
 */
/* Zamiast ceny bywa ZDANIE - "Zaloguj się, aby zobaczyć cenę" przy linii
   z cenami dla gabinetow. W stopniu pisma ceny (28 px) czytalo sie jak
   naglowek, wiec dostaje krój i wielkosc tekstu, a odnosnik - podkreslenie,
   po ktorym widac, ze jest w co kliknac. */
.zakup__cena--bez-zakupu,
.card__cena .vetted-hidden-price{font-family:var(--text);font-size:1rem;letter-spacing:normal}
.card__cena .vetted-hidden-price{font-size:.82rem;white-space:normal}
.zakup__cena .vetted-hidden-price a,
.card__cena .vetted-hidden-price a{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.zakup__niedostepny{margin-top:var(--s2);color:var(--muted)}

/* Trzy klasy w selektorze, bo tyle ma regula wtyczki Omnibusa
   (".wc-price-history.prior-price.lowest") - krotszy selektor przegrywal
   z nia waga i nota zostawala widoczna. */
.pasek-zakupu__cena del,
.pasek-zakupu .pasek-zakupu__cena .wc-price-history{display:none}

/* Cena wariantu ma wygladac jak .zakup__cena z makiety: WooCommerce wypisuje
   ja we wlasnym opakowaniu, wiec przenosimy na nie ten sam krój i rozmiar.
   Sufiks "z VAT" (ustawienie sklepu) idzie mniejszym stopniem obok kwoty. */
.zakup .woocommerce-variation-price{margin-top:var(--s2)}
/*
 * Selektor musi byc dluzszy niz wyglada. WooCommerce stawia cene na
 * "div.product span.price" wewnatrz .woocommerce - trzy klasy i dwa znaczniki.
 * Krotszy selektor przegrywal i cena schodzila do 20 px zamiast 28 px.
 */
.woocommerce div.product .zakup .woocommerce-variation-price span.price{
  font-family:var(--font-display);font-size:1.75rem;font-weight:400;letter-spacing:.02em;color:var(--ink);
  /* Interlinia z tekstu strony, tak jak w makiecie: cena stoi tam w akapicie
     i ma przez to 46 px wysokosci. Bez tego wiersz ma 33 px i cala kolumna
     zakupowa siada o 13 px wyzej niz projekt. */
  line-height:var(--lh-body);
  display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;
}
/* Dopisek "z VAT" (ustawienie sklepu) stoi w makiecie TYLKO przy cenie
   w bloku zakupowym. Na kafelkach, w zestawach i w koszyku ceny sa czyste -
   dopisek przy kazdej kwocie robi z listy szum. */
.woocommerce-price-suffix{display:none}
.zakup .woocommerce-price-suffix{display:inline;font-family:var(--text);font-size:.78rem;color:var(--muted)}
.zakup .woocommerce-variation-availability .stock,
.woocommerce div.product .zakup__form .stock{margin-top:.35rem;font-size:.78rem;color:var(--muted)}


/* "Wyczysc" spod wariantow. Makieta go nie ma i slusznie: pojemnosc jest
   wybrana od wejscia, wiec odnosnik kasujacy wybor prowadzi wylacznie do
   stanu, w ktorym nie da sie kupic. */
/* WooCommerce ma dla tego odnosnika wlasna regule z wieksza waga, stad
   selektor ze znacznikiem. Bez tego "Wyczysc" zostawal w ukladzie i dokladal
   40 px pustki miedzy pojemnoscia a cena. */
/* !important, bo to nie wojna ze stylami, tylko ze SKRYPTEM Woo: przy
   wybranym wariancie jego kod ustawia odnosnikowi styl bezposrednio na
   elemencie, a takiego nie da sie przebic zwyklym selektorem. */
.zakup a.reset_variations{display:none!important}
/* Odstepy w bloku zakupowym liczy makieta: pod formularzem stoi juz lista
   zaufania z wlasnym marginesem, a Woo dokladal do formularza swoje 2em. */
/* Selektory z "div.product form.cart", bo dokladnie takich uzywa WooCommerce
   dla swoich odstepow (2em pod formularzem, 1em pod lista wariantow). Krotsze
   przegrywaly i kolumna zakupowa byla o 28 px wyzsza niz w makiecie. */
.woocommerce div.product form.cart.zakup__form{margin-bottom:0}
.woocommerce div.product form.cart .variations{margin-bottom:0}
/* Odstep nad pojemnoscia daje juz formularz - makieta liczy go raz.
   Zostawiony podwajal sie do 40 px. */
.zakup .variations .warianty{margin-top:0}
/* Woo daje swojemu opakowaniu ceny i przycisku wlasne marginesy (1em z gora
   i z dolu). Odstepy w kolumnie zakupowej liczy makieta - ceny i lista
   zaufania stoja przez to o 16 px za nisko. */
.zakup .single_variation_wrap{margin:0}
.zakup .woocommerce-variation-add-to-cart{margin-bottom:0}

/* Lista rozwijana wariantow zostaje w kodzie (to ona jest polem formularza),
   ale schodzi z oczu, gdy skrypt zbuduje obok przyciski z makiety. Gdy
   skryptu nie ma, lista jest widoczna i mozna kupic. */
.warianty--przebrane select{ position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%) }
.warianty__przyciski{ display:flex; gap:.5rem; flex-wrap:wrap }
.warianty .reset_variations{ display:none }

/* Wczesniejsza, wlasna wersja bloku ceny zostala zdjeta - wyglad idzie teraz
   z makiety (rozmiar 1,75 rem i interlinia tekstu), a stan magazynowy jest
   ukryty razem z reszta rzeczy, ktorych makieta nie pokazuje. */
/* align-items:stretch, nie center - w makiecie stepnik ilosci jest tak samo
   wysoki jak przycisk zakupu (52 px). Przy center kurczyl sie do wysokosci
   samej cyfry i mial 28 px. */
.zakup__form .woocommerce-variation-add-to-cart{ display:flex;gap:var(--s2);align-items:stretch;margin-top:var(--s3);flex-wrap:nowrap }
/* Bez zawijania i z podstawa "auto": na telefonie stepnik (142 px) i przycisk
   z podstawa 12 rem nie miescily sie w 335 px i przycisk spadal do drugiego
   wiersza - rzad mial 110 px zamiast 52 px. W makiecie ilosc i przycisk stoja
   obok siebie na kazdej szerokosci. */
.zakup__form .single_add_to_cart_button{ flex:1 1 auto;min-width:0 }

/* Powiekszenie zdjecia. */
.lupa{
  position:fixed;inset:0;z-index:120;background:rgba(13,13,13,.92);
  display:grid;place-items:center;padding:var(--s4);
}
.lupa__obraz{ max-width:min(100%,1100px);max-height:90vh;object-fit:contain }
.lupa__zamknij{
  position:absolute;top:var(--s3);right:var(--s3);width:44px;height:44px;
  color:#fff;font-size:1.6rem;line-height:1;
}

/* ---------- powloka sciezki zakupowej ----------
   Koszyk i kasa maja wlasny, skrocony naglowek i stopke - bez menu i bez
   koszyka, zeby nie wyprowadzac z platnosci. Makiety tego widoku nie
   obejmuja, wiec regule zostawiamy w dotychczasowej postaci i dostosujemy
   ja przy etapie koszyka i kasy. */
.header--checkout { position: static; }

/*
 * .header__inner i .footer__inner to znaczniki SKROCONEJ powloki - reszta
 * sklepu uzywa juz .header__bar i .footer__grid z makiet. Regula ukladu dla
 * nich przepadla przy przenoszeniu powloki (siedziala w wymienianym bloku)
 * i naglowek kasy zostal bez zadnego ukladu: logo, wskaznik krokow i kontakt
 * staly jeden pod drugim. Zlapane przy sprawdzaniu wszystkich podstron.
 */
.header__inner,
.footer__inner {
	display: flex; flex-wrap: wrap; align-items: center;
	gap: var(--s2) var(--s4); justify-content: space-between;
	min-height: 64px;
}
.header__contact { color: var(--muted); font-size: var(--t-6); }
.footer--checkout .footer__inner { align-items: center; }

/* ---------- pasek sciezki zakupowej: logo posrodku ----------
   Trzy rowne kolumny zamiast "space-between": powrot z lewej, logo na srodku,
   miejsce na kontakt z prawej. Przy rozkladaniu do krawedzi logo uciekalo
   w lewo, bo dwie pozostale czesci sa dzis puste. */
.header--checkout .header__inner{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:var(--s2);
}
.header--checkout .logo{justify-self:center}
/* Wlasna szerokosc znaku w sciezce zakupowej. Regula z naglowka sklepu liczy
   go od szerokosci sciezki logo ("100% - 24px"), a tutaj ta sciezka jest
   kolumna dopasowana do... samego znaku - kolo sie zamykalo i logo rozlewalo
   sie na 297 px, spychajac sie z osi paska. */
.header--checkout .logo__img{width:min(200px,45vw)}
.header--checkout .header__contact{justify-self:end}
.header__wroc{margin:0;font-size:.82rem}
.header__wroc a{
  display:inline-flex;align-items:center;gap:.4rem;min-height:44px;color:var(--muted);
  transition:color .2s;
}
.header__wroc a:hover{color:var(--ink)}
.header__wroc svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.5}
/* Na telefonie zostaje sama strzalka - napis "Wróć do sklepu" zabieral tam
   tyle miejsca, ze logo przestawalo byc na srodku. */
@media(max-width:520px){
  .header__wroc span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
}

/* ---------- stopka sciezki zakupowej ----------
   Odnosniki prawne w JEDNYM WIERSZU, a nie jeden pod drugim: to lista czterech
   krotkich napisow, ktora w kolumnie zajmowala pol ekranu telefonu i wygladala
   jak menu, ktorego w sciezce zakupowej swiadomie nie ma. */
.footer--checkout .footer__legal-nav ul{
  display:flex;flex-wrap:wrap;gap:.4rem var(--s3);margin:0;padding:0;list-style:none;
}
/* Kolory jak w calej stopce: bialy tekst na czerni, rozjasniany przy
   najechaniu. Wczesniej staly tu barwy z jasnego tla - szarosc "muted"
   i czarny atrament przy najechaniu, czyli odnosnik, ktory po najechaniu
   znikal w tle. */
.footer--checkout .footer__legal-nav a{
  display:inline-flex;align-items:center;min-height:44px;font-size:.8rem;
  color:rgba(255,255,255,.72);transition:color .2s;
}
.footer--checkout .footer__copy{margin:0;font-size:.78rem;color:rgba(255,255,255,.55)}

/*
 * ODSTEPY. Pelna stopka ma nad plakietkami cztery kolumny odnosnikow, wiec
 * zaczyna od duzego oddechu (--s6 u gory) i odsuwa plakietki jeszcze raz
 * (margin-top:--s6). W sciezce zakupowej nad plakietkami NIE MA NICZEGO -
 * te dwa odstepy skladaly sie na kilkanascie centymetrow czarnej pustki
 * nad napisem "Płatności".
 */
.footer--checkout{padding-block:var(--s4)}
.footer--checkout .footer__badges{
  margin-top:0;padding-top:0;padding-bottom:var(--s3);
  border-top:0;border-bottom:1px solid rgba(255,255,255,.15);
}
@media(max-width:620px){
  .footer--checkout .footer__inner{justify-content:center;text-align:center}
  .footer--checkout .footer__legal-nav ul{justify-content:center}
}

/* ---------- przyciski sciezki zakupowej ----------
   Tylko te, ktore prowadza do zakupu: dodanie do koszyka z listy i z karty
   produktu, przejscie do kasy i zlozenie zamowienia. Reszta przyciskow
   w sklepie - wyslij wniosek, zapisz sie, filtruj - zostaje granatowa.
   Gdyby zzielenialy wszystkie, kolor przestalby cokolwiek znaczyc. */
.woocommerce a.button.add_to_cart_button,
.woocommerce button.single_add_to_cart_button.alt,
.woocommerce button.single_add_to_cart_button,
.woocommerce .checkout-button,
.woocommerce #place_order {
	background: var(--akcja); color: #fff;
}
/*
 * Przycisk "Do koszyka" na karcie produktu.
 *
 * WooCommerce ma dla niego regule z trzema klasami (button.button.alt), wiec
 * nasza z dwiema przegrywala mimo pozniejszego arkusza - przycisk wychodzil
 * FIOLETOWY i o 6 px za niski. Szablonu przycisku nie nadpisujemy (to plik,
 * ktory Woo zmienia co kilka wydan), wiec wyglad z makiety - Jost, wersaliki,
 * 52 px wysokosci - dokladamy tutaj, w jednym miejscu.
 */
.woocommerce .zakup__form button.single_add_to_cart_button {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 52px; padding: .9rem 1.75rem; border-radius: var(--radius);
	font-family: var(--font-display); font-size: .78rem; letter-spacing: var(--track);
	line-height: 1.3; text-transform: uppercase;
	background: var(--akcja); color: #fff;
}
.woocommerce .zakup__form button.single_add_to_cart_button:hover,
.woocommerce .zakup__form button.single_add_to_cart_button:focus-visible {
	background: var(--akcja-ciemna);
}

/*
 * Stan magazynowy spod ceny. Makieta go nie ma, a liczba sztuk na stanie to
 * informacja dla sklepu, nie dla klientki. Regula jest jedna i latwa do
 * cofniecia, gdyby Klientka chciala pokazywac dostepnosc.
 */
.zakup .woocommerce-variation-availability { display: none; }
.woocommerce a.button.add_to_cart_button:hover,
.woocommerce button.single_add_to_cart_button:hover,
.woocommerce .checkout-button:hover,
.woocommerce #place_order:hover,
.woocommerce a.button.add_to_cart_button:focus-visible,
.woocommerce button.single_add_to_cart_button:focus-visible,
.woocommerce .checkout-button:focus-visible,
.woocommerce #place_order:focus-visible {
	background: var(--akcja-ciemna); color: #fff;
}

/* ---------- formularze ---------- */
input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
input[type="password"], input[type="search"], input[type="number"], select, textarea {
	width: 100%; min-height: 44px; padding: .6rem .75rem;
	border: 1px solid var(--line-control); border-radius: var(--radius);
	font: inherit; color: var(--ink); background: var(--bg);
}
/* Nie gasimy obrysu bez podania zamiennika - inaczej nawigacja klawiatura
   przestaje byc widoczna (WCAG 2.4.7). */
input:focus-visible, select:focus-visible, textarea:focus-visible {
	border-color: var(--navy);
	outline: 2px solid var(--navy);
	outline-offset: 1px;
}

/* Pole z bledem: kolor nie moze byc jedynym nosnikiem informacji (WCAG 1.4.1),
   dlatego obok koloru zawsze idzie komunikat tekstowy przy polu. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
	border-color: #b3261e;
	border-width: 2px;
}
.field-error { color: #b3261e; font-size: var(--t-6); margin-top: .25rem; }

/*
 * Gwiazdka pola wymaganego.
 *
 * Klase wprowadza Vetted i definiuje ja wlasnym stylem, ale TYLKO na formularzu
 * wniosku. Formularz komentarza nalezy do motywu i uzywa tej samej klasy, wiec
 * bez tej reguly gwiazdka bylaby tam czarna. Powtarzamy ja swiadomie, zeby
 * motyw nie zalezal od tego, czy wtyczka jest wlaczona.
 *
 * Sama gwiazdka nie jest jedynym nosnikiem informacji - pola wymagane maja
 * atrybut required, ktory czyta czytnik ekranu (WCAG 1.4.1).
 */
.vetted-req { color: #b3261e; }

/*
 * POLE DUZE - wariant pola z makiety wniosku B2B.
 *
 * W makietach sa DWA formularze i roznia sie swiadomie:
 *
 *   .pole          formularz opinii z karty produktu - etykieta wersalikami,
 *                  pole 44 px. Krotki formularz przy tresci, ma nie
 *                  przykrywac recenzji, obok ktorych stoi.
 *   .pole--duze    wniosek o konto B2B - etykieta w kroju naglowkowym bez
 *                  wersalikow, pole 54 px. Formularz jest tu GLOWNA trescia
 *                  ekranu, a nie dodatkiem, wiec dostaje wiecej powietrza.
 *
 * Wariantu --duze uzywaja logowanie i formularze konta (decyzja Klienta
 * z 31.08.2026), a docelowo takze sam wniosek B2B.
 *
 * Obramowanie zostaje neutralne (--line-control), a nie czarne: czarna ramka
 * (.input z powloki) nalezy do POJEDYNCZEGO pola bedacego wezwaniem do
 * dzialania. Dziewiec czarnych prostokatow pod soba czytaloby sie jak
 * dziewiec wezwan.
 */
.pole--duze > label:not(.checkbox) {
	font-family: var(--font-display); font-size: .82rem; letter-spacing: .03em;
	text-transform: none; color: var(--ink); margin: 0;
}
.pole--duze input[type="text"], .pole--duze input[type="email"], .pole--duze input[type="tel"],
.pole--duze input[type="password"], .pole--duze input[type="number"], .pole--duze select,
.pole--duze .input-text {
	min-height: 54px; padding: 0 1rem; font-size: .95rem;
	border: 1px solid var(--line-control); border-radius: var(--radius); background: #fff;
	transition: border-color .2s;
}
.pole--duze textarea {
	padding: .85rem 1rem; font-size: .95rem; min-height: 88px;
	border: 1px solid var(--line-control); border-radius: var(--radius);
}
.pole--duze input:hover, .pole--duze textarea:hover, .pole--duze select:hover { border-color: var(--ink); }
.wymagane { color: #b3261e; margin-left: .15rem; }

/*
 * KARTA POBOCZNA - komponent z tej samej makiety.
 *
 * Sluzy tresci, ktora TOWARZYSZY formularzowi: korzysciom, informacji "masz
 * juz konto", danym kontaktowym. Wariant --akcent na porcelanie, bez ramki,
 * zeby nie konkurowal z polami formularza obok.
 */
/* Odstep wewnetrzny 32 px, na waskim ekranie 20 px. Przy jednolitych 20 px
   naglowek, lista, przycisk i przypis o koncie B2B siedzialy przy samych
   krawedziach porcelanowego tla - karta wygladala na ciasna przy formularzu
   obok, ktory ma pola po 54 px wysokosci. */
.bok-karta { border: 1px solid var(--line); padding: var(--s4); }
@media (max-width: 560px) { .bok-karta { padding: var(--s3); } }
.bok-karta--akcent { background: var(--porcelain); border-color: transparent; }
.bok-karta h2 {
	font-family: var(--font-display); font-size: .72rem; letter-spacing: var(--track);
	text-transform: uppercase; color: var(--muted); margin-bottom: var(--s3); font-weight: 400;
}
.bok-karta ul { display: flex; flex-direction: column; gap: .7rem; font-size: .86rem; list-style: none; margin: 0; padding: 0; }
.bok-karta li { position: relative; padding-left: 1.5rem; color: var(--ink-soft); }
/* Ptaszek rysowany dwiema krawedziami - ten sam co w makiecie, bez ikony. */
.bok-karta li::before {
	content: ""; position: absolute; left: 0; top: .42em; width: 10px; height: 6px;
	border-left: 1.6px solid var(--navy); border-bottom: 1.6px solid var(--navy); rotate: -45deg;
}
.bok-karta p { font-size: .86rem; color: var(--ink-soft); margin: 0; }
.bok-karta p + p { margin-top: var(--s2); }

/*
 * KOMUNIKAT (.alert) - wspolny dla kasy, konta i sekcji B2B.
 *
 * Mieszkal w arkuszu kasy, dopoki uzywala go tylko kasa. Od kiedy te same
 * bloki stoja na koncie i przy wniosku B2B, arkusz kasy musialby jechac
 * na strony, ktore z kasa nie maja nic wspolnego.
 */
.alert{
  background:var(--porcelain);border-left:3px solid var(--ink);
  padding:var(--s2) var(--s3);margin-bottom:var(--s3);
  font-size:.9rem;line-height:1.5;color:var(--ink);
}
.alert--ok{border-left-color:var(--akcja)}
.alert--blad{border-left-color:#b3261e}
/* Potwierdzenia i informacje maja czesto przycisk po prawej ("Zobacz koszyk") -
   stad wiersz. Bledy sa lista i musza zostac blokiem. */
.alert--ok,
.alert--info{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.alert--blad{display:block}
.alert__tytul{
  font-family:var(--font-display);font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
  color:#b3261e;margin:0 0 .5rem;
}
/* Jeden blad w jednym wierszu, z myslnikiem zamiast punktora - lista bledow
   ma sie czytac jak lista rzeczy do zrobienia, a nie jak akapit. */
.alert__lista{margin:0;padding:0;list-style:none;display:grid;gap:.35rem}
.alert__lista li{position:relative;padding-left:1rem}
.alert__lista li::before{content:"–";position:absolute;left:0;color:var(--muted)}
.alert__lista a{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.alert__lista a:hover{color:#b3261e}

/* ---------- WooCommerce: listing ---------- */
.woocommerce ul.products {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--s4); list-style: none; margin: 0; padding: 0;
}
.woocommerce ul.products::before, .woocommerce ul.products::after { content: none; }
.woocommerce ul.products li.product {
	width: auto !important; margin: 0 !important; float: none !important;
	display: flex; flex-direction: column;
	border: 1px solid var(--line); border-radius: var(--radius);
	padding: 1rem; background: var(--bg);
}
.woocommerce ul.products li.product a img { margin-bottom: .75rem; border-radius: 4px; }
/* Nazwa produktu wedlug .card__name z makiety kategorii. */
.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-family: var(--font-display); font-size: var(--t-7); font-weight: var(--w-regular);
	letter-spacing: var(--track-label); text-transform: uppercase;
	padding: 0; margin: 0 0 .35rem;
}
/* Cena: prominencje daje kroj naglowkowy i rozstrzelenie, a nie grubosc -
   tak jest w makietach (.price uzywa --display przy wadze 400). */
.woocommerce ul.products li.product .price {
	color: var(--ink); font-family: var(--font-display); font-weight: var(--w-regular);
	font-size: var(--t-8); letter-spacing: .06em; margin-bottom: .75rem;
}
.woocommerce ul.products li.product .button { margin-top: auto; align-self: flex-start; }
.woocommerce span.onsale {
	background: var(--navy); color: #fff; border-radius: var(--radius);
	min-height: auto; min-width: auto; line-height: 1; padding: .35rem .6rem;
	font-size: var(--t-4); font-weight: var(--w-medium);
}

/* ---------- WooCommerce: karta produktu ----------
 *
 * Uklad karty przejal szablon z makiety (.karta, .zakup, .opis), wiec dawna
 * siatka dwukolumnowa na .woocommerce div.product ZOSTALA USUNIETA.
 *
 * Nie byla martwa: nasz kontener nosi rowniez klase "product", ktora dokłada
 * wc_product_class - i przez to caly uklad karty rozjezdzal sie na dwie
 * kolumny po 568 px, z galeria w jednej i opisem w drugiej. Zlapane od razu
 * po pierwszym wgraniu szablonu.
 *
 * Zostaja tylko reguly, ktore nie dotycza ukladu strony produktu. */
.woocommerce .quantity input.qty { width: 5rem; text-align: center; }

/* ---------- WooCommerce: koszyk ---------- */
/*
 * WooCommerce wklada rekomendacje i podsumowanie do jednego kontenera
 * .cart-collaterals i ustawia je obok siebie na float. Zamieniamy to na siatke:
 * float w tym miejscu potrafi rozjechac uklad, gdy kafelek rekomendacji urosnie.
 *
 * Kolejnosc w kodzie to rekomendacje, potem podsumowanie - i taka zostaje.
 * Na szerokim ekranie idzie to na lewo i na prawo, wiec kolejnosc czytania
 * pokrywa sie z kolejnoscia wzrokowa i ognisko klawiatury nie skacze.
 */
.cart-collaterals { display: grid; gap: var(--s4); }
/*
 * WooCommerce czysci float pseudo-elementami ::before i ::after. W siatce
 * przestaja byc niewidocznym dodatkiem i staja sie pelnoprawnymi komorkami:
 * pusty ::before zajmuje pierwsza kolumne, rekomendacje spychaja do drugiej,
 * a podsumowanie laduje w nastepnym rzedzie. Selektor WooCommerce jest bardziej
 * szczegolowy od nazwy samej klasy, wiec bez !important reset nie dziala.
 */
.cart-collaterals::before, .cart-collaterals::after { content: none !important; }
.cart-collaterals .cross-sells,
.cart-collaterals .cart_totals {
	width: auto !important; float: none !important; margin: 0 !important;
}

@media (min-width: 861px) {
	.cart-collaterals { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); align-items: start; }
}

.cart_totals {
	background: var(--porcelain); border: 1px solid var(--line);
	border-radius: var(--radius); padding: 1.25rem;
}
.cart_totals h2 { font-size: var(--t-8); }
.cart_totals .checkout-button { display: block; text-align: center; margin-top: .75rem; }

.cross-sells h2 { font-size: var(--t-8); }
/* Kafelki rekomendacji sa mniejsze niz na listingu - to podpowiedz obok koszyka,
   a nie druga wystawa sklepowa. */
.cross-sells ul.products {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1rem;
}
.cross-sells ul.products li.product { padding: .75rem; }
/*
 * Zdjecia produktow sa kwadratowe, wiec w kafelku o szerokosci ~300 px daja
 * 300 px samej grafiki. Bez ograniczenia blok rekomendacji byl dwa razy wyzszy
 * niz podsumowanie koszyka, czyli element poboczny gorowal nad tym, po co
 * klient tu przyszedl. Kadrujemy, zamiast skalowac - inaczej zdjecie sie zgniata.
 */
.cross-sells ul.products li.product a img {
	max-height: 160px; width: 100%; object-fit: cover;
}
.cross-sells ul.products li.product .woocommerce-loop-product__title { font-size: var(--t-6); }
.cross-sells ul.products li.product .price { font-size: var(--t-6); margin-bottom: .5rem; }
.cross-sells ul.products li.product .button { font-size: var(--t-5); padding: .55rem .9rem; }

/*
 * Na waskim ekranie rekomendacje sa NAD podsumowaniem, wiec kazdy dodatkowy
 * kafelek odsuwa przycisk "Przejdz do kasy" w dol. Pokazujemy dwa zamiast czterech.
 * display:none usuwa je rowniez z czytnika ekranu, wiec obraz i odczyt sa zgodne.
 */
@media (max-width: 600px) {
	.cross-sells ul.products li.product:nth-child(n + 3) { display: none; }
}

/* ---------- WooCommerce: kasa ---------- */
/*
 * Pole dotyku przy wyborze dostawy i platnosci.
 *
 * Pola tekstowe i przyciski maja 44 px od poczatku, ale etykiety metod platnosci
 * mialy 19 px - przy najwazniejszym wyborze w calej kasie i przy grupie odbiorcow
 * 35-50+ korzystajacej glownie z telefonu. Zmierzone, nie oszacowane.
 *
 * Etykieta obejmuje przelacznik, wiec powiekszenie jej powieksza caly cel.
 */
/*
 * display idzie z !important swiadomie.
 *
 * Etykieta jest domyslnie elementem liniowym, a min-height NIE DZIALA na elementy
 * liniowe - wysokosc zostaje przy wysokosci wiersza tekstu. Sama regula ponizej
 * jest wczytana (sprawdzone w przegladarce), ale jej display przegrywa z czyms,
 * czego nie udalo sie wskazac przez wyliczenie regul we wszystkich arkuszach.
 * Zmierzone: bez !important etykieta platnosci ma 19 px, z nim 44 px.
 *
 * Pole dotyku to nie miejsce na poleganie na kolejnosci kaskady, ktorej nie
 * potrafimy odtworzyc. Wynik pilnuje test-a11y.
 */
.wc_payment_methods > li > label,
#shipping_method > li > label,
.woocommerce-checkout .woocommerce-form__label-for-checkbox {
	display: flex !important; align-items: center; gap: .5rem;
	min-height: 44px; margin: 0;
}
.wc_payment_methods > li > label input,
#shipping_method > li > label input,
.woocommerce-checkout .woocommerce-form__label-for-checkbox input {
	width: auto; min-height: 0; flex: none;
}
.wc_payment_methods { list-style: none; margin: 0; padding: 0; }
.wc_payment_methods .payment_box {
	background: var(--porcelain); border-radius: var(--radius);
	padding: .75rem 1rem; margin: 0 0 .75rem; font-size: var(--t-6);
}
.wc_payment_methods .payment_box p:last-child { margin-bottom: 0; }

/* Lista bledow kasy dostaje ognisko po nieudanej wysylce (Docket).
   Bez tego obrys ogniskowej wypadalby na samej krawedzi tekstu. */
.woocommerce-error:focus { outline: 2px solid var(--navy); outline-offset: 3px; }

/* ---------- WooCommerce: komunikaty ---------- */
.woocommerce-message, .woocommerce-info, .woocommerce-error {
	border-top: 0; border-left: 3px solid var(--navy);
	background: var(--porcelain); border-radius: var(--radius);
	padding: .9rem 1.1rem; list-style: none;
}
.woocommerce-error { border-left-color: #c0392b; }

/*
 * WooCommerce wstawia do powiadomien ikone przez ::before, uzywajac WLASNEGO
 * kroju ikonicznego. Motyw swiadomie nie wczytuje zadnych webfontow, wiec
 * przegladarka rysowala w tym miejscu pusty prostokaz zastepczy - ustawiony
 * absolutnie, czyli NA pierwszej literze tekstu.
 *
 * Widac to bylo na kazdym powiadomieniu w sklepie: koszyk, kasa, konto.
 * Wykryte przy ogladaniu kasy 02.08.2026, wczesniej niezauwazone, bo w kodzie
 * strony nie ma po tym sladu - to czysto wizualny skutek braku kroju.
 */
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before { content: none !important; }

/* ---------- wyniki wyszukiwania ---------- */
/* Zakladki zawezaja wyniki do produktow albo artykulow. Dzialaja bez JavaScriptu -
   to zwykle odnosniki z post_type w adresie. */
/* Zakladka to .chip z powloki - ta sama pigulka co dzialy bazy wiedzy
   i filtry katalogu. Otwarta poznaje sie po tle ORAZ po aria-current:
   kolor nie moze byc jedynym nosnikiem informacji (WCAG 1.4.1). */
.szukaj__zakladki ul {
	display: flex; flex-wrap: wrap; gap: .4rem;
	list-style: none; margin: 0 0 var(--s4); padding: 0;
}
.szukaj__zakladki .chip { gap: .35rem }
.szukaj__licznik { font-variant-numeric: tabular-nums; }

/* Wyniki ida w tej samej siatce co baza wiedzy - kafelek jest ten sam. */
.szukaj__wyniki { padding-block-end: var(--s5) }
/* Cena zamiast metadanych wpisu przy produkcie. */
.wpis-meta--cena { margin-top: .2rem; color: var(--ink) }
.wpis-meta--cena .amount { font-family: var(--font-display); letter-spacing: .02em }

/* ---------- pusty widok ---------- */
/* Pusta lista bez slowa wyjasnienia wyglada jak awaria strony. */
.pusto {
	border: 1px dashed var(--line-control); border-radius: var(--radius);
	padding: clamp(1.25rem, 4vw, 2rem); color: var(--muted);
	text-align: center;
}
.pusto__title { color: var(--ink); font-weight: var(--w-medium); margin: 0 0 .35rem; }
.pusto__text { margin: 0; }

/* ---------- stronicowanie wlasne ---------- */
.strony ul {
	display: flex; flex-wrap: wrap; gap: .4rem;
	list-style: none; margin: var(--s4) 0 0; padding: 0;
}
.strony .page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 44px; min-height: 44px; padding: 0 .6rem;
	border: 1px solid var(--line-control); border-radius: var(--radius);
	text-decoration: none;
}
.strony .page-numbers.current {
	background: var(--navy); color: #fff; border-color: var(--navy);
}

/* ---------- Baza wiedzy ---------- */
.archive-header { margin-bottom: clamp(1.25rem, 3vw, 2rem); }
.archive-intro { color: var(--muted); max-width: 60ch; }

.knowledge-nav ul {
	display: flex; flex-wrap: wrap; gap: .5rem;
	list-style: none; margin: 0 0 1.5rem; padding: 0;
}
.knowledge-nav a {
	display: inline-flex; align-items: center; min-height: 44px;
	padding: 0 .9rem; border: 1px solid var(--line-control);
	border-radius: 999px; text-decoration: none; font-size: var(--t-6);
}
/* Dzial otwarty poznaje sie po tle ORAZ po aria-current - kolor nie moze
   byc jedynym nosnikiem informacji (WCAG 1.4.1). */
.knowledge-nav a[aria-current] {
	background: var(--navy); color: #fff; border-color: var(--navy);
}

/* Kafelek .post-card usuniety 31.08.2026 - wszystkie listy (baza wiedzy,
   powiazane wpisy, wyniki wyszukiwania) uzywaja komponentu .post z powloki. */

.post-meta { color: var(--muted); font-size: var(--t-5); margin: 0; }
.post-meta a { color: var(--muted); }
.post-meta__sep { margin: 0 .15rem; }

.entry--post { max-width: 72ch; }
.entry-header { margin-bottom: clamp(1rem, 3vw, 1.75rem); }
.entry-thumb { margin: 0 0 1.5rem; }
.entry-thumb img { width: 100%; border-radius: var(--radius); }
.entry-thumb figcaption { color: var(--muted); font-size: var(--t-5); margin-top: .4rem; }

.related { margin-top: clamp(2rem, 5vw, 3.5rem); }
/* Naglowek podsekcji, jak .cart_totals h2 i .cross-sells h2. */
.related h2 { font-size: var(--t-8); }

/* Paginacja: cel dotyku 44 px, tak jak wszedzie indziej. */
.pagination .nav-links { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: var(--s4); }
.pagination .page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 44px; min-height: 44px; padding: 0 .6rem;
	border: 1px solid var(--line-control); border-radius: var(--radius);
	text-decoration: none;
}
.pagination .page-numbers.current {
	background: var(--navy); color: #fff; border-color: var(--navy);
}

/* ---------- komentarze ---------- */
.comments { margin-top: clamp(2rem, 5vw, 3.5rem); max-width: 72ch; }
.comment-list { list-style: none; margin: 0 0 2rem; padding: 0; }
.comment-list ol { list-style: none; padding-left: 1.25rem; }
.comment-body {
	border: 1px solid var(--line); border-radius: var(--radius);
	padding: 1rem; margin-bottom: 1rem;
}
.comment-meta { font-size: var(--t-5); color: var(--muted); margin-bottom: .5rem; }
.comment-notes { color: var(--muted); font-size: var(--t-6); }
.comment-form label { display: block; font-weight: var(--w-medium); margin-bottom: .25rem; }
.comment-form p { margin-bottom: 1rem; }
.comment-form .comment-form-cookies-consent {
	display: flex; align-items: center; gap: .5rem; min-height: 44px;
}
.comment-form .comment-form-cookies-consent input { width: auto; }
.comment-form .comment-form-cookies-consent label { font-weight: var(--w-regular); margin: 0; }

/* ---------- tresc ---------- */
.entry-content > * + * { margin-top: 1rem; }
.entry-content ul, .entry-content ol { padding-left: 1.25rem; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid var(--line); padding: .55rem .7rem; text-align: left; }

/* szerokie tabele nie moga rozpychac strony na mobile */
.entry-content table, .woocommerce table.shop_table { display: block; overflow-x: auto; }

/* ---------- filtry katalogu ----------
 *
 * Znaczniki wypisuje Docket, wyglad nalezy do motywu. Wtyczka miala wczesniej
 * wlasny <style> z paleta sprzed przeniesienia tokenow - kolor krawedzi zostal
 * tam wpisany na sztywno i po zmianie palety przestal pasowac do reszty.
 *
 * Na szerokim ekranie formularz stoi w kolumnie obok siatki i jest LEPKI.
 * Na telefonie wysuwa sie od dolu, tak jak w makiecie kategorii.
 */
.docket-filters__title { font-size: var(--t-8); margin: 0; }

.docket-filters__group { border: 0; padding: 0; margin: 0 0 var(--s3); }
.docket-filters__group legend {
	font-family: var(--font-display); font-size: var(--t-3);
	letter-spacing: var(--track-eyebrow); text-transform: uppercase;
	color: var(--muted); padding: 0; margin-bottom: var(--s1);
}
.docket-filters__opt {
	display: flex; align-items: center; gap: var(--s1);
	min-height: 44px; font-weight: var(--w-regular);
}
.docket-filters__opt input { width: auto; min-height: 0; }
.docket-filters__clear { margin-left: var(--s3); }

/* Naglowek formularza z przyciskiem zamkniecia - potrzebny tylko w szufladzie. */
.docket-filters__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.docket-filters__close, .docket-filters__toggle { display: none; }

.docket-active__list {
	list-style: none; display: flex; flex-wrap: wrap; gap: var(--s1);
	padding: 0; margin: var(--s1) 0 var(--s3);
}
.docket-active__list a {
	display: inline-flex; gap: .4rem; align-items: center; min-height: 44px;
	padding: 0 var(--s2); border: 1px solid var(--line-control);
	border-radius: 999px; text-decoration: none; color: var(--ink);
}
.docket-active__list a:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }

@media (min-width: 1000px) {
	.docket-filters {
		position: sticky; top: calc(var(--head-h) + var(--s3));
		max-height: calc(100vh - var(--head-h) - var(--s5));
		overflow: auto;
	}
}

@media (max-width: 999px) {
	/*
	 * Szuflada TYLKO wtedy, gdy jest czym ja otworzyc. Bez JavaScriptu
	 * formularz zostaje w normalnym przeplywie i dziala dalej - to zwykly
	 * formularz GET, a nie widget wymagajacy skryptu.
	 */
	.js .docket-filters__toggle {
		display: inline-flex; align-items: center; gap: var(--s1);
		min-height: 44px; padding: 0 var(--s3);
		background: none; color: var(--ink);
		border: 1px solid var(--line-control); border-radius: var(--radius);
		font-family: var(--font-display); font-size: var(--t-4);
		letter-spacing: var(--track-label); text-transform: uppercase;
		cursor: pointer;
	}
	.js .docket-filters__toggle b {
		display: grid; place-items: center; min-width: 20px; height: 20px;
		padding: 0 .3rem; background: var(--ink); color: var(--bg);
		font-family: var(--text); font-size: var(--t-2); font-weight: var(--w-regular);
	}

	.js .docket-filters__close {
		display: inline-flex; align-items: center; justify-content: center;
		width: 44px; height: 44px; background: none; cursor: pointer;
		border: 1px solid var(--line-control); border-radius: var(--radius);
		color: var(--ink); font-size: var(--t-8); line-height: 1;
	}

	.js .docket-filters {
		position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
		max-height: 82vh; overflow: auto;
		background: var(--bg); border-top: 1px solid var(--line);
		/* env() chroni przed paskiem gestow na telefonach bez przycisku Home. */
		padding: var(--s3) var(--pad) calc(var(--s3) + env(safe-area-inset-bottom, 0px));
		transform: translateY(100%);
		visibility: hidden;
		transition: transform .2s ease, visibility .2s;
	}
	.js .docket-filters.is-open { transform: none; visibility: visible; }
}

/* ---------- plakietki, dobor ---------- */
/* Style tych elementow siedza w motywie, a nie we wtyczce. Docket celowo nie
   wnosi wlasnego arkusza.

   Reguly listy ulubionych usuniete razem z modulem (decyzja Klientki
   z 10.08.2026). Zostaje position:relative na kafelku - z tego korzysta
   plakietka przeceny w rogu zdjecia. */

.woocommerce ul.products li.product { position: relative; }

.docket-plakietka {
	display: inline-block; margin-bottom: .35rem;
	font-size: var(--t-3); letter-spacing: .08em; text-transform: uppercase;
	color: var(--navy);
}

.docket-dobor { display: flex; flex-wrap: wrap; gap: .5rem; }
.docket-dobor__chip {
	display: inline-flex; align-items: center; min-height: 44px;
	padding: 0 1.1rem; border: 1px solid var(--line-control);
	border-radius: 999px; text-decoration: none; color: var(--ink);
	transition: background .2s, color .2s, border-color .2s;
}
.docket-dobor__chip:hover { background: var(--ink); color: #fff; border-color: var(--ink); }


@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* --- klauzula informacyjna przy formularzu ---
   Zwinieta, bo rozwinieta ma dwadziescia wierszy i odsuwa przycisk zamowienia
   o ekran w dol. Tresc siedzi w znacznikach od poczatku, wiec czytnik ekranu
   i wyszukiwarka widza ja bez klikania - <details> chowa ja tylko przed okiem. */
/* Odstep z OBU stron: klauzula stoi miedzy trescia formularza a przyciskiem
   wysylki, a bez dolnego marginesu przycisk przyklejal sie do jej dolnej
   kreski (0 px). Audyt mobilny 02.09.2026. */
.klauzula{margin-block:var(--s3);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.klauzula summary{
  list-style:none;cursor:pointer;display:block;position:relative;padding:var(--s2) 2rem var(--s2) 0;
  min-height:44px;font-family:var(--font-display);font-size:.78rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft);
}
.klauzula summary::-webkit-details-marker{display:none}
.klauzula summary::after{
  content:"+";position:absolute;right:0;top:50%;transform:translateY(-50%);
  color:var(--navy);font-size:1.1rem;line-height:1;
}
.klauzula[open] summary::after{content:"–"}
.klauzula summary:focus-visible{outline:2px solid var(--navy);outline-offset:2px}
.klauzula__tresc{padding-bottom:var(--s3);font-size:.82rem;line-height:1.7;color:var(--muted);max-width:62ch}
.klauzula__tresc p + p,.klauzula__tresc ol{margin-top:.6rem}
.klauzula__tresc ol{padding-left:1.3rem;display:grid;gap:.4rem}
.klauzula__tresc ol ol{list-style:lower-alpha;margin-top:.4rem}
.klauzula__wiecej{margin-top:.8rem}
.klauzula__wiecej a{text-decoration:underline;text-underline-offset:2px}
