/*
 * Reanimatik, style główne.
 * Kolejność: reset, baza, układ, komponenty, utilities.
 */

/* ==========================================================================
   1. Reset
   ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;

	/* Naglowek jest przyklejony i ma 72 px, wiec kazde przewiniecie do kotwicy
	   albo do kroku formularza chowalo pod nim pierwsza linijke celu. */
	scroll-padding-top: 88px;
}

/* Przejscie miedzy stronami zamiast bialego mrugniecia. Strona jest zwykla
   witryna na wielu adresach, wiec bez tego kazde klikniecie wyglada jak
   zaladowanie od nowa, a nie jak zmiana widoku. Przegladarka, ktora tego nie
   zna, po prostu przechodzi jak dotad. */
@view-transition {
	navigation: auto;
}

/* Naglowek i pasek akcji nie sa czescia widoku, tylko rama wokol niego.
   Bez wlasnej nazwy przenikalyby razem z trescia, czyli mrugalyby przy
   kazdym przejsciu, mimo ze na obu stronach wygladaja tak samo. */
.site-header {
	view-transition-name: rama-naglowek;
}

.action-dock {
	view-transition-name: rama-pasek;
}

@media (prefers-reduced-motion: reduce) {
	@view-transition {
		navigation: none;
	}

	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
	margin: 0;
}

ul[class],
ol[class] {
	padding: 0;
	list-style: none;
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
	height: auto;
}

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

button {
	background: none;
	border: 0;
	cursor: pointer;
}

/* ==========================================================================
   2. Baza
   ========================================================================== */

body {
	background-color: var(--c-bg);
	color: var(--c-body);
	font-family: var(--font-sans);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
	color: var(--c-ink);
	font-weight: var(--fw-bold);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-heading);
	text-wrap: balance;
}

h1 {
	font-size: var(--fs-h1);
}

h2 {
	font-size: var(--fs-h2);
}

h3 {
	font-size: var(--fs-h3);
	font-weight: var(--fw-semibold);
	letter-spacing: -0.018em;
}

h4 {
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	letter-spacing: 0;
}

p {
	text-wrap: pretty;
}

a {
	color: var(--c-ink);
	text-decoration-color: var(--c-border-strong);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.22em;
	transition: text-decoration-color var(--dur) var(--ease);
}

a:hover {
	text-decoration-color: var(--c-ink);
}

:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
	outline: var(--focus-ring);
	outline-offset: var(--focus-offset);
	border-radius: 2px;
}

::selection {
	background-color: var(--c-accent);
	color: var(--c-ink);
}

/* ==========================================================================
   3. Układ
   ========================================================================== */

