/* tp_atelier — assets/css/styles.css
   PLIK GENEROWANY z partiali w template-parts/scss.
   Nie edytuj go ręcznie — poprawki idą do partiala, potem:
   python3 narzedzia/zbuduj-arkusz.py
   Kolejność partiali: main.scss */

/*
 * Kroje hostowane lokalnie — zero połączeń do CDN Google.
 *
 * Powód jest podwójny: RODO (brak wysyłania adresu IP czytelnika do
 * Google przy każdym wejściu) oraz wydajność — arkusz z fonts.googleapis.com
 * blokował renderowanie i kosztował dodatkowe połączenie do drugiego hosta.
 *
 * Subsety: latin + latin-ext (polskie znaki diakrytyczne są w latin-ext).
 * Pliki wygenerowane przez tools/makieta/fonts.cjs — nie edytować ręcznie.
 *
 * Lora i Public Sans są na licencji SIL Open Font License 1.1.
 */

/* ==========================================================================
   ATELIER — motyw blogowy moda / uroda dla sieci Traffic Peaks
   Makieta koncepcyjna. Nazwa robocza motywu: tp-atelier
   (nie `tp_theme_maker` — patrz pułapka podmiany src→data-src w TP WP plugin).

   Kolejność sekcji: tokeny → reset → typografia → układ → nagłówek →
   ściana (masonry) → kafel → sekcje strony głównej → archiwum → wpis →
   panel boczny → dane (skaner, rankingi, quiz) → stopka → panel kolorów → druk.

   Konfigurowalne są DWA kolory: --brand i --accent. Cała reszta palety
   liczy się z nich przez color-mix(). Szarości są stałe i nie podlegają
   konfiguracji, żeby bloga nie dało się zepsuć jednym kliknięciem.
   Bez trybu dzień/noc — jeden dopracowany wygląd.
   ========================================================================== */

/* ==========================================================================
   1. TOKENY
   ========================================================================== */

:root {
  /* --- DWA KOLORY Z CUSTOMIZERA ----------------------------------------- */
  --brand:  #5C2E3E;   /* śliwka   — identyfikacja, linki, nagłówki sekcji */
  --accent: #C0693F;   /* terakota — wyróżnienia, dane, stany aktywne      */

  /* Kolor tekstu NA kolorze liczy PHP z luminancji (w makiecie: app.js),
     więc przycisk zdaje WCAG AA niezależnie od tego, co wybierze klient.   */
  --brand-ink:  #fff;
  --accent-ink: #fff;

  /* --- pochodne — nic do ustawiania ręcznie ------------------------------ */
  --brand-900: color-mix(in oklab, var(--brand), #000 42%);
  --brand-700: color-mix(in oklab, var(--brand), #000 18%);
  --brand-300: color-mix(in oklab, var(--brand), #fff 55%);
  --brand-100: color-mix(in oklab, var(--brand), #fff 88%);
  --brand-050: color-mix(in oklab, var(--brand), #fff 95%);

  --accent-900: color-mix(in oklab, var(--accent), #000 40%);
  --accent-700: color-mix(in oklab, var(--accent), #000 18%);
  --accent-300: color-mix(in oklab, var(--accent), #fff 58%);
  --accent-100: color-mix(in oklab, var(--accent), #fff 88%);
  --accent-050: color-mix(in oklab, var(--accent), #fff 95%);

  /* akcent bywa jasny (musztarda, limonka) — wersja czytelna na papierze */
  --brand-text:  color-mix(in oklab, var(--brand), #000 12%);
  --accent-text: color-mix(in oklab, var(--accent), #000 30%);

  /* --- neutralne (stałe) ------------------------------------------------- */
  --paper:   #FFFFFF;
  --paper-2: #FAF9F7;   /* ciepła kość słoniowa — tło sekcji              */
  --paper-3: #F1EEEA;
  --ink:     #16141A;
  --ink-2:   #4A4650;
  --ink-3:   #6E6973;
  --rule:    #E6E2DD;
  --rule-2:  #D3CDC6;

  /* --- semantyczne ------------------------------------------------------- */
  --ok:   #2C6B4F;
  --uwaga:#8A5A12;
  --stop: #A32C1F;
  --mit:  #4A5A8A;

  /* --- kroje (hostowane lokalnie — zero połączeń do CDN Google) ---------- */
  --font-serif: 'Lora', Georgia, 'Times New Roman', serif;
  --font-sans:  'Public Sans', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --font-mono:  ui-monospace, 'Cascadia Mono', Consolas, monospace;

  /* --- skala typograficzna ---------------------------------------------- */
  --fs-masthead: clamp(2.4rem, 7vw, 4.6rem);
  --fs-display:  clamp(2rem, 4.2vw, 3.4rem);
  --fs-h1:       clamp(1.75rem, 3.2vw, 2.6rem);
  --fs-h2:       clamp(1.35rem, 2.2vw, 1.85rem);
  --fs-h3:       clamp(1.1rem, 1.5vw, 1.3rem);
  --fs-lead:     clamp(1.0625rem, 1.4vw, 1.1875rem);
  --fs-body:     1.0625rem;
  --fs-sm:       0.875rem;
  --fs-xs:       0.75rem;
  --fs-micro:    0.6875rem;

  /* --- siatka 8 pt ------------------------------------------------------- */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;
  --s9: 96px; --s10: 128px;

  --wrap: 1360px;
  /* Miara kolumny tekstu. 720 px przy akapicie 17 px to 84 znaki w wierszu —
     powyżej progu, na którym oko gubi początek następnej linii (wygodnie
     czyta się 45–75). 620 px daje ~72 znaki i tyle zostaje. Jednostka ch nie
     nadaje się tutaj: liczy się od kroju .tresc, a akapity mają własny. */
  --wrap-tekst: 620px;

  /* --- ściana zdjęć ------------------------------------------------------ */
  --rytm: 8px;          /* wysokość jednego wiersza siatki masonry */
  --przerwa: 20px;      /* odstęp między kaflami                   */
  --kolumny: 4;

  --radius: 2px;
  --cien-1: 0 1px 2px rgba(22, 20, 26, .05);
  --cien-2: 0 4px 24px rgba(22, 20, 26, .10);
  --cien-3: 0 24px 64px rgba(22, 20, 26, .20);

  --ease: cubic-bezier(.22, .68, .3, 1);
}

/* ==========================================================================
   2. RESET
   ========================================================================== */

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

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

@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

img { height: auto; }

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

button { cursor: pointer; }

/* Hover NIE zmienia koloru tekstu. Zmiana barwy na kafelku ze zdjęciem
   robiła z białego tytułu ciemny napis na ciemnym kadrze — nieczytelny.
   Sygnałem najechania jest podkreślenie, które działa na każdym tle.      */

a { color: var(--brand-text); text-decoration-thickness: 1px; text-underline-offset: 3px; }

a:hover { text-decoration-thickness: 2px; }

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 1px;
}

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--ink); color: #fff; padding: var(--s3) var(--s5);
  font-size: var(--fs-sm);
}

.skip:focus { left: 0; }

.tylko-czytnik {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ==========================================================================
   3. TYPOGRAFIA
   ========================================================================== */

h1, h2, h3, h4 {
  font-family: var(--font-serif);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.012em;
  margin: 0;
  text-wrap: balance;
}

/* Baza rytmu, a po niej wyjątki. Wszystkie mają tę samą specyficzność,
   więc decyduje kolejność — od ogólnego do szczegółowego.            */

.tresc > * + * { margin-top: var(--s6); }

@media print {
  .nawigacja, .cfg, .baner, .baner-top, .panel, .pasek-czytania, .do-gory,
  .kafel--wiecej, .sek-glowa__link, .stopka__linki, .okruszki {
    display: none !important;
  }

  /* Druk czyta się z kartki: czarny tekst na bieli, bez tła i cieni. */
  :root { --paper: #fff; --paper-2: #fff; --ink: #000; --ink-2: #222; }
  body { background: #fff; color: #000; }
  .wrap, .wrap--wpis { width: auto; max-width: none; padding: 0; }
  .kafel, .karta, .cytat, .nota { box-shadow: none; break-inside: avoid; }
  img { max-width: 100%; }

  /* Adres linku obok treści — na papierze sam podkreślnik nic nie mówi. */
  .tresc a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 90%; }

  h1, h2, h3 { break-after: avoid; }
  p, li, figure { orphans: 3; widows: 3; }
}

/* Slot banerowy 1150×90 / 728×90 / 300×50 — wymiary z Journala.
   Gdy kampanii nie ma, motyw nie wypisuje slotu w ogóle: ani piksela.       */

.baner {
  display: flex; align-items: center; justify-content: center;
  margin: var(--s5) auto 0;
  border: 1px dashed var(--rule-2); background: var(--paper-2);
  color: var(--ink-3); font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .18em;
}

/* KREACJA NIGDY NIE WYCHODZI POZA SWÓJ SLOT.

   Reguła bazowa `img { height: auto }` liczy wysokość z PROPORCJI PLIKU,
   nie z wymiarów slotu. Kreacja 300×50 wstawiona w slot 1150×90 dostawała
   przez to 1148×191 i wychodziła 101 px poniżej ramki — prosto na winietę
   (zmierzone na zantalo.pl). `contain` w granicach slotu sprawia, że
   najgorsze, co może zrobić kreacja w złym formacie, to zostawić wolne
   miejsce po bokach. Właściwą naprawą jest podanie kreacji we właściwym
   formacie — to jest bezpiecznik na wypadek, gdy wydawca tego nie zrobi. */

.baner img,
.baner picture {
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  object-fit: contain;
}

.baner--1150 { width: 1150px; height: 90px; }

.baner--728 { width: 728px; height: 90px; }

.baner--300 { width: 300px; height: 50px; }

/* Maszt: JEDEN slot, którego wymiary zmieniają się z szerokością okna.
   Formatem kreacji steruje `<picture>` w atl_baner_masztu() — progi
   `min-width` tam są o piksel większe od tutejszych `max-width`, bo pytają
   o drugą stronę tej samej granicy. ATL_MASZT_PROG_* w inc/stale.php
   pilnuje, żeby obie pary liczb zostały razem. */

.baner-top { display: flex; justify-content: center; }

.baner-top__slot { width: 1150px; height: 90px; }

@media (max-width: 1210px) {
  .baner-top__slot { width: 728px; }
}

@media (max-width: 780px) {
  .baner-top__slot { width: 300px; height: 50px; }
}

.naglowek { background: var(--paper); }

.winieta {
  display: grid; justify-items: center; gap: var(--s2);
  padding-block: var(--s6) var(--s5);
  text-align: center;
}

/* Winieta na stronie głównej jest nagłówkiem h1, ale ma wyglądać tak samo
   jak link na pozostałych stronach — dlatego zeruje własną typografię. */

.winieta__h1 { margin: 0; font: inherit; line-height: inherit; }

.winieta__logo {
  font-family: var(--font-serif);
  font-size: var(--fs-masthead);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: .95;
  color: var(--ink);
  text-decoration: none;
}

.winieta__logo em {
  font-style: italic;
  font-weight: 400;
  color: var(--brand);
}

.winieta__motto {
  font-size: var(--fs-micro); letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-3);
}

/* Nawigacja — dwie cienkie linie i litery rozstrzelone jak w magazynie */

.nawigacja {
  border-block: 1px solid var(--ink);
  position: sticky; top: 0; z-index: 40;
  background: var(--paper);
}

.nawigacja__inner { display: flex; align-items: center; justify-content: center; gap: var(--s6); position: relative; }

.nawigacja__lista {
  display: flex; gap: var(--s6); list-style: none; margin: 0; padding: 0;
  flex-wrap: wrap; justify-content: center;
}

.nawigacja__link {
  display: block; padding: var(--s3) 0;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; text-decoration: none; color: var(--ink);
  position: relative;
}

.nawigacja__link::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--brand); transform: scaleX(0);
  transition: transform .25s var(--ease); transform-origin: left;
}

.nawigacja__link:hover::after,
.nawigacja__link[aria-current]::after { transform: scaleX(1); }

/* Slot sprzedażowy w menu. Kropka przed nazwą odróżnia go od działów bloga
   bez krzykliwej etykiety — czytelniczka widzi, że to inny rodzaj pozycji. */

.nawigacja__link--sprzedazowy { color: var(--ink-3); }

.nawigacja__link--sprzedazowy::before {
  content: ''; display: inline-block;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); margin-right: 7px; vertical-align: 1px;
}

.nawigacja__link--sprzedazowy:hover { color: var(--ink); }

/* --- PODMENU (drugi poziom Wygląd → Menu) -----------------------------
   Pozycja z dziećmi zachowuje własny link — kategoria nadrzędna musi być
   klikalna. Rozwijaniem steruje osobny przycisk obok, bo na dotyku
   „najechanie" nie istnieje i pierwsze dotknięcie linku tylko
   otwierałoby listę zamiast wejść w kategorię.                          */

.nawigacja__poz { position: relative; display: flex; align-items: center; }

.nawigacja__rozwin {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 44px; padding: 0; margin-left: 2px;
  border: 0; background: none; color: var(--ink-3);
}

.nawigacja__rozwin svg { width: 12px; height: 12px; transition: transform .2s var(--ease); }

.nawigacja__poz--ma-pod:hover .nawigacja__rozwin svg,
.nawigacja__rozwin[aria-expanded="true"] svg { transform: rotate(180deg); }

.podmenu {
  position: absolute; top: 100%; left: calc(var(--s4) * -1);
  min-width: 220px; margin: 0; padding: var(--s3) 0;
  list-style: none; z-index: 50;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brand);
  box-shadow: var(--cien-2);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s var(--ease), transform .18s var(--ease), visibility 0s linear .18s;
}

.nawigacja__poz--ma-pod:hover .podmenu,
.nawigacja__poz--ma-pod:focus-within .podmenu,
.podmenu[data-otwarte="true"] {
  opacity: 1; visibility: visible; transform: none; transition-delay: 0s;
}

.podmenu__link {
  display: block; padding: var(--s2) var(--s5);
  font-size: var(--fs-sm); letter-spacing: .01em;
  text-transform: none; text-decoration: none; color: var(--ink-2);
}

.podmenu__link:hover { background: var(--brand-050); color: var(--ink); }

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

.nawigacja__narzedzia { position: absolute; right: 0; display: flex; gap: var(--s2); }

.ikonka {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 44px; height: 44px; padding: 0 var(--s2);
  border: 0; background: none; color: var(--ink);
  font-size: var(--fs-xs); font-weight: 700;
}

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

.menu-przelacz { display: none; }

@media (max-width: 900px) {
  .nawigacja__inner { justify-content: space-between; }
  .nawigacja__lista {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0; align-items: stretch;
    background: var(--paper); border-bottom: 1px solid var(--ink);
    padding: var(--s2) var(--s4) var(--s4);
    display: none;
  }
  .nawigacja[data-otwarte="true"] .nawigacja__lista { display: flex; }
  .nawigacja__poz { flex-wrap: wrap; }
  .nawigacja__poz .nawigacja__link { flex: 1; }
  .nawigacja__link { padding: var(--s3) 0; border-bottom: 1px solid var(--rule); letter-spacing: .1em; }
  /* Na wąskim ekranie podmenu nie wisi nad treścią — rozwija się w miejscu
     i przesuwa resztę listy w dół. Sterowanie tylko przyciskiem.        */
  .podmenu {
    position: static; opacity: 1; visibility: visible; transform: none; transition-delay: 0s;
    display: none; width: 100%; min-width: 0;
    border: 0; border-left: 2px solid var(--brand); box-shadow: none;
    margin: 0 0 var(--s2) var(--s3); padding: var(--s2) 0;
  }
  .podmenu[data-otwarte="true"] { display: block; }
  .nawigacja__poz--ma-pod:hover .podmenu { display: none; }
  .nawigacja__poz--ma-pod:hover .podmenu[data-otwarte="true"] { display: block; }
  .podmenu__link { padding: var(--s2) var(--s4); }
  .nawigacja__narzedzia { position: static; }
  .menu-przelacz { display: inline-flex; }
}

/* ==========================================================================
   7. ŚCIANA (masonry)

   Dlaczego nie `columns:` — układ wielokolumnowy CSS-a układa elementy
   w dół pierwszej kolumny, potem drugiej, więc kolejność czytania rozjeżdża
   się z kolejnością wizualną. To błąd WCAG 1.3.2 i chaos dla robota.
   Stąd CSS Grid + `grid-row-end: span N` liczone z proporcji kafla:
   kolejność DOM = kolejność wizualna = kolejność w indeksie.
   ========================================================================== */

.sciana {
  display: grid;
  grid-template-columns: repeat(var(--kolumny), minmax(0, 1fr));
  gap: var(--przerwa);
  align-items: start;
}

/* ==========================================================================
   MENU WIELOPOZIOMOWE — trzeci poziom i głębiej

   Makieta znała dwa poziomy: dział i podmenu wiszące pod nim. Ten motyw
   obsługuje dowolną głębokość z „Wygląd → Menu”, bo redakcja układa działy
   drzewem (Pielęgnacja → Twarz → Kwasy), a walker nie ma prawa uciąć
   gałęzi, której nie przewidział arkusz.

   Trzeci poziom NIE powtarza zachowania drugiego. Drugi spada w dół pod
   pozycję w pasku; trzeci wysuwa się w BOK, bo pod nim nie ma już miejsca
   w pasku, a spadanie w dół nakładałoby listę na listę.

   Mieszczenie się w oknie liczy skrypt (funkcja `ustawKierunki`
   w assets/js/scripts.js), nie arkusz: przy dziale stojącym z prawej
   strony paska panel wyjechałby za krawędź okna. Skrypt mierzy pozycję
   i przesuwa panel ujemnym marginesem o brakującą liczbę pikseli. Bez
   JS-a panel zostaje po prawej i w skrajnym przypadku wymaga przewinięcia
   — na węższych ekranach nie ma to zastosowania, bo tam wszystkie poziomy
   schodzą do akordeonu.
   ========================================================================== */

/* Pozycja podmenu, która ma własne dzieci — jak .nawigacja__poz, tylko
   o poziom niżej. Bez position:relative panel trzeciego poziomu liczyłby
   swoje left:100% od panelu drugiego, nie od wiersza. */
.podmenu__poz {
  position: relative;
  display: flex;
  align-items: stretch;
}

.podmenu__poz .podmenu__link {
  flex: 1;
  min-width: 0;
}

.podmenu__rozwin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-3);
}

/* Strzałka pokazuje kierunek wysuwania: w bok, nie w dół. */
.podmenu__rozwin svg {
  width: 12px;
  height: 12px;
  transform: rotate(-90deg);
  transition: transform .2s var(--ease);
}

.podmenu__poz:hover > .podmenu__rozwin,
.podmenu__rozwin[aria-expanded="true"] {
  color: var(--brand);
}

.podmenu--glebokie {
  top: calc(var(--s3) * -1);
  left: 100%;
  border-top: 2px solid var(--accent);
}

/* Gdy z prawej brakuje miejsca, skrypt (`atl_menu` w scripts.js) przesuwa
   panel ujemnym `margin-left` o dokładnie brakującą liczbę pikseli. Nie ma
   tu klasy „wysuń w lewo”: przerzucenie panelu na drugą stronę pozycji
   kładło go na liście, z której wyszedł, i ścieżka przestawała być
   czytelna. Bez JS panel zostaje po prawej i w skrajnym przypadku wymaga
   przewinięcia — czytelne, tylko niewygodne. */

.podmenu__poz:hover > .podmenu--glebokie,
.podmenu__poz:focus-within > .podmenu--glebokie,
.podmenu--glebokie[data-otwarte="true"] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* Czwarty poziom i dalej dostają ten sam wygląd co trzeci. Nie budujemy
   dla nich osobnych reguł — jeśli redakcja zejdzie tak głęboko, lepiej,
   żeby menu wyglądało nudno, niż żeby się rozsypało. Skrypt nadal je
   otwiera, bo działa na dowolnym `.podmenu` z przyciskiem. */
.podmenu .podmenu .podmenu {
  border-top-color: var(--rule-2);
}

/* --------------------------------------------------------------------------
   AKORDEON NA WĄSKIM EKRANIE

   Tu wszystkie poziomy zachowują się tak samo: rozwijają się w miejscu
   i przesuwają resztę listy w dół. Zagnieżdżenie widać po wcięciu i po
   kolorze kreski, a nie po kierunku wysuwania — na 360 px nie ma boku,
   w który dałoby się wysunąć cokolwiek.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .podmenu__poz { flex-wrap: wrap; }

  .podmenu--glebokie {
    position: static;
    display: none;
    width: 100%;
    min-width: 0;
    top: auto;
    left: auto;
    right: auto;
    margin: 0 0 var(--s2) var(--s4);
    padding: var(--s1) 0;
    border: 0;
    border-left: 2px solid var(--accent);
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  .podmenu--glebokie[data-otwarte="true"] { display: block; }

  /* Hover na dotyku „przykleja się” po tapnięciu i zostawiał otwartą listę,
     której nie da się zamknąć. Na tej szerokości steruje wyłącznie przycisk. */
  .podmenu__poz:hover > .podmenu--glebokie { display: none; }
  .podmenu__poz:hover > .podmenu--glebokie[data-otwarte="true"] { display: block; }

  .podmenu .podmenu .podmenu { border-left-color: var(--rule-2); }

  .podmenu__rozwin { width: 44px; }
  .podmenu__rozwin svg { transform: none; }
  .podmenu__rozwin[aria-expanded="true"] svg { transform: rotate(180deg); }
}

/* Kropka odróżniająca pozycję sprzedażową działa na każdym poziomie —
   link z wtyczki może wejść także do podmenu. */
.podmenu__link--sprzedazowy::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
}

/* Znacznik kategorii na kaflu i w treści */

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--brand-text); text-decoration: none;
}

