/* ============================================================================
   content.css — blog, case study, kontakt, o nas
   ----------------------------------------------------------------------------
   OSOBNY PLIK, nie site.css. Powód: site.css jest WKLEJANY do każdej strony
   serwisu (BaseLayout, import ?raw), więc dorzucenie tam 1500 linijek
   spowolniłoby też stronę główną i podstrony usługowe. Ten plik wczytują
   tylko strony, które go potrzebują.

   ZAKRESOWANIE: wszystko siedzi pod .art / .blog / .cs / .kt / .on.
   Nie ruszamy .prose (używają go polityki i kariera) ani svc.css (8 podstron
   usługowych) — zero regresu tam, gdzie już działa.
   ========================================================================== */

/* ==========================================================================
   1. TREŚĆ ARTYKUŁU (.art) — wpisy bloga i case studies
   Mediana wpisu to 20 tys. znaków. To nie notka, to długi tekst — typografia
   musi go unieść: szerokość wiersza, oddech między akapitami, rytm nagłówków.
   ========================================================================== */

.art {
  /* ~68 znaków w wierszu — poniżej 50 i powyżej 90 czyta się źle */
  max-width: 42rem;
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: 1.125rem;      /* 18px */
  line-height: 1.75;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  /* przeglądarka sama unika sierotek w akapitach */
  text-wrap: pretty;
  /* SIATKA BEZPIECZEŃSTWA NA TWARDE SPACJE Z WORDPRESSA (etap 4).
     W treści wpisów jest ich 4790 w 77 wpisach — postawili je autorzy, nie my.
     Dla przeglądarki tekst sklejony twardą spacją to JEDNO słowo, a znaczniki
     „w środku zdania" (<strong>, <a>) nie dają jej gdzie złamać wiersza. Tak
     powstają zlepki do 75 znaków, np. „domen chatgpt.com, perplexity.ai,
     copilot.microsoft.com, gemini.google.com." — na telefonie taki zlepek nie
     mieści się w linijce i jego koniec znika za krawędzią ekranu. Mierzone:
     39 wpisów ma zlepek dłuższy niż 24 znaki.
     `break-word` łamie taki zlepek DOPIERO wtedy, gdy inaczej się nie da —
     zwykły tekst zawija się bez zmian, po spacjach. */
  overflow-wrap: break-word;
}

.art > * + * { margin-top: 1.15em; }

.art p { margin: 0; }