.container {
	width: 100%;
	max-width: calc(var(--container) + var(--gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.container--prose {
	max-width: calc(var(--container-prose) + var(--gutter) * 2);
}

.section {
	padding-block: var(--sp-section);
}

/* Sekcja "inna" juz nie zmienia jasnosci tla o siedem procent, tylko o jeden,
   a granice rysuje kreska. Klasa siedzi w szesnastu szablonach, wiec taniej
   jest zmienic jej wyglad niz wycinac ja z kazdego z osobna. */
.section--alt {
	border-block: 1px solid var(--c-hairline);
	background-color: var(--c-bg-alt);
}

/* Dwie sekcje "inne" jedna pod druga daly podwojna kreske w miejscu styku. */
.section--alt + .section--alt {
	border-top: 0;
}

/* Sekcja z jednym waskim paskiem w srodku. Pelny odstep sekcji liczy sie od
   naglowka i akapitu, a nad samym paskiem liczb zostawal pas pustego tla
   wyzszy od tego, co mial otaczac. */
.section--tight {
	padding-block: clamp(2.5rem, 1rem + 5vw, 5rem);
}

/* Dawniej pelny gradient marki przez cala szerokosc. Pas pelnego nasycenia to
   jedyne miejsce na stronie, gdzie kolor krzyczal glosniej niz tresc. Teraz
   sekcja stoi na jasnym tle, a mgle rysuje .aurora--soft w srodku.
   Celowo nie ma tu wlasnego tla: mgla lezy na z-index -1, wiec tlo rodzica
   zaslonilo by ja w calosci. Pod spodem swieci tlo strony i o to chodzi. */
.section--aurora {
	position: relative;
	overflow: hidden;
	color: var(--c-ink);
}

/* Jedyna ciemna sekcja w tresci strony. Sluzy procesowi obslugi, zeby dalo sie
   go znalezc przy przewijaniu bez czytania calej strony. Mgla lezy tu nad tlem,
   a nie pod nim jak w .section--aurora, bo sekcja ma wlasny kolor tla, ktory
   zaslonilby warstwe z z-index -1. Dlatego tresc dostaje wlasny z-index. */
.section--dark {
	position: relative;
	overflow: hidden;
	background-color: var(--c-ink);
	color: rgba(255, 255, 255, 0.72);
}

.section--dark > .container {
	position: relative;
	z-index: 1;
}

.section--dark h2,
.section--dark h3 {
	color: var(--c-inverse);
}

.section--dark .kicker {
	color: var(--c-accent);
}

/* Ten sam powod co w stopce: czarny pierscien fokusa na czarnym tle znika. */
.section--dark :focus-visible {
	outline-color: var(--c-inverse);
}

.section__head {
	max-width: 62ch;
	margin-bottom: var(--sp-9);
}

.section__head--center {
	margin-inline: auto;
	text-align: center;
}

/* Dopisek pod sekcja, nie kolejny kafel. Ma byc czytelny, ale nie ma konkurowac
   z kaflami nad soba, bo to lektura na potem, a nie akcja do wykonania teraz. */
.section__aside {
	margin-top: var(--sp-7);
	font-size: var(--fs-small);
	color: var(--c-muted);
}

.section__aside a {
	color: var(--c-text);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.stack > * + * {
	margin-top: var(--flow, var(--sp-4));
}

.grid {
	display: grid;
	gap: var(--sp-5);
}

/* Stala liczba kolumn na kazdym progu. auto-fit potrafi dolozyc piata kolumne
   i zostawic poszarpany ostatni rzad, np. 12 kafli jako 5+5+2. */
.grid--2,
.grid--3,
.grid--4 {
	grid-template-columns: 1fr;
}

@media (min-width: 36rem) {
	.grid--3,
	.grid--4 {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 48rem) {
	.grid--2 {
		grid-template-columns: repeat(2, 1fr);
	}

	.grid--3 {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (min-width: 62rem) {
	/* minmax(0, 1fr), a nie 1fr: przy samym 1fr kolumna nie schodzi ponizej
	   swojej najweszej mozliwej tresci i to ona rozpycha siatke, zamiast
	   dzielic sie po rowno tym, co jest. */
	.grid--4 {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* Kafle uslug dziela wiersze siatki, zamiast kazdy uklada sie u siebie. Bez tego
   wystarczylo, ze jedna nazwa zlamala sie na dwie linijki ("Informatyk z dojazdem"),
   i w calym kaflu wszystko schodzilo o linijke nizej niz u sasiadow: opis zaczynal
   sie gdzie indziej, kreska stala gdzie indziej, cena stala gdzie indziej.
   Ile wierszy, tego nie wpisujemy recznie: siatka bierze tyle, ile ma jej
   najbogatszy kafel. Inaczej trzeba by pamietac, ze usluga ma cztery wiersze,
   wpis bloga trzy, a wynik wyszukiwania dwa. Nadmiarowy wiersz sam w sobie ma
   zerowa wysokosc, ale odstep siatki przed nim juz nie: kafle opieki IT, stron
   i reklamy mialy przez to 33 px luzu nad ikona i 51 px pod opisem, wiec cala
   czworka czytala sie jak osiadla na dol. */
.grid--cards > .card {
	display: grid;
	grid-template-rows: subgrid;
	grid-row: span 2;
}

.grid--cards:has(.card > :nth-child(3)) > .card {
	grid-row: span 3;
}

.grid--cards:has(.card > :nth-child(4)) > .card {
	grid-row: span 4;
}

/* Tekst obok ilustracji, ze srodkowaniem w pionie. */
.grid--split {
	align-items: center;
	gap: var(--sp-8);
}

/* Gdy kolumny mocno sie roznia wysokoscia, wysrodkowanie zostawia dziure pod
   krotsza z nich. Wtedy obie zaczynaja od gory. */
.grid--top {
	align-items: start;
}

/* ==========================================================================
   4. Typografia pomocnicza
   ========================================================================== */

.kicker {
	display: block;
	margin-bottom: var(--sp-3);
	color: var(--c-muted);
	font-size: var(--fs-kicker);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-kicker);
	line-height: 1.3;
	text-transform: uppercase;
}

.section--aurora .kicker {
	color: inherit;
	opacity: 0.75;
}

.display {
	font-size: var(--fs-display);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
}

.lead {
	font-size: var(--fs-lead);
	line-height: 1.5;
}

.lead--narrow {
	max-width: 44rem;
	margin-inline: auto;
}

.text-small {
	font-size: var(--fs-small);
}

.text-muted {
	color: var(--c-muted);
}

/* Odpowiedź wprost, otwiera każdą stronę usługową. Cytowalny akapit dla AI. */
.answer {
	max-width: 62ch;
	font-size: var(--fs-lead);
	line-height: 1.55;
	color: var(--c-ink);
}

.prose > * + * {
	margin-top: var(--sp-4);
}

/* Skala naglowkow jest zrobiona pod naglowki sekcji, a w dlugim tekscie h2
   w rozmiarze 3,5rem bylo wieksze od h1 strony. W tresci schodzimy o stopien. */
.prose h2 {
	margin-top: var(--sp-8);
	font-size: var(--fs-h3);
	font-weight: var(--fw-medium);
	letter-spacing: -0.012em;
}

.prose h3 {
	margin-top: var(--sp-6);
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
}

/* Reset zdejmuje markery z ul[class], wiec listy w tresci musza je odzyskac. */
.prose ul,
.prose ol {
	padding-left: 1.25rem;
	list-style: revert;
}

.prose li + li {
	margin-top: var(--sp-2);
}

.list-check {
	display: grid;
	gap: var(--sp-3);
	max-width: 62ch;
}

.list-check li {
	position: relative;
	padding-left: 2rem;
}

.list-check li::before {
	content: '';
	position: absolute;
	top: 0.45em;
	left: 0;
	width: 1.15rem;
	height: 1.15rem;
	background: var(--c-ink);
	border-radius: var(--radius-pill);
	/* Ptaszek jako maska, zeby nie dokladac plikow SVG dla trzech punktow listy. */
	-webkit-mask: no-repeat center / 0.7rem url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"), linear-gradient(#000, #000);
	mask: no-repeat center / 0.7rem url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"), linear-gradient(#000, #000);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
}

/* Wariant do wnetrza kart planow: wezsze wciecie i mniejszy ptaszek. */
.list-check--sm {
	gap: var(--sp-2);
	font-size: var(--fs-small);
	line-height: 1.55;
}

.list-check--sm li {
	padding-left: 1.6rem;
}

.list-check--sm li::before {
	width: 0.95rem;
	height: 0.95rem;
	top: 0.35em;
	/* Druga warstwa maski to gradient wypelniajacy pigulke, musi zostac na auto. */
	-webkit-mask-size: 0.6rem, auto;
	mask-size: 0.6rem, auto;
}

/* Widelki cenowe na podstronach uslugowych. Nazwa pracy i kwota na przeciwnych
   koncach wiersza, zeby kwoty ustawily sie w kolumne i dalo sie je porownac
   wzrokiem. Na waskim ekranie wiersz sie lamie, bo kwota z zastrzezeniem obok
   nazwy pracy nie miesci sie w 390 px. */
.pricelist {
	display: grid;
	gap: var(--sp-4);
	max-width: 34rem;
}

.pricelist li {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2) var(--sp-4);
	align-items: baseline;
	justify-content: space-between;
	padding-bottom: var(--sp-4);
	border-bottom: 1px solid var(--c-border);
}

.pricelist li:last-child {
	padding-bottom: 0;
	border-bottom: 0;
}

/* Zastrzezenie idzie zawsze do wlasnego wiersza, zeby kolejnosc nazwa, kwota,
   zastrzezenie byla ta sama niezaleznie od tego, czy wiersz sie zlamal. */
.pricelist__note {
	flex-basis: 100%;
	margin-top: calc(var(--sp-1) * -1);
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* Cyfry o stalej szerokosci. Kwoty stoja jedna pod druga, a w proporcjonalnym
   kroju "1" jest wezsze od "3", wiec kolumna sie faluje i porownanie wzrokiem,
   po ktore ta lista istnieje, przestaje dzialac. */
.pricelist__price {
	font-weight: 600;
	color: var(--c-ink);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.figure-panel {
	display: grid;
	place-items: center;
	margin: 0;
	padding: var(--sp-7);
	background: var(--c-bg-alt);
	border-radius: var(--radius-lg);
}

.figure-panel img {
	border-radius: var(--radius);
}

/* Zajawka planow abonamentu obok tekstu na stronie glownej. Wiersze rozdziela
   wlos, a nie ramka wokol kazdego planu: cztery kafle w kaflu robilyby drugi
   poziom zaokraglen w tej samej kolumnie. */
.plans-teaser {
	gap: var(--sp-5);
}

.plans-teaser__head {
	margin: 0;
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	color: var(--c-ink);
}

.plans-teaser__list {
	display: grid;
	margin: 0;
	padding: 0;
	list-style: none;
}

.plans-teaser__list li {
	padding-block: var(--sp-3);
	border-top: 1px solid var(--c-hairline);
}

.plans-teaser__list li:first-child {
	padding-top: 0;
	border-top: 0;
}

.plans-teaser__list li:last-child {
	padding-bottom: 0;
}

.plans-teaser__name {
	display: block;
	font-weight: var(--fw-semibold);
	color: var(--c-ink);
}

.plans-teaser__for {
	display: block;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

.plans-teaser__note {
	margin: 0;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* ==========================================================================
   5. Przyciski
   ========================================================================== */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sp-2);
	min-height: 48px;
	padding: 0.85rem 1.5rem;
	border: 1px solid transparent;
	border-radius: var(--radius);
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	letter-spacing: 0.01em;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
		transform var(--dur-fast) var(--ease);
}

/* Wlasny `display` przykrywa atrybut hidden, wiec schowany przycisk trzeba
   schowac jeszcze raz. */
.btn[hidden] {
	display: none;
}

/* Wygaszony jest tylko przycisk wysylki, i tylko na czas wysylania. Ma wygladac
   na zajety, a nie na zepsuty, wiec zostaje kolor marki, schodzi sam kontrast. */
.btn:disabled {
	cursor: progress;
	opacity: 0.72;
	transform: none;
}

/* Glowny przycisk schodzil pod kursorem z #0a0a0a na #262626, czyli o roznice,
   ktorej na czerni nie widac. Zrzuty stanu spoczynku i najechania byly nie do
   odroznienia. Uniesienie o piksel z cieniem czyta sie od razu i jest tym samym
   ruchem, ktorym reaguje kafel uslugi, wiec cala strona odpowiada jednym gestem. */
.btn:hover {
	text-decoration: none;
	transform: translateY(-1px);
}

.btn:active {
	transform: translateY(1px);
}

.btn--primary {
	background-color: var(--c-ink);
	color: var(--c-inverse);
}

.btn--primary:hover {
	background-color: #262626;
	box-shadow: var(--shadow-md);
}

/* Secondary jest wyraźnie lżejszy od primary. Na starej stronie oba CTA wyglądały tak samo. */
.btn--secondary {
	background-color: transparent;
	border-color: var(--c-border-strong);
	color: var(--c-ink);
}

.btn--secondary:hover {
	border-color: var(--c-ink);
	background-color: rgba(10, 10, 10, 0.04);
}

/* Na aurorze jasnoszara ramka ginie, więc secondary dostaje przyciemnioną krawędź. */
.section--aurora .btn--secondary,
.hero .btn--secondary {
	border-color: rgba(10, 10, 10, 0.35);
}

.section--aurora .btn--secondary:hover,
.hero .btn--secondary:hover {
	border-color: var(--c-ink);
}

.btn--inverse {
	background-color: var(--c-inverse);
	color: var(--c-ink);
}

.btn--inverse:hover {
	background-color: var(--c-peach);
}

.btn--lg {
	min-height: 56px;
	padding: 1.05rem 1.85rem;
	font-size: 1rem;
}

.btn--full {
	width: 100%;
}

.btn-group {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3);
}

/* Na waskim ekranie przyciski i tak ida jeden pod drugim, wiec rowna szerokosc
   wyglada porzadniej niz dwa bloki roznej dlugosci. */
.btn-group > .btn {
	flex: 1 1 100%;
}

@media (min-width: 30rem) {
	.btn-group > .btn {
		flex: 0 0 auto;
	}
}

.btn-group--center {
	justify-content: center;
}

/* Link ze strzałką, używany w kaflach */
.link-arrow {
	display: inline-flex;
	align-items: center;
	gap: 0.4em;
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	text-decoration: none;
}

.link-arrow::after {
	content: '\2192';
	transition: transform var(--dur) var(--ease);
}

.link-arrow:hover::after {
	transform: translateX(3px);
}

/* ==========================================================================
   6. Badge, pigułki, ocena
   ========================================================================== */

.badge {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	padding: 0.4rem 0.85rem;
	border: 1px solid var(--c-border);
	border-radius: var(--radius-pill);
	background-color: var(--c-surface);
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	line-height: 1.4;
	color: var(--c-ink);
	text-decoration: none;
}

.rating {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
}

.rating__stars {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	color: var(--c-star);
}

.rating__stars svg {
	display: block;
	width: 1.0625rem;
	height: 1.0625rem;
	fill: currentColor;
}

.rating__value {
	font-weight: var(--fw-bold);
	color: var(--c-ink);
}

/* ==========================================================================
   7. Karty
   ========================================================================== */

/* Kafel odciaga sie od tla cieniem albo obwodka, nigdy oboma naraz. Wczesniej
   mial jedno i drugie, a do tego stal na tle o innej jasnosci, wiec kazda krawedz
   byla narysowana trzy razy. Obwodka zostaje przezroczysta, zeby na :hover bylo
   co zabarwic bez przeliczania ukladu. */
.card {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	padding: var(--sp-card);
	border: 1px solid transparent;
	border-radius: var(--radius-lg);
	background-color: var(--c-surface);
	box-shadow: var(--shadow-sm);
	transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
		box-shadow var(--dur) var(--ease);
}

.card__title {
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	letter-spacing: 0;
}

/* Tytul kafla jest linkiem, wiec domyslnie dostawal podkreslenie i cala kratka
   uslug wygladala jak spis tresci, a nie jak oferta. Rolę "to jest klikalne"
   przejmuje uniesienie kafla i strzalka. */
.card__title a,
.card__link {
	text-decoration: none;
}

.card__text {
	flex-grow: 1;
	font-size: var(--fs-small);
	line-height: 1.6;
}

/* Kreska nad zdaniem o cenie to jedyna widoczna pozioma linia w calym wierszu
   kafli. Gdy tekst kafla rosl do pelnej wysokosci, kreska ladowala raz wyzej,
   raz nizej, zaleznie od tego, czy zdanie o cenie zlamalo sie na dwie linijki:
   w siatce uslug rozjazd wynosil 22 px i widac go bylo z drugiego konca ekranu.
   Teraz kreska stoi zawsze tyle samo pod opisem, a luz schodzi na dol kafla,
   gdzie nie ma czego rozjechac, bo tlo jest jednolicie biale. */
.card__text:has(+ .card__hook) {
	flex-grow: 0;
}

/* Numer telefonu i adres e-mail na kaflu kontaktowym. Wczesniej szly zwykla
   trescia kafla, wiec numer, po ktory klient tu wszedl, wygladal dokladnie tak
   samo jak zdanie o godzinach obok niego. Kolor tuszu i wieksza waga robia
   z niego to, czym jest, czyli glowna rzecza na kaflu. */
.card__value {
	font-size: 1.0625rem;
	font-weight: var(--fw-medium);
	line-height: 1.45;
	color: var(--c-ink);
}

.card__value a {
	text-decoration: none;
}

.card--link:hover .card__value a {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Kafel obszaru pracy nie jest odnosnikiem, wiec jego pierwsza linia ma czytac
   sie jak zdanie, a nie jak zaproszenie do klikniecia. */
.card__value--plain {
	font-weight: var(--fw-regular);
	color: var(--c-body);
}

/* Zdanie o pieniadzach na dole kafla. Pierwsze pytanie, z ktorym klient wchodzi
   na strone serwisu, brzmi "ile to bedzie kosztowac", wiec odpowiedz stoi juz
   w ofercie, a nie dopiero na podstronie uslugi. */
.card__hook {
	margin-top: var(--sp-4);
	padding-top: var(--sp-4);
	border-top: 1px solid var(--c-border);
	font-size: var(--fs-kicker);
	font-weight: var(--fw-medium);
	color: var(--c-ink);
}

/* Pozostale osiem uslug jako jeden wiersz nazw. Dostaja tyle miejsca, ile
   naprawde wazą w ofercie: da sie je znalezc, ale nie zaglusza trzonu. */
.service-row {
	display: grid;
	gap: var(--sp-2);
	margin: var(--sp-5) 0 0;
	padding: 0;
	list-style: none;
}

.service-row__item {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	min-height: 52px;
	padding: var(--sp-2) var(--sp-4);
	border: 1px solid transparent;
	border-radius: var(--radius-pill);
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	color: var(--c-ink);
	text-decoration: none;
	transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.service-row__item:hover {
	border-color: var(--c-border);
	background-color: var(--c-surface);
}

.service-row__icon {
	display: grid;
	place-items: center;
	flex: none;
	width: 32px;
	height: 32px;
	border-radius: 9px;
	border: 1px solid rgba(255, 143, 77, 0.28);
	background-image: var(--grad-tint);
}

.service-row__icon svg {
	width: 17px;
	height: 17px;
}

/* Jedna kolumna na telefonie. W dwoch nazwy takie jak "Google i Facebook Ads"
   lamaly sie na trzy wiersze i lista wygladala na potarganą. */
@media (min-width: 36rem) {
	.service-row {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 48rem) {
	.service-row {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* Cały kafel klikalny, ale w DOM link jest tylko jeden, więc czytniki nie dublują treści. */
.card--link {
	position: relative;
}

.card--link:hover {
	border-color: var(--c-border);
	transform: translateY(-3px);
	box-shadow: var(--shadow-md);
}

.card--link .card__link::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
}

/* Strzalka rysowana z ramki, bez dodatkowego znaku w HTML. Lezy w rogu kafla
   i wysuwa sie po najechaniu, wiec kafel od razu mowi, ze prowadzi dalej. */
.card--link::after {
	content: '';
	position: absolute;
	top: var(--sp-card);
	right: var(--sp-card);
	width: 9px;
	height: 9px;
	border-top: 2px solid var(--c-border-strong);
	border-right: 2px solid var(--c-border-strong);
	transform: rotate(45deg);
	transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.card--link:hover::after {
	border-color: var(--c-ink);
	transform: rotate(45deg) translate(3px, -3px);
}

/* Kafelek pod ikona niesie kolor marki na spoczynku, ale w rozcienczeniu.
   Wersja na pelnym czarnym dawala cztery ciezkie bloki w rzedzie, ktore
   przykuwaly wzrok mocniej niz nazwa uslugi obok. */
.card__icon {
	display: grid;
	place-items: center;
	width: 52px;
	height: 52px;
	border-radius: var(--radius);
	border: 1px solid rgba(255, 143, 77, 0.18);
	background-image: var(--grad-tint);
	color: var(--c-ink);
	transition: background-image var(--dur) var(--ease), transform var(--dur) var(--ease),
		box-shadow var(--dur) var(--ease);
}

/* Pelna aurora wchodzi dopiero przy najechaniu, jako jeden akcent na ekran. */
.card--link:hover .card__icon {
	background-image: var(--grad-aurora);
	transform: scale(1.04);
	box-shadow: 0 6px 16px rgba(244, 96, 60, 0.24);
}

.card__icon svg,
.card__icon img {
	width: 26px;
	height: 26px;
}

/* Karty planow abonamentowych. Bez kwot, wiec ciezar wizualny niesie nazwa. */
.plan__name {
	font-size: var(--fs-h3);
	line-height: 1.15;
}

.plan__for {
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* Nazwa, zdanie o adresacie, lista i przycisk stoja u wszystkich czterech
   planow w tych samych wierszach, bo karta jest podsiatka (patrz .grid--cards).
   Wczesniej lista tylko rozpychala sie flexem do dolu i wystarczylo, ze zdanie
   "Dla osob prywatnych i malych firm" zlamalo sie na dwie linijki, zeby w planie
   Start kreska nad lista stala 12 px nizej niz w trzech pozostalych. */
.plan .list-check {
	margin-top: var(--sp-2);
	padding-top: var(--sp-4);
	border-top: 1px solid var(--c-border);
}

/* Przyciski w calej stronie nie lamia napisu, bo stoja obok siebie w rzedzie
   i zlamany napis wygladalby jak blad. Ten stoi sam w kaflu na cala szerokosc
   kolumny, wiec zakaz lamania nic tu nie chroni, a szkodzi: "Wycen plan
   Premium" w jednej linii jest najszerszym elementem kafla i to on ustawial
   minimalna szerokosc kolumny. Cztery takie kolumny nie miescily sie na
   ekranie 1024 px i cala strona jechala w bok o 68 px. */
.plan__cta {
	margin-top: var(--sp-5);
	white-space: normal;
}

/* ==========================================================================
   8. Nawigacja
   ========================================================================== */

.skip-link {
	position: absolute;
	left: -9999px;
	z-index: var(--z-overlay);
	padding: var(--sp-3) var(--sp-4);
	background-color: var(--c-ink);
	color: var(--c-inverse);
}

.skip-link:focus {
	left: var(--sp-4);
	top: var(--sp-4);
}

/* Pojemniki, ktore dostaja focus tylko z reki skryptu, po to zeby czytnik ekranu
   trafil we wlasciwe miejsce. Klient sam tam skoczyl, wiec obwodka wokol calej
   tresci nic mu nie mowi, a wyglada jak blad. */
main:focus,
[data-form-notice]:focus {
	outline: none;
}

.site-header {
	position: sticky;
	top: 0;
	z-index: var(--z-nav);
	background-color: rgba(var(--c-bg-rgb), 0.92);
	backdrop-filter: saturate(180%) blur(12px);
	box-shadow: var(--shadow-nav);
}

.site-header__inner {
	display: flex;
	align-items: center;
	gap: var(--sp-5);
	min-height: 72px;
}

/* Logo to link do strony glownej, wiec musi miec pole dotyku, a nie sam obrazek.
   Naglowek trzyma 72 px z min-height, wiec ten padding go nie rusza. */
.site-brand {
	display: flex;
	flex: none;
	align-items: center;
	padding-block: var(--sp-2);
}

/* Bez `flex: none` logo jako element flex kurczylo sie razem z naglowkiem:
   na telefonie zamiast 129 px szerokosci mialo 73, czyli napis "Reanimatik"
   byl scisniety do 57 procent. Wysokosc trzymala 34 px, wiec proporcja szla
   w niwecz i nikt tego nie widzial jako bledu, tylko jako weza w logo. */
.site-brand img {
	flex: none;
	width: auto;
	height: 34px;
}

.site-nav {
	margin-left: auto;
}

.site-nav__list {
	display: flex;
	align-items: center;
	gap: var(--sp-5);
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-nav__list > li > a {
	display: inline-block;
	padding-block: var(--sp-2);
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	text-decoration: none;
}

.site-nav__list > li > a:hover,
.site-nav__list .current-menu-item > a {
	text-decoration: underline;
	text-decoration-color: var(--c-ink);
	text-underline-offset: 0.4em;
}

/* ==========================================================================
   8a. Panel uslug w naglowku
   ========================================================================== */

.site-nav__item--panel {
	position: relative;
	display: flex;
	align-items: center;
	gap: var(--sp-1);
}

/* Strzalke pokazuje dopiero JavaScript, bo bez niego nie ma czego rozwijac. */
.site-nav__chevron {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2rem;
	min-height: 2rem;
	padding: 0.25rem;
	border-radius: var(--radius);
	color: var(--c-muted);
	line-height: 0;
}

/* Niewidoczna, ale nadal zajmuje swoje miejsce. Wczesniej znikala calkiem,
   wiec w chwili, gdy skrypt ja pokazywal, cale menu rozjezdzalo sie na boki:
   to bylo jedyne przesuniecie ukladu, jakie zostalo na tej stronie. Sama
   visibility wystarczy, zeby przycisk wypadl z kolejnosci tabulacji i z drzewa
   dostepnosci, wiec bez JavaScriptu nadal nie ma tu czego kliknac. */
.site-nav__chevron[hidden] {
	visibility: hidden;
}

.site-nav__chevron svg {
	width: 15px;
	height: 15px;
	transition: transform var(--dur) var(--ease);
}

.site-nav__chevron[aria-expanded='true'] svg {
	transform: rotate(180deg);
}

.nav-panel {
	position: absolute;
	top: calc(100% + var(--sp-4));
	left: 50%;
	z-index: var(--z-nav);
	width: min(46rem, calc(100vw - 2 * var(--gutter)));
	padding: var(--sp-6);
	background-color: var(--c-surface);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-pop);
	transform: translate(-50%, -6px);
	opacity: 0;
	transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.nav-panel[hidden] {
	display: none;
}

.nav-panel[data-open='true'] {
	transform: translate(-50%, 0);
	opacity: 1;
}

.nav-panel__inner {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sp-5) var(--sp-6);
}

/* Miejsce na dwie linie nagłówka nawet tam, gdzie starcza jedna. "Instalacje
   i konfiguracja" sie zawija, wiec bez tego srodkowa kolumna zaczynala liste
   o wiersz nizej niz sasiednie i cala siatka wygladala na krzywa. */
.nav-panel__kicker {
	display: block;
	min-height: 2.8em;
	margin-bottom: var(--sp-3);
	font-size: var(--fs-kicker);
	line-height: 1.4;
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-kicker);
	text-transform: uppercase;
	color: var(--c-muted);
}

.nav-panel__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.nav-panel__link {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-2) var(--sp-3);
	margin-inline: calc(var(--sp-3) * -1);
	border-radius: var(--radius);
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	text-decoration: none;
	transition: background-color var(--dur-fast) var(--ease);
}

.nav-panel__link:hover {
	background-color: var(--c-bg);
	text-decoration: none;
}

.nav-panel__icon {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	border-radius: var(--radius);
	background-color: var(--c-bg);
	color: var(--c-ink);
	transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.nav-panel__icon svg {
	width: 17px;
	height: 17px;
}

.nav-panel__link:hover .nav-panel__icon {
	background-color: var(--c-ink);
	color: var(--c-inverse);
}

.nav-panel__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-4);
	margin-top: var(--sp-6);
	padding-top: var(--sp-5);
	border-top: 1px solid var(--c-border);
}

.nav-panel__more {
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
}

@media (prefers-reduced-motion: reduce) {
	.nav-panel {
		transition: none;
	}
}

/* Na telefonie menu jest juz rozwinieta lista, wiec panel nie ma nad czym
   plywac. Zostaje w miejscu jako wciecie pod "Uslugami", a strzalka jest tu
   jedynym sposobem na jego otwarcie, bo nie ma kursora do najechania. */
@media (max-width: 60rem) {
	.site-nav__item--panel {
		flex-wrap: wrap;
		justify-content: space-between;
	}

	.site-nav__item--panel > a {
		flex: 1;
	}

	.site-nav__chevron {
		padding: var(--sp-4) var(--sp-2);
	}

	.nav-panel {
		position: static;
		width: 100%;
		padding: 0 0 var(--sp-4);
		background: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		transform: none;
		opacity: 1;
	}

	.nav-panel[data-open='true'] {
		transform: none;
	}

	.nav-panel__inner {
		grid-template-columns: 1fr;
		gap: var(--sp-5);
	}

	.nav-panel__kicker {
		min-height: 0;
	}

	.nav-panel__link {
		padding-block: var(--sp-3);
		margin-inline: 0;
		font-size: 1rem;
	}

	.nav-panel__foot {
		flex-direction: column;
		align-items: stretch;
		margin-top: var(--sp-5);
	}
}

.site-header__actions {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
}

/* Reset wyzej daje kazdemu svg height: auto, wiec ikona jako element flex
   kurczyla sie razem z wysokoscia i schodzila do trzech pikseli. Trzy kreski
   hamburgera byly na telefonie plamka obok slowa "Menu". */
.nav-toggle svg {
	flex: none;
	width: 18px;
	height: 18px;
}

/* Jedyna droga do menu na telefonie, a mierzyl 39 px wysokosci. Ponizej
   czterdziestu czterech palec zaczyna chybiac, wiec ten jeden przycisk
   dostaje wysokosc na sztywno, niezaleznie od tego, ile ma paddingu. */
.nav-toggle {
	display: none;
	align-items: center;
	gap: var(--sp-2);
	min-height: 44px;
	padding: 0.6rem 0.85rem;
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius);
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
}

@media (max-width: 60rem) {
	.nav-toggle {
		display: inline-flex;
		margin-left: auto;
	}

	/* Menu wisi poza ukladem strony, wiec nie podnosi jej wysokosci i strona
	   pod nim nie ma sie jak przewinac. Po rozwinieciu uslug lista jest
	   dluzsza niz ekran, wiec przewijanie musi byc w samym menu. Bez tego
	   "Kontakt" na dole po prostu nie da sie dosiegnac. */
	.site-nav {
		display: none;
		position: absolute;
		inset-inline: 0;
		top: 100%;
		max-height: calc(100vh - 72px);
		max-height: calc(100dvh - 72px);
		padding: var(--sp-5) var(--gutter) var(--sp-6);
		overflow-y: auto;
		overscroll-behavior: contain;
		background-color: var(--c-surface);
		border-top: 1px solid var(--c-border);
		box-shadow: var(--shadow-pop);
	}

	.site-nav[data-open='true'] {
		display: block;
	}

	.site-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.site-nav__list > li + li {
		border-top: 1px solid var(--c-border);
	}

	.site-nav__list > li > a {
		display: block;
		padding-block: var(--sp-4);
		font-size: 1.0625rem;
	}

	.site-header__actions .btn--phone {
		display: none;
	}
}

/* Miedzy progiem menu a duzym ekranem naglowek ma szesc pozycji, numer telefonu
   i przycisk w jednym rzedzie. Przy pelnej etykiecie telefonu ("Zadzwon: numer",
   ta sama, co na calej stronie) menu lamalo sie na 1024 px na dwie linie.
   Zbijamy odstepy zamiast skracac napis, bo napis jest tu ta sama nazwa akcji,
   co wszedzie indziej, a odstep jest tylko odstepem. */
@media (min-width: 60.01rem) and (max-width: 75rem) {
	.site-header__inner {
		gap: var(--sp-4);
	}

	.site-nav__list {
		gap: var(--sp-4);
	}

	.site-header__actions {
		gap: var(--sp-2);
	}

	.site-header__actions .btn {
		padding-inline: var(--sp-4);
	}
}

/* Tuz nad progiem menu jest najciasniej: pasek dostaje szesc pozycji i numer
   naraz, a szerokosci jeszcze nie przybylo. Tutaj menu schodzi o stopien
   w dol skali, zeby nazwy zostaly w calosci. */
@media (min-width: 60.01rem) and (max-width: 64rem) {
	.site-nav__list > li > a {
		font-size: var(--fs-small);
	}
}

.site-header__actions .btn,
.site-nav__list > li > a {
	white-space: nowrap;
}

/* Na waskim ekranie naglowek ma trzy elementy w jednym rzedzie,
   wiec zbijamy odstepy, zeby CTA nie lamalo sie na dwie linie. */
@media (max-width: 26rem) {
	.site-header__inner {
		gap: var(--sp-3);
	}

	.site-header__actions .btn {
		padding-inline: var(--sp-4);
		font-size: var(--fs-small);
	}
}

/* ==========================================================================
   9. Hero
   ========================================================================== */

.hero {
	position: relative;
	padding-block: clamp(4rem, 1.5rem + 9vw, 7.5rem) clamp(5rem, 2rem + 9vw, 8.5rem);
	overflow: hidden;
}

/* Aurora rysowana w CSS, nie obrazkiem. Zero kosztu LCP i zero kolorow spoza palety.
   Klasa jest wspolna dla hero i sekcji CTA, zeby mgla powstawala w jednym miejscu.
   .hero__aurora zostaje jako alias, bo siedzi w kilku szablonach. */
.aurora,
.hero__aurora {
	position: absolute;
	inset: 0;
	z-index: -1;
	overflow: hidden;
	background:
		radial-gradient(80% 60% at 88% 4%, rgba(255, 217, 184, 0.85) 0%, rgba(255, 217, 184, 0) 68%),
		radial-gradient(70% 55% at 104% 46%, rgba(255, 188, 125, 0.68) 0%, rgba(255, 188, 125, 0) 66%),
		radial-gradient(64% 58% at 74% 104%, rgba(255, 143, 77, 0.4) 0%, rgba(255, 143, 77, 0) 64%),
		radial-gradient(90% 70% at 6% 88%, rgba(223, 227, 245, 0.75) 0%, rgba(223, 227, 245, 0) 66%),
		radial-gradient(70% 60% at 22% -8%, rgba(255, 217, 184, 0.45) 0%, rgba(255, 217, 184, 0) 62%);
	/* Rodzic ma overflow: hidden, wiec bez tego mgla urywa sie przy dolnej
	   krawedzi hero rowna pozioma kreska przez cala szerokosc ekranu. Maska
	   wygasza ja, zanim dojdzie do ciecia, i przejscie do nastepnej sekcji
	   przestaje byc widoczne. */
	mask-image: linear-gradient(to bottom, #000 58%, rgba(0, 0, 0, 0.35) 82%, transparent 100%);
}

/* Ziarno. Gradient rozciagniety na pol ekranu ma tylko 256 stopni na kanal,
   wiec bez tego widac na nim koncentryczne obreczy, zwlaszcza na tanszych
   matrycach. Szum je rozbija i to jest jedyny powod, dla ktorego mgla na starej
   stronie wyglada gladko. Obrazek jest w data:, wiec nie kosztuje zapytania. */
.aurora::after,
.hero__aurora::after {
	content: '';
	position: absolute;
	inset: -50%;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
	opacity: 0.035;
	mix-blend-mode: overlay;
	pointer-events: none;
}

/* Mgla oddycha. Cykl jest dlugi i ruch maly, wiec przy patrzeniu wprost nie
   widac animacji, tylko to, ze obrazek nie jest martwy. Skala 1,06 daje z kazdej
   strony wiecej zapasu, niz zabiera przesuniecie, wiec krawedz nigdy nie odslania
   tla. Tylko od 48rem: na telefonie plama zajmuje caly ekran, wiec kazdy jej ruch
   jest widoczny, a warstwa przez caly czas trzyma osobny bufor kompozytora. */
@media (min-width: 48rem) and (prefers-reduced-motion: no-preference) {
	.aurora,
	.hero__aurora {
		animation: aurora-drift 45s var(--ease) infinite alternate;
	}
}

@keyframes aurora-drift {
	from {
		transform: translate3d(0, 0, 0) scale(1);
	}

	to {
		transform: translate3d(-2%, 1.5%, 0) scale(1.06);
	}
}

/* Wariant pod sekcje CTA. Ta sama mgla, mocno sciszona, bo pod spodem stoi
   tekst na calej szerokosci, a nie kolumna obok zdjecia. */
.aurora--soft {
	opacity: 0.75;
}

/* Wariant na czarnym tle. Te same kolory, ale w ulamku nasycenia: na jasnym
   tle plama o kryciu 0,85 jest ledwie widoczna, na czarnym te same 0,85 daja
   pomaranczowy reflektor. Maska wylaczona, bo sekcja ma ostra krawedz z gory
   i z dolu, wiec nie ma czego wygaszac. */
.aurora--dark {
	z-index: 0;
	background:
		radial-gradient(64% 60% at 92% -8%, rgba(255, 143, 77, 0.2) 0%, rgba(255, 143, 77, 0) 66%),
		radial-gradient(58% 52% at 4% 6%, rgba(223, 227, 245, 0.1) 0%, rgba(223, 227, 245, 0) 62%),
		radial-gradient(76% 56% at 46% 118%, rgba(244, 96, 60, 0.16) 0%, rgba(244, 96, 60, 0) 62%);
	mask-image: none;
}

/* Overlay na prawie czarnym tle nie robi nic, bo mnozy przez zero. Screen
   rozjasnia, wiec ziarno w ogole widac. */
.aurora--dark::after {
	opacity: 0.05;
	mix-blend-mode: screen;
}

/* Kotwice sa ustawione pod szeroki ekran: cieplo siedzi po prawej, obok kolumny
   z trescia, ktora konczy sie w polowie. Na telefonie kolumna
   i zajmuje cala szerokosc, wiec ta sama mgla wychodzi poza ekran i zostaje
   prawie biale tlo. Tutaj plamy wracaja do srodka i schodza nizej. */
@media (max-width: 47.99rem) {
	.aurora:not(.aurora--dark),
	.hero__aurora {
		background:
			radial-gradient(90% 40% at 78% 2%, rgba(255, 217, 184, 0.9) 0%, rgba(255, 217, 184, 0) 70%),
			radial-gradient(80% 34% at 96% 24%, rgba(255, 188, 125, 0.6) 0%, rgba(255, 188, 125, 0) 68%),
			radial-gradient(76% 32% at 62% 62%, rgba(255, 143, 77, 0.3) 0%, rgba(255, 143, 77, 0) 66%),
			radial-gradient(100% 40% at 4% 46%, rgba(223, 227, 245, 0.7) 0%, rgba(223, 227, 245, 0) 68%);
	}

	/* Kroki stoja tu jeden pod drugim, wiec cieplo wraca do gory sekcji. */
	.aurora--dark {
		background:
			radial-gradient(80% 26% at 84% -2%, rgba(255, 143, 77, 0.22) 0%, rgba(255, 143, 77, 0) 68%),
			radial-gradient(90% 30% at 10% 104%, rgba(244, 96, 60, 0.14) 0%, rgba(244, 96, 60, 0) 64%);
	}
}

/* Kolumna jest jedna, bez zdjecia obok. Naglowek dostaje wiecej niz akapit,
   bo ma sie lamac na dwa wiersze, a nie na cztery. Prawa strona zostaje pusta
   i to jest jej rola: tam siedzi najcieplejsza czesc aurory. */
.hero__inner {
	max-width: 52rem;
}

/* Jedyny naglowek, ktory wolno postawic wyzej niz --fs-h1, bo nie ma nad soba
   nic innego. Bez zdjecia obok jest na to miejsce: pierwszy ekran ma teraz
   jeden punkt ciezkosci zamiast dwoch, wiec naglowek moze go udzwignac. */
.hero__title {
	font-size: clamp(2.125rem, 1.55rem + 2.4vw, 3.75rem);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
}

/* Wezszy niz naglowek. Wiersz dluzszy niz okolo 75 znakow czyta sie gorzej,
   a przy 52rem akapit doszedlby do dziewiecdziesieciu. */
.hero__lead {
	max-width: 38rem;
	margin-top: var(--sp-5);
	font-size: var(--fs-lead);
	line-height: 1.5;
}

.hero__actions {
	margin-top: var(--sp-7);
}

.hero__proof {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-2);
	margin-top: var(--sp-6);
}

/* Trzy dowody musza zmiescic sie w jednym rzedzie. Przy szerszych odstepach
   ostatni spadal do drugiego wiersza i wisial sam pod reszta. */
.hero__proof .badge {
	padding: 0.35rem 0.7rem;
	font-size: var(--fs-kicker);
}

/* Pierwszy dowod jest linkiem do profilu w Google, dwa pozostale to sam tekst.
   Na dotyku podnosimy wszystkie trzy, zeby link dal sie wygodnie trafic,
   a rzad nadal czytal sie jako jeden rzad, a nie jeden wyzszy kafelek. */
@media (pointer: coarse) {
	.hero__proof .badge {
		padding-block: 0.7rem;
	}
}

/* ==========================================================================
   9b. Naglowek podstrony, okruszki, pasek zaufania
   ========================================================================== */

.breadcrumbs {
	padding-block: var(--sp-5) 0;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

.breadcrumbs__list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
	list-style: none;
}

.breadcrumbs__item + .breadcrumbs__item::before {
	content: '/';
	margin-right: var(--sp-2);
	color: var(--c-border);
}

.breadcrumbs a {
	display: inline-block;
	padding-block: 4px;
	color: inherit;
	text-decoration: none;
}

.breadcrumbs a:hover {
	color: var(--c-ink);
	text-decoration: underline;
}

/* Naglowek podstrony siedzi tuz pod okruszkami, a nastepna sekcja wnosi
   wlasny odstep, wiec u dolu wystarcza polowa. */
.page-hero {
	padding-block: var(--sp-7) 0;
}

/* Naglowek podstrony nie ma juz wlasnego rozmiaru. Siedzial tu osobny clamp
   i przez to zmiana skali w tokenach omijala dwanascie podstron uslugowych. */
.page-hero h1 {
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-display);
}

/* Bez zdjecia naglowek rozjechalby sie na cala szerokosc kontenera. */
.page-hero .stack {
	max-width: 46rem;
}

/* Zdjecia uslug maja rozne proporcje, od pionu po poziom. Staly kadr trzyma
   naglowek podstrony w jednej wysokosci niezaleznie od zrodla. */
.page-hero .figure-panel img {
	width: 100%;
	height: clamp(20rem, 30vw, 28rem);
	object-fit: cover;
}

.trust-bar {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3) var(--sp-5);
	margin-top: var(--sp-6);
	list-style: none;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* Pieć pozycji o roznej dlugosci lamalo sie na telefonie na cztery wiersze
   w ukladzie jeden, dwa, jeden, jeden. Czytalo sie to jak usterka, a nie jak
   lista. Ponizej 48rem kazdy fakt dostaje wlasny wiersz. Panel jest juz
   siatka jednokolumnowa, wiec ta regula go nie rusza. */
@media (max-width: 47.99rem) {
	.trust-bar {
		display: grid;
		gap: var(--sp-3);
	}
}

.trust-bar__item {
	position: relative;
	padding-left: var(--sp-4);
}

.trust-bar__item::before {
	content: '';
	position: absolute;
	top: 0.55em;
	left: 0;
	width: 0.4rem;
	height: 0.4rem;
	background: var(--c-orange);
	border-radius: var(--radius-pill);
}

/* Ten sam zestaw faktow, ale jako panel obok naglowka tam, gdzie nie ma
   zdjecia z warsztatu. Kolumna zamiast paska, bo w polowie szerokosci
   pieć pozycji obok siebie lamalo sie na trzy nierowne wiersze. */
.trust-bar.trust-bar--panel {
	display: grid;
	gap: var(--sp-4);
	align-content: start;
	margin-top: 0;
	padding: var(--sp-7);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	background-color: var(--c-surface);
	box-shadow: var(--shadow-sm);
	font-size: var(--fs-body);
	color: var(--c-body);
}

@media (min-width: 64rem) {
	.trust-bar.trust-bar--panel {
		margin-top: var(--sp-8);
	}
}

/* Objawy, ktore klient rozpoznaje u siebie. Wyliczanka, wiec bez ptaszkow. */
.list-symptoms {
	display: grid;
	gap: var(--sp-3);
	list-style: none;
}

/* Objaw jest przyciskiem, nie zdaniem do przeczytania. Strzalka po prawej
   mowi to bez dopisku "kliknij", a caly kafelek jest celem, wiec na telefonie
   nie trzeba trafiac w tekst. */
.symptom {
	display: flex;
	align-items: center;
	gap: var(--sp-4);
	padding: var(--sp-4) var(--sp-5);
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	border-radius: var(--radius);
	box-shadow: var(--shadow-sm);
	color: inherit;
	text-decoration: none;
	transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
		transform var(--dur) var(--ease);
}

.symptom:hover {
	border-color: var(--c-border-strong);
	box-shadow: var(--shadow-md);
	text-decoration: none;
	transform: translateY(-2px);
}

.symptom:active {
	transform: translateY(0);
}

.symptom__text {
	flex: 1;
}

.symptom__go {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--radius-pill);
	background-color: var(--c-bg);
	color: var(--c-muted);
	transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.symptom__go svg {
	width: 18px;
	height: 18px;
}

.symptom:hover .symptom__go {
	background-color: var(--c-ink);
	color: var(--c-inverse);
}

@media (prefers-reduced-motion: reduce) {
	.symptom:hover {
		transform: none;
	}
}

@media (min-width: 48rem) {
	.list-check--cols {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: var(--sp-7);
		max-width: none;
	}
}

/* ==========================================================================
   10. Pasek partnerów i liczb
   ========================================================================== */

.partners {
	padding-block: var(--sp-7);
	border-block: 1px solid var(--c-border);
}

/* Podpis nad logotypami. Bez niego widac siedem znaczkow bez wyjasnienia,
   czym sa: klientem, certyfikatem czy odznaka platnosci. Sam pasek nie mowi
   nic, dopiero to jedno slowo robi z niego dowod. */
.partners__label {
	display: block;
	margin-bottom: var(--sp-6);
	text-align: center;
}

.partners__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: clamp(1.5rem, 4vw, 3.5rem);
}

/* Logotypy partnerow to biala grafika na przezroczystosci, na bieli sa niewidoczne.
   brightness(0) sprowadza je do jednolitej czerni, czyli czytelnego znaku monochromatycznego. */
.partners__list img {
	width: auto;
	height: clamp(30px, 4vw, 42px);
	object-fit: contain;
	filter: brightness(0);
	opacity: 0.8;
}

/* Liczby siedza w jednym wyniesionym panelu, a nie luzem na tle sekcji.
   Cztery osobne slupki tekstu zajmowaly caly ekran wysokosci i mimo to nie
   wygladaly na nic wiecej niz akapit z duza czcionka. */
.stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
	gap: var(--sp-5);
	padding: var(--sp-7) var(--sp-6);
	border: 1px solid transparent;
	border-radius: var(--radius-lg);
	background-color: var(--c-surface);
	box-shadow: var(--shadow-md);
}

.stat {
	text-align: center;
}

/* Kreski tylko miedzy kolumnami i tylko wtedy, gdy kolumny naprawde stoja obok
   siebie. Po zwinieciu do jednej kolumny ta sama kreska wisialaby w powietrzu. */
@media (min-width: 48rem) {
	.stat + .stat {
		border-left: 1px solid var(--c-border);
	}
}

/* Liczby na pasku nie sa naglowkiem, wiec wage dziedziczyly po tresci i po
   pogrubieniu naglowkow zostalyby jedynym cienkim wielkim napisem na stronie.
   Sufit schodzi ponizej H1: pasek ma wspierac naglowek sekcji, a nie go przekrzykiwac. */
.stat__value {
	display: block;
	font-size: clamp(1.875rem, 1.55rem + 1.33vw, 2.75rem);
	font-weight: var(--fw-bold);
	font-variant-numeric: tabular-nums;
	line-height: 1.1;
	letter-spacing: var(--ls-heading);
	color: var(--c-ink);
}

.stat__label {
	display: block;
	margin-top: var(--sp-2);
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* ==========================================================================
   11. Proces, 3 kroki
   ========================================================================== */

.steps {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
	gap: var(--sp-5);
}

/* Krok nie jest kaflem. Na czarnym pasie trzy jasne prostokaty z obwodka
   czytaly sie jak wycinanka, wiec zostaje sam rytm: kreska, numer, tytul,
   zdanie. */
.step {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	padding-top: var(--sp-6);
}

.step__title {
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	letter-spacing: 0;
}

/* Kreska nad kazdym krokiem. Trzy odcinki przedzielone przerwami siatki czytaja
   sie jak podzialka postepu, a nie jak ramka. Gasnie w prawo, wiec oko idzie
   od numeru dalej, w strone nastepnego kroku. */
.step::before {
	content: '';
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	height: 1px;
	background-image: linear-gradient(to right, rgba(255, 188, 125, 0.55), rgba(255, 255, 255, 0.08));
	transform-origin: left center;
	transition: transform 700ms var(--ease);
	transition-delay: var(--reveal-delay, 0ms);
}

/* Dociagana dopiero przy wejsciu w ekran, ale tylko wtedy, gdy reveal w ogole
   dziala. Bez JavaScriptu kreska ma byc od razu, a nie nigdy. */
body.has-reveal .step::before {
	transform: scaleX(0);
}

body.has-reveal .step.is-in::before {
	transform: scaleX(1);
}

.step__num {
	color: var(--c-accent);
	font-size: var(--fs-h3);
	font-weight: var(--fw-semibold);
	font-variant-numeric: tabular-nums;
	letter-spacing: var(--ls-heading);
	line-height: 1;
}

.step__text {
	color: inherit;
}

/* ==========================================================================
   11b. Zasieg dojazdu
   ========================================================================== */

.zasieg-layout__map {
	display: flex;
	justify-content: center;
}

.zasieg {
	width: 100%;
	max-width: 23rem;
	height: auto;
}

/* Pierscien to obszar, nie obwodka: wypelnienie mowi "tu przyjezdzamy",
   przerywana kreska mowi, ze granica jest umowna, bo dalej tez jezdzimy,
   tylko z ustalonym kosztem dojazdu. */
.zasieg__ring {
	fill: rgba(255, 188, 125, 0.13);
	stroke: var(--c-orange);
	stroke-width: 1.5;
	stroke-dasharray: 5 7;
}

/* Druga tarcza lezy na pierwszej, wiec srodek jest ciemniejszy i oko samo
   znajduje punkt, wokol ktorego to wszystko sie krec. */
.zasieg__ring--inner {
	fill: rgba(255, 188, 125, 0.16);
	stroke: none;
}

.zasieg text {
	font-size: 11px;
	font-weight: var(--fw-medium);
	fill: var(--c-body);
}

.zasieg__place circle {
	fill: var(--c-orange);
}

.zasieg__home circle {
	fill: var(--c-ink);
}

.zasieg__home text {
	font-weight: var(--fw-semibold);
	fill: var(--c-ink);
}

.zasieg__label {
	font-size: 10px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	fill: var(--c-muted);
}

/* ==========================================================================
   12. FAQ
   ========================================================================== */

.faq-layout {
	display: grid;
	gap: var(--sp-7);
}

.faq-layout__aside h2 {
	margin-top: var(--sp-3);
}

.faq-layout__note {
	margin: var(--sp-5) 0;
	max-width: 28ch;
}

.faq-layout__hours {
	margin-top: var(--sp-4);
	font-size: var(--fs-small);
	color: var(--c-muted);
}

@media (min-width: 62rem) {
	.faq-layout {
		grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
		gap: var(--sp-9);
	}

	/* Naglowek jedzie z lista pytan, zeby przy dlugim FAQ nie zostawal sam
	   w gorze ekranu, a numer telefonu byl w zasiegu przez cala sekcje. */
	.faq-layout__aside {
		position: sticky;
		top: calc(var(--sp-9) + var(--sp-4));
		align-self: start;
	}
}

/* Zamowienie odbioru. Formularz jest tresc glowna, wiec dostaje szeroka kolumne
   i idzie pierwszy takze w kodzie. Telefon obok, dla tych, ktorzy wola powiedziec. */
/* Kolumna musi miec jawne minimum zero. Domyslna kolumna siatki nie schodzi
   ponizej najwezszej mozliwej szerokosci swojej tresci, wiec na ekranie 320 px
   bez JavaScriptu, gdzie widac wszystkie trzy kroki formularza naraz, rozpychala
   sie do 320 px w kontenerze majacym 280 px i cala strona jechala 20 px w bok. */
.order-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sp-7);
}

/* Ten sam promien i cien co panel szybkiej wyceny, zeby zgloszenie odbioru
   czytalo sie jako dalszy ciag tego samego okna, a nie osobny formularz. */
.order-layout__form {
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-md);
}

/* Kolumna obok ma 20 rem, wiec naglowek w rozmiarze h2 rozbijalby sie na cztery
   linie i przykrywal formularz. */
.order-layout__title {
	margin-top: var(--sp-3);
	font-size: var(--fs-h3);
}

.order-layout__note {
	margin: var(--sp-5) 0;
}

.order-layout__hours {
	margin-top: var(--sp-4);
	font-size: var(--fs-kicker);
	color: var(--c-muted);
}

@media (min-width: 62rem) {
	.order-layout {
		grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
		gap: var(--sp-9);
		align-items: start;
	}

	/* Numer telefonu jedzie z formularzem, bo zgloszenie ma trzy ekrany
	   i inaczej znikalby po pierwszym kroku. */
	.order-layout__aside {
		position: sticky;
		top: calc(var(--sp-9) + var(--sp-4));
	}
}

.faq {
	border-top: 1px solid var(--c-border);
}

.faq__item {
	border-bottom: 1px solid var(--c-border);
}

.faq__q {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-4);
	padding-block: var(--sp-5);
	color: var(--c-ink);
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	line-height: 1.35;
	cursor: pointer;
	list-style: none;
}

.faq__q::-webkit-details-marker {
	display: none;
}

.faq__q::after {
	content: '+';
	flex-shrink: 0;
	font-size: 1.5rem;
	font-weight: var(--fw-regular);
	line-height: 1;
	transition: transform var(--dur) var(--ease);
}

.faq__item[open] .faq__q::after {
	transform: rotate(45deg);
}

.faq__a {
	max-width: 62ch;
	padding-bottom: var(--sp-5);
}

.faq__a > * + * {
	margin-top: var(--sp-3);
}

/* ==========================================================================
   13. Opinie
   ========================================================================== */

.review {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	padding: var(--sp-6);
	border: 1px solid var(--c-border);
	border-radius: var(--radius);
	background-color: var(--c-surface);
}

.review__text {
	font-size: var(--fs-small);
	line-height: 1.65;
}

/* Stopke dosuwa auto-margines, a nie flex-grow na akapicie. Przy opinii
   wieloakapitowej rosly odstepy miedzy akapitami zamiast pustki pod cytatem. */
.review > footer {
	margin-top: auto;
}

/* Do sekcji idzie sam pierwszy akapit opinii, wiec karty roznia sie najwyzej
   o linijke albo dwie. Przy takiej roznicy rowna gora i poszarpany dol czytaja
   sie jak niedorobka, a nie jak decyzja. Pelne opinie stoja na /opinie/,
   w ukladzie kolumnowym, i tam nic sie nie rozciaga. */
.reviews-grid > .review {
	height: 100%;
}

/* Lista wszystkich opinii. Kolumny CSS zamiast siatki, bo dlugosci roznia sie
   od jednego zdania do pieciu akapitow i w siatce zostawaly pustki na cala karte. */
.reviews-list {
	column-gap: var(--sp-6);
}

.reviews-list > .review {
	margin-bottom: var(--sp-6);
	break-inside: avoid;
}

@media (min-width: 48rem) {
	.reviews-list {
		column-count: 2;
	}
}

@media (min-width: 64rem) {
	.reviews-list {
		column-count: 3;
	}
}

/* Czego dotyczyla naprawa. Stoi nad cytatem, bo to po niej klient poznaje,
   czy opinia jest o jego sprawie, i dopiero wtedy czyta caly akapit. */
/* Chip jest linkiem do uslugi, a mial 31 px wysokosci. Do 44 px nie idziemy,
   bo przy tym stopniu pisma zrobilby sie z tego przycisk i przykryl cytat,
   ktory jest tu trescia. Osiem pikseli wystarczy, zeby przestal chybiac. */
.review__topic {
	align-self: flex-start;
	padding: 8px 12px;
	border: 1px solid var(--c-border);
	border-radius: 999px;
	font-size: var(--fs-kicker);
	font-weight: var(--fw-medium);
	color: var(--c-muted);
	text-decoration: none;
	transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.review__topic:hover,
.review__topic:focus-visible {
	border-color: var(--c-border-strong);
	color: var(--c-ink);
}

.review__author {
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	color: var(--c-ink);
}

.review__meta {
	font-size: var(--fs-kicker);
	color: var(--c-muted);
}

/* ==========================================================================
   14. Formularze
   ========================================================================== */

.form > * + * {
	margin-top: var(--sp-5);
}

/* Pola ukryte, czyli nonce i pulapka na boty, nie odmierzaja odstepu. Pulapka
   jest w ukladzie, ma jeden piksel wysokosci i stoi poza ekranem, ale dla
   selektora sasiada liczy sie tak samo jak zwykle pole. Rytm formularza liczy
   sie od pierwszej rzeczy, ktora widac.
   Bez tego pasek postepu dostawal po nich 24 px marginesu z gory. Pasek nie
   domyka wlasnego kontekstu formatowania, wiec margines wychodzil poza
   formularz i spychal go w dol. Dopoki pasek czekal schowany, marginesu nie
   bylo. Skrypt odslanial pasek jakies 270 ms po pierwszym malowaniu i cala
   ramka formularza skakala wtedy o 24 px. Jedyne przesuniecie, jakie zostalo
   na stronie: CLS 0,0071 na /zamow-odbior/ przy 390 px, lapane mniej wiecej
   co trzecie wejscie. */
.form > input[type='hidden'] + *,
.form > .hp-field + * {
	margin-top: 0;
}

/* Formularz w ramce, zeby na tle sekcji alt czytal sie jako osobny blok. */
.panel {
	padding: var(--sp-6);
	border: 1px solid var(--c-border);
	border-radius: var(--radius);
	background-color: var(--c-surface);
}

@media (min-width: 48rem) {
	.panel {
		padding: var(--sp-8);
	}
}

.field {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

.field__label {
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	color: var(--c-ink);
}

.field__hint {
	font-size: var(--fs-kicker);
	color: var(--c-muted);
}

/* Komunikat bledu czyta sie w momencie, gdy formularz i tak juz irytuje,
   wiec stoi o stopien wyzej od podpowiedzi: 15 px zamiast 13 px. */
.field__error {
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	color: var(--c-danger);
}

.input,
.textarea,
/* Prawy margines wewnetrzny robi miejsce pod strzalke listy. Bez niego
   dluzszy temat wchodzil pod nia i tracil ostatnia litere. */
.select {
	width: 100%;
	min-height: 48px;
	padding: 0.7rem 2.2rem 0.7rem 0.9rem;
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius);
	background-color: var(--c-surface);
	font-size: 1rem;
	transition: border-color var(--dur) var(--ease);
}

.input:hover,
.textarea:hover,
.select:hover {
	border-color: var(--c-muted);
}

.input:focus,
.textarea:focus,
.select:focus {
	border-color: var(--c-ink);
}

.textarea {
	min-height: 8rem;
	resize: vertical;
}

/* Stan bledu wisi na samym polu, nie na opakowaniu, bo aria-invalid ustawiaja
   tak samo szablon po powrocie z serwera i skrypt przed wyslaniem. Wczesniej
   czerwona krawedz pokazywala sie tylko wtedy, gdy zrobil to skrypt. */
:where(.input, .textarea, .select)[aria-invalid='true'] {
	border-color: var(--c-danger);
}

/* Skrypt sam ustawia kursor na pierwszym blednym polu, wiec ramka fokusu
   i czerwona krawedz pojawiaja sie razem. Czarny pierscien obok czerwonej
   ramki wyglada jak dwa rozne stany naraz, wiec tutaj tez jest czerwony. */
:where(.input, .textarea, .select)[aria-invalid='true']:focus-visible {
	outline-color: var(--c-danger);
}

.choice {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--sp-3);
	font-size: var(--fs-small);
	line-height: 1.5;
}

/* Bez tego komunikat wchodzi jako trzeci element rzedu i staje obok tresci
   zgody, w waskiej kolumnie po prawej. */
.choice .field__error {
	flex-basis: 100%;
}

/* Zawijanie rzedu odsuwa element, ktory sie nie miesci, do nastepnej linii,
   zamiast go sciesnic. Tresc zgody spadala wiec pod kratke. Ma sie zwezac
   i lamac w sobie, tak jak przed dolozeniem komunikatu bledu. */
.choice label {
	flex: 1;
	min-width: 0;
}

.choice input[aria-invalid='true'] {
	outline: 2px solid var(--c-danger);
	outline-offset: 2px;
}

/* 1.5rem, nie 1.25rem: to ostatni obowiazkowy klik przed wyslaniem zgloszenia,
   a WCAG 2.2 chce co najmniej 24 px. Trafia w niego starsza osoba z telefonem
   w reku, wiec liczy sie kazdy piksel. */
.choice input {
	flex-shrink: 0;
	width: 1.5rem;
	height: 1.5rem;
	margin-top: 0.05rem;
	accent-color: var(--c-ink);
}

.form__notice {
	padding: var(--sp-4);
	border-left: 3px solid var(--c-danger);
	background-color: var(--c-bg-alt);
	font-size: var(--fs-small);
}

/* Pole pliku bez skryptu zostaje natywne, tylko wyrownane do reszty pol.
   Ze skryptem schodzi z oczu, a jego prace przejmuje blok .uploader ponizej:
   pliki caly czas siedza w tym samym polu, wiec wysylka i sprawdzenie po
   stronie serwera nie zmieniaja sie ani o linijke. */
.input--file {
	padding: 0.6rem 0.9rem;
	font-size: var(--fs-small);
}

.uploader.is-enhanced .input--file {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.uploader__drop {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-4);
	border: 1px dashed var(--c-border-strong);
	border-radius: var(--radius);
	background-color: var(--c-bg-alt);
	transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.uploader__drop[data-over='true'] {
	border-color: var(--c-ink);
	border-style: solid;
	background-color: var(--c-surface);
}

.uploader__add {
	gap: var(--sp-2);
}

/* Obietnica przeciagania tylko tam, gdzie jest czym przeciagac. Na telefonie
   zdanie o upuszczaniu pliku nie znaczy nic. */
.uploader__drag {
	display: none;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

@media (min-width: 48rem) and (pointer: fine) {
	.uploader__drag {
		display: inline;
	}
}

.uploader__count {
	margin-inline-start: auto;
	font-size: var(--fs-small);
	font-variant-numeric: tabular-nums;
	color: var(--c-muted);
}

.uploader__list {
	display: grid;
	gap: var(--sp-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.uploader__list:not(:empty) {
	margin-top: var(--sp-3);
}

.uploader__item {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-2);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-sm);
	background-color: var(--c-surface);
}

.uploader__thumb {
	flex-shrink: 0;
	width: 48px;
	height: 48px;
	border-radius: var(--radius-sm);
	object-fit: cover;
	background-color: var(--c-bg-alt);
}

/* Nazwa pliku ze zdjecia z telefonu bywa dluzsza niz cale pole, wiec urywa sie
   wielokropkiem zamiast rozpychac wiersz. */
.uploader__name {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	font-size: var(--fs-small);
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--c-ink);
}

.uploader__size {
	flex-shrink: 0;
	font-size: var(--fs-small);
	font-variant-numeric: tabular-nums;
	color: var(--c-muted);
}

.uploader__kill {
	display: grid;
	flex-shrink: 0;
	place-items: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	border-radius: var(--radius-sm);
	background-color: transparent;
	color: var(--c-muted);
	cursor: pointer;
	transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.uploader__kill:hover {
	background-color: var(--c-bg-alt);
	color: var(--c-ink);
}

.uploader__say:empty {
	display: none;
}

.uploader__say {
	margin: var(--sp-3) 0 0;
	font-size: var(--fs-small);
	color: var(--c-danger);
}

/* Objawy do klikniecia. Kafle sa mniejsze od tych z pierwszego kroku, bo tam
   wybiera sie jedna rzecz z trzech, a tu zaznacza dowolnie wiele z siedmiu.
   Ten sam rozmiar zrobilby z drugiego kroku sciane. */
.chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
}

.chip {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: var(--sp-2) var(--sp-4);
	border: 1px solid var(--c-border-strong);
	border-radius: 999px;
	background-color: var(--c-surface);
	cursor: pointer;
	transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* Sam kwadracik znika, bo zaznaczenie widac po calym kaflu. Pole zostaje
   w drzewie dostepnosci, wiec czytnik ekranu nadal mowi "pole wyboru,
   zaznaczone", a klawiatura obsluguje je spacja jak zawsze. */
.chip input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.chip:hover {
	border-color: var(--c-muted);
}

.chip__label {
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	color: var(--c-ink);
}

.chip:has(input:checked) {
	border-color: var(--c-ink);
	background-color: var(--c-ink);
}

.chip:has(input:checked) .chip__label {
	color: var(--c-surface);
}

.chip:has(input:focus-visible) {
	outline: 2px solid var(--c-ink);
	outline-offset: 3px;
}

/* Potwierdzenie na ekranie po wyslaniu. Znak rysuje sie sam, bo strona
   ma powiedziec "przyjelismy" w pierwszej sekundzie, zanim ktokolwiek
   zacznie czytac. Kolo i ptaszek to jedna sciezka rysowana dasharrayem,
   zero JS i zero obrazka do pobrania. */
.receipt-mark {
	display: block;
	width: 56px;
	height: 56px;
}

.receipt-mark svg {
	display: block;
	width: 100%;
	height: 100%;
	overflow: visible;
	fill: none;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.receipt-mark__ring {
	stroke: var(--c-accent);
	stroke-width: 3;
	stroke-dasharray: 133;
	stroke-dashoffset: 133;
	animation: receipt-draw 0.5s var(--ease) forwards;
}

.receipt-mark__tick {
	stroke: var(--c-ink);
	stroke-width: 3.5;
	stroke-dasharray: 28;
	stroke-dashoffset: 28;
	animation: receipt-draw 0.35s var(--ease) 0.4s forwards;
}

@keyframes receipt-draw {
	to {
		stroke-dashoffset: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.receipt-mark__ring,
	.receipt-mark__tick {
		animation: none;
		stroke-dashoffset: 0;
	}
}

/* Formularz w krokach. Fieldset ma wlasne domyslne obramowanie i marginesy,
   ktore trzeba zdjac, zanim zacznie wygladac jak reszta strony. */
.form__step {
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
}

.form__step > * + * {
	margin-top: var(--sp-5);
}

.form__legend {
	padding: 0;
	font-size: var(--fs-h4);
	font-weight: var(--fw-medium);
	color: var(--c-ink);
}

/* Bez JS wszystkie kroki sa widoczne naraz i formularz dziala jak jeden dlugi,
   wiec musza sie od siebie odkleic. Klase chowajaca dokłada skrypt,
   wiec nikt nie zostaje z ukrytymi polami. */
.form__step + .form__step {
	margin-top: var(--sp-8);
}

/* Przyciski "Dalej" i "Wstecz" bez skryptu nie maja co przelaczac.
   Zostawione na widoku wygladalyby jak zepsuty formularz. */
.form--steps:not(.is-enhanced) [data-step-next],
.form--steps:not(.is-enhanced) [data-step-prev] {
	display: none;
}

/* Bez skryptu w dwoch pierwszych krokach zostalby pusty pasek akcji,
   a po nim odstep bez powodu. */
.form--steps:not(.is-enhanced) .form__step:not(:last-of-type) .form__actions {
	display: none;
}

.form--steps.is-enhanced .form__step[hidden] {
	display: none;
}

.form--steps.is-enhanced .form__step + .form__step {
	margin-top: 0;
}

/* Pasek postepu, ta sama forma co w szybkiej wycenie, zeby oba flow wygladaly
   jak jedna aplikacja. Ma sens dopiero wtedy, gdy kroki faktycznie sie przelaczaja,
   wiec bez JS zostaje schowany, a licznik "1 z 3" nie klamie. */
.form__progress {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

/* Wlasny display przykrywa atrybut hidden. */
.form__progress[hidden] {
	display: none;
}

/* O tym, czy pasek postepu stoi w ukladzie, decyduje arkusz stylow, a nie
   skrypt. Skrypt zdejmowal atrybut hidden dopiero jakies 270 ms po pierwszym
   malowaniu i pasek wchodzil w gotowa strone, spychajac pierwszy krok o wlasna
   wysokosc. Przegladarka wie o wlaczonym JavaScripcie juz przy liczeniu stylow,
   wiec pasek jest na swoim miejscu od pierwszej klatki. Skrypt nadal zdejmuje
   hidden, ale tylko po to, zeby czytnik ekranu tez go zobaczyl. */
@media (scripting: enabled) {
	.form--steps .form__progress[hidden] {
		display: flex;
	}
}

.form__bars {
	display: flex;
	gap: 6px;
}

.form__bar {
	flex: 1;
	height: 3px;
	border-radius: var(--radius-pill);
	background-color: var(--c-border);
	transition: background-color var(--dur) var(--ease);
}

.form__bar[data-done='true'] {
	background-color: var(--c-ink);
}

.form__count {
	font-size: var(--fs-kicker);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-kicker);
	text-transform: uppercase;
	color: var(--c-muted);
}

.choice-cards {
	display: grid;
	gap: var(--sp-3);
}

.choice-card {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	min-height: 56px;
	padding: var(--sp-4);
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius);
	background-color: var(--c-surface);
	cursor: pointer;
	transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.choice-card:hover {
	border-color: var(--c-muted);
}

.choice-card input {
	flex-shrink: 0;
	width: 1.25rem;
	height: 1.25rem;
	accent-color: var(--c-ink);
}

.choice-card:has(input:checked) {
	border-color: var(--c-ink);
	background-color: var(--c-bg);
}

.choice-card:has(input:focus-visible) {
	outline: 2px solid var(--c-ink);
	outline-offset: 3px;
}

.choice-card__label {
	font-weight: var(--fw-medium);
	color: var(--c-ink);
}

/* Na telefonie akcja glowna idzie na cala szerokosc i stoi wyzej niz "Wstecz",
   bo w tym flow prawie zawsze klika sie dalej. Dlatego "Dalej" jest pierwsze
   takze w HTML: wczesniej uklad odwracal kolejnosc przez column-reverse,
   wiec tabulator wchodzil najpierw na przycisk cofajacy, stojacy nizej.
   Na szerokim ekranie powrot wraca na lewa strone przez row-reverse, ktory
   przestawia sam obraz, nie kolejnosc czytania. */
.form__actions {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

.form__actions > .btn {
	width: 100%;
}

@media (min-width: 34rem) {
	.form__actions {
		flex-direction: row-reverse;
		justify-content: flex-start;
		gap: var(--sp-3);
	}

	.form__actions > .btn {
		width: auto;
	}

	.form__actions > [data-step-prev] {
		margin-left: auto;
	}
}

/* Zdanie o koszcie diagnozy stoi pod przyciskiem wysylki, czyli w miejscu
   decyzji, a nie w zwinietym FAQ ponizej. */
.form__reassurance {
	margin-top: var(--sp-3);
	font-size: var(--fs-small);
	color: var(--c-muted);
	text-align: center;
}

@media (min-width: 34rem) {
	.form__reassurance {
		text-align: right;
	}
}

/* Mapa dojazdu. Stala proporcja rezerwuje miejsce zanim iframe sie zaladuje,
   inaczej leniwa ramka Google przesuwa cala sekcje i psuje CLS. */
.map-embed {
	overflow: hidden;
	aspect-ratio: 16 / 10;
	border: 1px solid var(--c-border);
	border-radius: var(--radius);
	background-color: var(--c-bg-alt);
}

@media (min-width: 48rem) {
	.map-embed {
		aspect-ratio: 21 / 8;
	}
}

.map-embed iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* Zasłona przed wczytaniem mapy. Ta sama proporcja co ramka, więc podmiana
   nie przesuwa strony. */
.map-embed__facade {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--sp-4);
	width: 100%;
	height: 100%;
	padding: var(--sp-5);
	text-align: center;
}

.map-embed__facade p {
	max-width: 34em;
}

/* Honeypot, ukryty przed człowiekiem, widoczny dla bota */
.hp-field {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ==========================================================================
   15. Wpis bloga
   ========================================================================== */

.entry__header {
	margin-bottom: var(--sp-7);
}

.entry__title {
	margin-top: var(--sp-3);
}

.entry__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3);
	margin-top: var(--sp-4);
	font-size: var(--fs-small);
	color: var(--c-muted);
}

/* Na karcie listy kategoria i data siedza w jednym wierszu, rozdzielone kropka.
   Dwa osobne wiersze szarego tekstu nad tytulem wygladaly jak blad skladu. */
.entry__meta--card {
	margin-top: 0;
	margin-bottom: var(--sp-3);
	gap: var(--sp-2);
	/* Strzalka kafla lezy w prawym gornym rogu, dokladnie nad koncem daty. */
	padding-right: var(--sp-7);
	font-size: var(--fs-kicker);
}

/* Kropka konczy nazwe kategorii, a nie zaczyna date. Gdy wiersz sie lamie,
   zostaje na koncu pierwszej linii zamiast wyjsc na poczatek drugiej. */
.entry__meta--card span:not(:last-child)::after {
	content: " ·";
}

/* Pierwszy akapit wpisu to odpowiedz na pytanie z tytulu, wiec ma wygladac
   jak lead, a nie jak zwykly akapit. Klasa idzie z edytora bloków.
   Na telefonie sam --fs-lead tego nie zalatwial: 18,04 px przy 17,07 px
   zwyklego akapitu to roznica na oko niewidoczna, a do tego .lead ma sztywne
   line-height 1.5, wiec lead mial ciasniejsza interlinie (27,05 px) niz tekst
   pod nim (28,16 px). Wygladal jak akapit, ktoremu cos sie stalo. W hero
   i na stronach uslug problemu nie ma, bo tam lead nie stoi obok zwyklego
   tekstu, dlatego zmiana siedzi tylko tutaj. */
.prose > .lead:first-child {
	margin-bottom: var(--sp-7);
	font-size: clamp(1.1875rem, 1.05rem + 0.55vw, 1.3125rem);
	line-height: 1.55;
}

.page-links {
	margin-top: var(--sp-7);
	font-size: var(--fs-small);
}

/* Blok "Szczegoly" z edytora. Wyglada jak FAQ z szablonow, zeby wpis
   i strona uslugowa nie rozjezdzaly sie stylistycznie. */
.wp-block-details {
	padding-block: var(--sp-4);
	border-bottom: 1px solid var(--c-border);
}

.wp-block-details:first-of-type {
	border-top: 1px solid var(--c-border);
}

.wp-block-details summary {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-4);
	cursor: pointer;
	font-size: var(--fs-h4);
	font-weight: var(--fw-medium);
	color: var(--c-ink);
	list-style: none;
}

/* Ten sam plus co w sekcjach FAQ. Natywny trojkat przegladarki wygladal
   w tekscie wpisu jak element z innej strony. */
.wp-block-details summary::-webkit-details-marker {
	display: none;
}

.wp-block-details summary::after {
	content: '+';
	flex-shrink: 0;
	font-size: 1.5rem;
	font-weight: var(--fw-regular);
	line-height: 1;
	transition: transform var(--dur) var(--ease);
}

.wp-block-details[open] summary::after {
	transform: rotate(45deg);
}

.wp-block-details summary:focus-visible {
	outline: 2px solid var(--c-ink);
	outline-offset: 4px;
}

.wp-block-details[open] summary {
	margin-bottom: var(--sp-3);
}

/* ==========================================================================
   16. Stopka
   ========================================================================== */

.site-footer {
	padding-block: var(--sp-9) var(--sp-6);
	background-color: var(--c-ink);
	color: rgba(255, 255, 255, 0.72);
	font-size: var(--fs-small);
}

/* Pierscien fokusa jest czarny, bo cala reszta strony stoi na jasnym tle.
   Stopka ma tlo tego samego czarnego, wiec ring byl w niej niewidzialny:
   klawiatura przechodzila przez czternascie linkow i nic sie nie zapalalo.
   Tu, i tylko tu, ring musi byc bialy. */
.site-footer :focus-visible {
	outline-color: var(--c-inverse);
}

.site-footer a {
	color: rgba(255, 255, 255, 0.72);
	text-decoration: none;
}

.site-footer a:hover {
	color: var(--c-inverse);
	text-decoration: underline;
}

.site-footer h2 {
	margin-bottom: var(--sp-4);
	color: var(--c-inverse);
	font-size: var(--fs-kicker);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-kicker);
	text-transform: uppercase;
}

.site-footer__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
	gap: var(--sp-7);
}

.site-footer__brand img {
	width: auto;
	height: 34px;
	margin-bottom: var(--sp-4);
}

.site-footer__list li + li {
	margin-top: var(--sp-2);
}

/* Linki w stopce mialy 20 px wysokosci i 8 px przerwy miedzy soba, wiec kciuk
   trafial w sasiada. Pole dotyku rosnie paddingiem, sam napis stoi tam, gdzie stal.
   Na ekranie dotykowym idziemy do pelnych 44 px i przerwe niesie juz padding. */
.site-footer__list a {
	display: inline-block;
	padding-block: var(--sp-1);
}

@media (pointer: coarse) {
	.site-footer__list a {
		padding-block: var(--sp-3);
	}

	.site-footer__list li + li {
		margin-top: 0;
	}
}

.site-footer__social {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2) var(--sp-5);
	margin-top: var(--sp-4);
}

.site-footer__social a {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding-block: var(--sp-2);
	font-size: var(--fs-small);
}

.site-footer__social svg {
	flex: none;
}

/* Dolny pasek stoi na jednej linii, bo tylko link ma wlasny zapas na kciuk.
   Bez tego pudelka rozciagaly sie do rownej wysokosci, ale napisy w srodku
   zaczynaly sie kazdy u siebie i "Polityka prywatnosci" siedziala 12 px
   nizej niz "2026 Reanimatik". */
.site-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-4);
	margin-top: var(--sp-8);
	padding-top: var(--sp-5);
	border-top: 1px solid rgba(255, 255, 255, 0.14);
	font-size: var(--fs-kicker);
}

/* Kazdy link w stopce ma na telefonie 49 px wysokosci. "Polityka prywatnosci"
   w dolnym pasku miala 37 px, bo jako jedyna niesie mniejszy krok pionowy.
   Kciuk nie rozroznia sekcji stopki, wiec ostatni link nie moze byc trudniejszy
   do trafienia niz te nad nim. */
.site-footer__bottom a {
	display: inline-block;
	padding-block: var(--sp-3);
}

/* ==========================================================================
   17. Utilities
   ========================================================================== */

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.center {
	text-align: center;
}

.mt-0 {
	margin-top: 0;
}

.mt-5 {
	margin-top: var(--sp-5);
}

.mt-7 {
	margin-top: var(--sp-7);
}

.mt-8 {
	margin-top: var(--sp-8);
}

/* ==========================================================================
   18. Baner zgody na cookies
   ========================================================================== */

/* Baner lezy nad trescia i nie rezerwuje miejsca w ukladzie, wiec jego pojawienie
   sie po zaladowaniu skryptu niczego nie przesuwa. */
.zgoda {
	position: fixed;
	right: var(--gutter);
	bottom: var(--gutter);
	left: var(--gutter);
	z-index: var(--z-overlay);
	display: flex;
	justify-content: flex-end;
}

.zgoda[hidden] {
	display: none;
}

.zgoda__box {
	width: min(36rem, 100%);
	padding: var(--sp-5);
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius-lg);
	background: var(--c-surface);
	box-shadow: var(--shadow-pop);
}