.tag::before { content: ''; width: 14px; height: 1px; background: var(--brand); }

.tag--akcent { color: var(--accent-text); }

.tag--akcent::before { background: var(--accent); }

/* Plakietka AI — meta załącznika isAiGenerated (AI Act).
   Na liście dyskretny skrót, na stronie wpisu pełne zdanie —
   tak samo jak w Journalu, żeby sieć mówiła jednym głosem.                  */

.ai-chip {
  position: absolute; left: var(--s2); bottom: var(--s2); z-index: 2;
  font-family: var(--font-sans); font-size: 10px; font-weight: 700;
  letter-spacing: .1em; line-height: 1;
  padding: 4px 5px; border-radius: 2px;
  background: rgba(22, 20, 26, .62); color: #fff;
}

.ai-pelne {
  position: absolute; left: 0; bottom: 0; z-index: 2;
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .06em;
  padding: 6px var(--s3);
  background: rgba(22, 20, 26, .72); color: #fff;
}

/* ==========================================================================
   6. NAGŁÓWEK
   ========================================================================== */

/* Etykieta materiału sponsorowanego — sam napis, bez wyjaśnień
   i bez nazwy partnera. Ustalenie sieciowe z Journala.                      */

.wpis-glowa__sponsor {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
}

/* Nadkreślenie sekcji: numer + nazwa działu, jak w spisie treści magazynu */

.nad {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.nad::before {
  content: attr(data-nr);
  font-family: var(--font-mono);
  font-weight: 400;
  color: var(--brand);
  letter-spacing: .04em;
}

.meta {
  font-size: var(--fs-xs);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}

.lead {
  font-size: var(--fs-lead);
  line-height: 1.62;
  color: var(--ink-2);
  margin: 0;
  text-wrap: pretty;
}

/* ==========================================================================
   4. UKŁAD
   ========================================================================== */

.wrap { width: min(100% - 2 * var(--s5), var(--wrap)); margin-inline: auto; }

@media (max-width: 640px) { .wrap { width: min(100% - 2 * var(--s4), var(--wrap)); } }

.sekcja { padding-block: var(--s8); }

.sekcja--ciasna { padding-block: var(--s7); }

/* Pas kremowy zaczyna się włosową kreską, która gaśnie po bokach —
   twarda krawędź między dwoma odcieniami bieli wyglądała jak szew.  */

.sekcja--papier {
  background-color: var(--paper-2);
  background-image: linear-gradient(90deg, transparent,
    color-mix(in oklab, var(--brand), transparent 78%), transparent);
  background-repeat: no-repeat;
  background-size: 100% 1px;
  background-position: top center;
}

.sekcja + .sekcja--papier { margin-top: 0; }

/* Nagłówek sekcji: nadkreślenie, tytuł, link do archiwum w jednej linii */

.sek-glowa {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s5);
  padding-bottom: var(--s4);
  margin-bottom: var(--s6);
  border-bottom: 1px solid var(--rule);
}

/* Blok tytułu ma rosnąć — inaczej opis kategorii łamie się w wąską kolumnę
   przy pustym pasie z prawej. Opisy kategorii bywają na kilka zdań. */

.sek-glowa > div { flex: 1 1 auto; min-width: 0; }

.sek-glowa__tytul { font-size: var(--fs-h2); margin-top: var(--s2); }

.sek-glowa__opis {
  color: var(--ink-2);
  font-size: var(--fs-body);
  line-height: 1.62;
  margin: var(--s3) 0 0;
  max-width: 72ch;
  text-wrap: pretty;
}

.sek-glowa__opis p { margin: 0; }

.sek-glowa__opis p + p { margin-top: var(--s3); }

/* Opis kategorii idzie na trzy czwarte szerokości separatora — dość szeroko,
   żeby nie zostawiał pustego pasa, i dość krótko, żeby oko wracało do
   początku wiersza bez gubienia się.                                        */

.sek-glowa--archiwum { display: block; }

.sek-glowa--archiwum .sek-glowa__opis { max-width: 75%; }

@media (max-width: 900px) { .sek-glowa--archiwum .sek-glowa__opis { max-width: none; } }

.sek-glowa__wiecej {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  font-weight: 700; white-space: nowrap; text-decoration: none;
  color: var(--brand-text); padding-bottom: 2px;
  border-bottom: 1px solid var(--brand-300);
}

.sek-glowa__wiecej:hover { border-bottom-color: var(--accent); }

@media (max-width: 720px) {
  .sek-glowa { flex-direction: column; align-items: flex-start; gap: var(--s3); }
}

/* Pasek działów — skróty, każdy z własnym znakiem */

.dzialy {
  display: grid; gap: 1px; background: var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  border: 1px solid var(--rule);
}

.dzialy__poz {
  background: var(--paper); padding: var(--s5) var(--s4);
  text-decoration: none; color: var(--ink);
  display: flex; flex-direction: column; gap: 6px;
  transition: background-color .2s var(--ease);
}

.dzialy__poz:hover { background: var(--brand-050); color: var(--ink); }

.dzialy__nr { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--brand); letter-spacing: .1em; }

.dzialy__nazwa { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; }

.dzialy__ile { font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: .06em; }

/* ==========================================================================
   10. PASEK NARZĘDZI — to, czego nie ma konkurencja
   ========================================================================== */

.narzedzia { display: grid; gap: var(--przerwa); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.narzedzie {
  display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s6) var(--s5);
  border: 1px solid var(--rule);
  background: var(--paper);
  text-decoration: none; color: inherit;
  position: relative; overflow: hidden;
  transition: border-color .25s var(--ease), transform .25s var(--ease);
}

.narzedzie::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease);
}

.narzedzie:hover { border-color: var(--rule-2); transform: translateY(-2px); color: inherit; }

.narzedzie:hover::before { transform: scaleX(1); }

.narzedzie__ikona { width: 26px; height: 26px; color: var(--brand); }

.narzedzie__tytul { font-family: var(--font-serif); font-size: var(--fs-h3); font-weight: 600; }

.narzedzie__opis { font-size: var(--fs-sm); color: var(--ink-2); margin: 0; }

.narzedzie__cta { font-size: var(--fs-micro); letter-spacing: .12em; text-transform: uppercase; font-weight: 700; color: var(--brand-text); margin-top: auto; }

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