/* --- Nagłówki w treści --------------------------------------------------- */
.art h2,
.art h3,
.art h4 {
  color: var(--text-primary, #fff);
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
  /* kotwica ze spisu treści nie może wjechać pod przyklejone menu */
  scroll-margin-top: 110px;
}
.art h2 {
  font-size: clamp(1.5rem, 1.15rem + 1.1vw, 1.875rem);
  margin-top: 2.4em;
  margin-bottom: 0.7em;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
}
.art h3 {
  font-size: clamp(1.2rem, 1.05rem + 0.5vw, 1.375rem);
  margin-top: 2em;
  margin-bottom: 0.55em;
}
.art h4 {
  font-size: 1.0625rem;
  margin-top: 1.7em;
  margin-bottom: 0.45em;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
}
/* pierwszy nagłówek nie potrzebuje kreski i wielkiego odstępu — jest tuż pod leadem */
.art > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* --- Odnośniki -----------------------------------------------------------
   Czerwień AW jest akcentem, a w 20-tysięcznym artykule linków bywa dziesiątki.
   Dlatego: biały tekst + czerwone podkreślenie (widać, że to link, ale tekst
   nie robi się czerwony w co drugim zdaniu). Czerwony dopiero pod kursorem. */
.art a {
  color: var(--text-primary, #fff);
  text-decoration: underline;
  text-decoration-color: var(--accent-default, #ff2c2c);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: color 0.15s ease;
  /* Adres strony wklejony w tekst jest JEDNYM długim słowem — na telefonie
     wychodził poza ekran i był ucięty (np. „https://www.growthloop.com/…"
     o 58 px, w 4 wpisach i w polityce cookies). Łamiemy go dopiero wtedy, gdy
     inaczej się nie da; zwykłe odnośniki („czytaj więcej") zawijają się po staremu. */
  overflow-wrap: break-word;
}
.art a:hover,
.art a:focus-visible { color: var(--accent-default, #ff2c2c); }

/* --- Listy --------------------------------------------------------------- */
.art ul,
.art ol { margin: 1.15em 0; padding-left: 1.35em; }
.art li { margin-bottom: 0.5em; }
.art li::marker { color: var(--accent-default, #ff2c2c); }
.art ol > li::marker { color: var(--text-muted, rgba(255, 255, 255, 0.56)); font-weight: 700; }
.art li > ul, .art li > ol { margin: 0.5em 0; }

.art strong { color: var(--text-primary, #fff); font-weight: 600; }

/* --- Cytat --------------------------------------------------------------- */
.art blockquote {
  margin: 1.8em 0;
  padding: 0.2em 0 0.2em 1.4rem;
  border-left: 3px solid var(--accent-default, #ff2c2c);
  color: var(--text-primary, #fff);
  font-size: 1.1875rem;
  font-style: normal;
}
.art blockquote p + p { margin-top: 0.8em; }

.art hr {
  border: 0;
  border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  margin: 2.5em 0;
}

.art img {
  max-width: 100%;
  height: auto;
  border-radius: 14px;
  display: block;
  margin: 1.8em 0;
}

.art code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.9em;
  background: var(--surface-chip, rgba(255, 255, 255, 0.06));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 6px;
  padding: 0.12em 0.4em;
  /* To samo co przy odnośnikach: adres w ramce („gemini.google.com",
     „/%category%/%postname%/") to jedno słowo bez spacji. Na telefonie
     wyjeżdżał poza ekran nawet o 328 px. */
  overflow-wrap: break-word;
}

/* ==========================================================================
   2. TABELE — 183 sztuk w 77 wpisach. Połowa bloga to rankingi.
   Tabela przewija się SAMA w poziomie; strona nigdy.
   ========================================================================== */

.tbl {
  /* .art ma ~672 px, a tabele rankingów bywają szersze — niech mają własne okno,
     szersze niż kolumna tekstu, wyśrodkowane względem niej */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  margin: 2em 0;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 14px;
  -webkit-overflow-scrolling: touch;

  /* Cień na krawędzi POKAZUJE SIĘ SAM, gdy jest co przewijać (czysty CSS, zero JS).
     Dwie warstwy „local" zasłaniają cień, gdy dojechaliśmy do końca;
     dwie warstwy „scroll" rysują sam cień. */
  background:
    linear-gradient(to right, var(--bg-page, #0a0a0c) 30%, rgba(10, 10, 12, 0)) left center / 44px 100% no-repeat local,
    linear-gradient(to left, var(--bg-page, #0a0a0c) 30%, rgba(10, 10, 12, 0)) right center / 44px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0)) left center / 16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0)) right center / 16px 100% no-repeat scroll;
}
.tbl:focus-visible {
  outline: 2px solid var(--accent-default, #ff2c2c);
  outline-offset: 2px;
}

.art table {
  width: 100%;
  min-width: 34rem;          /* poniżej tego rankingi robią się nieczytelne — wtedy przewijamy */
  border-collapse: collapse;
  font-size: 0.9375rem;      /* 15px — tabela jest gęsta, nie musi mieć wagi akapitu */
  line-height: 1.55;
}
.art thead th {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-primary, #fff);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.art th,
.art td {
  padding: 12px 16px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
}
.art tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.02); }
.art tbody tr:last-child td { border-bottom: 0; }
.art td strong { color: #fff; }
/* pierwsza kolumna rankingu to zwykle nazwa — niech się wyróżnia */
.art tbody td:first-child { color: var(--text-primary, #fff); }

@media (max-width: 640px) {
  .art table { font-size: 0.875rem; }
  .art th, .art td { padding: 10px 12px; }
}

/* ==========================================================================
   3. STOPKA KONWERSJI (.conv) — wspólna dla wpisu, case study, /o-nas/, /kontakt/
   ========================================================================== */

/* SZEW Z SEKCJĄ WYŻEJ — przerobiony 31.07.2026.
   Karol: „odcięcie sekcji formularza od case study nie jest zrobione płynnie".
   Co tworzyło twardą krawędź (zmierzone, nie na oko):
     1. kreska 1 px na całą szerokość (biel przy 8% krycia),
     2. poświata `at 50% 0%` — środek elipsy leżał DOKŁADNIE na górnej krawędzi,
        więc czerwień włączała się w pełnej mocy z pierwszego piksela sekcji.
   Razem: skok jasności 2,5 punktu (skala 0-100, tak widzi oko) na wysokości
   jednego piksela. Dla porównania karta realizacji jest 7,2 punktu nad tłem
   i jest wyraźnie widoczna — czyli 2,5 punktu na jednym pikselu to widoczna kreska.
   Teraz: kreski nie ma, a ten sam skok rozłożony jest na 280 px. Poświata zaczyna
   się 180 px NAD sekcją (wchodzi w listę realizacji) i narasta stopniowo.
   Pionowy promień elipsy = połowa wysokości pola, więc na obu krawędziach pola
   czerwień ma zero krycia — nie da się złapać miejsca, w którym się zaczyna. */
.conv {
  position: relative;
  padding: clamp(64px, 9vh, 104px) 0;
}
.conv::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -180px;
  height: 560px;
  z-index: -1;              /* pod treścią sekcji wyżej — nie barwi kart realizacji */
  pointer-events: none;
  background:
    radial-gradient(ellipse 66% 50% at 50% 50%, rgba(255, 44, 44, 0.1), rgba(255, 44, 44, 0) 70%);
}
.conv--compact { padding-top: 0; }
.conv--compact::before { content: none; }

.conv__grid {
  display: grid;
  grid-template-columns: 1fr minmax(320px, 420px);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

.conv__h {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.5rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 18px;
  text-wrap: balance;
  max-width: 18ch;
}
.conv__lead {
  font-size: 1.125rem;
  line-height: 1.7;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  margin: 0 0 28px;
  max-width: 46ch;
  text-wrap: pretty;
}

.conv__promises { list-style: none; margin: 0 0 32px; padding: 0; display: grid; gap: 12px; }
.conv__promises li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  color: #fff;
  font-size: 1.0625rem;
  line-height: 1.5;
}
.conv__tick { width: 20px; height: 20px; flex: none; margin-top: 2px; color: #fff; }

/* Ludzki akcent przy formularzu: twarz osoby, z którą klient będzie rozmawiał. */
.conv__person {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 20px 16px 16px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.03);
  max-width: 30rem;
}
.conv__avatar {
  width: 56px;
  height: 56px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  object-position: center;
  background: rgba(255, 255, 255, 0.06);
}
.conv__persontxt {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  text-wrap: pretty;
}
.conv__persontxt strong { color: #fff; font-weight: 600; }

@media (max-width: 900px) {
  .conv__grid { grid-template-columns: 1fr; }
  .conv__h { max-width: none; }
}

/* ==========================================================================
   4. STRONA WPISU (.post)
   ========================================================================== */

.crumbs {
  font-size: 0.85rem;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  margin-bottom: 22px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.crumbs a { color: inherit; text-decoration: none; }
.crumbs a:hover { color: #fff; }
.crumbs span { opacity: 0.45; }

.post__head { padding: clamp(112px, 15vh, 160px) 0 0; }

/* Kategoria: jedyny czerwony element w nagłówku wpisu. Czerwień AW = akcent, rzadko. */
.post__cat {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 44, 44, 0.1);
  color: var(--accent-default, #ff2c2c);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  margin-bottom: 20px;
  /* Pole kliknięcia z 31 px na 44 px — BEZ zmiany wyglądu pigułki (etap 4,
     decyzja Karola 09.08). Tu NIE da się użyć samej wyściółki z ujemnym odstępem
     jak przy logotypie w belce: pigułka ma widoczne tło i obwódkę, więc wyściółka
     powiększyłaby ją na oczach użytkownika. Dlatego pole powiększa niewidoczna
     nakładka — napis i ramka zostają co do piksela takie same. */
  position: relative;
}
.post__cat::after {
  content: '';
  position: absolute;
  inset: -8px 0;   /* 31 px + 2 × 8 px = 47 px wysokości pola kliknięcia */
}
.post__cat:hover { background: rgba(255, 44, 44, 0.2); color: #fff; }

.post__title {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.25rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 28px;
  max-width: 20ch;
  text-wrap: balance;
}
/* TELEFON: tytuł wpisu o stopień mniejszy (decyzja Karola 14.07) — patrz svc.css.
   Przy 32 px w linijkę wchodziło 18 znaków, a para „Kompleksowy Ranking" ma 19,
   więc ostatnie słowo musiało zostawać samo. Tytułów z WordPressa nie skracamy. */
@media (max-width: 430px) {
  .post__title { font-size: 1.8rem; }
}

.post__meta {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.9375rem;
  padding-bottom: 40px;
}
.post__dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: 0.5; }

/* Autor z twarzą — mamy portrety całej trójki, a Google premiuje widocznego autora. */
.post__author { display: flex; align-items: center; gap: 10px; }
.post__avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center;
  background: rgba(255, 255, 255, 0.06);
}
.post__authorname { color: #fff; font-weight: 600; display: flex; align-items: baseline; gap: 8px; }
.post__role {
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}

/* Zdjęcie tylko wtedy, gdy jest (59 ze 130 wpisów go NIE MA — i to jest w porządku). */
.post__cover {
  width: 100%;
  max-height: 460px;
  object-fit: cover;
  border-radius: 20px;
  display: block;
  margin-bottom: 56px;
  background: rgba(255, 255, 255, 0.04);
}

/* Układ wpisu: spis treści (L) | treść w czytelnej szerokości (C) | karta zachęty (P).
   Domyślnie (telefon/tablet) jedna kolumna: spis jako pudełko na górze, treść, karta
   zachęty pod spodem. Trzy kolumny włączają się dopiero, gdy jest na nie miejsce
   (≥1200px, niżej w tym pliku) — inaczej kolumna tekstu zrobiłaby się za wąska. */
.post__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(28px, 4vh, 40px);
  justify-items: center;
  padding-bottom: clamp(56px, 8vh, 96px);
}
/* min-width:0 — bez tego kolumna nie zejdzie poniżej najdłuższego słowa i tabele
   rozepchną układ poza ekran (lekcja z sesji 18) */
.post__body { min-width: 0; width: 100%; max-width: 42rem; }

/* --- Karta zachęty w kolumnie prawej (zbiera leady → /kontakt/) ----------
   Osobny element — NIE ConversionBlock ani ContactForm (te są współdzielone przez
   ~130 stron). Prowadzi na działającą stronę /kontakt/ z formularzem (sesja 30).
   Na telefonie/tablecie to zwykły blok pod treścią; przyklejenie z boku dostaje
   w układzie trzykolumnowym (≥1200px). */
.post-cta { width: 100%; max-width: 42rem; }
.post-cta__card {
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(10px);
  padding: clamp(22px, 2.2vw, 28px);
}
.post-cta__h {
  margin: 0 0 4px;
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: #fff;
  text-wrap: balance;
}
/* Twarz zamiast ściany tekstu — kto poprowadzi rozmowę (jak blok na dole strony).
   Człowiek robi kartę cieplejszą i wiarygodniejszą, a przy tym mniej tekstu. */
.post-cta__person {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0 22px;
}
/* Zdjęcie jako tło z powiększeniem — kadr na CAŁĄ głowę z włosami (to samo ustawienie,
   które Karol zaakceptował na /kontakt/: portret + size 172% + pozycja 57%/15%). */
.post-cta__avatar {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 2px solid rgba(255, 44, 44, 0.5);
  background-color: #101014;
  background-image: url("/assets/img/zespol/portret/damian-korszun.jpg");
  background-repeat: no-repeat;
  background-size: 172%;
  background-position: 57% 15%;
}
.post-cta__pmeta { display: flex; flex-direction: column; min-width: 0; }
.post-cta__pname { color: #fff; font-weight: 600; font-size: 0.9375rem; line-height: 1.25; }
.post-cta__prole {
  margin-top: 2px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
  line-height: 1.3;
}
.post-cta__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 20px;
  border-radius: 12px;
  background: var(--accent-default, #ff2c2c);
  color: #fff;
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
  transition: background 0.2s ease, transform 0.2s ease;
}
.post-cta__btn:hover { background: var(--accent-hover, #e62424); transform: translateY(-2px); }
.post-cta__btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.post-cta__btn svg { width: 18px; height: 18px; flex: none; }

/* Po usunięciu widocznego nagłówka listy (/blog/ i /blog/page/N/) pierwsza sekcja
   dostaje niewielki oddech pod menu — wcześniej robił to .lhead, ale jego duży odstęp
   robił miejsce na tekst nagłówka; bez nagłówka byłaby to pusta luka nad kartą „Zacznij
   tu". Menu jest w normalnym układzie (zajmuje górę), więc karcie wystarczy sam oddech. */
.sr-only + .feat-sec,
.sr-only + .blog { padding-top: clamp(28px, 4vh, 44px); }

.post__lead {
  font-size: 1.3125rem;
  line-height: 1.6;
  color: #fff;
  margin: 0 0 32px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  text-wrap: pretty;
}
.post__lead a { color: #fff; text-decoration: underline; text-decoration-color: var(--accent-default, #ff2c2c); }

/* --- Lewa kolumna wpisu: spis treści + udostępnianie (sesja 38) -----------
   Telefon/tablet: zwykły słupek na górze treści (spis, pod nim udostępnianie) —
   dzięki temu udostępnianie widać od razu, a nie po 39 ekranach (audyt S37).
   Desktop (≥1200px): słupek przyklejony, jedzie z czytelnikiem. */
.post__rail {
  width: 100%;
  max-width: 42rem;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

/* --- Spis treści --------------------------------------------------------- */
/* Telefon/tablet: spis jako pudełko na górze treści. Przyklejenie z boku dostaje
   w układzie trzykolumnowym (≥1200px, niżej w tym pliku). */
.toc {
  width: 100%;
  max-width: 42rem;
  padding: 20px 22px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
}
.toc__h {
  margin: 0 0 14px;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}
.toc__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
}
.toc__list li { margin: 0; }
.toc__list a {
  display: block;
  padding: 7px 0 7px 16px;
  margin-left: -1px;
  border-left: 2px solid transparent;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.875rem;
  line-height: 1.45;
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
  /* Zabezpieczenie na wypadek pojedynczego DŁUGIEGO słowa w nazwie rozdziału
     (adres strony, nazwa własna) — w słupku 190 px takie słowo wyszłoby poza
     krawędź i koniec byłby niewidoczny. Łamie się dopiero wtedy, gdy inaczej
     się nie da; normalne słowa zawijają się po staremu, po spacjach.
     Sklejanie par twardą spacją jest tu wyłączone osobno — patrz
     `ZAWSZE_WASKIE` w src/lib/typografia.js. */
  overflow-wrap: break-word;
}
.toc__list a:hover { color: #fff; }
/* sekcja, którą właśnie czytasz (ustawia to content.js; bez JS spis i tak działa) */
.toc__list a[aria-current="true"] {
  color: #fff;
  border-left-color: var(--accent-default, #ff2c2c);
}

/* Trzy kolumny — dopiero od 1200px, gdzie kolumna tekstu zostaje szeroka na ≥38rem
   (optimum czytania). 190 (spis) + 280 (karta) + 2× odstęp mieści się w kontenerze
   bez ściskania treści — policzone dla 1200 i 1440. Obie boczne kolumny przyklejone
   (jadą z czytelnikiem); treść wyśrodkowana między nimi. */
@media (min-width: 1200px) {
  .post__grid {
    grid-template-columns: 190px minmax(0, 1fr) 280px;
    column-gap: clamp(24px, 2.2vw, 48px);
    row-gap: 0;
    justify-items: stretch;
    align-items: start;
  }
  /* treść wyśrodkowana w swojej kolumnie — oprawiona słupkiem i kartą z dwóch stron */
  .post__body { margin: 0 auto; }
  /* Przyklejony jest CAŁY słupek (sesja 38), nie sam spis treści. Dzięki temu
     udostępnianie jedzie z czytelnikiem przez całą długość wpisu — tak samo robi
     Backlinko (przyklejony pasek na wpisie długim na 45 tys. px). */
  .post__rail {
    position: sticky;
    top: 104px;
    max-width: none;
    max-height: calc(100vh - 140px);
    gap: 0;
  }
  /* Spis przewija się WEWNĄTRZ słupka (flex: 0 1 auto + min-height:0), a udostępnianie
     zostaje pod nim zawsze widoczne — inaczej długi spis zepchnąłby je poza ekran. */
  .toc {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    max-width: none;
    padding: 0 8px 0 0;
    border: 0;
    border-radius: 0;
    background: none;
  }
  /* Wygląd samego paska „Udostępnij" w słupku — NIŻEJ, za definicją `.share`.
     (Tu by nie zadziałał: `.share--rail` i `.share` mają tę samą siłę selektora,
     więc wygrywa ten zapisany PÓŹNIEJ w pliku, a `.share` stoi dalej.) */
  .post-cta {
    position: sticky;
    top: 104px;
    max-width: none;
  }
}

/* „Zaktualizowano" — sygnał świeżości przy dacie publikacji (tylko gdy wpis
   był poprawiony wyraźnie później). Ton stonowany, nie konkuruje z tytułem. */
.post__updated { color: var(--text-muted, rgba(255, 255, 255, 0.56)); }

/* --- Stopka artykułu: udostępnianie + wizytówka autora ------------------- */
.post__foot {
  max-width: 42rem;
  margin: 0 auto;
  padding: clamp(28px, 4vh, 44px) 0 clamp(8px, 2vh, 20px);
}

/* Przyciski udostępniania — zwykłe odnośniki, działają bez JavaScriptu.
   Od sesji 38 ten sam zestaw stoi w dwóch miejscach: w lewym słupku (--rail)
   i pod treścią (--foot). Wspólna jest tylko sama „pigułka" przycisku. */
.share {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
/* Pod treścią: oddzielone kreską od wizytówki autora (jak było do sesji 37). */
.share--foot {
  padding-bottom: clamp(28px, 4vh, 44px);
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
}
.share__label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  margin-right: 4px;
}
.share__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44×44 = minimalny cel dotykowy (warunek zamknięcia rozdziału, plan sekcja 4).
     Do sesji 38 było 42 px — na telefonie za mało. */
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.share__btn:hover {
  border-color: var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
  transform: translateY(-2px);
}
.share__btn svg { width: 18px; height: 18px; display: block; }

/* Pasek „Udostępnij" w przyklejonym słupku (tylko układ trzykolumnowy).
   MUSI stać za `.share`, bo selektory są tak samo silne i wygrywa późniejszy —
   zapisany wyżej `gap: 4px` przegrywał z `.share { gap: 12px }` i cztery ikony
   nie mieściły się w kolumnie: „kopiuj link" spadał do drugiego rzędu (zrzut S38).
   Rachunek: 4 ikony × 44 px + 3 odstępy × 4 px = 188 px w kolumnie 190 px.
   Ikon NIE zmniejszamy poniżej 44 px — to minimalny cel dotykowy (plan sekcja 4). */
@media (min-width: 1200px) {
  .share--rail {
    flex: 0 0 auto;
    align-items: flex-start;
    gap: 4px;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  }
  .share--rail .share__label { flex: 1 0 100%; margin: 0 0 6px; }
}

/* „Skopiowano" — chmurka pojawia się po skopiowaniu linku (dokłada content.js;
   bez JavaScriptu odnośnik po prostu prowadzi do wpisu). */
.share__copied {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 4px 10px;
  border-radius: 8px;
  background: #fff;
  color: #0a0a0c;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.share__copy.is-copied .share__copied { opacity: 1; transform: translateX(-50%) translateY(0); }

/* Wizytówka autora — twarz + imię + rola + odnośnik do zespołu. Bez bio (nie mamy). */
.authorcard {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: clamp(28px, 4vh, 44px);
  padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.03);
}
.authorcard__photo {
  flex: none;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center;
  background: rgba(255, 255, 255, 0.06);
}
.authorcard__body { min-width: 0; }
.authorcard__eyebrow {
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  margin-bottom: 6px;
}
.authorcard__name {
  margin: 0 0 8px;
  color: #fff;
  font-size: 1.125rem;
  font-weight: 700;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.authorcard__role {
  font-weight: 400;
  font-size: 0.875rem;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}
.authorcard__link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: #fff;
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
  /* Odnośnik ma 21 px wysokości, a kciukiem trafia się pewnie dopiero w 44 px.
     Powiększamy SAMO POLE KLIKANIA (niewidoczna nakładka), a nie napis —
     gdybyśmy dołożyli wyściółkę, karta autora urosłaby o 23 px i rozjechałby się
     jej układ. Napis zostaje dokładnie tam, gdzie był. */
  position: relative;
}
.authorcard__link::after {
  content: '';
  position: absolute;
  inset: -12px -8px;
}
.authorcard__link svg { width: 16px; height: 16px; transition: transform 0.2s ease; }
.authorcard__link:hover svg { transform: translateX(3px); }

@media (max-width: 520px) {
  .authorcard { flex-direction: column; align-items: flex-start; gap: 14px; }
}

/* ==========================================================================
   5. KARTY WPISÓW (.card) — miniaturka 16:9 na górze + treść pod spodem
   Każdy wpis widoczny na blogu MA już zdjęcie (66/66). Wpisy bez zdjęcia to
   64 strony rankingowe (ukryte z /blog/, widoczne na /category/rankingi/) —
   dostają markowy KAFELEK ZASTĘPCZY (Kierunek 02: „tytuł jako grafika").
   Ta sama strefa 16:9 dla zdjęcia i kafelka → karty równej wysokości, zero
   skoków układu (aspect-ratio rezerwuje miejsce, zanim zdjęcie się wczyta).
   ========================================================================== */

/* 3 karty w rzędzie na desktopie (życzenie Karola 17.07; do sesji 37 było
   auto-fill minmax(288px) = 4 kolumny w kontenerze 1376 px). Kolumny podane
   WPROST, bo auto-fill przy 3 kartach w „Przeczytaj też" rozjeżdżał ich szerokość.
   Ten sam rytm ma /blog/, „Przeczytaj też" (3 wpisy) i „Zobacz inne realizacje"
   (3 realizacje) — lista realizacji ma własne kolumny (.cards--cs niżej). */
.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
}
@media (max-width: 900px) {
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
}

/* Cała karta klikalna (<a>). Miniaturka i treść jako dwie strefy, bez wewnętrznej
   ramki — obramowanie i zaokrąglenie na całej karcie, miniaturka przycięta do rogów. */
.card {
  display: flex;
  flex-direction: column;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  background: rgba(255, 255, 255, 0.03);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.22s ease, background 0.22s ease, transform 0.22s ease;
}
.card:hover {
  border-color: var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 255, 255, 0.05);
  transform: translateY(-3px);
}

.card__thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #0c0c0e;
}
.card__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}
.card:hover .card__thumb img { transform: scale(1.04); }

.card__body {
  display: flex;
  flex-direction: column;
  gap: 9px;
  flex: 1;
  padding: 18px 20px 16px;
}
.card__cat {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-default, #ff2c2c);
}
.card__title {
  margin: 0;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.34;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.card__excerpt {
  margin: 0;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.9rem;
  line-height: 1.55;
  text-wrap: pretty;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card__meta {
  margin-top: auto;
  padding-top: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
}
.card__arrow {
  width: 18px;
  height: 18px;
  color: #fff;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.card:hover .card__arrow { opacity: 1; transform: translateX(0); }

/* --- KAFELEK ZASTĘPCZY (Kierunek 02 „tytuł jako grafika") ---
   Wypełnia strefę 16:9 miniaturki dla wpisów BEZ zdjęcia. Ciemny gradient,
   mały czerwony sygnet AW w lewym górnym rogu, nadtytuł (kategoria) + tytuł
   wpisany w kafelek. Pod kafelkiem NIE powtarzamy kategorii ani tytułu.
   Czysty CSS = zero pobierania, zero skoków układu. Czerwień AW = TYLKO sygnet. */
.card__fb {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  padding: 16px 18px;
}
.card__fb--title { background: linear-gradient(158deg, #16161a 0%, #0a0a0c 100%); }

/* Sygnet AW jako kształt o dowolnym kolorze (maska z pliku SVG — bez wklejania
   SVG do każdej z 62 kart). Jedyny czerwony element na kafelku. */
.card__fbsig {
  position: absolute;
  left: 16px;
  top: 14px;
  width: 30px;
  aspect-ratio: 96 / 62;
  -webkit-mask: url(/assets/img/aw-sygnet.svg) center / contain no-repeat;
          mask: url(/assets/img/aw-sygnet.svg) center / contain no-repeat;
  background: var(--accent-default, #ff2c2c);
}
.card__fbeyebrow {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 6px;
}
.card__fbtitle {
  margin: 0;
  color: #fff;
  font-weight: 700;
  font-size: 1.15rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ==========================================================================
   6. FAQ (.faq) — rozwijane bez JavaScriptu (znacznik <details>)
   ========================================================================== */

.faq { padding: clamp(56px, 8vh, 88px) 0 clamp(8px, 2vh, 24px); }
.faq__h {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 28px;
  text-wrap: balance;
}
.faq__list { display: grid; gap: 12px; max-width: 54rem; }
.faq__item {
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  overflow: hidden;
}
.faq__item[open] { border-color: var(--border-accent, rgba(255, 44, 44, 0.75)); }
.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 24px;
  cursor: pointer;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.4;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { background: rgba(255, 255, 255, 0.03); }
.faq__chev {
  width: 14px;
  height: 8px;
  flex: none;
  color: #fff;
  transition: transform 0.22s ease;
}
.faq__item[open] .faq__chev { transform: rotate(180deg); }

/* Rozwijanie NATYWNE (bez animacji wysokości). Animowanie wysokości treści przy
   ciężkim, ruchomym tle (cząsteczki + poświaty) przelicza układ całej strony w każdej
   klatce → zacinanie (uwaga Karola). Zamiast tego lekkie, TANIE pojawienie odpowiedzi
   (opacity + drobne przesunięcie — warstwa kompozytora, zero przeliczania układu).
   Treść ZAWSZE w HTML → SEO bez zmian. Łączy się z name="faq-aw" (jeden otwarty naraz). */
@media (prefers-reduced-motion: no-preference) {
  .faq__item[open] .faq__a { animation: faqReveal 0.22s ease both; }
}
@keyframes faqReveal {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .faq__chev { transition: none; }
}
.faq__a {
  margin: 0;
  padding: 0 24px 22px;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 1rem;
  line-height: 1.7;
  max-width: 62ch;
  text-wrap: pretty;
}

/* Układ „split" (tylko /kontakt/, props): nagłówek + wstęp w lewej kolumnie,
   lista pytań w prawej — prawa połowa nie świeci pustką. Domyślnie brak wpływu. */
.faq__intro { min-width: 0; }
.faq__introtxt {
  margin: 16px 0 0;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 1.0625rem;
  line-height: 1.7;
  max-width: 40ch;
  text-wrap: pretty;
}
.faq--split .faq__list { max-width: none; }
@media (min-width: 880px) {
  .faq--split .container {
    display: grid;
    /* 30.07.2026: lewa kolumna poszerzona z 340 na 480 px. Tytul sekcji doszedl
       do 46 px (wspolna skala) i przy 340 px wychodzil poza swoja kolumne
       — zmierzone: pudelko 340 px, tresc potrzebowala 458 px, napis nachodzil
       na pytania obok. */
    grid-template-columns: minmax(300px, 480px) 1fr;
    gap: clamp(40px, 5vw, 80px);
    align-items: start;
  }
  .faq--split .faq__intro { position: sticky; top: 100px; }
  .faq--split .faq__h { margin-bottom: 0; }
}

/* ==========================================================================
   7. POWIĄZANE WPISY (.related)
   ========================================================================== */

.related { padding: clamp(56px, 8vh, 88px) 0 clamp(72px, 10vh, 112px); }
.related__h {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 28px;
}

/* ==========================================================================
   8. NAGŁÓWEK LISTY (.lhead) — /blog/, /category/…/, /case-study/
   ========================================================================== */

.lhead { padding: clamp(112px, 15vh, 168px) 0 clamp(32px, 5vh, 56px); }
/* 🔴 17.08.2026, uwaga Karola: „case study mobile, też jest przerwa między tytułem
   a belką górną, »zobacz, co…« do podciągnięcia wyżej".
   Pomiar odstępu od dołu belki do tytułu przy oknie 390 × 844:
     /pozycjonowanie-stron/ i /audyt-seo/ (wzorzec) …  20 px
     pojedyncza realizacja /case-study/<nazwa>/ …….…  34 px
     listy realizacji (5 adresów) ………………………………… 126,6 px  ⛔
   Powód: 15vh z reguły wyżej na wysokim ekranie telefonu daje prawie 127 px, czyli
   trzy razy więcej niż na stronie, do której lista prowadzi. Na komputerze 1440 × 900
   ta sama reguła daje 135 px i tam jest DOBRZE (wzorce mają 181–236 px), dlatego
   poprawka siedzi wyłącznie pod telefonem i nie rusza szerokich ekranów.
   Cel 32 px — rytm pojedynczej realizacji, żeby przejście z listy do realizacji
   nie przesuwało tytułu.
   Cofnięcie: skasować ten blok @media. */
@media (max-width: 640px) {
  .lhead { padding-top: 32px; }
}
.lhead__h {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.25rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 20px;
  max-width: 22ch;
  text-wrap: balance;
}
/* nazwa kategorii jest krótka — nie potrzebuje szerokości zdania */
.lhead__h--cat { max-width: none; }
.lhead__lead {
  font-size: 1.1875rem;
  line-height: 1.65;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  margin: 0 0 16px;
  max-width: 52ch;
  text-wrap: pretty;
}
.lhead__count {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}

/* ==========================================================================
   9. FILTR KATEGORII (.filter) + WYSZUKIWARKA (.blogsearch)
   Filtr = zwykłe odnośniki, działa bez JavaScriptu.
   Wyszukiwarka = wygoda na JS, bez JS w ogóle się nie pokazuje (sesja 38).
   ========================================================================== */

.blog { padding-bottom: clamp(24px, 4vh, 48px); }

/* Pasek narzędzi listy: pigułki kategorii, a ZA nimi wyszukiwarka (życzenie
   Karola 17.07). Na desktopie jeden rząd — pigułki z lewej, pole z prawej.
   Na telefonie pole zawija się pod pigułki na całą szerokość. */
.blog__tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px 20px;
  flex-wrap: wrap;
  margin: 0 0 36px;
}

.filter {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  /* odstęp pod paskiem przejął .blog__tools */
  margin: 0;
  padding: 0;
  list-style: none;
  flex: 1 1 auto;
}
.filter__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 10px zamiast 9px: pigułka ma 44 px wysokości, czyli tyle, ile najmniejsze
     pole do trafienia kciukiem. Wcześniej 43 px — brakowało jednego piksela. */
  padding: 10px 16px;
  border-radius: 999px;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.15));
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9375rem;
  text-decoration: none;
  transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
.filter__pill:hover { color: #fff; border-color: rgba(255, 255, 255, 0.4); }

/* --- Wyszukiwarka wpisów (sesja 38) --------------------------------------

   🔴 PUŁAPKA (złapana pomiarem w S38, nie teorią): atrybut `hidden` chowa element
   regułą PRZEGLĄDARKI `[hidden]{display:none}`, a KAŻDA nasza reguła `display`
   ją bije — bo reguły autora zawsze wygrywają z regułami przeglądarki, niezależnie
   od tego, jak „słaby" jest selektor. Bez poniższego bloku:
     • pudełko szukania (`display:flex`) pokazywało się BEZ JavaScriptu, czyli
       stało puste i nic nie robiło (dokładnie ta atrapa, której nie wolno robić),
     • stara siatka kart (`display:grid`, 2744 px) i pasek stron (`display:flex`)
       zostawały widoczne POD wynikami szukania.
   Selektor `klasa[hidden]` jest mocniejszy od samej `klasa`, więc wygrywa. */
.blogsearch[hidden],
.blogsearch__clear[hidden],
.blogsearch__info[hidden],
.cards[hidden],
.pag[hidden] { display: none; }

.blogsearch {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 280px;
  min-width: 220px;
}
.blogsearch__icon {
  position: absolute;
  left: 14px;
  width: 18px;
  height: 18px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  pointer-events: none;
}
.blogsearch__input {
  width: 100%;
  height: 44px; /* cel dotykowy (plan sekcja 4) */
  padding: 0 46px 0 40px;
  border-radius: 999px;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.15));
  background: rgba(255, 255, 255, 0.03);
  color: #fff;
  font-family: inherit;
  font-size: 0.9375rem;
  transition: border-color 0.18s ease, background 0.18s ease;
  -webkit-appearance: none;
  appearance: none;
}
.blogsearch__input::placeholder { color: var(--text-muted, rgba(255, 255, 255, 0.56)); }
.blogsearch__input:focus {
  outline: none;
  border-color: var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 255, 255, 0.05);
}
/* natywny krzyżyk Chrome/Safari — mamy własny, większy (cel dotykowy) */
.blogsearch__input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
.blogsearch__clear {
  position: absolute;
  right: 0;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  cursor: pointer;
  transition: color 0.18s ease;
}
.blogsearch__clear:hover { color: #fff; }
.blogsearch__clear svg { width: 16px; height: 16px; display: block; }

/* Ile znaleziono / że nic nie ma — pod paskiem, nad wynikami. */
.blogsearch__info {
  margin: -14px 0 22px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.9375rem;
}

@media (max-width: 700px) {
  /* na telefonie pole na całą szerokość, pod pigułkami */
  .blogsearch { flex: 1 1 100%; }
}
.filter__pill[aria-current="true"] {
  color: #fff;
  border-color: var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 44, 44, 0.12);
}
.filter__count {
  font-size: 0.75rem;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-variant-numeric: tabular-nums;
}
.filter__pill[aria-current="true"] .filter__count { color: rgba(255, 255, 255, 0.75); }

/* ==========================================================================
   10. PASEK STRON (.pag)
   ========================================================================== */

.pag {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: clamp(40px, 6vh, 64px);
}
.pag__nums {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* 44 px zamiast 42 px w całym pasku stron (etap 4): tyle wynosi najmniejsze pole,
   w które da się pewnie trafić kciukiem. Brakowało dwóch pikseli — zmiany nie widać,
   a chybionych kliknięć ubywa. To samo w `.pag__gap` i `.pag__step` niżej. */
.pag__num {
  display: grid;
  place-items: center;
  min-width: 44px;
  height: 44px;
  padding: 0 8px;
  border-radius: 11px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
a.pag__num:hover { color: #fff; border-color: rgba(255, 255, 255, 0.4); }
.pag__num--on {
  color: #fff;
  border-color: var(--border-accent, rgba(255, 44, 44, 0.75));
  background: rgba(255, 44, 44, 0.14);
  font-weight: 600;
}
.pag__gap {
  display: grid;
  place-items: center;
  min-width: 24px;
  height: 44px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}
.pag__step {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 44px;
  padding: 0 16px;
  border-radius: 11px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9375rem;
  text-decoration: none;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.pag__step svg { width: 17px; height: 17px; }
a.pag__step:hover { color: #fff; border-color: rgba(255, 255, 255, 0.4); }
/* skrajna strona: przycisk zostaje na miejscu, ale jest wygaszony (układ nie skacze) */
.pag__step--off { opacity: 0.3; }

/* 🔴 17.08.2026 (Karol): „kategoria blog na mobile, na dole jest listowanie stron
   od 1 do 5, ale na moim telefonie strzałka w prawo jest w drugiej linii; wszystko
   powinno być w jednej, żeby wyglądało czysto".

   POLICZONE, ZANIM COKOLWIEK RUSZYŁEM (390 × 844 px, pojemnik 335 px):
     pięć numerów po 44 px + cztery odstępy po 6 px      244 px
     dwie strzałki po 43 px + dwa odstępy po 12 px       110 px
     razem                                               354 px przy dostępnych 335 px
   Brakuje 19 px, więc pasek łamał się na dwie linie. Przy 360 px brakowało 49 px,
   przy 320 px pasek miał trzy linie.

   ⚠️ Samo ścieśnienie odstępów NIE WYSTARCZY i to jest arytmetyka, nie kwestia gustu:
   pięć pól po 44 px plus dwie strzałki po 44 px to 332 px NAWET przy zerowych odstępach,
   czyli więcej niż 305 px dostępne przy ekranie 360 px. Pole 44 px jest w kodzie
   świadomie od etapu 4 („najmniejsze pole, w które da się pewnie trafić kciukiem")
   i nie schodzimy poniżej — więc na telefonie zmniejsza się LICZBA widocznych numerów,
   nie ich rozmiar.

   Na telefonie zostają: strona bieżąca i po jednej z każdej strony. Skok na dalsze
   strony robi się strzałkami, a komplet numerów widzi komputer i roboty Google —
   pełna lista dalej jest w kodzie strony, tylko schowana. */
@media (max-width: 640px) {
  .pag { gap: 10px; flex-wrap: nowrap; }
  /* na telefonie liczby stron zabierają całą szerokość — zostają strzałki i liczby */
  .pag__step span { display: none; }
  /* 44 px także w poziomie: dotąd strzałka miała 43 px szerokości, czyli o piksel
     mniej, niż wymaga próg dotykowy z etapu 4 */
  .pag__step { padding: 0 12px; min-width: 44px; justify-content: center; }
  .pag__nums { gap: 6px; }
  .pag__poz--daleka { display: none; }
}

/* ==========================================================================
   11. CASE STUDY (.cs) — wynik na wierzchu
   ========================================================================== */

.cs__head { padding: clamp(112px, 15vh, 160px) 0 0; }
.cs__title {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(1.875rem, 1.2rem + 2.4vw, 3rem);
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 36px;
  max-width: 24ch;
  text-wrap: balance;
}

/* Klient / branża / usługa */
.cs__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  margin: 0;
  padding: 0 0 44px;
}
.cs__fact { margin: 0; }
.cs__fact dt {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  margin-bottom: 6px;
}
.cs__fact dd {
  margin: 0;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 600;
}

/* --- Kafelki liczb: to jest powód, dla którego ktoś czyta case study ------ */
.cs__metrics {
  padding: clamp(36px, 5vh, 56px) 0;
  border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  background: radial-gradient(ellipse 60% 100% at 50% 50%, rgba(255, 44, 44, 0.07), rgba(255, 44, 44, 0) 72%);
}
/* Kafelki stoją OBOK SIEBIE, nie rozciągnięte na całą szerokość — przy dwóch
   liczbach siatka „auto-fit, 1fr" odsuwała je od siebie na pół ekranu i wyglądało
   to jak dwa osobne elementy, a nie jeden zestaw wyników. */
.cs__tiles {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 5vw, 72px);
}
.cs__tile { display: flex; flex-direction: column; gap: 6px; min-width: 180px; }
.cs__num {
  font-family: var(--type-family-display), "Zalando Sans", "DM Sans", sans-serif;
  font-weight: 900;
  font-size: clamp(2.5rem, 1.6rem + 3.2vw, 4rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: #fff;
  /* tusz wielkiej cyfry nie zaczyna się na krawędzi jej pudełka — wyrównanie optyczne */
  margin-left: -0.04em;
  font-variant-numeric: tabular-nums;
  /* odstep tysiecy: w Zalando 900 zwykla spacja rozpycha '44 000' na dwie liczby */
  word-spacing: -0.16em;
}
.cs__lab {
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 1rem;
  line-height: 1.4;
}

/* Odstęp tysięcy w wielkiej liczbie („44 000"). Rysujemy go SAMI, bo spacja
   w Zalando Sans 900 jest tak szeroka, że „44 000" czytało się jak dwie liczby.
   Szerokość w `em` = skaluje się razem z liczbą. */
.num-sp {
  display: inline-block;
  width: 0.22em;
}

.cs__kw { margin-top: 32px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px 20px; }
.cs__kwlab {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}
.cs__kwlist { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.cs__kwlist li {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  background: rgba(255, 255, 255, 0.04);
  color: #fff;
  font-size: 0.875rem;
}

/* --- Treść case study ---------------------------------------------------- */
.cs__body {
  max-width: 46rem;
  padding: clamp(48px, 7vh, 80px) 0 clamp(24px, 4vh, 40px);
}
.cs__sec { margin-bottom: clamp(44px, 6vh, 64px); }
.cs__h2 {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.375rem, 1.1rem + 0.9vw, 1.75rem);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 20px;
  text-wrap: balance;
}
.cs__body .art { max-width: none; }

.cs__list, .cs__results {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
}
.cs__list li, .cs__results li {
  position: relative;
  padding-left: 30px;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 1.0625rem;
  line-height: 1.65;
  text-wrap: pretty;
}
/* „co nie działało" = problem: krzyżyk. „co miało się wydarzyć" i wynik = znacznik. */
.cs__list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.62em;
  width: 10px;
  height: 2px;
  background: var(--accent-default, #ff2c2c);
  border-radius: 2px;
}
.cs__list--goals li::before,
.cs__results li::before {
  content: "";
  left: 2px;
  top: 0.42em;
  width: 14px;
  height: 8px;
  background: none;
  /* znacznik wyboru BIAŁY — czerwony „ptaszek" czyta się jak ostrzeżenie */
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  border-radius: 0;
  transform: rotate(-45deg);
}
.cs__results li { color: #fff; }

/* --- Co zrobiliśmy: kroki ------------------------------------------------ */
.cs__steps { margin: 0; padding: 0; list-style: none; display: grid; gap: 24px; }
.cs__step {
  display: grid;
  grid-template-columns: 46px 1fr;
  gap: 18px;
  padding: 22px 24px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
}
.cs__stepno {
  display: grid;
  place-items: center;
  /* 46 px, nie 40: numery są DWUZNAKOWE („01"), a po powiększeniu cyfry do 21 px
     (uwaga Karola 31.07) para cyfr dotykała krawędzi kółka. 46 px to szerokość
     kolumny, w której kółko stoi — układ się nie zmienia. */
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--accent-default, #ff2c2c);
  color: #fff;
  font-weight: 700;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}
.cs__steph {
  margin: 8px 0 10px;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.35;
}
.cs__steplist { margin: 0; padding-left: 1.1em; display: grid; gap: 6px; }
.cs__steplist li {
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9375rem;
  line-height: 1.6;
}
.cs__steplist li::marker { color: var(--accent-default, #ff2c2c); }

/* --- Prawdziwa opinia klienta (tylko tam, gdzie ją mamy) ----------------- */
.cs__quote {
  margin: 8px 0 0;
  padding: 28px 30px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-left: 3px solid var(--accent-default, #ff2c2c);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
}
.cs__quote blockquote {
  margin: 0 0 16px;
  color: #fff;
  font-size: 1.1875rem;
  line-height: 1.6;
  text-wrap: pretty;
}
.cs__quote figcaption { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.cs__quote figcaption strong { color: #fff; font-size: 0.9375rem; }
.cs__quote figcaption span {
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
}

/* --- Nadtytuł, wezwanie do kontaktu w nagłówku, „wcześniej X" (R6) -------- */
.cs__eyebrow {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-default, #ff2c2c);
  margin: 0 0 14px;
}
.cs__ctarow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  padding: 0 0 clamp(4px, 2vh, 16px);
}
.cs__cta svg { width: 17px; height: 17px; flex: none; transition: transform 0.22s ease; }
.cs__cta:hover svg { transform: translateX(3px); }
.cs__ctanote {
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.875rem;
}
/* Prawdziwa wartość wyjściowa pod liczbą („wcześniej 290") — TYLKO gdy dane ją niosą.
   Kreska w kolorze akcentu = mikro-sygnał „urosło z tego". */
.cs__was {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  align-self: flex-start;
  margin-top: 4px;
  padding: 3px 11px;
  border-radius: 999px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}
.cs__was::before {
  content: "";
  width: 12px;
  height: 2px;
  background: var(--accent-default, #ff2c2c);
  border-radius: 2px;
}

@media (max-width: 640px) {
  .cs__facts { gap: 24px 32px; }
  .cs__step { grid-template-columns: 1fr; gap: 12px; }
}

/* ==========================================================================
   12. KARTA REALIZACJI (.ccard) — kierunek B + „wygląd 1: samo wypełnienie"
        (oba wybrane przez Karola 31.07.2026)

   ZARZUT KAROLA 31.07: „prostokąty które trzymają pojedyncze case study są ledwo
   widoczne, zlewają się z tłem, są zbyt minimalistyczne — nie ma w nich w ogóle stylu".

   POMIAR PRZED ZMIANĄ (scripts/karty-pomiar.mjs --kolory; miara = punkty jasności L*,
   skala 0-100, tak widzi oko). Różnica jasności karty i tła pod nią:

     useorigin.com  .track-card-black   #1f1f20 na #0f1011   7,1 pkt   0/20 kart z obramowaniem
     ugly.cash      (strona jasna)      #ffffff na #f7f7f7   2,8 pkt   0/18
     linear.app     .MwJdiW_panel       #0f1011 na #08090a   2,2 pkt   5/19
     NASZA .ccard   przed zmianą        #080808 na #000000   2,1 pkt   3/3  ← jako jedyni
                                                                             na kresce

     metalab.com i phantom.land: ZERO kart na całej stronie — klienci jako tabletki
     z nazwami na wielkiej grafice. Dwa z pięciu wzorów nie używają prostokątów.

   DECYZJA: biel przy 8,5% krycia = #161616 na czerni = 7,2 pkt (zmierzone po zmianie),
   czyli tyle co useorigin — jedyny ciemny wzór, który w ogóle używa kart.
   Obramowanie przestaje być tym, co odcina kartę od tła; robi to wypełnienie.
   Krok po najechaniu myszą (8,5% → 13%) NIE jest zmierzony na wzorach — dobrany tak,
   żeby zmianę było widać.
   ========================================================================== */

.cards--cs { grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }

.ccard {
  display: flex;
  flex-direction: column;
  padding: 28px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.085);
  text-decoration: none;
  color: inherit;
  transition: background 0.22s ease, transform 0.22s ease;
}
.ccard:hover {
  background: rgba(255, 255, 255, 0.13);
  transform: translateY(-3px);
}

.ccard__svc {
  margin: 0 0 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-default, #ff2c2c);
}
.ccard__client { margin: 0 0 4px; color: #fff; }
.ccard__branza { margin: 0 0 24px; color: var(--text-body, rgba(255, 255, 255, 0.8)); }

/* Wynik odcięty od reszty — linia dwa razy mocniejsza niż dawne obramowanie karty
   (0,16 zamiast 0,08 krycia bieli), bo teraz to ona rozdziela „kto" od „ile". */
.ccard__metric {
  margin: auto 0 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.ccard__num {
  font-family: var(--type-family-display), "Zalando Sans", "DM Sans", sans-serif;
  letter-spacing: -0.03em;
  color: #fff;
  font-variant-numeric: tabular-nums;
  /* odstep tysiecy: w Zalando 900 zwykla spacja rozpycha '44 000' na dwie liczby */
  word-spacing: -0.16em;
}
.ccard__lab { color: #fff; font-weight: 500; }
.ccard__arr {
  width: 17px;
  height: 17px;
  margin-left: auto;
  flex: none;
  align-self: center;
  transition: transform 0.22s ease;
}
.ccard:hover .ccard__arr { transform: translateX(3px); }

/* ==========================================================================
   13. KONTAKT (.kt-) — REDESIGN sesja 30 (pod maks. konwersję formularza)
   Kompozycja: hero = panel (formularz-bohater + Damian) OBOK timeline procesu
   (5 etapów) — razem pełna szerokość → lekki dowód (sam przewijany pas logotypów)
   → FAQ → dane firmy. Cięte w sesji 30: sekcja wartości i liczby/case study.
   Tła sekcji SOLIDNE (#101014) — czerwona poświata `body` przez nie nie przebija.
   ========================================================================== */

/* Wspólne nagłówki sekcji na stronie kontaktu */
.kt-eyebrow {
  display: inline-block;
  margin: 0 0 14px;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-default, #ff2c2c);
}
.kt-h2 {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.6rem, 1.2rem + 1.3vw, 2.25rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 12px;
  max-width: 22ch;
  text-wrap: balance;
}
.kt-h3 {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: 1.25rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 20px;
}

/* --- HERO: jedna kompozycja — panel spinający formularz (bohater) z Damianem ---
   Minimum copy nad panelem (eyebrow + krótki nagłówek, bez leada). Panel zajmuje
   całą szerokość container — zero pustej prawej strony. */
.kt-hero { padding: clamp(104px, 14vh, 160px) 0 clamp(48px, 7vh, 80px); }

/* Siatka 2×2: [tytuł hero | tytuł procesu] u góry (ta sama wysokość),
   [panel formularza | kroki] pod spodem (kroki startują na wysokości formularza). */
.kt-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, 1fr);
  grid-template-areas:
    "title proctitle"
    "form  steps";
  column-gap: clamp(32px, 3.5vw, 56px);
  row-gap: clamp(18px, 2.6vh, 28px);
  align-items: start;
}
.kt-hero__h1 {
  grid-area: title;
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(1.9rem, 1.35rem + 2.1vw, 2.875rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0;
  max-width: 18ch;
  text-wrap: balance;
}

/* Panel: karta szkła z formularzem (bohater). Damian jako AWATAR (małe zdjęcie w
   kółku) u góry — nie osobna kolumna: robi miejsce, żeby formularz i timeline obok
   nie były ściśnięte (uwaga Karola „za ciasno"). */
.kt-hero__panel {
  grid-area: form;
  border: 1px solid var(--border-default, rgba(255, 255, 255, 0.16));
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(10px);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.45);
  padding: clamp(24px, 2.4vw, 34px);
}
/* Awatar + dane osoby — pasek u góry panelu (jak „Twój opiekun" na żywej stronie AW) */
.kt-hero__contact {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-bottom: clamp(18px, 2.4vh, 24px);
  margin-bottom: clamp(20px, 2.6vh, 26px);
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
}
/* Awatar jako tło z powiększeniem — zbliżenie na twarz (background-size) i
   wyśrodkowanie na niej (background-position), z pełną głową w kadrze. */
.kt-hero__avatar {
  flex: none;
  /* 72 → 96 px (06.08, Karol: „powieksz troche avatar Damiana, zeby byl bardziej
     widoczny"). Tyle samo, co wysokosc dwoch wierszy danych obok — dzieki temu
     zdjecie i podpisy tworza jeden pasek, a nie kolko doklejone z boku. */
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 2px solid rgba(255, 44, 44, 0.55);
  background-color: #101014;
  background-image: url("/assets/img/zespol/portret/damian-korszun.jpg");
  background-repeat: no-repeat;
  background-size: 172%;
  /* poziomo 57%: przesuwa kadr tak, że twarz Damiana ląduje idealnie na środku */
  background-position: 57% 15%;
}
.kt-hero__cmeta { min-width: 0; }
.kt-hero__pname { margin: 0; color: #fff; font-size: 1.125rem; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
.kt-hero__prole {
  margin: 3px 0 11px;
  color: rgba(255, 255, 255, 0.74);
  font-size: 0.875rem;
  line-height: 1.4;
}
.kt-hero__plinks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 7px 20px; }
.kt-hero__plinks a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.9);
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  word-break: break-word;
}
.kt-hero__plinks svg { width: var(--kt-ikona-przy-tekscie); height: var(--kt-ikona-przy-tekscie); flex: none; color: var(--accent-default, #ff2c2c); }
.kt-hero__plinks a:hover { color: #fff; }

/* ==========================================================================
   CIĄG WIELKOŚCI IKON NA /kontakt/ (06.08.2026)

   ⭐ Karol: „ikona telefonu i listu za mała przy danych Damiana, wyrównaj
   wielkości w sekcjach bo słabo to wygląda".

   Spis sprzed zmiany — /kontakt/ miało PIĘĆ wielkości znaków graficznych
   i żadnej reguły, która by mówiła, skąd się biorą:
     10×6 px   strzałka rozwijania w menu          (wspólny nagłówek strony)
     14×8 px   strzałka rozwijania w pytaniach FAQ (wspólny blok FAQ)
     16×16 px  słuchawka i koperta przy Damianie   ← tu jest uwaga Karola
     52×52 px  kółko z numerem kroku
     96×96 px  zdjęcie Damiana

   Przypisanie po ROLI, tak samo jak przy skali pisma — nie „ile ma mieć
   pikseli", tylko „co ten znak robi":
     przy tekście  20 px — znak niosący treść, stoi w wierszu danych
     znacznik      52 px — kółko wyznaczające pozycję na osi kroków
     portret       96 px — zdjęcie człowieka

   Dlaczego 20 px, a nie 16 px: wiersz danych ma 15 px pisma i 22,5 px wysokości.
   Ikona 16 px zajmowała 71 % wysokości wiersza, a jej kreska po przeskalowaniu
   z siatki 20 jednostek schodziła do 1,2 px — czyli cieńsza niż litery obok.
   Przy 20 px kreska wraca do 1,5 px i znak ma tę samą wagę co tekst.

   ⚠️ Strzałki rozwijania (menu, FAQ) zostają nietknięte: to wspólne części
   całej strony, a nie elementy /kontakt/. Zmiana tutaj rozjechałaby je
   z resztą podstron. Do ujednolicenia osobno, na całej stronie naraz.
   ========================================================================== */
.kt { --kt-ikona-przy-tekscie: 20px; }

/* Formularz = bohater. Wyłączamy jego własną powierzchnię (conv__form/kt-form) —
   panel JEST powierzchnią; padding niesie panel. */
.kt-hero__formwrap { min-width: 0; }
.kt-form {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  backdrop-filter: none;
  box-shadow: none;
}
.kt-form__opt { color: var(--text-muted, rgba(255, 255, 255, 0.5)); font-weight: 400; }
/* Zgoda RODO (checkbox) — w miejsce dawnych „ptaszków". Native, działa bez JS. */
.kt-form .zgl__consent {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  margin: 4px 0 18px;
  color: var(--text-body, rgba(255, 255, 255, 0.72));
  font-size: 0.8125rem;
  line-height: 1.5;
  text-wrap: pretty;
  cursor: pointer;
}
.kt-form .zgl__check {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 1px 0 0;
  accent-color: var(--accent-default, #ff2c2c);
  cursor: pointer;
}
.kt-form .zgl__consent a { color: #fff; text-decoration: underline; text-decoration-color: var(--accent-default, #ff2c2c); text-underline-offset: 2px; }

/* Formularz = główny punkt sekcji: pola i etykiety WYRAŹNE, czytelne (nie szare). */
.kt-form .zgl__label { color: rgba(255, 255, 255, 0.9); font-weight: 500; }
.kt-form .field {
  background: rgba(0, 0, 0, 0.5);
  border-color: rgba(255, 255, 255, 0.3);
}
.kt-form .field::placeholder { color: rgba(255, 255, 255, 0.46); }

/* --- PROCES jako timeline (prawa kolumna siatki hero): oś + numerowane węzły ---
   Tytuł procesu w rzędzie z tytułem hero (ta sama wysokość); kroki startują na
   wysokości formularza. Równe, oddechowe odstępy; nagłówek kroku przy górnej
   krawędzi kółka. Czysty CSS, czytelne bez JavaScriptu. */
.kt-proc__h {
  grid-area: proctitle;
  /* Siada przy DOLNEJ krawedzi rzedu, zeby stanac na linii podstawy tytulu podstrony,
     a nie startowac razem z nim od gory. Drugi skladnik naprawy z 06.08 („albo nizej"). */
  align-self: end;
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0;
  /* 38ch zamiast 22ch: po zejsciu na 28 px caly napis miesci sie w JEDNYM wierszu,
     a jeden wiersz przy jednym wierszu tytulu to czytelna roznica wielkosci.
     Wezszy ekran zawija go z powrotem do dwoch — i to jest w porzadku. */
  max-width: 38ch;
  text-wrap: balance;
}
.kt-hero__proc { grid-area: steps; min-width: 0; }
.kt-time {
  list-style: none;
  margin: 0;
  padding: 0;
}
.kt-time__step {
  position: relative;
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: 20px;
  padding-bottom: clamp(36px, 5vh, 56px);
}
.kt-time__step:last-child { padding-bottom: 0; }
/* oś łącząca — od dołu numeru do następnego węzła; przy ostatnim znika */
.kt-time__step::before {
  content: "";
  position: absolute;
  left: 25px;
  top: 52px;
  bottom: -2px;
  width: 2px;
  background: linear-gradient(to bottom, rgba(255, 44, 44, 0.45), rgba(255, 255, 255, 0.07));
}
.kt-time__step:last-child::before { display: none; }
.kt-time__no {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid rgba(255, 44, 44, 0.4);
  background: #101014;
  font-family: var(--type-family-display), "Zalando Sans", "DM Sans", sans-serif;
  font-weight: 900;
  font-size: 1.25rem;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
/* padding-top 0 → nagłówek kroku startuje przy GÓRNEJ krawędzi kółka (uwaga Karola) */
.kt-time__body { padding-top: 0; min-width: 0; }
.kt-time__h { margin: 0 0 8px; color: #fff; font-size: 1.1875rem; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; }
.kt-time__t {
  margin: 0;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9375rem;
  line-height: 1.6;
  max-width: none;
  text-wrap: pretty;
}

/* --- DOWÓD: przewijany pas logotypów (marquee) + twarde liczby -------------- */
.kt-proof { padding: clamp(40px, 6vh, 68px) 0 clamp(48px, 7vh, 80px); border-top: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08)); }
.kt-proof__head {
  text-align: center;
  margin: 0 0 30px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* Pas pełnej szerokości — mechanizm .clients__ z home; tu tylko odstęp pod spodem */
/* Sam pas logo (bez liczb/case study — Karol, sesja 30). Odstęp niesie padding sekcji. */
.kt-proof__wall { margin: 0; }

/* ⛔ Style sekcji „Dane firmy" (.kt-firma*) SKASOWANE 06.08.2026. Sama sekcja poszła
   05.08 („mamy footer" — Karol), a reguły zostały i wisiały bez właściciela.
   Komplet danych rejestrowych stoi w stopce (`src/components/Footer.astro`). */

/* Tablet/telefon: siatka schodzi do jednej kolumny w kolejności
   tytuł → formularz → tytuł procesu → kroki. */
@media (max-width: 1000px) {
  .kt-hero__grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "title"
      "form"
      "proctitle"
      "steps";
    row-gap: clamp(20px, 3.2vh, 34px);
  }
  .kt-proc__h { margin: 0 0 clamp(16px, 2.6vh, 24px); }
  .kt-time__t { max-width: 62ch; }        /* czytelna długość linii na szerokim ekranie */
  .kt-time__step { padding-bottom: clamp(26px, 4vh, 40px); }
}

/* 🔴 17.08.2026 (Karol): „zakładka kontakt mobile, nagłówek »Zarezerwuj spotkanie«
   ma być bliżej belki górnej, teraz jest pusta sekcja, nie wygląda to dobrze".

   ZMIERZONE PRZED ZMIANĄ (żywa wersja testowa, 390 × 844 px):
     belka                                    80 px wysokości
     przerwa belka → góra liter „Zarezerwuj"  118 px
   Skąd 118: reguła podstawowa ma `clamp(104px, 14vh, 160px)`, a 14vh przy ekranie
   844 px daje dokładnie 118,16 px. To odstęp liczony od góry strony, więc na telefonie
   dokłada się do belki zamiast ją zastępować.

   WZORZEC, a nie liczba na oko: `/pozycjonowanie-stron/` i `/audyt-seo/` przeszły
   przegląd Karola i mają w tym samym miejscu 20 px przy nagłówku tej samej wielkości
   (36 px). Zrównane do 20 px.

   ⚠️ Zmieniana jest WYŁĄCZNIE wersja telefonowa — na komputerze ten odstęp nie był
   kwestionowany, więc wartość podstawowa zostaje nietknięta. */
@media (max-width: 640px) {
  .kt-hero { padding-top: 20px; }
}

@media (max-width: 480px) {
  /* Wąski telefon: awatar nad danymi → mail (długi) dostaje pełną szerokość i nie
     łamie się w środku słowa. */
  .kt-hero__contact { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* ==========================================================================
   14. O NAS (.on) — nie o nas, tylko o tym, czego klient chce się dowiedzieć
   ========================================================================== */

.on__proof, .on__care, .on__cases, .on__flow, .on__who, .on__from { padding: clamp(48px, 7vh, 80px) 0; }
.on__h2 {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-size: clamp(1.5rem, 1.15rem + 1.3vw, 2.125rem);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0 0 16px;
  max-width: 24ch;
  text-wrap: balance;
}
.on__lead {
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  margin: 0 0 36px;
  max-width: 54ch;
  text-wrap: pretty;
}

/* Dowód = liczby z realizacji */
.on__nums {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
}
.on__num {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 28px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-radius: 18px;
  /* SOLIDNE tło (jak karty na /kontakt/) — czerwona poświata nie prześwituje. */
  background: #101014;
  text-decoration: none;
  transition: border-color 0.22s ease, transform 0.22s ease;
}
.on__num:hover { border-color: var(--border-accent, rgba(255, 44, 44, 0.75)); transform: translateY(-3px); }
.on__numv {
  font-family: var(--type-family-display), "Zalando Sans", "DM Sans", sans-serif;
  font-weight: 900;
  font-size: clamp(2.25rem, 1.8rem + 1.6vw, 3rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: #fff;
  margin-left: -0.04em;
}
.on__numl { color: var(--text-body, rgba(255, 255, 255, 0.8)); font-size: 1rem; }
.on__numw {
  margin-top: 8px;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.on__more { margin: 16px 0 0; }
/* inline-block + padding, żeby palec miał w co trafić (min. 44 px wysokości) */
.on__more a {
  display: inline-block;
  padding: 12px 0;
  color: #fff;
  font-size: 1rem;
  text-decoration: underline;
  text-decoration-color: var(--accent-default, #ff2c2c);
  text-underline-offset: 4px;
}

/* Opiekun — brzmienie zatwierdzone przez Karola, sesja 13 */
.on__carebox {
  padding: clamp(32px, 5vw, 56px);
  border: 1px solid var(--border-accent, rgba(255, 44, 44, 0.75));
  border-radius: 24px;
  background: radial-gradient(ellipse 80% 120% at 20% 0%, rgba(255, 44, 44, 0.12), rgba(255, 44, 44, 0.02) 70%);
}
.on__carebox .on__h2 { max-width: 26ch; }
.on__carebox .on__lead { margin-bottom: 0; }
/* Dwa panele obok siebie na dużym ekranie, jeden pod drugim na telefonie. */
/* stretch (domyślne), NIE start — panele różnej wysokości obok siebie wyglądają
   jak niedokończone. Karol zgłaszał to już przy kartach z opiniami. */
.on__caregrid { display: grid; gap: clamp(20px, 2.5vw, 28px); }
@media (min-width: 900px) {
  .on__caregrid { grid-template-columns: 1fr 1fr; }
}
/* Drugi panel jest cichszy: dwie identyczne czerwone plamy obok siebie krzyczą
   tak samo głośno i nic nie prowadzi wzroku. Hierarchia: opiekun najpierw. */
.on__carebox--cichy {
  border-color: var(--border-subtle, rgba(255, 255, 255, 0.08));
  background: rgba(255, 255, 255, 0.03);
}

/* Drugi akapit w sekcji (dopowiedzenie pod głównym) — bez podwójnego odstępu */
.on__lead--pod { margin-top: -20px; }
.on__carebox .on__lead--pod { margin-top: 18px; margin-bottom: 0; }

/* --------------------------------------------------------------------------
   PIERWSZY MIESIĄC — oś czasu wdrożenia.
   Na telefonie pionowa lista z pionową szyną po lewej, na dużym ekranie cztery
   kolumny z szyną poziomą. Świadomie INNY układ niż oś czasu na /kontakt/
   (.kt-time, pionowa): tam opisujemy proces PRZED podpisaniem, tu PO.
   -------------------------------------------------------------------------- */
.on__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 28px;
}
.on__step {
  position: relative;
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 16px;
  align-items: start;
}
/* pionowa szyna łącząca numery (telefon) */
.on__step::before {
  content: "";
  position: absolute;
  left: 21px;
  top: 44px;
  bottom: -28px;
  width: 2px;
  background: linear-gradient(180deg, rgba(255, 44, 44, 0.4), rgba(255, 255, 255, 0.06));
}
.on__step:last-child::before { display: none; }
.on__stepno {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border-accent, rgba(255, 44, 44, 0.75));
  background: #101014;
  color: #fff;
  font-family: var(--type-family-display), "Zalando Sans", "DM Sans", sans-serif;
  font-weight: 900;
  font-size: 1.125rem;
  line-height: 1;
}
.on__steph {
  margin: 10px 0 6px;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.25;
  text-wrap: balance;
}
.on__stept {
  margin: 0;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 0.9688rem;
  line-height: 1.65;
  text-wrap: pretty;
}

@media (min-width: 900px) {
  .on__steps { grid-template-columns: repeat(4, 1fr); gap: 24px; }
  .on__step { grid-template-columns: 1fr; gap: 0; }
  /* szyna pozioma na wysokości środka numeru */
  .on__step::before {
    left: 44px;
    right: -24px;
    top: 21px;
    bottom: auto;
    width: auto;
    height: 2px;
    background: linear-gradient(90deg, rgba(255, 44, 44, 0.4), rgba(255, 255, 255, 0.06));
  }
}

/* Uczciwość obietnic: „kiedy efekty" bez podawania terminu */
.on__note {
  margin-top: clamp(32px, 4vw, 48px);
  padding: clamp(24px, 3vw, 32px);
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
  border-left: 2px solid var(--accent-default, #ff2c2c);
  border-radius: 0 18px 18px 0;
  background: rgba(255, 255, 255, 0.03);
}
.on__noteh {
  margin: 0 0 8px;
  color: #fff;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.3;
}
.on__notet {
  margin: 0;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 1rem;
  line-height: 1.7;
  max-width: 62ch;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   DLA KOGO JESTEŚMY — pas logotypów jako dowód rozpiętości (bez progu wielkości).
   Sam mechanizm przewijania siedzi w styles.css (.clients__), tu tylko odstępy.
   -------------------------------------------------------------------------- */
.on__wall { margin-top: clamp(28px, 4vw, 40px); }

/* --------------------------------------------------------------------------
   SKĄD JESTEŚMY — tekst + mapa Polski.
   -------------------------------------------------------------------------- */
.on__fromgrid {
  display: grid;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}
@media (min-width: 900px) {
  .on__fromgrid { grid-template-columns: 1fr 1fr; }
}
.on__fromtext .on__lead:last-child { margin-bottom: 0; }

.on__mapa {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: 520px;
}
/* poświata pod mapą — na czerni daje jej głębię, sama mapa jest tylko konturem */
.on__mapa::before {
  content: "";
  position: absolute;
  inset: 8% 12%;
  border-radius: 50%;
  background: radial-gradient(ellipse at 30% 65%, rgba(255, 44, 44, 0.16), rgba(255, 44, 44, 0) 65%);
  pointer-events: none;
}
.mapa__svg { position: relative; display: block; width: 100%; height: auto; }

/* Ruch WŁĄCZAMY dopiero wtedy, gdy przeglądarka nie prosi o mniej animacji.
   Stan domyślny (bez animacji) = mapa gotowa i widoczna, więc nikt nie zobaczy
   pustego miejsca, jeśli animacja się nie odpali. */
@media (prefers-reduced-motion: no-preference) {
  /* kontur Polski rysuje się w miarę przewijania strony (bez JavaScriptu).
     Przeglądarka, która nie zna „animation-timeline", odtworzy to raz przy
     wczytaniu i zostawi mapę narysowaną — czyli w stanie docelowym. */
  /* Zakres CELOWO kończy się w fazie „entry": rysowanie ma być gotowe w chwili,
     gdy mapa w całości wejdzie na ekran. Przy zakresie sięgającym dalej ktoś, kto
     zatrzyma przewijanie w połowie, widziałby przerwany kontur Polski i czytałby
     to jako usterkę, nie jako efekt. */
  .mapa__kontur {
    animation: mapa-rysuj 1.6s ease-out forwards;
    animation-timeline: view();
    animation-range: entry 10% entry 90%;
  }
  .mapa__znak {
    animation: mapa-pojaw 1s ease-out forwards;
    animation-timeline: view();
    animation-range: entry 55% entry 100%;
  }
  /* sygnał radaru na Wrocławiu */
  .mapa__fala {
    transform-box: fill-box;
    transform-origin: center;
    animation: mapa-fala 3.2s ease-out infinite;
  }
  .mapa__fala--pozniej { animation-delay: 1.6s; }
}

@keyframes mapa-rysuj {
  from { stroke-dasharray: 1; stroke-dashoffset: 1; }
  to { stroke-dasharray: 1; stroke-dashoffset: 0; }
}
@keyframes mapa-pojaw {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes mapa-fala {
  0% { transform: scale(1); opacity: 0.7; }
  70% { transform: scale(3.4); opacity: 0; }
  100% { transform: scale(3.4); opacity: 0; }
}

/* ==========================================================================
   15. (WOLNE) — dowód na /kontakt/ przeniesiony do sekcji 13 (redesign sesja 28):
   ocena Google usunięta na życzenie Karola; statyczny rząd logotypów zastąpiony
   przewijanym pasem (.clients__ z home) + twardymi liczbami (.kt-num).
   Warstwa dowodu na /blog/ ma własne klasy poniżej (16.).
   ========================================================================== */

/* ==========================================================================
   16. WPIS „NA START" (.feat) — wyróżniony wpis na górze /blog/
   adwise ma „Najczęściej czytany". My NIE znamy statystyk czytań, więc nie
   udajemy liczby — to uczciwie „polecany na start" (wybór redakcji), a nie
   fałszywy pomiar. Blok tekstowy: 59 ze 130 wpisów nie ma zdjęcia.
   ========================================================================== */

.feat-sec { padding-bottom: clamp(20px, 3vh, 36px); }
/* Dwie kolumny: duża miniaturka 16:9 z lewej, treść z prawej. Zdjęcie „wpuszczone"
   w kartę (niewielki margines dookoła) — czerwona poświata AW zostaje widoczna. */
.feat {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(24px, 3vw, 44px);
  align-items: center;
  position: relative;
  padding: clamp(18px, 2.2vw, 26px);
  border: 1px solid var(--border-accent, rgba(255, 44, 44, 0.75));
  border-radius: 24px;
  background: radial-gradient(ellipse 80% 130% at 12% 0%, rgba(255, 44, 44, 0.12), rgba(255, 44, 44, 0.02) 68%);
  text-decoration: none;
  color: inherit;
  transition: transform 0.22s ease, border-color 0.22s ease;
}
.feat:hover { transform: translateY(-3px); }

.feat__media {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  background: #0c0c0e;
}
.feat__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.feat__content { min-width: 0; padding: clamp(6px, 1vw, 16px) clamp(6px, 1.2vw, 18px); }

/* Bezpieczna gałąź: gdyby wyróżniony wpis kiedyś nie miał zdjęcia — kafelek AW.
   Wyróżniony ma zdjęcie, więc w praktyce się nie pokazuje. Tytuł na kafelku chowamy
   (H2 jest po prawej), zostaje sygnet + kategoria. */
.feat__media .card__fbtitle { display: none; }

/* TELEFON: kolumna treści szeroka, zdjęcie na górze. */
@media (max-width: 820px) {
  .feat { grid-template-columns: 1fr; gap: clamp(16px, 3vw, 24px); }
  .feat__content { padding: 4px 6px 8px; }
}

.feat__top { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 18px; }
.feat__tag {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--accent-default, #ff2c2c);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.feat__cat {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted, rgba(255, 255, 255, 0.56));
}
.feat__title {
  font-family: var(--type-family-body), "DM Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.25rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 14px;
  max-width: 26ch;
  text-wrap: balance;
}
.feat__excerpt {
  margin: 0 0 22px;
  color: var(--text-body, rgba(255, 255, 255, 0.8));
  font-size: 1.0625rem;
  line-height: 1.65;
  max-width: 62ch;
  text-wrap: pretty;
}
.feat__go {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: #fff;
  font-weight: 600;
  font-size: 1rem;
}
.feat__go svg { width: 18px; height: 18px; transition: transform 0.22s ease; }
.feat:hover .feat__go svg { transform: translateX(3px); }

/* ==========================================================================
   17. PODMIANA LISTY BLOGA BEZ PRZEŁADOWANIA (sesja 36)
   (Poprzednia sekcja 17 — dolne CTA listy .blog-cta* — usunięta w całości,
   decyzja Karola.)
   Skrypt w content.js po kliknięciu filtra lub paginacji pobiera docelową stronę
   w tle i podmienia zawartość [data-swap-root]. Na czas pobierania lista lekko
   gaśnie — czytelny sygnał „coś się dzieje" bez skoku układu. Bez JavaScriptu
   klasa .is-swapping nigdy się nie pojawia, odnośniki działają normalnie.
   ========================================================================== */
/* overflow-anchor: none — przeglądarka „kotwiczy" pozycję przewijania do elementu
   w kadrze i przy zmianach treści potrafi sama korygować scroll; przy podmienianym
   bloku (i doładowujących się miniaturkach) wolimy pełną kontrolę w skrypcie. */
[data-swap-root] { transition: opacity 0.15s ease; overflow-anchor: none; }
[data-swap-root].is-swapping { opacity: 0.45; }
/* wrapper dostaje focus() po podmianie (dla czytników ekranu) — bez wizualnej ramki
   wokół całej listy; to fokus programowy (tabindex="-1"), nie klawiaturowy */
[data-swap-root]:focus { outline: none; }

/* ==========================================================================
   WSPOLNA SKALA STRONY na /kontakt/ (30.07.2026, v1)
   Te same siedem stopni co na podstronach uslugowych — przypiete do .kt,
   zeby nie ruszyc bloga i case study (dziela ten plik).
   Przypisanie po ROLI W TRESCI: co zawiera inne naglowki, jest od nich wieksze.
   Przed zmiana strona miala 12 rozmiarow liter (13·14·15·16·17·18·19·20·21·25,6·32·46).
   Uzasadnienie: docs/aw/RESEARCH-WYGLAD-WSPOLNY-v1.md sekcja 1b — ten sam
   naglowek mial na kazdej podstronie inny rozmiar i to bylo zrodlo problemu.
   ========================================================================== */

/* --- 1. TEKST DO CZYTANIA (najpierw, zeby dalsze reguly mogly nadpisac) --- */
.kt p,
.kt li,
.kt .faq__a,
.kt .faq__introtxt,
.kt .kt-time__t { font-size: var(--skala-tekst); line-height: 1.65; }

/* --- 2. ETYKIETY: oznaczenia, dane pomocnicze, przyciski --- */
.kt .zgl__label,
.kt .zgl__btn,
.kt .btn,
.kt .kt-hero__prole,
.kt .kt-hero__contact a,
.kt .kt-hero__plinks a,
.kt .footer__addr { font-size: var(--skala-etykieta); line-height: 1.5; }

/* --- 3. PODPISY — najnizszy stopien dla tekstu do czytania --- */
.kt .kt-proof__head,
.kt .conv__zgoda,
.kt .conv__zgoda a,
.kt .kt-time__no { font-size: var(--skala-podpis); }

/* --- 4. TYTUL POJEDYNCZEGO ELEMENTU: krok, pytanie, tytul grupy danych --- */
.kt .kt-time__h,
.kt .faq__q,
.kt .kt-h3 { font-size: var(--skala-wstep); font-weight: 700; line-height: 1.3; }

/* nazwisko opiekuna stoi NAD jego rolą (15 px), wiec o stopien wyzej */
.kt .kt-hero__pname { font-size: var(--skala-tekst); font-weight: 700; line-height: 1.25; }

/* --- 5. TYTUL SEKCJI — zawiera tytuly krokow i pytan, wiec jest od nich wiekszy --- */
.kt .faq__h { font-size: var(--skala-h2); font-weight: 700; line-height: 1.12; }

/* „Co sie stanie, gdy zostawisz kontakt?" — 06.08 zeszlo ze stopnia TYTUL SEKCJI (46 px)
   na TYTUL GRUPY (28 px). Karol: „zbyt duzy font, gryzie sie z »Zarezerwuj spotkanie«
   — to jest naglowek glowny". Powod byl w przypisaniu roli: ten napis nie stoi sam
   nad sekcja, tylko OBOK tytulu podstrony, w tym samym rzedzie siatki, i zawiera
   piec tytulow krokow (21 px) — czyli jest tytulem grupy, nie tytulem sekcji.
   Przy 46 px w dwoch wierszach zajmowal tyle samo wysokosci, co jednowierszowy
   tytul 68 px, wiec czytal sie jak drugi naglowek glowny. */
.kt .kt-proc__h { font-size: var(--skala-grupa); font-weight: 700; line-height: 1.2; }

/* --- 6. TYTUL PODSTRONY — ten sam co na podstronach uslugowych --- */
.kt .kt-hero__h1 { font-size: var(--skala-h1); font-weight: 700; line-height: 1.08; }

/* --- tablet --- */
@media (max-width: 860px) {
  .kt { --skala-h1: 44px; --skala-h2: 34px; --skala-grupa: 24px;
        --skala-wstep: 19px; --skala-tekst: 17px; }
}
/* --- telefon --- */
@media (max-width: 480px) {
  .kt { --skala-h1: 36px; --skala-h2: 29px; --skala-grupa: 22px;
        --skala-wstep: 18px; --skala-tekst: 16px; --skala-etykieta: 14px; }
}

/* ==========================================================================
   WSPOLNA SKALA STRONY — BLOG (30.07.2026, v1)
   Te same siedem stopni co na podstronach uslugowych i /kontakt/.
   Przypisanie po ROLI: co zawiera inne naglowki, jest od nich wieksze.
   Przed zmiana wpis blogowy mial 16 rozmiarow liter
   (11·12·13·13,6·14·14,4·15·16·17·18·20·21·22·30·32·52).
   Uzasadnienie: docs/aw/RESEARCH-WYGLAD-WSPOLNY-v1.md sekcja 1b.
   ========================================================================== */

/* --- 1. TEKST DO CZYTANIA (najpierw, zeby dalsze reguly mogly nadpisac) --- */
.post .art,
.post .art p,
.post .art li,
.post .art blockquote,
.post .art td,
.post .faq__a,
.post .faq__introtxt { font-size: var(--skala-tekst); line-height: 1.65; }

/* --- 2. ETYKIETY: oznaczenia, dane pomocnicze, przyciski --- */
.post .toc a,
.post .post__role,
.post .post__authorname,
.post .authorcard__role,
.post .authorcard__link,
.post .post-cta__prole,
.post .post-cta__btn,
.post .btn,
.feat__cat,
.feat__go,
.feat__excerpt,
.card__excerpt { font-size: var(--skala-etykieta); line-height: 1.5; }

/* --- 3. PODPISY --- */
.post .crumbs,
.post .crumbs a,
.filter__count,
.post .post__cat,
.post .toc__h,
.post .share__label,
.post .authorcard__eyebrow,
.card__cat,
.card__meta,
.feat__tag { font-size: var(--skala-podpis); }

/* --- 4. TYTUL POJEDYNCZEGO ELEMENTU: karta, pytanie, imie opiekuna --- */
.post .faq__q,
.card__title,
.feat__title,
.post .authorcard__name,
.post .post-cta__pname { font-size: var(--skala-wstep); font-weight: 700; line-height: 1.3; }

/* --- 5. TYTUL GRUPY: podrozdzial artykulu, panel zachety --- */
.post .art h3,
.post .art h4,
.post .post-cta__h { font-size: var(--skala-grupa); font-weight: 700; line-height: 1.22; }

/* --- 6. TYTUL SEKCJI: rozdzial artykulu, "Przeczytaj tez", pytania --- */
.post .art h2,
.post .related__h,
.post .faq__h { font-size: var(--skala-h2); font-weight: 700; line-height: 1.12; }

/* --- 7. TYTUL PODSTRONY --- */
.post .post__title { font-size: var(--skala-h1); font-weight: 700; line-height: 1.08; }

/* naglowki w tresci artykulu czesto przychodza z WordPressa owiniete w <strong>
   — bez tego <strong> nadawal wlasna grubosc i rozmiar */
.post .art h2 strong,
.post .art h3 strong,
.post .art h4 strong { font-size: 1em; font-weight: inherit; }

/* --- tablet --- */
@media (max-width: 860px) {
  .post, .feat, .card { --skala-h1: 44px; --skala-h2: 34px; --skala-grupa: 24px;
                        --skala-wstep: 19px; --skala-tekst: 17px; }
}
/* --- telefon --- */
@media (max-width: 480px) {
  .post, .feat, .card { --skala-h1: 36px; --skala-h2: 29px; --skala-grupa: 22px;
                        --skala-wstep: 18px; --skala-tekst: 16px; --skala-etykieta: 14px; }
}

/* TYTUŁ WPISU NA TELEFONIE — 35 px zamiast 36 px (etap 4, pomiar na 139 wpisach).
   Powód jest arytmetyczny, nie estetyczny: nazwę „Agencja Wrocławska" sklejamy
   twardą spacją (nazwa firmy nie ma się łamać na dwie linijki). Przy 36 px ta
   sklejona para ma 355 px, a linijka na ekranie 390 px ma 350 px — w 7 wpisach
   koniec nazwy wychodził poza ekran i był niewidoczny. 35 px daje 345 px, czyli
   5 px zapasu. Różnicy jednego piksela nie widać, ucięcia — widać.

   `overflow-wrap` to zabezpieczenie na przyszłość: gdyby w tytule trafiła się
   dłuższa sklejona nazwa (np. „Google Business Profile" ma przy tym piśmie
   ~450 px), lepiej żeby złamała się brzydko, niż zniknęła za krawędzią ekranu.
   Przy dzisiejszych tytułach ta reguła nie robi NIC — sprawdzone pomiarem. */
@media (max-width: 430px) {
  .post .post__title { font-size: 35px; overflow-wrap: break-word; }
}

/* ==========================================================================
   WSPOLNA SKALA STRONY — CASE STUDY i /o-nas/ (30.07.2026, v1)
   Te same siedem stopni. Przypisanie po ROLI: co zawiera inne naglowki,
   jest od nich wieksze. Przed zmiana: case study 11 rozmiarow, /o-nas/ 14.
   Uzasadnienie: docs/aw/RESEARCH-WYGLAD-WSPOLNY-v1.md sekcja 1b.
   ========================================================================== */

/* --- 1. TEKST DO CZYTANIA (najpierw) --- */
.cs p, .cs li, .cs dd,
.on p, .on li,
.on__stept, .on__notet, .on__lead,
.ccard__branza,
.conv__lead { font-size: var(--skala-tekst); line-height: 1.65; }

/* --- 2. ETYKIETY --- */
.ccard__lab,
.zgl__label, .zgl__btn, .conv__persontxt,
.lhead__count, .filter__pill,
.cs .btn, .on .btn, .cs__lab, .on__numl,
.on .on__more, .on .on__more a { font-size: var(--skala-etykieta); line-height: 1.5; }

/* --- 3. PODPISY --- */
.ccard__svc,
.cs__eyebrow, .cs__kwlab, .cs__ctanote,
.cs .crumbs, .cs .crumbs a,
.cs dt, .on__numw,
.zgl__legal, .zgl__legal a { font-size: var(--skala-podpis); }

/* --- 4. TYTUL POJEDYNCZEGO ELEMENTU: krok, tytul formularza --- */
.cs__steph, .on__steph,
.zgl__h,
.lhead__lead { font-size: var(--skala-wstep); font-weight: 700; line-height: 1.3; }
.on .lhead__lead, .cs .lhead__lead, .lhead__lead {
  font-size: var(--skala-wstep); font-weight: 400; line-height: 1.5;
}

/* --- 5. TYTUL GRUPY: nazwa klienta i liczba-bohater na karcie realizacji.
       28 px, a nie 48: liczba w starym rozmiarze byla 2,3x wieksza od sasiedniego
       napisu. Zasada Karola: wielka liczba nie moze miazdzyc tego, co obok
       (najwyzej ~2x). Teraz liczba i nazwa klienta sa w tym samym stopniu — to sa
       dwie rzeczy tej samej wagi: KTO i ILE (kierunek B, 31.07). --- */
.ccard__num, .on__numv { font-size: var(--skala-grupa); font-weight: 900; line-height: 1.1; }
.ccard__client { font-size: var(--skala-grupa); font-weight: 700; line-height: 1.15; }

/* --- 6. TYTUL SEKCJI --- */
.cs__h2, .on__h2,
.cs .related__h, .on .related__h,
.conv__h { font-size: var(--skala-h2); font-weight: 700; line-height: 1.12; }

/* liczba-bohater w naglowku realizacji: stopien nizej niz tytul podstrony,
   zeby z nim nie konkurowala (bylo 64 px przy tytule 48 px — liczba wygrywala) */
.cs__num { font-size: var(--skala-h2); font-weight: 900; line-height: 1; }

/* naglowek W KARCIE to tytul grupy, nie tytul sekcji: karta ma ~610 px,
   przy 46 px napis mial trzy wiersze i przytlaczal tekst obok (46/17 = 2,7x).
   Zasada: to samo .on__h2 pelni dwie role — decyduje pojemnik, nie nazwa klasy. */
.on__carebox .on__h2 { font-size: var(--skala-grupa); line-height: 1.22; }

/* --- 7. TYTUL PODSTRONY --- */
.cs__title, .lhead__h { font-size: var(--skala-h1); font-weight: 700; line-height: 1.08; }
/* Zabezpieczenie: ograniczenie dlugosci wiersza liczy sie w ZNAKACH (ch), a znak
   rosnie razem z literami — po podniesieniu tytulu do 68 px limit 20-24 znakow
   robi sie szerszy niz pojemnik. min(...,100%) zostawia limit dlugosci wiersza,
   ale nigdy nie przekracza pojemnika.
   UWAGA: to NIE bylo zrodlo rozpychania naglowkow z 30.07 — prawdziwa przyczyna
   byla nieaktualna mapa pojemnosci wierszy (src/lib/mapa-typografii.json),
   przeliczona ponownie po zmianie skali. */
.post .post__title { max-width: min(20ch, 100%); }
.cs .cs__title { max-width: min(24ch, 100%); }
.lhead__h { max-width: min(26ch, 100%); }

/* --- CYFRA W KÓŁKU = oznaczenie kroku, nie podpis (uwaga Karola 31.07) ---
   Pomiar wszystkich naszych kółek z numerem (scripts/kolka-pomiar.mjs, okno 1440):

     miejsce                 średnica  cyfra   udział
     /kontakt/ oś czasu        52 px    13 px    25%   ← Karol: za mała
     /case-study/ kroki        40 px    13 px  32,5%   ← Karol: za mała
     /o-nas/ oś                44 px    18 px    41%   nie zgłoszona
     /audyt-seo/ zakres        34 px    15 px    44%   nie zgłoszona
     /pozycjonowanie/ pozycje  26 px    13 px    50%   nie zgłoszona
     jeton.com (wzór)          24 px    14 px    58%

   Granica jest widoczna w danych: wszystko poniżej 40% średnicy Karol zgłosił,
   wszystko powyżej — nie. Stąd reguła: cyfra w kółku ≥40% średnicy kółka.
   Jeden stopień skali (wstęp, 21 px) pokrywa wszystkie nasze kółka 40–52 px
   i daje 40–53% — bez wymyślania osobnej wartości dla każdej strony.
   Kółka zostają w swoich rozmiarach: rosną cyfry, nie okręgi. */
.kt .kt-time__no,
.cs__stepno,
.on__stepno { font-size: var(--skala-wstep); }


/* --- tablet --- */
@media (max-width: 860px) {
  .cs, .on, .ccard, .conv, .lhead { --skala-h1: 44px; --skala-h2: 34px; --skala-grupa: 24px;
                                    --skala-wstep: 19px; --skala-tekst: 17px; }
}
/* --- telefon --- */
@media (max-width: 480px) {
  .cs, .on, .ccard, .conv, .lhead { --skala-h1: 36px; --skala-h2: 29px; --skala-grupa: 22px;
                                    --skala-wstep: 18px; --skala-tekst: 16px; --skala-etykieta: 14px; }
}