.zgoda__title {
	margin: 0;
	font-size: var(--fs-h4);
}

.zgoda__text {
	margin: var(--sp-2) 0 0;
	color: var(--c-body);
	font-size: var(--fs-small);
}

.zgoda__options {
	display: grid;
	gap: var(--sp-3);
	margin-top: var(--sp-4);
}

.zgoda__options[hidden] {
	display: none;
}

.zgoda__option {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--sp-3);
	align-items: start;
	font-size: var(--fs-small);
	line-height: 1.45;
}

.zgoda__option input {
	margin-top: 0.2em;
}

.zgoda__option strong {
	display: block;
	color: var(--c-ink);
}

.zgoda__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3);
	align-items: center;
	margin-top: var(--sp-5);
}

.zgoda__link {
	padding: 0;
	border: 0;
	background: none;
	color: var(--c-body);
	font: inherit;
	font-size: var(--fs-small);
	text-decoration: underline;
	cursor: pointer;
}

.zgoda__link:hover {
	color: var(--c-ink);
}

/* Przycisk w stopce odslania skrypt, bo bez niego nie ma czego przelaczac. */
.site-footer__bottom button {
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	text-decoration: underline;
	cursor: pointer;
}

/* ==========================================================================
   19. Pasek akcji przyklejony do dolu i naglowek po zjechaniu
   ========================================================================== */