/* ==========================================================================
   11. MATERIAŁY SPONSOROWANE
   Na listach karta pokazuje kategorię, nie etykietę sponsorowania —
   oznaczenie zostaje tam, gdzie ma znaczenie dla czytelniczki,
   czyli na stronie samego wpisu. Jedna sekcja na stronie głównej.
   ========================================================================== */

.sponsor-sekcja { background: var(--paper-2); border-block: 1px solid var(--rule); }

.etykieta-sponsor {
  display: inline-block;
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3);
  margin-bottom: var(--s3);
}

/* ==========================================================================
   12. FILTRY ARCHIWUM
   ========================================================================== */

.filtry__etykieta {
  font-size: var(--fs-micro); letter-spacing: .12em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-3); margin-right: var(--s2);
}

.chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 34px; padding: 0 var(--s3);
  border: 1px solid var(--rule-2); border-radius: 17px;
  background: var(--paper); color: var(--ink-2);
  font-size: var(--fs-xs); font-weight: 500; letter-spacing: .02em;
  transition: border-color .18s var(--ease), background-color .18s var(--ease), color .18s var(--ease);
}

.chip:hover { border-color: var(--ink-3); color: var(--ink); }

.chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }

.chip__probka {
  width: 14px; height: 14px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .16);
  background: var(--probka);
}

.filtry__czysc { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-3); background: none; border: 0; text-decoration: underline; }

.wynik-info { font-size: var(--fs-sm); color: var(--ink-3); margin: 0 0 var(--s5); }

.wynik-info b { color: var(--ink); font-weight: 600; }

.stronicowanie { display: flex; gap: var(--s2); justify-content: center; padding-top: var(--s7); }

.stronicowanie a, .stronicowanie span {
  min-width: 40px; height: 40px; display: grid; place-items: center;
  border: 1px solid var(--rule); text-decoration: none; color: var(--ink-2);
  font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
}

.stronicowanie [aria-current] { background: var(--ink); border-color: var(--ink); color: #fff; }

/* ==========================================================================
   13. PANEL BOCZNY
   ========================================================================== */

.panel { display: grid; gap: var(--s7); align-content: start; }

.sekcja[data-nr]::before {
  content: attr(data-nr);
  /* Znak wychodzi poza górną krawędź sekcji — widać z niego mniej więcej
     dwie trzecie. Pełna cyfra przy krawędzi zderzała się z linkiem
     „cała kategoria" i wyglądała jak drugi element interfejsu zamiast
     jak tło. Przycięty czyta się od razu jako ozdoba.                 */
  position: absolute; top: -.42em; right: 1.5vw;
  font-family: var(--font-serif); font-weight: 600;
  font-size: clamp(8rem, 16vw, 14rem); line-height: 1;
  color: var(--brand); opacity: .05;
  pointer-events: none; user-select: none; z-index: 0;
}

@media (max-width: 860px) { .sekcja[data-nr]::before { display: none; } }

/* --- poświata sekcji kremowych ---------------------------------------
   Pierwsza wersja miała tu ukośne włoski. Przy zdjęciach obok czytały
   się jak prążki z zepsutego wydruku, a nie jak faktura — wzór
   regularny zawsze wygrywa z fotografią o uwagę, choćby był blady.
   Zostaje miękka plama przy lewej krawędzi: daje głębię, nie ma
   rytmu, więc oko jej nie śledzi.                                     */

.sekcja--papier::after {
  content: ""; position: absolute; inset: 0;
  pointer-events: none; z-index: 0;
  background: radial-gradient(45% 70% at 0% 40%,
    color-mix(in oklab, var(--brand), transparent 94%), transparent 70%);
}

/* --- ornament pod winietą --------------------------------------------
   Włosowa kreska z rombem pośrodku — najstarszy znak z główki gazety.
   Zamyka winietę od dołu i oddziela ją od menu miękcziej niż sama
   linia. Romb bierze kolor akcentu, kreska — marki.                   */

.winieta::after {
  content: "";
  width: min(240px, 38%); height: 7px;
  /* dwie warstwy: włosowa kreska na całą szerokość i romb pośrodku */
  background-image:
    linear-gradient(90deg, transparent,
      color-mix(in oklab, var(--brand), transparent 62%) 22%,
      color-mix(in oklab, var(--brand), transparent 62%) 78%, transparent),
    linear-gradient(45deg, var(--accent), var(--accent));
  background-size: 100% 1px, 5px 5px;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}

/* --- kreska pod tytułem sekcji ---------------------------------------
   Krótki gradient od koloru marki w nicość. Wiąże tytuł z sekcją
   i daje nagłówkom rytm, którego nie da sama typografia.              */

.sek-glowa__tytul::after {
  content: ""; display: block;
  width: 44px; height: 2px; margin-top: var(--s3);
  background: linear-gradient(90deg, var(--brand), transparent);
  opacity: .55;
}

/* --- siatka punktów na sekcjach białych ------------------------------
   Odpowiednik poświaty z sekcji kremowych, tylko na bieli: bardzo rzadkie
   punkty, wygaszane maską w dół, żeby nie leżały pod kaflami. Wzór jest
   na tyle rzadki, że oko czyta go jako fakturę papieru, a nie jako kratkę.
   Sekcje kremowe mają własną warstwę, więc :not() je omija.           */

.sekcja[data-nr]:not(.sekcja--papier)::after {
  content: ""; position: absolute; inset: 0;
  pointer-events: none; z-index: 0;
  background-image: radial-gradient(
    color-mix(in oklab, var(--brand), transparent 90%) 1px, transparent 1.4px);
  background-size: 28px 28px;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 45%);
          mask-image: linear-gradient(180deg, #000, transparent 45%);
}

/* Wyjście do archiwum przy nagłówku sekcji jest akcją nawigacyjną, nie
   przypisem — dostaje zapas ponad minimum i własne pole kliknięcia.   */

.sek-glowa__wiecej {
  display: inline-flex; align-items: center; min-height: 32px;
  padding-inline: var(--s2); margin-inline: calc(var(--s2) * -1);
}

/* Z JS-em: wiersze mają stały rytm, kafel dostaje wyliczony span.
   Bez JS-a (klasa nie zostanie dodana) siatka zostaje zwykłą siatką
   równych kafli — degradacja bez utraty treści.                            */

.sciana.jest-js { grid-auto-rows: var(--rytm); }

/* Punkty łamania ściany i klasy `sciana--kN` stoją w _poprawki.scss.

   NIE TUTAJ, bo ten partial jest ODTWARZANY Z MAKIETY przy każdym
   uruchomieniu narzedzia/wyciagnij-makiete.py — ręczna poprawka w nim ginie
   bez śladu. Zdarzyło się to już dwa razy (przyciemniony --ink-3 i usunięty
   @import), a objaw był cichy: arkusz budował się dalej.                  */

/* Ściana krótsza niż liczba kolumn. `auto-fit` zwija puste ścieżki, więc
   kafle dzielą rząd równo między siebie — dwa wpisy zajmują pół i pół,
   trzy po jednej trzeciej. Bez tego pół rzędu zostaje puste i sekcja
   wygląda na niedokończoną.                                               */

/* Rząd sekcji kategorii: jeden poziom, równe kadry 4:3, tytuł pod zdjęciem.
   Wszystkie kafle mają tę samą proporcję, więc masonry nie ma czego
   przesuwać i rząd kończy się równo. Rytm strony robi naprzemienne tło
   i numeracja sekcji, a nie zmiana siatki co dział.                      */

.sciana--rzad .kafel__tytul { -webkit-line-clamp: 2; }

/* Karta domykająca rząd w kategorii, która ma mniej wpisów niż kolumn.
   Zajmuje wszystkie wolne kolumny i stoi na kolorze marki — to jedyne
   miejsce w sekcji, gdzie paleta interfejsu wychodzi na wierzch. Dzięki
   temu rząd kończy się równo, a slot niesie treść zamiast powietrza.
   Nikt nie pomyli jej z wpisem: nie ma zdjęcia i ma inny kolor.        */

.kafel.kafel--wiecej {
  display: flex; flex-direction: column; justify-content: center;
  gap: var(--s3);
  padding: var(--s7) var(--s6);
  background: var(--brand);
  color: var(--brand-ink);
  border: 0;
  text-decoration: none;
  align-self: stretch;
  min-height: 100%;
  position: relative; overflow: hidden;
  transition: background-color .25s var(--ease);
}

/* delikatny znak wodny — nadaje kartę głębi bez dokładania grafiki */

.kafel--wiecej::after {
  content: ""; position: absolute; right: -60px; bottom: -80px;
  width: 240px; height: 240px; border-radius: 50%;
  background: rgba(255, 255, 255, .06);
}

.kafel--wiecej:hover { background: var(--brand-700); color: var(--brand-ink); }

.kafel--wiecej > * { position: relative; z-index: 1; }

.kafel--wiecej__nad {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; opacity: .72;
}

.kafel--wiecej__tytul {
  font-family: var(--font-serif); font-size: clamp(1.5rem, 2.4vw, 2rem);
  font-weight: 600; line-height: 1.15;
}

.kafel--wiecej__ile { font-size: var(--fs-xs); letter-spacing: .06em; opacity: .72; }

.kafel--wiecej__strzalka { font-size: 1.5rem; line-height: 1; margin-top: var(--s2); }

/* Kafel dwukolumnowy — jeden na jedenaście, żeby ściana miała rytm.
   Bez JS-a zajmuje dwie kolumny zwykłym `span`; z JS-em dokładną pozycję
   wylicza rozmieszczanie (patrz app.js → przeliczSciane).                  */

.sciana .kafel--duzy { grid-column: span 2; }

.sciana .kafel--duzy .kafel__kadr { aspect-ratio: 3 / 2; }

@media (max-width: 420px) { .sciana .kafel--duzy { grid-column: span 1; } }

/* ==========================================================================
   8. KAFEL
   ========================================================================== */

/* Kafel NIE jest kartą — nie ma własnego tła. Białe pudełko pod podpisem
   zostało po wcześniejszej wersji, w której kafel udawał kartę. Przy różnej
   długości tytułów te pudełka kończyły się na różnych wysokościach i rząd
   wyglądał na poszarpany. Podpis leży teraz wprost na tle sekcji, a jedynym
   prostokątem w rzędzie jest zdjęcie.

   Wyjątki mają własne tło i wyższą specyficzność: kafel okładkowy trzyma
   podpis na zdjęciu, a karta domykająca rząd stoi na kolorze marki.    */

.kafel {
  position: relative;
  display: flex; flex-direction: column;
  background: transparent;
  min-width: 0;
}

/* Podgląd LQIP leży jako TŁO kadru, nie jako osobny obrazek z `filter: blur`.
   Miniatura 20 px rozciągnięta do szerokości kafla jest rozmyta sama z siebie,
   bo przeglądarka wygładza skalowanie. Przy czterdziestu kaflach naraz różnica
   jest zasadnicza: zero dodatkowych warstw i zero filtrów do złożenia.      */

.kafel__kadr {
  position: relative;
  overflow: hidden;
  background-color: var(--dom, var(--paper-3));   /* kolor dominujący zdjęcia */
  background-image: var(--lqip, none);
  background-size: cover;
  background-position: var(--ognisko, 50% 35%);
  aspect-ratio: var(--prop, 3 / 4);
}

.kafel__foto {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--ognisko, 50% 35%);
  opacity: 0;
  transition: opacity .5s var(--ease), transform .7s var(--ease);
}

.kafel__foto.zaladowane { opacity: 1; }

.kafel:hover .kafel__foto { transform: scale(1.035); }

.kafel__opis { padding-top: var(--s3); }

.kafel__tytul {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.008em;
  margin: var(--s2) 0 0;
  /* Tytuł do dwóch linii — dzięki temu wysokość kafla jest przewidywalna
     jeszcze przed załadowaniem zdjęć i siatka nie przeskakuje.             */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.kafel--duzy .kafel__tytul { font-size: 1.375rem; -webkit-line-clamp: 3; }

/* Data i czas czytania muszą móc zejść do drugiej linii: przy 320 px
   pełna data po polsku (27 października 2022) zjada cały wiersz i minuty
   wystawały poza kafel. */

.kafel__stopka {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2);
  margin-top: var(--s2); min-width: 0;
  font-size: var(--fs-micro); letter-spacing: .06em; color: var(--ink-3);
}

.kafel__stopka span + span::before { content: '·'; margin-right: var(--s2); }

/* Cały kafel jest klikalny, ale przyciski w środku zostają osobnymi celami:
   link rozciąga się pseudo-elementem, przyciski stoją nad nim.
   Zagnieżdżanie <button> w <a> byłoby błędem w HTML i pułapką dla klawiatury. */

.kafel__link { text-decoration: none; color: inherit; }

.kafel__link::after { content: ''; position: absolute; inset: 0; z-index: 1; }

.kafel__link { color: inherit; }

.kafel__link:hover { color: inherit; }