/* Pasek nie dotyka krawedzi ekranu, tylko plywa nad trescia w zaokraglonej
   plytce. Wersja na pelna szerokosc czyta sie jak systemowy pasek przegladarki
   i klient przestaje ja widziec, plywajaca zostaje elementem strony. */
.action-dock {
	position: fixed;
	right: var(--gutter);
	bottom: calc(var(--sp-4) + env(safe-area-inset-bottom));
	left: var(--gutter);
	z-index: calc(var(--z-nav) + 1);
	display: grid;
	grid-template-columns: auto auto minmax(0, 1fr);
	gap: var(--sp-2);
	padding: var(--sp-2);
	border: 1px solid rgba(10, 10, 10, 0.08);
	border-radius: var(--radius-pill);
	background-color: rgba(var(--c-bg-rgb), 0.82);
	backdrop-filter: saturate(180%) blur(18px);
	box-shadow: 0 12px 32px rgba(10, 10, 10, 0.16), 0 2px 6px rgba(10, 10, 10, 0.06);
	/* Start poza ekranem, zeby pierwsze pojawienie sie bylo wjazdem z dolu,
	   a nie mignieciem w miejscu. */
	transform: translateY(calc(100% + var(--sp-6)));
	opacity: 0;
	visibility: hidden;
	transition: transform 380ms var(--ease), opacity 220ms var(--ease), visibility 0s linear 380ms;
}