.kafel__link:hover .kafel__tytul { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

.kafel:focus-within { outline: 2px solid var(--brand); outline-offset: 4px; }

.kafel:focus-within .kafel__link::after { outline: none; }

.kafel__link:focus-visible { outline: none; }

/* Kafel-okładka: tytuł leży na zdjęciu. Tekst nigdy nie stoi bezpośrednio
   na fotografii — zawsze na policzonym przyciemnieniu.                     */

.kafel--okladka .kafel__kadr { aspect-ratio: var(--prop, 4 / 5); }

/* Kafel-okładka przycina zawartość: warstwa z tytułem rośnie w górę od dołu,
   więc na niskim kaflu jej górna krawędź wychodziła poza kadr i kładła się
   cieniem na sąsiedztwie.                                                  */

/* Podpis leży w TYM SAMYM polu siatki co kadr, a nie nad nim absolutnie.

   Wcześniej `.kafel__opis` był `position: absolute; inset: auto 0 0 0`,
   czyli przyklejony do dołu kafla, a treść rosła w dół od swojej górnej
   krawędzi. Gdy tytuł miał trzy wiersze, `max-height: 100%` przycinało
   pudełko i `overflow: hidden` ucinało OSTATNI wiersz — czyli datę,
   w połowie wysokości liter. Zmierzone na stronie głównej: nadmiar od
   32 do 96 px, zależnie od szerokości ekranu.

   Ułożenie obu warstw w jednej komórce siatki odwraca zależność: to podpis
   wyznacza minimalną wysokość kafla, a kadr rozciąga się do niej
   (`height: 100%` przy `object-fit: cover` nie zniekształca zdjęcia).
   Nic nie może zostać ucięte, bo nie ma już czego przycinać.           */

.kafel--okladka {
  display: grid; grid-template-columns: 1fr;
  overflow: hidden;
}

.kafel--okladka > .kafel__kadr {
  grid-area: 1 / 1; height: 100%; min-height: 0;
}

.kafel--okladka > .kafel__opis {
  grid-area: 1 / 1; align-self: end;
  max-height: none; overflow: visible;
}

/* Przyciemnienie pod tytułem na kaflu-okładce.

   Zasada nadrzędna: TYTUŁ MUSI BYĆ CZYTELNY. Lekko przygaszony dół zdjęcia
   jest mniejszym problemem niż biały napis, który znika na jasnym kadrze —
   dlatego domyślna warstwa jest mocna, a dane o jasności służą do jej
   ZDJĘCIA przy ciemnych zdjęciach, nie do dokładania przy jasnych.

   Wartość data-scrim liczy PHP przy uploadzie z pasa zdjęcia poniżej górnej
   trzeciej — bo kafel pokazuje kadr, a nie całą fotografię.                */

/* BEZ `position: relative` — ROZMYŚLNIE, TO NIE JEST PRZEOCZENIE.

   `.kafel__link::after` rozciąga odnośnik tytułu na cały kafel (inset: 0),
   ale liczy te zera od NAJBLIŻSZEGO POZYCJONOWANEGO przodka. Dopóki
   `.kafel__opis` był `position: relative`, nakładka kończyła się na krawędzi
   samego opisu — klikalny był więc pas z tytułem, a nie kafel. Na małych
   kaflach opis ma 22% wysokości górnego wypełnienia i zakrywa środek kadru,
   więc zdjęcie dawało się kliknąć przypadkiem; na kaflu wiodącym
   (`data-szeroki`, dwie kolumny, znacznie wyższy) opis to już tylko dolny
   pas i zdjęcie przestawało reagować. Zmierzone na zantalo.pl:
   `document.elementFromPoint` w środku kadru pierwszego kafla zwracał
   `img.kafel__foto` zamiast `a.kafel__link`. Zgłoszone z produkcji:
   „zdjęcie główne na stronie głównej zróbmy klikalne”.

   `z-index` działa tu bez `position`, bo `.kafel__opis` jest elementem
   siatki (`.kafel--okladka` to `display: grid`) — a elementy siatki
   respektują `z-index` niezależnie od pozycjonowania. Tekst zostaje więc
   nad nakładką i nadal daje się zaznaczyć.                                 */

.kafel--okladka .kafel__opis {
  z-index: 2;
  padding: min(var(--s8), 22%) var(--s5) var(--s5);
  color: #fff;
  text-shadow: 0 1px 3px rgba(8, 6, 10, .55);
  background: linear-gradient(to top,
    rgba(10, 8, 12, .95) 0%,
    rgba(10, 8, 12, .88) 34%,
    rgba(10, 8, 12, .60) 66%,
    rgba(10, 8, 12, 0) 100%);
}

/* zdjęcie ciemne w całym pasie — można oddać mu trochę powietrza */

.kafel--okladka[data-scrim="0"] .kafel__opis {
  padding-top: min(var(--s6), 16%);
  background: linear-gradient(to top,
    rgba(10, 8, 12, .88) 0%,
    rgba(10, 8, 12, .70) 40%,
    rgba(10, 8, 12, 0) 100%);
}

/* zdjęcie bardzo jasne — pełna płyta pod tekstem, zero ryzyka */

.kafel--okladka[data-scrim="2"] .kafel__opis {
  padding-top: min(var(--s9), 30%);
  text-shadow: 0 1px 3px rgba(8, 6, 10, .7);
  background: linear-gradient(to top,
    rgba(8, 6, 10, .97) 0%,
    rgba(8, 6, 10, .94) 42%,
    rgba(8, 6, 10, .72) 72%,
    rgba(8, 6, 10, 0) 100%);
}

.kafel--okladka .kafel__link, .kafel--okladka .kafel__link:hover { color: #fff; }

.kafel--okladka .kafel__tytul { color: #fff; font-size: clamp(1.25rem, 2.4vw, 2rem); -webkit-line-clamp: 3; }

.kafel--okladka .kafel__stopka { color: rgba(255, 255, 255, .82); }

.kafel--okladka .tag { color: #fff; }

.kafel--okladka .tag::before { background: var(--accent); width: 18px; height: 2px; }

.kafel--okladka .kafel__lead {
  margin: var(--s3) 0 0; font-size: var(--fs-sm); line-height: 1.55;
  color: rgba(255, 255, 255, .88); max-width: 56ch;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Wejście kafla. Opóźnienie zależy od kolumny, nie od indeksu — inaczej
   przy czterdziestu kaflach powstaje „fala", która wygląda jak zacięcie.   */

.kafel[data-wejscie] { opacity: 0; transform: translateY(10px); }

.kafel[data-wejscie].widoczny {
  opacity: 1; transform: none;
  transition: opacity .5s var(--ease) var(--zwloka, 0ms),
              transform .5s var(--ease) var(--zwloka, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .kafel[data-wejscie] { opacity: 1; transform: none; transition: none; }
  .kafel__foto, .kafel:hover .kafel__foto { transition: none; transform: none; }
}

/* ==========================================================================
   9. OTWARCIE STRONY GŁÓWNEJ
   ========================================================================== */

.otwarcie { padding-top: var(--s6); }

.otwarcie__siatka {
  display: grid; gap: var(--przerwa);
  grid-template-columns: 1fr;
}

.otwarcie__glowny .kafel__kadr { aspect-ratio: 4 / 3; }

@media (min-width: 900px) {
  .otwarcie__siatka { grid-template-columns: 1.62fr 1fr; align-items: stretch; }
  /* `1fr 1fr` dzieliło wysokość na pół niezależnie od tego, ile miejsca
     potrzebuje podpis — i to była druga połowa problemu z uciętą datą.
     `minmax(min-content, 1fr)` mówi: rząd nigdy nie mniejszy niż treść,
     a wolne miejsce nadal dzieli się po równo. Warunkiem jest to, że podpis
     w ogóle liczy się do treści — stąd zmiana wyżej.                    */
  .otwarcie__bok {
    display: grid; gap: var(--przerwa);
    grid-template-rows: minmax(min-content, 1fr) minmax(min-content, 1fr);
  }
  .otwarcie__bok .kafel__kadr { aspect-ratio: auto; height: 100%; min-height: 180px; }
  /* Zajawka zostaje przy kaflu wiodącym. W bocznym, o połowę niższym,
     dokładała dwa wiersze do tego samego pola i to ona wypychała datę.  */
  .otwarcie__bok .kafel__lead { display: none; }
}

/* Kafel okładkowy na wąskim ekranie ------------------------------------
   W kadrze 4:3 przy 375 px nie mieszczą się naraz: kategoria, trzywierszowy
   tytuł, dwuwierszowa zajawka i stopka z datą. Opis miał 287 px przy kaflu
   257 px — overflow: hidden ucinał datę w połowie wysokości liter.
   Na telefonie zajawka i tak niewiele wnosi: decyduje zdjęcie i tytuł,
   a pierwszy akapit jest o jedno dotknięcie dalej.                      */

@media (max-width: 700px) {
  .kafel--okladka .kafel__lead { display: none; }
}

/* --- pasek działów: cienka ramka w kolorze marki ---------------------
   Kafelki „od czego zaczynasz" siedzą na jednopikselowej siatce. Sama
   szarość gubiła się na bieli; odrobina marki wiąże je z resztą strony. */

.dzialy { background: color-mix(in oklab, var(--brand), transparent 88%); }

.dzialy { border-color: color-mix(in oklab, var(--brand), transparent 82%); }

/* --- delikatne rozjaśnienie nad stopką -------------------------------
   Stopka jest jasna, więc zamiast twardej kreski oddziela ją miękkie
   przejście w kolorze marki.                                          */

.stopka { position: relative; overflow: hidden; }

.stopka::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 240px;
  pointer-events: none; z-index: 0;
  background: radial-gradient(70% 100% at 50% 0%, color-mix(in oklab, var(--brand), transparent 93%), transparent 70%);
}

.stopka > * { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  /* warstwy i tak się nie ruszają — nic do wyłączenia */
}

/* ==========================================================================
   18b. CELE DOTYKOWE
   ==========================================================================

   WCAG 2.2, kryterium 2.5.8 (AA): cel wskazywania ma mieć co najmniej
   24 × 24 px. Wyjątek „inline" obejmuje linki wewnątrz zdania — dlatego
   treść artykułu zostaje bez zmian. Poniższe linki stoją samodzielnie
   (okruszki, tagi, stopka, podpis autora), więc muszą mieć własną
   wysokość, a nie tylko wysokość swojego wiersza tekstu.

   Zmierzone przed poprawką na 390 px: okruszki 14 px, autor 14 px,
   stopka 16 px, tag 18 px, link autora 20 px, „cała kategoria" 23 px.  */

.meta > a,
.wpis-glowa__meta a,
.redakcja-glowa__inni a,
.stopka__lista > li > a,
.autor-box__link,
.tag {
  display: inline-flex; align-items: center; min-height: 24px;
}

/* Układ z panelem bocznym. W HTML treść stoi PRZED panelem —
   czytniki ekranu i roboty dostają ją pierwszą. Panel wchodzi
   na lewą stronę dopiero wizualnie, przez `order`.                          */

.z-panelem {
  display: grid;
  gap: var(--s7);
  grid-template-columns: 1fr;
}

/* min-width: 0 musi obowiązywać na KAŻDEJ szerokości, nie tylko na desktopie.
   Element siatki ma domyślnie min-width: auto, czyli nie zwęzi się poniżej
   swojej zawartości. Tabela porównawcza ma min-width: 560px, więc kolumna
   treści rozpychała się do 689 px i cały artykuł przewijał się w bok na
   telefonie. Z zerem tabela przewija się we własnej otoczce, tak jak miała. */

.z-panelem__tresc, .z-panelem__panel { min-width: 0; }

@media (min-width: 1000px) {
  .z-panelem { grid-template-columns: 280px minmax(0, 1fr); gap: var(--s8); }
  .z-panelem__tresc { order: 2; }
  .z-panelem__panel { order: 1; }
}

/* ==========================================================================
   5. PRZYCISKI I ZNACZNIKI
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 44px; padding: 0 var(--s5);
  font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: 600;
  letter-spacing: .04em; text-decoration: none; border: 1px solid transparent;
  border-radius: var(--radius); background: none; color: var(--ink);
  transition: background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}

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

.btn--brand:hover { background: var(--brand-700); color: var(--brand-ink); }

.btn--akcent { background: var(--accent); color: var(--accent-ink); }

.btn--akcent:hover { background: var(--accent-700); color: var(--accent-ink); }

.btn--kontur { border-color: var(--rule-2); color: var(--ink); }

.btn--kontur:hover { border-color: var(--ink); background: var(--paper-2); color: var(--ink); }

.btn--maly { min-height: 36px; padding: 0 var(--s4); font-size: var(--fs-xs); }

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

/* Węższy kontener na stronie wpisu: panel (280) + odstęp + kolumna tekstu
   wypełniają szerokość, zamiast zostawiać pusty pas z prawej.             */

.wrap--wpis { width: min(100% - 2 * var(--s5), 1120px); }

@media (max-width: 640px) { .wrap--wpis { width: min(100% - 2 * var(--s4), 1120px); } }

/* Lead stoi w treści, nad spisem — nie pod tytułem.

   Pod tytułem powtarzał to samo zdanie, które czytelnik ma zaraz niżej,
   i odsuwał treść o jeden ekran w dół. W treści robi to, do czego lead
   służy: wprowadza w tekst i daje wyszukiwarce akapit do zacytowania,
   a spis treści zostaje tuż nad pierwszym nagłówkiem, czyli tam, gdzie
   jest potrzebny.                                                     */

.tresc__lead {
  font-size: var(--fs-lead);
  color: var(--ink-2);
  margin: 0 0 var(--s6);
}

.tresc__lead + * { margin-top: var(--s6); }

.wpis-glowa__meta {
  display: flex; flex-wrap: wrap; gap: var(--s4); justify-content: center;
  margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--rule);
  font-size: var(--fs-xs); color: var(--ink-3); letter-spacing: .06em;
}

/* Na wąskim ekranie wyśrodkowany lead łamie się na sześć krótkich linii
   i czyta się źle — od 700 px w dół winieta wpisu wraca do lewej.
   Metryczka rozdziela się kropką zamiast rozpadać na kolumnę.              */

@media (max-width: 700px) {
  .wpis-glowa { padding-block: var(--s6) var(--s5); }
  .wpis-glowa__inner { text-align: left; }
  .wpis-glowa__lead { margin-inline: 0; }
  .wpis-glowa__meta {
    justify-content: flex-start;
    gap: var(--s2) var(--s3);
    margin-top: var(--s4);
  }
  .wpis-glowa__meta > span + span::before {
    content: '·'; margin-right: var(--s3); color: var(--rule-2);
  }
}

/* Zdjęcie wiodące ma robić wrażenie, ale nie zjadać całego pierwszego
   ekranu — stąd sufit wysokości. Plakietka AI Act siedzi w KADRZE, nie na
   figurze, żeby nie kładła się na podpisie.                                */

.wpis-foto { margin: 0 auto var(--s7); }

.wpis-foto__kadr {
  position: relative;
  background: var(--dom, var(--paper-3));
  overflow: hidden;
}

/* Zdjęcie wiodące w NATYWNYCH proporcjach generatora (1024×768 = 4:3).
   Figura jest zwężona tak, żeby przy tej proporcji wysokość nie przekroczyła
   560 px — dzięki temu nic nie jest przycinane i nic nie zjada pierwszego
   ekranu. Gdy redakcja wgra zdjęcie o innej proporcji, object-fit przytnie
   je do 4:3 z punktem ostrości nieco powyżej środka.                       */

.wpis-foto { max-width: 747px; margin-inline: auto; }

.wpis-foto__kadr img {
  width: 100%; height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover; object-position: 50% 42%;
}

.wpis-foto__podpis {
  display: flex; justify-content: space-between; gap: var(--s5);
  padding-top: var(--s3); font-size: var(--fs-xs); color: var(--ink-3);
  line-height: 1.5;
}

.wpis-foto__podpis span:last-child { white-space: nowrap; }

@media (max-width: 600px) {
  .wpis-foto__podpis { flex-direction: column; gap: var(--s2); }
  .wpis-foto__podpis span:last-child { white-space: normal; }
}

/* Kluczowa odpowiedź (BLUF) — konkret w pierwszym ekranie.
   To jest ten fragment, który cytują wyszukiwarki i modele.                 */

.bluf {
  border-left: 3px solid var(--accent);
  background: var(--accent-050);
  padding: var(--s5);
  margin: 0 0 var(--s6);
}

.bluf__etykieta {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-text); margin-bottom: var(--s2);
}

.bluf p { margin: 0; font-size: var(--fs-lead); line-height: 1.55; }

/* overflow-wrap jest tu obowiązkowe, nie ozdobne: w tekstach prawnych stoją
   pełne adresy (help.opera.com/Windows/12.10/pl/cookies.html), a takiego
   ciągu bez spacji przeglądarka nie złamie sama — przy 320 px wypychał
   stronę o 72 px w bok. */

.tresc { max-width: var(--wrap-tekst); margin-inline: auto; overflow-wrap: break-word; }

.tresc a[href^="http"] { overflow-wrap: anywhere; }

/* --- rytm pionowy treści ---------------------------------------------

   Kolejność i specyficzność są tu istotne, bo poprzednia wersja miała
   błąd, który psuł cały tekst: `.tresc p { margin: 0 }` ma wyższą
   specyficzność niż `.tresc > * + *`, więc zerowało odstępy MIĘDZY
   akapitami — artykuł czytał się jak jeden zlepiony blok, a nagłówki
   przyklejały się do własnego tekstu.

   Dlatego domyślne marginesy przeglądarki zeruje się w :where(), które
   ma specyficzność zero i nigdy nie wygrywa z regułami rytmu poniżej.

   POPRAWKA: zerowanie samo w sobie było zapisane tak, że ten zamiar go
   nie obejmował. `:where()` nie zeruje CAŁEGO selektora, tylko własną
   zawartość — `.tresc :where(p, ul, …)` liczy się wciąż jako jedna klasa,
   czyli dokładnie tyle co `.tresc > * + *`. Przy remisie decyduje
   kolejność, a ten plik jest wczytywany PO _baza.scss, więc zerowanie
   wygrywało i wracał ten sam objaw, przed którym ostrzega komentarz
   powyżej. Zmierzone w przeglądarce na prawdziwym arkuszu: akapit po
   akapicie 0 px zamiast 32, lista po akapicie 0 px, cytat po tabeli
   0 px — odstępy zostawały tylko tam, gdzie osobna reguła miała wyższą
   specyficzność (pod nagłówkiem, wokół figury).

   Żeby zamiar był zapisany naprawdę, w :where() musi być też kontener:
   wtedy cały selektor ma specyficzność zero i przegrywa z każdą regułą
   rytmu bez względu na kolejność plików. */

:where(.tresc) :where(p, ul, ol, figure, blockquote) { margin: 0; }

.tresc p { line-height: 1.72; }

.tresc ul, .tresc ol { padding-left: 1.25em; }

.tresc li + li { margin-top: var(--s2); }

.tresc strong { font-weight: 600; }

.tresc figcaption { font-size: var(--fs-xs); color: var(--ink-3); padding-top: var(--s2); }

/* Odstępy wokół nagłówków.

   Przed kreską było 64 px, a między kreską a tekstem nagłówka 16 px —
   czyli pusty pas nad separatorem i nagłówek doklejony do niego od dołu.
   Teraz: mniej powietrza przed kreską (48 px), więcej pod nią (24 px). */

.tresc h2 {
  font-size: var(--fs-h2); margin-top: var(--s7);
  padding-top: var(--s5); border-top: 1px solid var(--rule);
  line-height: 1.25;
  scroll-margin-top: 96px;
}

.tresc h3 { font-size: var(--fs-h3); margin-top: var(--s7); line-height: 1.3; scroll-margin-top: 96px; }

/* Element pod nagłówkiem stoi bliżej niż sąsiedni akapit: to ten odstęp
   mówi, że tekst należy DO tego nagłówka, a nie do poprzedniej sekcji. */

.tresc > :is(h2, h3) + * { margin-top: var(--s5); }

/* Figury dostają więcej powietrza z obu stron niż akapit. */

.tresc > figure { margin-block: var(--s7); }

/* Tabela jest takim samym obiektem jak figura — zamkniętym kadrem, a nie
   kolejnym akapitem — więc dostaje to samo powietrze z obu stron. Bez tej
   reguły otoczka brała odstęp z rytmu bazowego (32 px) i dolna krawędź
   ostatniego wiersza stała prawie na następnym bloku; na zantalo.pl pod
   tabelą stoi cytat „Co warto zapamiętać?", który wyglądał jak doklejony
   do niej wiersz. Reguła stoi PO regule odstępu pod nagłówkiem, więc
   tabela zaraz pod H2 też zachowa pełny odstęp — tak samo jak figura. */

.tresc > .tabela-otoczka { margin-block: var(--s7); }

/* Spis treści — wpisy w tej niszy mają 8–20 tys. znaków */

.spis {
  border: 1px solid var(--rule); padding: var(--s5);
  background: var(--paper-2);
}

.spis__tytul { font-size: var(--fs-micro); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s3); }

.spis ol { margin: 0; padding: 0; list-style: none; counter-reset: s; }

.spis li { counter-increment: s; }

.spis li + li { margin-top: 6px; }

.spis a { display: flex; gap: var(--s3); text-decoration: none; color: var(--ink-2); font-size: var(--fs-sm); }

.spis a::before { content: counter(s, decimal-leading-zero); font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--brand); }

.spis a:hover { color: var(--brand-text); text-decoration: underline; }

.spis a[aria-current] { color: var(--ink); font-weight: 600; }

/* Dymek składnika — nazwa w treści prowadzi do hasła w bazie */

.skladnik-link {
  border-bottom: 1px dashed var(--accent);
  text-decoration: none; color: inherit; cursor: help;
}

.skladnik-link:hover { background: var(--accent-050); color: inherit; }

/* Box produktu w treści — z zestawu „produkty" */

.produkt-box {
  display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: var(--s4);
  border: 1px solid var(--rule); padding: var(--s4);
  background: var(--paper);
}

.produkt-box__znak {
  aspect-ratio: 1; display: grid; place-items: center; text-align: center;
  background: var(--brand-050); color: var(--brand-900);
  font-family: var(--font-serif); font-size: 1.5rem; font-weight: 600;
}

.produkt-box__marka { font-size: var(--fs-micro); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }

.produkt-box__nazwa { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; margin: 2px 0 var(--s2); }

.produkt-box__werdykt { font-size: var(--fs-sm); color: var(--ink-2); margin: 0 0 var(--s3); }

.produkt-box__dol { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }

.produkt-box__cena { font-family: var(--font-mono); font-size: 1.0625rem; font-weight: 600; font-variant-numeric: tabular-nums; }

.produkt-box__info { font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: .05em; }

/* FAQ — widoczny blok, z którego motyw buduje FAQPage */

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

.faq__poz { border-bottom: 1px solid var(--rule); }

.faq__pyt {
  width: 100%; display: flex; justify-content: space-between; align-items: center; gap: var(--s4);
  padding: var(--s4) 0; background: none; border: 0; text-align: left;
  font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; color: var(--ink);
}

.faq__pyt::after { content: '+'; font-family: var(--font-mono); font-size: 1.25rem; color: var(--brand); flex: none; }

.faq__pyt[aria-expanded="true"]::after { content: '−'; }

.faq__odp { padding: 0 0 var(--s4); color: var(--ink-2); font-size: var(--fs-body); }

.faq__odp[hidden] { display: none; }

/* Galeria we wpisie */

.galeria { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s2); }

.galeria__poz { position: relative; aspect-ratio: 1; overflow: hidden; border: 0; padding: 0; background: var(--dom, var(--paper-3)); }

.galeria__poz img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }

.galeria__poz:hover img { transform: scale(1.05); }

/* Podgląd pełnoekranowy */

.lupa { position: fixed; inset: 0; z-index: 90; background: rgba(14, 12, 16, .94); display: grid; grid-template-rows: 1fr auto; padding: var(--s5); }

.lupa[hidden] { display: none; }

.lupa__kadr { display: grid; place-items: center; min-height: 0; }

.lupa__kadr img { max-width: 100%; max-height: 100%; object-fit: contain; }

.lupa__pasek { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); color: rgba(255, 255, 255, .8); font-size: var(--fs-sm); padding-top: var(--s4); }

.lupa__zamknij, .lupa__nawig button {
  min-width: 44px; min-height: 44px; background: none; border: 1px solid rgba(255, 255, 255, .3);
  color: #fff; border-radius: 2px;
}

.lupa__nawig { display: flex; gap: var(--s2); }

/* Stopka wpisu: autorka i wpisy powiązane */

.autorka-box {
  display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: var(--s5);
  border: 1px solid var(--rule); padding: var(--s6);
  background: var(--paper-2);
}

.autorka-box__awatar {
  width: 76px; height: 76px; border-radius: 50%;
  background: var(--brand); color: var(--brand-ink);
  display: grid; place-items: center;
  font-family: var(--font-serif); font-size: 1.75rem; font-weight: 600;
}

.autorka-box__zasady { list-style: none; margin: var(--s3) 0 0; padding: 0; display: grid; gap: 6px; }

.autorka-box__zasady li { font-size: var(--fs-sm); color: var(--ink-2); padding-left: 20px; position: relative; }

.autorka-box__zasady li::before { content: '✓'; position: absolute; left: 0; color: var(--ok); font-weight: 700; }

@media (max-width: 600px) { .autorka-box { grid-template-columns: 1fr; } }

/* ==========================================================================
   15. DANE — skaner składu, rankingi, quiz
   ========================================================================== */

.karta-danych { border: 1px solid var(--rule); background: var(--paper); }

.karta-danych__glowa { padding: var(--s5); border-bottom: 1px solid var(--rule); display: flex; justify-content: space-between; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }

.karta-danych__cialo { padding: var(--s5); }

/* Data aktualizacji — obowiązkowa i widoczna przy każdym zestawie z CSV.
   Bez niej tabela jest bezwartościowa dla czytelniczki i dla wyszukiwarki. */

.zrodlo { font-size: var(--fs-micro); color: var(--ink-3); padding-top: var(--s3); border-top: 1px solid var(--rule); margin-top: var(--s4); }

.lista-skladnikow { list-style: none; margin: 0; padding: 0; }

.lista-skladnikow > li { border-bottom: 1px solid var(--rule); padding: var(--s4) 0; display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: var(--s3); align-items: start; }

.poz-nr { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-3); padding-top: 3px; }

.poz-nazwa { font-family: var(--font-serif); font-weight: 600; font-size: 1.0625rem; }

.poz-inci { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-3); }

.poz-opis { font-size: var(--fs-sm); color: var(--ink-2); margin: var(--s2) 0 0; }

.poz-flagi { display: flex; gap: 6px; flex-wrap: wrap; margin-top: var(--s2); }

.plakietka {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .05em;
  padding: 3px 8px; border-radius: 2px; white-space: nowrap;
  border: 1px solid currentColor;
}

.plakietka--ok { color: var(--ok); }

.plakietka--uwaga { color: var(--uwaga); }

.plakietka--stop { color: var(--stop); }

.plakietka--mit { color: var(--mit); }

.plakietka--neutralna { color: var(--ink-3); }

.plakietka--pelna { border: 0; background: var(--accent); color: var(--accent-ink); }

.ostrzezenie { border-left: 3px solid; padding: var(--s4); background: var(--paper-2); }

.ostrzezenie--stop { border-color: var(--stop); }

.ostrzezenie--uwaga { border-color: var(--uwaga); }

.ostrzezenie--mit { border-color: var(--mit); }

.ostrzezenie__tytul { font-weight: 600; font-size: var(--fs-sm); margin: 0 0 4px; }

.ostrzezenie p { margin: 0; font-size: var(--fs-sm); color: var(--ink-2); }

/* Tabele danych */

/* position: relative jest tu potrzebne, nie kosmetyczne: bez niego opisy
   .tylko-czytnik wewnątrz komórek (position: absolute) zaczepiają się o dalszy
   kontener, wychodzą poza otoczkę i rozciągają szerokość przewijania całego
   dokumentu. Z nim przycina je ta sama otoczka, w której leży tabela. */

.tabela-otoczka { overflow-x: auto; -webkit-overflow-scrolling: touch; position: relative; }

table.dane { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); min-width: 560px; }

table.dane caption { text-align: left; font-size: var(--fs-xs); color: var(--ink-3); padding-bottom: var(--s3); }

table.dane th, table.dane td { padding: var(--s3) var(--s4); text-align: left; border-bottom: 1px solid var(--rule); }

/* Nagłówek tabeli łapiemy dwiema drogami, bo `<thead>` nie zawsze jest.
   Pipeline publikacyjny wstawia goły HTML i tabela potrafi zacząć się od
   `<tr><th>` — przeglądarka dorabia wtedy `tbody`, ale `thead` już nie,
   więc reguła oparta wyłącznie na `thead` nie trafiała w nic i wiersz
   nagłówkowy wyglądał jak zwykły wiersz danych. */