.action-dock[data-visible='true'] {
	transform: none;
	opacity: 1;
	visibility: visible;
	transition-delay: 0s;
}

/* Wlasny display przykrywa atrybut hidden, wiec trzeba go schowac drugi raz. */
.action-dock[hidden] {
	display: none;
}

.action-dock__item {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--sp-2);
	min-height: 52px;
	/* Trzy przyciski w jednym rzedzie na ekranie 390 px. Przy szerszym
	   marginesie wewnetrznym "Zamow odbior" nie miesci sie w calosci. */
	padding-inline: var(--sp-4);
	border-radius: var(--radius-pill);
	color: var(--c-ink);
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}

.action-dock__item:hover {
	text-decoration: none;
	background-color: rgba(10, 10, 10, 0.06);
}

.action-dock__item:active {
	transform: scale(0.97);
}

.action-dock__item--icon {
	width: 52px;
	padding-inline: 0;
}

/* Pasek niesie teraz te same nazwy, co reszta strony, wiec dwie etykiety sa
   dluzsze niz dawne "Wycen". Na waskim telefonie wygrywa slowo: ikona obok
   podpisu nie dodaje nic, czego podpis juz nie mowi, a zabiera trzydziesci
   kilka pikseli, przez ktore "Zamow odbior" urywalo sie w polowie. Sluchawka
   zostaje, bo ona jest calym przyciskiem. */