table.dane thead th,
table.dane tr:first-child th {
  font-family: var(--font-sans); font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--ink);
}

/* Przyklejenie zostaje przy `thead`: bez niego nie ma czego przyklejać,
   a `tr:first-child` w `tbody` przykleiłby pierwszy wiersz danych. */

table.dane thead th { position: sticky; top: 0; background: var(--paper); z-index: 1; }

table.dane tbody tr:hover { background: var(--paper-2); }

table.dane td.liczba { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }

table.dane th[aria-sort] { cursor: pointer; }

table.dane th[aria-sort]::after { content: '↕'; margin-left: 6px; opacity: .4; }

table.dane th[aria-sort="ascending"]::after { content: '↑'; opacity: 1; color: var(--brand); }

table.dane th[aria-sort="descending"]::after { content: '↓'; opacity: 1; color: var(--brand); }

/* Pierwsza kolumna przyklejona — tabele porównawcze są szersze niż telefon */

table.dane--sticky td:first-child, table.dane--sticky th:first-child {
  position: sticky; left: 0; background: var(--paper); z-index: 2;
  border-right: 1px solid var(--rule);
}

/* ==========================================================================
   16. STOPKA
   ========================================================================== */

/* Panel przyklejony przy przewijaniu — TYLKO na stronie wpisu.

   `position: sticky` stało tu od początku i nie robiło nic: panel jest
   elementem siatki, a te domyślnie rozciągają się na całą wysokość rzędu.
   Na wpisie rząd ma prawie 7000 px, więc panel był tak samo wysoki jak
   treść i przyklejanie nie miało po czym jechać. Dopiero `align-self:
   start` daje mu własną, niską wysokość.

   `max-height` + `overflow-y` są zabezpieczeniem na wypadek panelu
   dłuższego niż ekran: bez nich jego dół byłby nie do obejrzenia.     */

@media (min-width: 1000px) {
  .wrap--wpis .z-panelem__panel {
    position: sticky;
    top: calc(46px + var(--s5));
    align-self: start;
    max-height: calc(100vh - 46px - var(--s6));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
  }
}

.panel__blok { border-top: 2px solid var(--ink); padding-top: var(--s4); }

.panel__tytul {
  font-family: var(--font-sans); font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; margin: 0 0 var(--s4);
}

.mini-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }

/* Cały wiersz jest celem kliknięcia, nie sam tytuł. Bez tego miniatura
   64 × 64 nie reaguje na dotyk, a jedynym celem zostaje 20-pikselowy pasek
   tekstu — dokładnie ta sytuacja, którą opisuje WCAG 2.5.8.            */

.mini {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: var(--s3);
  align-items: start; position: relative;
}

.mini__tytul::after { content: ''; position: absolute; inset: 0; }

.mini__kadr { aspect-ratio: 1; overflow: hidden; background: var(--dom, var(--paper-3)); position: relative; }

.mini__kadr img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.mini__tytul {
  font-family: var(--font-serif); font-size: .9375rem; font-weight: 600; line-height: 1.3;
  margin: 0; text-decoration: none; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}

a.mini__tytul:hover { color: var(--brand-text); }

.mini__meta { font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: .05em; margin-top: 4px; }

.mini__nr { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--brand); }

/* Powiązane wpisy pod artykułem. Bez nagłówka — etykieta jest akapitem,
   żeby nie zaśmiecać konspektu tekstu. Oddziela je mocny włos, nie h2.    */

.powiazane { margin-top: var(--s8); padding-top: var(--s5); border-top: 2px solid var(--ink); }

.powiazane__etykieta {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
  margin: 0 0 var(--s5);
}

/* Box autora w panelu bocznym wpisu. Świadomie bez nagłówka — to podpis pod
   tekstem, nie kolejna sekcja serwisu. Kadr zdjęcia ma stały rozmiar, więc
   wariant z monogramem zajmuje dokładnie tyle samo miejsca.                */

.panel__blok--autor { border-top-color: var(--rule-2); }

.autor-box { display: grid; gap: var(--s2); }

.autor-box__foto {
  width: 72px; height: 72px;
  border-radius: 50%; overflow: hidden;
  background: var(--brand-050);
  display: grid; place-items: center;
  margin-bottom: var(--s2);
}

.autor-box__foto img { width: 100%; height: 100%; object-fit: cover; }

.autor-box__foto[data-brak-zdjecia] { border: 1px dashed var(--rule-2); }

.autor-box__monogram {
  font-family: var(--font-serif); font-size: 1.75rem; font-weight: 600;
  color: var(--brand); line-height: 1;
}

.autor-box__imie { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; margin: 0; }

.autor-box__rola {
  font-size: var(--fs-micro); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); margin: 0;
}

.autor-box__opis { font-size: var(--fs-sm); color: var(--ink-2); margin: var(--s2) 0 0; }

.autor-box__link {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em;
  text-decoration: none; color: var(--brand-text); margin-top: var(--s2);
}

.autor-box__link:hover { text-decoration: underline; }

/* Box z cytatem w panelu bocznym. Treść i autor to dwa pola w Customizerze;
   przy pustym polu motyw nie wypisuje bloku.

   Bez ozdobnego cudzysłowu w pseudo-elemencie — kładł się na pierwszej
   literze. Cytat wyróżnia pionowa linia w kolorze marki: działa przy każdej
   długości tekstu i nie wchodzi w słowa.                                   */

.panel__blok--cytat { border-top-color: var(--brand); }

.cytat {
  margin: 0;
  padding-left: var(--s4);
  border-left: 2px solid var(--brand);
}

.cytat__tresc {
  font-family: var(--font-serif);
  font-size: 1.125rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
  text-wrap: pretty;
}

.cytat__autor {
  margin-top: var(--s3);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-style: normal;
}

/* Autorka w panelu — E-E-A-T ma stać wysoko, nie w stopce */

.autorka-panel { display: grid; gap: var(--s3); }

.autorka-panel__glowa { display: flex; gap: var(--s3); align-items: center; }

.autorka-panel__awatar {
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--brand-100); color: var(--brand-900);
  display: grid; place-items: center;
  font-family: var(--font-serif); font-size: 1.25rem; font-weight: 600;
}

.autorka-panel__imie { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; }

.autorka-panel__rola { font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: .05em; text-transform: uppercase; }

.autorka-panel__bio { font-size: var(--fs-sm); color: var(--ink-2); margin: 0; }

/* ==========================================================================
   14. WPIS
   ========================================================================== */

.pasek-czytania {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
  background: transparent; pointer-events: none;
}

.pasek-czytania i { display: block; height: 100%; width: 0; background: var(--accent); }

.wpis-glowa { padding-block: var(--s7) var(--s6); }

.wpis-glowa__inner { max-width: var(--wrap-tekst); margin-inline: auto; text-align: center; }

.wpis-glowa__tytul { font-size: var(--fs-display); margin: var(--s4) 0 var(--s4); }

.wpis-glowa__lead { font-size: var(--fs-lead); color: var(--ink-2); margin: 0 auto; max-width: 60ch; }

/* Stopka jest JASNA, bo logo klienta bywa czarnym plikiem — na ciemnym tle
   winieta w stopce po prostu znika. Rozdziela ją od treści mocny włos,
   a nie kontrast tła.                                                     */

.stopka {
  background: var(--paper-2);
  color: var(--ink-2);
  margin-top: var(--s9);
  border-top: 2px solid var(--ink);
}

.stopka a { color: var(--ink); }

/* Liczbę TORÓW ustala klasa `stopka__gora--kN` (patrz _stopka-polecane.scss):
   kolumny stopki są warunkowe, a cztery tory na sztywno zostawiały pusty
   tor na portalu bez kolumny płatnej i bez wyboru redakcji. Tu zostaje
   tylko to, co od liczby kolumn nie zależy. Wartość poniżej jest
   awaryjna — dla stopki bez klasy `--kN`.                                */
.stopka__gora { display: grid; gap: var(--s7); padding-block: var(--s8); grid-template-columns: 1.6fr 1fr 1fr 1.1fr; }


@media (max-width: 620px) { .stopka__gora { gap: var(--s6); } }

.stopka__logo { font-family: var(--font-serif); font-size: 1.75rem; font-weight: 500; letter-spacing: -0.02em; color: var(--ink); text-decoration: none; }

.stopka__logo em { font-style: italic; color: var(--brand); }

.stopka__opis { font-size: var(--fs-sm); color: var(--ink-2); max-width: 46ch; margin: var(--s3) 0 0; }

.stopka__tytul { font-size: var(--fs-micro); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s4); }

.stopka__lista { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); font-size: var(--fs-sm); }

.stopka__lista a { text-decoration: none; color: var(--ink-2); }

.stopka__lista a:hover { text-decoration: underline; color: var(--brand-text); }

/* Kolumna sprzedażowa stopki: do pięciu linków i do pięciu banerów 300×50.
   Banery leżą jeden pod drugim i skalują się do szerokości kolumny, żeby
   pełny komplet nie rozpychał stopki na wąskim ekranie.                   */

.stopka__sprzedaz .stopka__lista { gap: var(--s2); }

/* Pas banerowy: do pięciu slotów 300×50 w jednym rzędzie. Kreacje są
   rastrowe, więc przy węższym ekranie skalują się proporcjonalnie
   (aspect-ratio 6/1) zamiast łamać się do słupka.                        */

.stopka__pas {
  display: grid; gap: var(--s3);
  padding-block: var(--s6);
  border-top: 1px solid var(--rule);
  justify-items: center;
}

.stopka__pas-etykieta {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
}

/* Pas banerów jest elementem siatki, więc bez min-width: 0 nie zwęzi się
   poniżej szerokości pojedynczego banera (300 px) i przy 320 px ekranu
   wypycha całą stopkę poza widok. */

.stopka__banery {
  display: flex; flex-wrap: wrap; gap: var(--s3);
  justify-content: center; width: 100%;
  min-width: 0; max-width: 100%;
}

.stopka__banery .baner {
  flex: 1 1 180px; max-width: 300px; min-width: 0;
  height: auto; aspect-ratio: 6 / 1; margin: 0;
}

.stopka__dol {
  border-top: 1px solid var(--rule);
  padding-block: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s4);
  justify-content: space-between; font-size: var(--fs-xs); color: var(--ink-3);
}

.stopka__ai { font-size: var(--fs-xs); color: var(--ink-3); margin-top: var(--s5); }

/* ==========================================================================
   16a. STRONA REDAKTORA
   Nazwa, opis i wpisy — nic więcej. Zdjęcie jest opcjonalne: kadr ma stały
   rozmiar, więc jego brak nie przesuwa układu, a w miejscu zdjęcia zostaje
   monogram.
   ========================================================================== */

.redakcja-glowa {
  display: grid;
  grid-template-columns: 128px minmax(0, 1fr);
  gap: var(--s6);
  align-items: start;
  padding-bottom: var(--s6);
  border-bottom: 1px solid var(--rule);
}

.redakcja-glowa__foto {
  width: 128px; height: 128px;
  overflow: hidden; border-radius: 50%;
  background: var(--brand-050);
  display: grid; place-items: center;
}

.redakcja-glowa__foto img { width: 100%; height: 100%; object-fit: cover; }

/* stan bez zdjęcia — cienka kreskowana obwódka mówi, że slot istnieje */

.redakcja-glowa__foto[data-brak-zdjecia] {
  border: 1px dashed var(--rule-2);
  background: var(--brand-050);
}

.redakcja-glowa__monogram {
  font-family: var(--font-serif); font-size: 3rem; font-weight: 600;
  color: var(--brand); line-height: 1;
}

.redakcja-glowa__nazwa { font-size: var(--fs-h1); margin: var(--s3) 0 var(--s2); }

.redakcja-glowa__rola {
  font-size: var(--fs-xs); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); margin: 0 0 var(--s4);
}

.redakcja-glowa__inni { font-size: var(--fs-sm); color: var(--ink-3); margin: var(--s5) 0 0; }

@media (max-width: 640px) {
  .redakcja-glowa { grid-template-columns: 1fr; gap: var(--s4); }
  .redakcja-glowa__foto { width: 96px; height: 96px; }
}

/* ==========================================================================
   16b. STRONA KONTAKTU — reguły przeniesione do _strony.scss.

   Stała tu klasa `.kontakt-adres`, a nad nią komentarz o danych kontaktowych
   „na grafice, nie w treści HTML”. Obie rzeczy są nieaktualne: strona
   kontaktu pokazuje adres tekstem (klasy `.kontakt-mail*`, wspólne dla całej
   sieci), a osierocona reguła w pliku stopki była dokładnie tym rodzajem
   martwego przepisu, przez który poprawki wyglądu trafiają w próżnię.
   ========================================================================== */

/* ==========================================================================
   WYBÓR REDAKCJI W STOPCE — wpisy polecane ręcznie

   W tej sieci wpisy polecane wskazuje redakcja checkboxem w edytorze.
   W tp_fundament stały w szynie obok materiału wiodącego na stronie
   głównej; tutaj — na życzenie — schodzą do stopki i pokazują się na
   KAŻDEJ podstronie. Stopka jest jedynym miejscem wspólnym dla wszystkich
   widoków, więc polecane trafiają też pod archiwum i pod dokument prawny.

   KOLUMNA, NIE PAS. Pierwsza wersja stawiała je w szerokim pasie
   z miniaturami NAD kolumnami stopki — układ, którego w makiecie nie ma.
   Makieta pokazuje stopkę jako rząd równych kolumn z listami odnośników,
   więc wybór redakcji jest po prostu kolejną taką kolumną: ten sam
   `.stopka__tytul` i `.stopka__lista`, co „Działy” i „Serwis”. Dlatego
   w tym pliku prawie nie ma już własnych reguł — cały wygląd przychodzi
   z `_stopka.scss` i to jest zamierzone. Zostaje tu tylko to, czego
   sąsiednie kolumny nie potrzebują: proporcje siatki przy piątej kolumnie
   i łamanie długich tytułów wpisów.

   NAZWA MA ZOSTAĆ RÓŻNA. Sąsiednia kolumna to PŁATNE linki klienta
   (`rel="sponsored nofollow"` z `tp_wp_get_backend_links`) pod nagłówkiem
   „Polecane”. Odkąd obie listy stoją obok siebie i wyglądają identycznie,
   nagłówek jest JEDYNĄ rzeczą, która mówi czytelniczce, gdzie kończy się
   redakcja, a zaczyna reklama. Oba nagłówki są w Customizerze (Stopka)
   i nie wolno ustawić ich na to samo słowo.

   Kolumna nie wypisuje się, gdy nie ma ani jednego oznaczonego wpisu. Nie
   ma podmiany na „najnowsze”: nagłówek obiecujący wybór redakcji nad listą,
   której nikt nie wybrał, to ta sama usterka, którą naprawialiśmy w szynie
   Fundamentu.
   ========================================================================== */