@media (max-width: 30rem) {
	/* Logo, "Menu" i przycisk akcji nie mieszcza sie na telefonie w calosci.
	   Dotad ustepowalo logo, bo jako jedyne moglo sie skurczyc, wiec napis byl
	   sciskany w poziomie. Teraz ustepuje slowo "Menu": trzy kreski i tak sa
	   zrozumiale, a caly wyraz zostaje w nazwie dostepnej dla czytnika. */
	.nav-toggle__label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}

	.nav-toggle {
		gap: 0;
		padding-inline: var(--sp-3);
	}

	.site-header__inner {
		gap: var(--sp-2);
	}

	.site-brand img {
		height: 30px;
	}

	.site-header__actions .btn--primary {
		padding-inline: var(--sp-3);
		font-size: var(--fs-small);
	}

	.action-dock__item--ghost .action-dock__icon,
	.action-dock__item--primary .action-dock__icon {
		display: none;
	}

	.action-dock__item--ghost,
	.action-dock__item--primary {
		padding-inline: var(--sp-3);
	}
}

/* Na najwezszym telefonie, jaki jeszcze sie zdarza, dwa podpisy nie mieszcza
   sie obok siebie. Wtedy wycena wraca do samej ikony, a caly napis zostaje
   w nazwie dostepnej. Odbior sprzetu jest wazniejszy, wiec to on trzyma slowa. */