/* SIATKA STOPKI LICZY SIĘ Z LICZBY KOLUMN, KTÓRE FAKTYCZNIE SIĘ WYPISAŁY.

   Kolumny stopki są warunkowe: „Działy” i „Serwis” tylko z przypisanym
   menu, wybór redakcji tylko z oznaczonymi wpisami, kolumna płatna tylko
   z kampanią. Szablon dolicza je i dokłada klasę `stopka__gora--kN`
   (atl_klasa_stopki() w inc/sekcje.php).

   Wcześniej siatka miała na sztywno cztery tory. Na produkcji zantalo.pl
   wypisały się TRZY kolumny (portal nie ma jeszcze wpisów polecanych ani
   kampanii), więc czwarty tor stał pusty — jedna piąta szerokości stopki
   zostawała białą plamą po prawej, a nota o portalu ściskała się w węższej
   kolumnie, niż było miejsce.

   Proporcje, a nie `repeat(auto-fit, …)`: pierwsza kolumna (winieta i nota)
   musi zostać szersza od list, a auto-fit zrównałby wszystkie.           */

.stopka__gora--k1 { grid-template-columns: minmax(0, 46ch); }
.stopka__gora--k2 { grid-template-columns: 1.6fr 1fr; }
.stopka__gora--k3 { grid-template-columns: 1.6fr 1fr 1fr; }
.stopka__gora--k4 { grid-template-columns: 1.6fr 1fr 1fr 1.1fr; }
.stopka__gora--k5 { grid-template-columns: 1.5fr 1fr 1fr 1.2fr 1.2fr; }

/* Cztery tory na pięć kolumn wypchnęłyby piątą pod winietę, więc przy
   pięciu schodzimy od razu do trzech: 1–3 w pierwszym rzędzie, obie listy
   „polecanych” obok siebie w drugim. */
@media (max-width: 1200px) {
  .stopka__gora--k5 { grid-template-columns: 1.4fr 1fr 1fr; }
}

@media (max-width: 1000px) {
  .stopka__gora--k3, .stopka__gora--k4, .stopka__gora--k5 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 620px) {
  .stopka__gora--k2, .stopka__gora--k3, .stopka__gora--k4, .stopka__gora--k5 { grid-template-columns: 1fr; }
}

/* Tytuły wpisów są dłuższe od nazw linków sprzedażowych obok („Kwasy AHA
   i BHA — charakterystyka i zastosowanie” kontra „Sklep z kosmetykami”),
   więc w wąskiej kolumnie łamią się na kilka linii. Odstęp między
   pozycjami musi być wtedy większy niż odstęp między liniami jednej
   pozycji — inaczej lista czyta się jak jeden blok tekstu.               */
.stopka__redakcja .stopka__lista { gap: var(--s3); }

/* Cztery linie to sufit: dłuższy tytuł rozpycha kolumnę i wypycha sąsiednie
   listy w dół. Ucięcie jest widoczne (wielokropek), więc nie udaje, że
   tytuł się skończył. Jedna reguła na `a`, nie dwie — `display` ustawiony
   dwa razy na tym samym selektorze to gotowa pułapka przy następnej
   edycji.                                                                */
.stopka__redakcja .stopka__lista a {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.35;
}

@media print {
  .stopka__redakcja { display: none; }
}

/* Strony prawne: treść przeniesiona dosłownie z .docx, więc bywa długa.
   Węższa miara i mniejszy stopień, żeby dało się to przeczytać.           */

.tresc--prawna { font-size: var(--fs-sm); }

.tresc--prawna h2 { font-size: var(--fs-h3); margin-top: var(--s7); }

.tresc--prawna li + li { margin-top: var(--s1); }

/* ==========================================================================
   16c. POWRÓT NA GÓRĘ
   Pojawia się dopiero po zjechaniu na drugi ekran — na krótkiej stronie
   byłby kolejnym elementem zasłaniającym treść.
   ========================================================================== */

.do-gory {
  position: fixed; right: var(--s5); bottom: 84px; z-index: 70;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border: 1px solid var(--rule-2); border-radius: 50%;
  background: var(--paper); color: var(--ink);
  box-shadow: var(--cien-2);
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .25s var(--ease), transform .25s var(--ease), visibility 0s linear .25s;
}

.do-gory.widoczny { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }

.do-gory:hover { border-color: var(--ink); }

.do-gory svg { width: 20px; height: 20px; }

@media (max-width: 640px) { .do-gory { right: var(--s3); bottom: 76px; } }

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

/* ==========================================================================
   17. PANEL KOLORÓW — symulacja Customizera
   To NIE jest element frontu bloga. Stoi w makiecie po to, żeby można było
   sprawdzić dowolną parę kolorów przed decyzją.
   ========================================================================== */

.cfg { position: fixed; right: var(--s5); bottom: var(--s5); z-index: 80; display: grid; justify-items: end; gap: var(--s2); }

.cfg__przelacz {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px; padding: 0 var(--s4);
  background: var(--ink); color: #fff; border: 0; border-radius: 22px;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em;
  box-shadow: var(--cien-2);
}

.cfg__kropki { display: inline-flex; }

.cfg__kropki i { width: 13px; height: 13px; border-radius: 50%; border: 2px solid var(--ink); }

.cfg__kropki i + i { margin-left: -5px; }

.cfg__panel {
  width: 290px; padding: var(--s5);
  background: var(--paper); border: 1px solid var(--rule-2);
  box-shadow: var(--cien-3);
  display: none;
}

.cfg__panel[data-otwarte="true"] { display: block; }

.cfg__glowa { font-family: var(--font-serif); font-size: 1.0625rem; font-weight: 600; margin-bottom: var(--s2); }

.cfg__nota { font-size: var(--fs-xs); color: var(--ink-3); margin: 0 0 var(--s4); line-height: 1.5; }

.cfg__wiersz { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }

.cfg__wiersz label { font-size: var(--fs-sm); }

.cfg__wiersz input[type="color"] { width: 46px; height: 32px; padding: 0; border: 1px solid var(--rule-2); background: none; cursor: pointer; }

.cfg__presety { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2); margin-top: var(--s4); }

.cfg__preset {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border: 1px solid var(--rule); background: var(--paper);
  font-size: var(--fs-xs); text-align: left;
}

.cfg__preset[aria-pressed="true"] { border-color: var(--ink); }

.cfg__preset i { width: 12px; height: 12px; border-radius: 50%; flex: none; }

.cfg__kontrast { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--rule); font-size: var(--fs-micro); color: var(--ink-3); display: grid; gap: 4px; }

.cfg__kontrast b { font-family: var(--font-mono); color: var(--ink); }

@media (max-width: 640px) { .cfg { right: var(--s3); bottom: var(--s3); } .cfg__panel { width: min(88vw, 290px); } }

/* ==========================================================================
   18. RÓŻNE
   ========================================================================== */

.nota {
  border: 1px dashed var(--rule-2); background: var(--paper-2);
  padding: var(--s4); font-size: var(--fs-sm); color: var(--ink-2);
}

.nota strong { color: var(--ink); }

.siatka-2 { display: grid; gap: var(--s6); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* ==========================================================================
   STRONA KONTAKTU — karta z jednym zdaniem i adresem e-mail.

   Klasy .kontakt-mail* są WSPÓLNE DLA CAŁEJ SIECI (tp_atelier, tp_fundament,
   tp_glam, tp-journal): ten sam znacznik i to samo zdanie w każdym motywie,
   różni się wyłącznie warstwa wizualna, bo każdy motyw ma własne tokeny.
   Zastąpiły `.kontakt-adres` z _stopka.scss.
   ========================================================================== */

.kontakt-mail {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--s5);
  margin: var(--s5) 0;
}

.kontakt-mail__tekst { margin: 0 0 var(--s4); color: var(--ink-2); }
.kontakt-mail__adres { margin: 0; }

/* Adres jest jedyną treścią, po którą ktoś tu przyszedł — dostaje własny
   stopień pisma. clamp(), żeby na wąskim telefonie nie wyszedł poza kartę:
   „kontakt@torebki-inspirowane.pl” to 29 znaków. */
.kontakt-mail__adres a {
  font-family: var(--font-serif);
  font-size: clamp(1.2rem, 5vw, 1.75rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--brand-text);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.kontakt-mail__adres a:hover,
.kontakt-mail__adres a:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}

@media (min-width: 760px) {
  .kontakt-mail { padding: var(--s6); }
}

/* Sekcje poniżej pierwszego ekranu nie muszą być renderowane od razu */

.leniwa { content-visibility: auto; contain-intrinsic-size: auto 800px; }

/* Wyściółka boksów w treści na wąskim ekranie ---------------------------
   24 px z każdej strony to na ekranie 320 px osiemnaście procent szerokości
   boksu. Wiersz w „Krótko" i w spisie treści spadał wtedy do 26 znaków —
   poniżej progu, przy którym tekst czyta się płynnie (wygodny zakres to
   45–75 znaków, na telefonie realnie 35–40). Zejście do 16 px oddaje pięć
   znaków na wiersz i nie odbiera boksowi wyrazistości.                   */

@media (max-width: 480px) {
  .bluf, .spis { padding: var(--s4); }
}

/* ==========================================================================
   18a. WSTAWKI GRAFICZNE
   ==========================================================================

   Trzy warstwy dekoracyjne na stronie głównej. Wszystkie:
   • rysowane wyłącznie z --brand i --accent, więc zmiana dwóch kolorów
     w Customizerze przestawia je razem z resztą motywu;
   • czystym CSS-em, zero plików do pobrania;
   • w pseudoelementach z pointer-events: none, więc nic nie łapią
     i nic nie przesuwają w układzie;
   • w kontenerach z overflow: hidden, więc nie mogą rozepchnąć strony.

   Zasada nadrzędna została ta sama, co w całym motywie: kolor niosą
   zdjęcia. Te warstwy mają dawać głębię, a nie rywalizować z kadrem —
   stąd krycie w okolicach kilku procent.                              */

/* --- poświata pod otwarciem ------------------------------------------
   Dwie miękkie plamy w rogach: cieplejsza z akcentu po prawej, chłodniejsza
   z marki po lewej. Górny ekran przestaje być płaską bielą, a zdjęcia
   dostają tło, z którego wychodzą.                                    */

.otwarcie { position: relative; overflow: hidden; }

.otwarcie::before {
  content: ""; position: absolute; inset: -25% 0 0 0;
  pointer-events: none; z-index: 0;
  background:
    radial-gradient(55% 60% at 85% 8%, color-mix(in oklab, var(--accent), transparent 88%), transparent 70%),
    radial-gradient(50% 55% at 8% 0%, color-mix(in oklab, var(--brand), transparent 90%), transparent 72%);
}

.otwarcie > .wrap { position: relative; z-index: 1; }

/* --- duży numer sekcji w tle -----------------------------------------
   Ten sam numer, który stoi w nadkreśleniu, powtórzony szeryfowo
   i wielko przy krawędzi. Motyw ma już numerowane sekcje, więc znak
   nie jest ozdobnikiem znikąd — to ta sama informacja, tylko czytana
   kątem oka. Na wąskim ekranie znika: tam każdy piksel szerokości
   jest potrzebny treści.                                              */

.sekcja[data-nr] { position: relative; overflow: hidden; }

.sekcja[data-nr] > .wrap { position: relative; z-index: 1; }

/* Na dotyku sąsiadujące linki stopki nie mogą się stykać — 24 px celu
   bez odstępu to nadal jeden duży obszar pomyłki.                     */

@media (hover: none) {
  .stopka__lista, .stopka__sprzedaz .stopka__lista { gap: var(--s3); }
}

/* ==========================================================================
   19. DRUK
   ========================================================================== */

/* ==========================================================================
   POPRAWKI PO PRZENIESIENIU Z MAKIETY

   Makieta składała kafle skryptem i tylko skryptem, więc jej arkusz mógł
   założyć, że każdy `<img class="kafel__foto">` leży w kadrze o narzuconej
   wysokości i czeka na klasę `.zaladowane`. W motywie ten sam znacznik
   wypisuje `atl_kadr()` również poza ścianą — pod zdjęciem wiodącym wpisu
   i w miniaturach list bocznych. Bez tych dwóch reguł kadr zapada się do zera
   (obrazek jest `position:absolute` w kontenerze bez wysokości) i zostaje
   niewidoczny (`opacity:0` do momentu, w którym skrypt doda klasę —
   a poza ścianą nikt jej nie dodaje).

   Reguły stoją w osobnym partialu, nie w przeniesionych, żeby przy
   ponownym uruchomieniu narzedzia/wyciagnij-makiete.py nie zniknęły
   razem z nadpisanym plikiem.
   ========================================================================== */

.wpis-foto__kadr .kafel__foto,
.mini__kadr .kafel__foto {
  position: static;
  inset: auto;
  opacity: 1;
  transform: none;
}

/* Zdjęcie wiodące wpisu idzie w natywnych proporcjach generatora, więc
   nie wolno mu narzucać wysokości ani przycinać. */
.wpis-foto__kadr .kafel__foto {
  width: 100%;
  height: auto;
  object-fit: contain;
}

/* Hover na ścianie powiększa kadr; w listach bocznych to ruch bez powodu —
   kafel nie jest tam bohaterem widoku. */