@media (max-width: 21.5rem) {
	/* Na 320 px logo w pelnych proporcjach, "Menu" i przycisk akcji przestaja
	   sie miescic nawet po skroceniu. Naglowek oddaje wtedy boczny margines
	   i schodzi z logo o cztery piksele, zamiast znowu sciskac napis. */
	.site-header__inner {
		padding-inline: var(--sp-3);
	}

	.site-brand img {
		height: 26px;
	}

	.site-header__actions .btn--primary {
		padding-inline: var(--sp-2);
	}

	.action-dock__item--ghost .action-dock__icon {
		display: inline-block;
	}

	.action-dock__item--ghost .action-dock__label {
		display: none;
	}

	.action-dock__item--ghost {
		width: 52px;
		padding-inline: 0;
	}
}

/* Obie akcje drugoplanowe maja te sama obwodke, wiec trzy przyciski czytaja
   sie jak jeden zestaw, a nie jak przypadkowa zbieranina. */
.action-dock__item--icon,
.action-dock__item--ghost {
	border: 1px solid var(--c-border);
}

/* Przy otwartej wycenie pasek schodzi z drogi. Inaczej jego czarny przycisk
   wystaje zza gornej krawedzi arkusza. */
html.has-sheet .action-dock {
	opacity: 0;
	visibility: hidden;
}

.action-dock__item--primary {
	background-color: var(--c-ink);
	color: var(--c-inverse);
}

.action-dock__item--primary:hover {
	background-color: #262626;
}

.action-dock__icon {
	width: 20px;
	height: 20px;
	flex: none;
}

/* Miejsce pod pasek rezerwujemy na stale, a nie w chwili jego pokazania.
   Inaczej stopka podskakiwalaby dokladnie w momencie, w ktorym klient
   do niej dojezdza. */
@media (max-width: 60rem) {
	body {
		padding-bottom: calc(76px + env(safe-area-inset-bottom));
	}

	/* Gdy pasek jest na ekranie, naglowek oddaje mu przyciski i zostaje z samym
	   logo i menu. To samo CTA raz nad trescia i raz pod nia wyglada na
	   niedopilnowane, a nie na dopracowane. */
	body[data-dock-visible='true'] .site-header__actions {
		display: none;
	}
}

@media (min-width: 60.0625rem) {
	.action-dock {
		display: none;
	}
}

/* Naglowek po zjechaniu w dol: nizszy i z cieniem, zeby tresc pod nim
   nie sprawiala wrazenia, ze przeplywa przez pasek. */
.site-header__inner {
	transition: min-height var(--dur) var(--ease);
}

body[data-scrolled='true'] .site-header {
	box-shadow: 0 6px 24px rgba(10, 10, 10, 0.07), var(--shadow-nav);
}

@media (min-width: 60.0625rem) {
	body[data-scrolled='true'] .site-header__inner {
		min-height: 60px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.action-dock {
		transition: opacity 0s, visibility 0s;
	}
}

/* ==========================================================================
   20. Wejscie elementow przy przewijaniu
   ========================================================================== */

/* Klase `has-reveal` dokleja skrypt, wiec bez JavaScriptu nic sie nie chowa
   i strona wyglada dokladnie tak jak dzis. Ruch jest celowo maly: chodzi o to,
   zeby tresc sie skladala w trakcie czytania, a nie zeby wjezdzala z fajerwerkiem. */
body.has-reveal [data-reveal] {
	opacity: 0;
	transform: translateY(14px);
	transition: opacity 520ms var(--ease), transform 520ms var(--ease);
}

body.has-reveal [data-reveal].is-in {
	opacity: 1;
	transform: none;
}

/* Sasiadujace kafle wchodza z drobnym przesunieciem w czasie, dzieki czemu
   kratka sklada sie kolejno, a nie skacze cala naraz. */
body.has-reveal [data-reveal][style*='--reveal-delay'] {
	transition-delay: var(--reveal-delay);
}

@media (prefers-reduced-motion: reduce) {
	body.has-reveal [data-reveal] {
		opacity: 1;
		transform: none;
		transition: none;
	}

	/* Kreska nad krokiem jest czescia tego samego wejscia, wiec razem z nim
	   przestaje sie ruszac i po prostu stoi. */
	body.has-reveal .step::before {
		transform: none;
		transition: none;
	}
}

/* ==========================================================================
   21. Szybka wycena
   ========================================================================== */

/* Panel wyjezdza od dolu ekranu, jak arkusz w aplikacji na telefonie, a od
   szerokosci tabletu staje na srodku jak okno. Ten sam element, dwa zachowania,
   bo na telefonie kciuk jest na dole, a na duzym ekranie wzrok jest na srodku. */
.sheet {
	position: fixed;
	inset: 0;
	z-index: var(--z-overlay);
	display: flex;
	align-items: flex-end;
	justify-content: center;
}

.sheet[hidden] {
	display: none;
}

/* Przy otwartym panelu tresc pod spodem stoi. Bez tego kciuk przewijalby
   strone zamiast listy usterek. */
html.has-sheet,
html.has-sheet body {
	overflow: hidden;
}

.sheet__scrim {
	position: absolute;
	inset: 0;
	background-color: rgba(10, 10, 10, 0.5);
	opacity: 0;
	transition: opacity var(--dur) var(--ease);
}

.sheet[data-open='true'] .sheet__scrim {
	opacity: 1;
}

/* Na telefonie arkusz zajmuje caly ekran, jak w aplikacji. Wczesniej byl to
   kafelek na 88vh z wlasnym paskiem przewijania w srodku, wiec lista siedmiu
   usterek przewijala sie w okienku wysokim na dwie trzecie telefonu. Siedem
   dwuwierszowych pozycji i tak nie zmiesci sie na ekranie 390 px, ale teraz
   przewija sie normalny ekran, a nie ciasne pudelko. */
.sheet__panel {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	height: 100dvh;
	background-color: var(--c-surface);
	box-shadow: var(--shadow-lg);
	transform: translateY(100%);
	transition: transform 360ms var(--ease);
}

.sheet[data-open='true'] .sheet__panel {
	transform: none;
}

.sheet__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-4);
	padding: var(--sp-5) var(--sp-5) var(--sp-4);
	border-bottom: 1px solid var(--c-border);
}

.sheet__title {
	margin: 0;
	font-size: var(--fs-h4);
	letter-spacing: var(--ls-heading);
}

.sheet__close {
	display: grid;
	place-items: center;
	flex: none;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 1px solid var(--c-border);
	border-radius: var(--radius-pill);
	background-color: var(--c-surface);
	color: var(--c-ink);
	cursor: pointer;
	transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.sheet__close:hover {
	border-color: var(--c-border-strong);
	background-color: var(--c-bg-alt);
}

.sheet__close svg {
	width: 18px;
	height: 18px;
}

.sheet__body {
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: var(--sp-5) var(--sp-5) calc(var(--sp-5) + env(safe-area-inset-bottom));
	-webkit-overflow-scrolling: touch;
}

@media (min-width: 48rem) {
	.sheet {
		align-items: center;
		padding: var(--sp-6);
	}

	/* Panel rosnie do wysokosci tresci, a nie do sztywnych 44rem. Ten limit byl
	   jedyna przyczyna, dla ktorej lista siedmiu usterek laptopa obcinala sie
	   na ostatniej pozycji: 704 px to bylo mniej, niz potrzebowala. Sufit 92dvh
	   zostaje wylacznie na wypadek niskiego okna. */
	.sheet__panel {
		width: min(100%, 44rem);
		height: auto;
		max-height: 92dvh;
		border-radius: var(--radius-lg);
		transform: translateY(16px) scale(0.98);
		opacity: 0;
		transition: transform 300ms var(--ease), opacity 240ms var(--ease);
	}

	.sheet[data-open='true'] .sheet__panel {
		transform: none;
		opacity: 1;
	}
}

/* --- Kroki wewnatrz panelu --- */

.estimate__steps {
	display: flex;
	gap: var(--sp-2);
	margin-bottom: var(--sp-5);
}

/* Trzy kreski zamiast kolek z numerami. Numer trzeba przeczytac, dlugosc
   paska widac katem oka. */
.estimate__step {
	height: 3px;
	flex: 1;
	border-radius: var(--radius-pill);
	background-color: var(--c-border);
	transition: background-color var(--dur) var(--ease);
}

.estimate__step[data-done='true'] {
	background-color: var(--c-ink);
}

.estimate__lead {
	margin: 0 0 var(--sp-4);
	font-size: var(--fs-h4);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-heading);
}

.estimate__back {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	margin-bottom: var(--sp-4);
	padding: 0;
	border: 0;
	background: none;
	color: var(--c-muted);
	font: inherit;
	font-size: var(--fs-small);
	cursor: pointer;
}

.estimate__back:hover {
	color: var(--c-ink);
}

.estimate__back[hidden] {
	display: none;
}

/* Strzalki rysuje sam arkusz, dzieki czemu skrypt sklada kroki wylacznie
   z tekstu i nie musi wstawiac znacznikow. */
.estimate__back::before,
.pick--row::after {
	content: '';
	width: 7px;
	height: 7px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
}

.estimate__back::before {
	transform: rotate(135deg);
}

.pick--row::after {
	flex: none;
	color: var(--c-border-strong);
	transform: rotate(-45deg);
}

.estimate__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-3);
}

/* Wlasny display przykrywa atrybut hidden, wiec przy drugim kroku trzeba
   schowac wybor sprzetu drugi raz. */
.estimate__grid[hidden] {
	display: none;
}

.pick {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	width: 100%;
	min-height: 56px;
	padding: var(--sp-3) var(--sp-4);
	border: 1px solid var(--c-border);
	border-radius: var(--radius);
	background-color: var(--c-surface);
	color: var(--c-ink);
	font: inherit;
	font-size: var(--fs-small);
	font-weight: var(--fw-medium);
	text-align: left;
	cursor: pointer;
	transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
		transform var(--dur-fast) var(--ease);
}

.pick:hover {
	border-color: var(--c-border-strong);
	box-shadow: var(--shadow-sm);
}

.pick:active {
	transform: scale(0.99);
}

.pick--tile {
	flex-direction: column;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sp-4);
	min-height: 108px;
	padding: var(--sp-4);
}

.pick__icon {
	display: grid;
	place-items: center;
	flex: none;
	width: 40px;
	height: 40px;
	border: 1px solid rgba(255, 143, 77, 0.18);
	border-radius: var(--radius-sm);
	background-image: var(--grad-tint);
}

.pick__icon svg {
	width: 21px;
	height: 21px;
}

.pick__text {
	flex: 1;
}

.pick--row {
	justify-content: space-between;
	gap: var(--sp-4);
	padding: var(--sp-4);
	line-height: 1.35;
}

.estimate__list {
	display: grid;
	gap: var(--sp-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Dwie kolumny od tabletu w gore. Siedem usterek w jednej kolumnie mialo okolo
   620 px wysokosci i nie miescilo sie w panelu razem z naglowkiem i paskiem
   krokow. W dwoch kolumnach to cztery rzedy i scroll znika calkowicie. */
@media (min-width: 48rem) {
	.estimate__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--sp-3);
	}

	/* Ostatnia pozycja to zawsze "inna usterka albo nie wiem". Gdy wypada
	   samotnie w nowym rzedzie, ciagnie sie przez obie kolumny, zeby nie zostawiac
	   dziury obok. */
	.estimate__list > li:last-child:nth-child(odd) {
		grid-column: 1 / -1;
	}
}

/* Krok z polem tekstowym. Pole i "Dalej" stoja w jednej kolumnie, bo na telefonie
   przycisk obok pola zabralby wpisywanej nazwie polowe szerokosci. */
.estimate__ask {
	display: grid;
	gap: var(--sp-3);
}

.estimate__ask .btn {
	justify-self: start;
}

/* --- Wynik --- */

.quote {
	padding: var(--sp-5);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	background-color: var(--c-bg);
}

.quote__what {
	margin: 0;
	font-size: var(--fs-kicker);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-kicker);
	text-transform: uppercase;
	color: var(--c-muted);
}

.quote__price {
	margin: var(--sp-2) 0 0;
	font-size: var(--fs-h3);
	font-weight: var(--fw-semibold);
	letter-spacing: var(--ls-heading);
	line-height: var(--lh-heading);
}

.quote__note,
.quote__fee {
	margin: var(--sp-3) 0 0;
	font-size: var(--fs-small);
	color: var(--c-muted);
}

.quote__fee {
	padding-top: var(--sp-3);
	border-top: 1px solid var(--c-border);
}

.estimate__actions {
	display: grid;
	gap: var(--sp-3);
	margin-top: var(--sp-5);
}

.estimate__actions .btn {
	width: 100%;
}

.estimate__more {
	display: block;
	margin-top: var(--sp-4);
	font-size: var(--fs-small);
	text-align: center;
}

@media (prefers-reduced-motion: reduce) {
	.sheet__panel {
		transition: none;
	}
}