.mini__kadr .kafel__foto {
  transition: none;
}

/* ==========================================================================
   BELKA WP-ADMINA

   NIEAKTYWNE przy domyślnych ustawieniach: motyw zdejmuje belkę z frontu
   filtrem `show_admin_bar` (inc/setup.php), więc klasa `admin-bar` na
   <body> nie powstaje i żadna z tych reguł nie ma do czego się przyczepić.

   Zostają świadomie. Belka wraca jednym `remove_filter` — na portalu, gdzie
   redakcja będzie jej chciała, albo w motywie potomnym — i wtedy odstępy
   muszą już być na miejscu. Bez nich objaw jest taki, jaki widzieliśmy:
   pasek nawigacji traci pierwsze 32 px, w tym całą linię z nazwami działów.

   Poniżej opis dla tego przypadku:

   Belka jest `position: fixed`, więc przyklejona nawigacja z `top: 0`
   wjeżdża pod nią i traci pierwsze 32 px.

   Wysokości i zachowanie belki są takie same we wszystkich motywach
   WordPressa, więc progi są jej progami, nie naszymi:
     - od 783 px belka ma 32 px i jest przyklejona,
     - 601–782 px belka ma 46 px i nadal jest przyklejona,
     - do 600 px belka jest `position: absolute` i ODJEŻDŻA razem ze stroną,
       więc nawigacja wraca na `top: 0`.

   Reguły dotyczą wyłącznie widoku zalogowanego (`body.admin-bar`) —
   czytelniczka portalu nie widzi tu żadnej różnicy.
   ========================================================================== */

@media screen and (min-width: 783px) {
  body.admin-bar .nawigacja { top: 32px; }
}

@media screen and (min-width: 601px) and (max-width: 782px) {
  body.admin-bar .nawigacja { top: 46px; }
}

/* Panel boczny wpisu też przykleja się pod paskiem, więc też musi zejść
   niżej przy belce wp-admina. Makieta miała tu wpisane 46 px — wysokość
   paska nawigacji — i to zostaje, bo pasek nadal ma tyle. Dokładamy tylko
   wysokość belki, i to tam, gdzie belka faktycznie jest przyklejona.

   Bez tej poprawki panel startował 32 px za wysoko (etykieta „więcej
   w tym dziale” pod belką) i był o 32 px za wysoki, więc jego własny
   pasek przewijania pojawiał się wcześniej, niż powinien. */

@media screen and (min-width: 1000px) {
  body.admin-bar .wrap--wpis .z-panelem__panel {
    top: calc(46px + var(--s5) + 32px);
    max-height: calc(100vh - 46px - var(--s6) - 32px);
  }
}

/* Wariantu na belkę 46 px tu nie ma: panel boczny wchodzi od 1000 px,
   a belka jest wysoka na 46 px tylko do 782 px — te dwa zakresy nigdy się
   nie spotykają. Reguła „na wszelki wypadek” byłaby martwym selektorem,
   którego nikt później nie usunie. */

/* ==========================================================================
   BLOKI KODU

   W makiecie nie ma ani jednego bloku kodu, więc w przeniesionym arkuszu nie
   ma reguł na `pre` i `code`. Na portalu z poradnikami wystarczy jeden blok
   z edytora, żeby to zobaczyć: `pre` nie łamie linii i domyślnie ma
   `overflow: visible`, więc długa linia rozpycha nie siebie, a CAŁY
   dokument. Zmierzone na localhoście po wstawieniu jednej linii kodu:
   przy 320 px szerokość dokumentu 950 px, przy 768 px — 958 px. Cała
   strona jechała w poziomie.

   `pre` przewija się teraz sam, we własnym pudełku. Region przewijalny musi
   być osiągalny z klawiatury, więc `tabindex` i `role` dokłada PHP
   (atl_opakuj_kod() w inc/tresc.php) — tak samo jak przy tabelach.
   ========================================================================== */

.tresc pre {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  margin: var(--s5) 0;
  padding: var(--s4);
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: 1.5;
  tab-size: 2;
}

/* Kod w bloku nie dostaje własnego tła ani ramki — miałby wtedy pudełko
   w pudełku. */
.tresc pre code {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  white-space: pre;
}

/* Kod w zdaniu ma się łamać w dowolnym miejscu: nazwy funkcji i ścieżki
   bywają dłuższe niż kolumna tekstu na telefonie. */
.tresc code {
  font-family: var(--font-mono);
  font-size: .92em;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .1em .35em;
  overflow-wrap: anywhere;
}

.tresc pre:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ==========================================================================
   KAFEL-OKŁADKA SZERSZY OD SWOJEJ KOLUMNY

   `.kafel--okladka > .kafel__kadr` ma `height: 100%` (kadr wypełnia pole
   siatki, w którym leży też podpis) i jednocześnie `aspect-ratio`. Gdy
   podana jest tylko JEDNA oś, przeglądarka liczy z niej drugą — i liczyła
   SZEROKOŚĆ z wysokości wiersza. Zmierzone na produkcji zantalo.pl przy
   320 px: kadr 307 px w kolumnie 288 px, prawa krawędź na 323 px.
   Widać to było jako ucięty z prawej kafel wiodący na telefonie
   (`.kafel--okladka` ma `overflow: hidden`, więc strona się nie przewijała
   i usterka nie rzucała się w oczy).

   Podanie OBU osi wyłącza `aspect-ratio` z rachunku — kadr wypełnia pole
   siatki dokładnie, a o jego wysokości decyduje podpis, tak jak ma być
   na kaflu-okładce.
   ========================================================================== */

.kafel--okladka > .kafel__kadr { width: 100%; min-width: 0; }

/* LICZBA KOLUMN JEST KLASĄ, NIE ZMIENNĄ INLINE.

   Szablon mówi, ile kolumn ściana chce na szerokim ekranie, klasą
   `sciana--kN` (atl_klasa_sciany() w inc/sekcje.php). Wcześniej wpisywał
   to jako `style="--kolumny:N"` prosto na element — a deklaracja inline
   bije każdy selektor z arkusza, więc trzy zapytania niżej nie robiły NIC.
   Zmierzone na localhoście przy 320 px: cztery kolumny po 65 px, prawa
   krawędź kadru na 323 px, znacznik działu poza ekranem, tytuły przycięte.

   Klamry poniżej ZWĘŻAJĄ i nigdy nie rozszerzają. To nie jest kosmetyka:
   pierwsza próba naprawy dawała `--kolumny: 3 !important` całej klasie
   `.sciana`, więc ściana rekomendacji pod wpisem, która chce dwóch
   kolumn, dostawała przy 900 px trzy. Dlatego każde zapytanie wymienia
   tylko te warianty, które są od limitu SZERSZE.                         */

.sciana--k1 { --kolumny: 1; }
.sciana--k2 { --kolumny: 2; }
.sciana--k3 { --kolumny: 3; }
.sciana--k4 { --kolumny: 4; }
.sciana--k5 { --kolumny: 5; }

@media (max-width: 1200px) {
  .sciana--k4, .sciana--k5 { --kolumny: 3; }
}

@media (max-width: 860px) {
  .sciana { --przerwa: 14px; }
  .sciana--k3, .sciana--k4, .sciana--k5 { --kolumny: 2; }
}

@media (max-width: 420px) {
  .sciana--k2, .sciana--k3, .sciana--k4, .sciana--k5 { --kolumny: 1; }
}

/* ==========================================================================
   BLOK FAQ Z GENERATORA (`.faq-schema-container` + <details>)

   Motyw ma własny akordeon FAQ (`.faq__pyt` / `.faq__odp`) i to jego style
   stoją w _wpis.scss. Na produkcji generator sieci oddaje jednak CO INNEGO:
   `<div class="faq-schema-container">` z listą `<details><summary>`.
   Sprawdzone na zantalo.pl — siedem takich bloków w jednym wpisie.

   Motyw je ROZUMIE (atl_wyjmij_faq() ma zapasową ścieżkę na <details>
   i buduje z nich FAQPage), ale ich nie STYLIZOWAŁ: pytania szły domyślnym
   trójkątem przeglądarki, bez ramek, bez odstępów i bez kursora wskazującego,
   że da się je kliknąć. W środku wystylizowanego artykułu wyglądało to jak
   fragment strony bez arkusza.

   Znaczników nie przepisujemy na `.faq__*`: pochodzą z treści wpisu, więc
   ich zmiana wymagałaby przerabiania bazy przy każdym imporcie. Nadajemy im
   wygląd akordeonu motywu — tak samo jak `.tabela-otoczka` dostaje wygląd,
   choć jej klasę też dokłada warstwa treści.
   ========================================================================== */

.faq-schema-container {
  border-top: 1px solid var(--rule);
  margin: var(--s5) 0;
}

.faq-schema-container details {
  border-bottom: 1px solid var(--rule);
}

.faq-schema-container summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4) 0;
  cursor: pointer;
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
}

/* Domyślny trójek ujawniania: w Chrome i Firefoksie zdejmuje go
   `list-style: none`, w Safari dopiero ten pseudo-element. Bez obu
   znacznik zostaje i stoi w osobnej linii pod pytaniem — bo `summary`
   zawiera nagłówek, czyli element blokowy. */
.faq-schema-container summary::-webkit-details-marker { display: none; }
.faq-schema-container summary::marker { content: ''; }

/* Znak rozwinięcia jak w akordeonie motywu: plus i minus, nie strzałka. */
.faq-schema-container summary::after {
  content: '+';
  font-family: var(--font-mono);
  font-size: 1.25rem;
  line-height: 1;
  color: var(--brand);
  flex: none;
}

.faq-schema-container details[open] > summary::after { content: '−'; }

/* Pytanie bywa opakowane w nagłówek — wtedy nie może wnosić własnych
   odstępów ani swojego stopnia pisma, bo rozbija wiersz akordeonu. */
.faq-schema-container summary > * {
  margin: 0;
  font: inherit;
  color: inherit;
  display: inline;
}

.faq-schema-container summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.faq-schema-container details > *:not(summary) {
  margin: 0 0 var(--s4);
  color: var(--ink-2);
  font-size: var(--fs-body);
}

/* --------------------------------------------------------------------------
   KLASA RDZENIA DLA TEKSTU TYLKO DLA CZYTNIKA

   Motyw ma własną `.tylko-czytnik`, ale rdzeń, wtyczki i trzy miejsca
   w samym Atelierze (znak grafiki AI w inc/obrazy.php, gwiazdka polecanego
   w inc/polecane.php, etykieta pola szukania w searchform.php) używają
   nazwy rdzeniowej. Rdzeń tej reguły NIE dostarcza — należy do motywu —
   więc bez niej ten tekst był po prostu WIDOCZNY: „AI grafika AI” przy
   zdjęciu, „★ polecany” na kaflu i słowo „Szukaj” nad polem.

   Deklaracje te same, co w `.tylko-czytnik` (sekcja 2 arkusza) — jedna
   nazwa nie może wyglądać inaczej od drugiej.
   -------------------------------------------------------------------------- */

.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   KADR WPISU BEZ ZDJĘCIA

   atl_zastepnik() wypisuje `<span class="kafel__zastepnik">` z odcieniem
   policzonym z identyfikatora wpisu (`--kat`), żeby ściana kafli bez zdjęć
   nie była płaską szarą kratą — a arkusz nie miał dla tej klasy ani jednej
   reguły, więc wszystkie takie kafle wyglądały identycznie. Na świeżym
   portalu, gdzie połowa wpisów nie ma jeszcze obrazka wyróżniającego,
   widać to na pierwszy rzut oka.

   Odcień wchodzi w dwa przystanki gradientu, oba o niskim nasyceniu:
   kafel ma sugerować materiał, a nie konkurować z sąsiadem, który zdjęcie
   ma. `aria-hidden` na znaczniku jest już w PHP — to ozdoba, nie treść.
   -------------------------------------------------------------------------- */

.kafel__zastepnik {
  display: block;
  width: 100%;
  height: 100%;
  background-image: linear-gradient(
    135deg,
    hsl(var(--kat, 0deg) 34% 88%),
    hsl(calc(var(--kat, 0deg) + 36deg) 26% 95%)
  );
}

/* ==========================================================================
   ODSTĘP PO OKRUSZKACH

   `.okruszki` nie miały marginesu dolnego, a szablony stawiają zaraz pod
   nimi nagłówek strony. Zmierzone na zantalo.pl, archiwum redakcji: dół
   okruszków na 258 px, góra `.redakcja-glowa` na 258 px — zero przerwy,
   ścieżka nawigacji skleja się z treścią. Zgłoszone z produkcji: „dodajmy
   odstęp po breadcrumbsie”.

   Margines idzie na okruszki, a nie na każdy element, który po nich stoi:
   okruszki są jedne, a sąsiadów mają pięciu (wpis, archiwum, redakcja,
   strona prawna, mapa serwisu). `--s5` (24 px) to ten sam odstęp, którym
   motyw rozdziela blok od bloku w kolumnie tekstu.
   ========================================================================== */

.okruszki { margin-bottom: var(--s5); }

/* ==========================================================================
   ODSTĘP PRZED SEKCJĄ REDAKCJI

   Karta autorki pod artykułem (`.autorka-box`) stykała się z treścią:
   zmierzone na zantalo.pl 24 px między dołem `.tresc` a górą karty, czyli
   tyle, co odstęp między akapitami — a to ma być granica między artykułem
   a stopką redakcyjną, nie kolejny akapit. To samo na archiwum redakcji,
   gdzie `.redakcja-glowa` startowała dokładnie pod okruszkami.

   `--s7` (48 px) na telefonie i `--s8` (64 px) od 760 px: odstęp rośnie
   razem z szerokością kolumny, bo na szerokim ekranie 48 px przestaje
   czytać się jako przerwa. Zgłoszone z produkcji: „brakuje odstępu przed
   redakcją (tak samo mniejsze rozdzielczości)”.
   ========================================================================== */

.autorka-box { margin-top: var(--s7); }

.redakcja-glowa { margin-top: var(--s5); }

@media (min-width: 760px) {
  .autorka-box { margin-top: var(--s8); }
}
