@charset "UTF-8";
/* ============================================================
   THEME STYLE — entry point. Partiale przez @use (sass scala je przy kompilacji).
   Kompilacja: npx sass theme-style.scss:theme-style.css --style=expanded --no-source-map
   ============================================================ */
/* ============================================================
   DESIGN TOKENS — QTA Grupa.

   Trzy piętra, w tej kolejności:
     1. ALIASY presetów z theme.json (paleta, odstępy, promienie, layout).
        theme.json jest źródłem prawdy dla tego, co widzi klient w edytorze.
     2. RAMPY pomocnicze — pełne skale barw, których w pickerze nie ma.
        To JEDYNE miejsce w motywie, gdzie wolno wpisać hex z palca.
     3. ROLE semantyczne (--bg, --fg, --line) i skale (--step-*, --leading-*).

   W blokach i sekcjach używamy wyłącznie nazw z tego pliku albo
   var(--wp--preset--color--*). Nigdy hexów, nigdy sztywnych px.
   ============================================================ */
:root {
  /* ========================================================
     1. ALIASY PRESETÓW (theme.json)
     ======================================================== */
  /* Odstępy — skala QTA, baza 4px. 1:1 do theme.json spacingSizes. */
  --space-3xs: var(--wp--preset--spacing--3-xs); /* 4px  */
  --space-2xs: var(--wp--preset--spacing--2-xs); /* 8px  */
  --space-xs: var(--wp--preset--spacing--xs); /* 12px */
  --space-s: var(--wp--preset--spacing--s); /* 16px */
  --space-m: var(--wp--preset--spacing--m); /* 24px */
  --space-l: var(--wp--preset--spacing--l); /* 32px */
  --space-xl: var(--wp--preset--spacing--xl); /* 48px */
  --space-2xl: var(--wp--preset--spacing--2-xl); /* 64px */
  --space-3xl: var(--wp--preset--spacing--3-xl); /* 96px */
  --space-4xl: var(--wp--preset--spacing--4-xl); /* 128px */
  /* Promienie */
  --radius-xs: var(--wp--custom--radius--xs);
  --radius-s: var(--wp--custom--radius--s);
  --radius-m: var(--wp--custom--radius--m);
  --radius-l: var(--wp--custom--radius--l);
  --radius-pill: var(--wp--custom--radius--pill);
  /* Siatka */
  --container: var(--wp--custom--layout--content); /* 1280px */
  --container-text: var(--wp--custom--layout--narrow); /* 68ch */
  --container-wide: var(--wp--custom--layout--wide); /* 1600px */
  --gutter: var(--wp--custom--layout--gutter);
  --section-y: var(--wp--custom--layout--section);
  /* Wysokość nagłówka. Pasek leży NA treści (position: absolute), więc
     miejsce pod nim robi padding, nie pozycjonowanie. Wartość tutaj to
     stan spoczynku (topbar 2.6rem + mainbar 5.25rem); rzeczywistą,
     zmierzoną, nadpisuje JS nagłówka na <html>. */
  --header-h: 7.85rem;
  /* Aliasy pod nazewnictwo motywu (JAK-BUDOWAC.md §4) */
  --layout-narrow: var(--wp--custom--layout--narrow);
  --layout-content: var(--wp--custom--layout--content);
  --layout-wide: var(--wp--custom--layout--wide);
  --transition: var(--wp--custom--transition--duration) var(--wp--custom--transition--ease);
  /* Barwy z palety edytora — krótkie nazwy z projektu QTA */
  --navy-950: var(--wp--preset--color--black); /* #071424 */
  --navy-900: var(--wp--preset--color--ink); /* #082238 */
  --navy-800: var(--wp--preset--color--navy); /* #0e3659 */
  --paper-000: var(--wp--preset--color--white); /* #fffdf9 */
  --paper-050: var(--wp--preset--color--paper-raised); /* #fcf9f4 */
  --paper-100: var(--wp--preset--color--paper); /* #f7f1e8 */
  --brass-700: var(--wp--preset--color--brass); /* #8a6428 */
  --brass-500: var(--wp--preset--color--brass-light); /* #b4884d */
  --stamp-600: var(--wp--preset--color--stamp); /* #a63a2e */
  --ledger-500: var(--wp--preset--color--ledger); /* #3a8763 */
  /* ========================================================
     2. RAMPY POMOCNICZE — poza pickerem edytora.
        Klient ich nie wybierze, my ich używamy w blokach.
     ======================================================== */
  --navy-700: #14456f;
  --navy-600: #1c5788;
  --navy-500: #2e6fa4;
  --navy-400: #5a8fbb;
  --navy-300: #93b4cd;
  --navy-200: #c3d5e2;
  --navy-100: #dde8f0;
  --navy-050: #eef4f8;
  --white: #ffffff;
  --paper-200: #f0e6da;
  --paper-300: #ebddd1; /* dominanta ściany z renderu hero */
  --paper-400: #e0cdb9;
  --paper-500: #d5bea6;
  --paper-600: #c2a78d;
  --paper-700: #a7896f;
  --ink-900: #241d16;
  --ink-700: #44352b; /* blat biurka z renderu */
  --ink-500: #6b5949;
  --ink-400: #8a7765;
  --brass-900: #5c4218;
  --brass-800: #74531f;
  --brass-600: #a67c37;
  --brass-300: #d9bd8c;
  --brass-100: #f2e6d0;
  --stamp-500: #c04a3b;
  --stamp-300: #e8887c; /* ta sama czerwień, czytelna na granacie */
  --stamp-100: #f6e2de;
  --ledger-600: #2e6b4f;
  --ledger-100: #dcece4;
  /* Kanały RGB — do przezroczystości: rgb(var(--navy-950-rgb) / 0.4) */
  --navy-950-rgb: 7 20 36;
  --navy-900-rgb: 8 34 56;
  --paper-000-rgb: 255 253 249;
  --paper-050-rgb: 252 249 244;
  --paper-100-rgb: 247 241 232;
  --paper-200-rgb: 240 230 218;
  --ink-900-rgb: 36 29 22;
  --ink-700-rgb: 68 53 43;
  --brass-500-rgb: 180 136 77;
  --ledger-500-rgb: 58 135 99;
  --white-rgb: 255 255 255;
  /* ========================================================
     3. ROLE SEMANTYCZNE
     ======================================================== */
  --bg: var(--paper-100);
  --bg-raised: var(--paper-050);
  --bg-sunken: var(--paper-200);
  --bg-invert: var(--navy-900);
  --fg: var(--navy-900);
  --fg-muted: var(--wp--preset--color--muted); /* #4a5b6b */
  --fg-subtle: #5a6874; /* 5,45:1 na papierze */
  --fg-invert: var(--paper-100);
  --fg-invert-muted: #a9bccd;
  --fg-invert-subtle: #8fa6ba;
  --fg-invert-faint: #7f96ab;
  --fg-invert-dim: #5d7891;
  --accent: var(--navy-800);
  --accent-hover: var(--navy-700);
  --accent-quiet: var(--brass-500);
  --line: var(--wp--preset--color--line); /* #ddd0c1 */
  --line-strong: #c9b8a5;
  /* Ramka pola formularza i pudełka wyboru. WCAG 1.4.11 chce 3:1 wobec
     tła dla granic komponentów, których nie da się rozpoznać inaczej —
     --line (1,5:1) i --line-strong (1,9:1) tego nie robią, więc pola
     dostają własny, ciemniejszy odcień: 3,6:1 na bieli, 3,3:1 na papierze. */
  --line-field: #94836f;
  --line-invert: rgb(var(--paper-200-rgb) / 0.18);
  --line-invert-strong: #4a627a;
  --focus: var(--brass-600);
  /* ========================================================
     SKALA PISMA — aliasy presetów tekstu z theme.json.

     Stąd bierze rozmiar to, czego nie da się opisać presetem, bo nie
     ma na czym powiesić klasy: proza z edytora (gołe <h2>, <p>, <li>
     w treści przeniesionej ze starego serwisu) i przyciski, które mają
     w theme.json wyłączone kontrolki typografii.

     Wszystko inne — bloki i znaczniki PHP — dostaje stopień z klasy
     presetu, nie stąd. Stopni nagłówkowych nie ma tu w ogóle: po
     przeniesieniu ich do globalnego `settings.typography.fontSizes`
     WP rozdaje je sam, globalnie i z !important.
     ======================================================== */
  --step--2: var(--wp--preset--font-size--text-xs);
  --step--1: var(--wp--preset--font-size--text-sm);
  --step-0: var(--wp--preset--font-size--text);
  --step-1: var(--wp--preset--font-size--text-lg);
  --step-2: var(--wp--preset--font-size--text-xl);
  --step-3: var(--wp--preset--font-size--text-xxl);
  /* ========================================================
     POSTACIE DEKORACYJNE

     Szerokość liczona od KONTENERA, nie od sekcji. Sekcja jest
     pełnoekranowa, więc procent od niej rósł razem z monitorem:
     przy 1920 px sylwetka miała 480 px i przerastała treść, obok
     której stoi. Od kontenera skala jest stała powyżej 1280 px.

     Jedna wartość dla wszystkich sekcji — inaczej każda postać
     ma inną wielkość i strona wygląda jak zlepek.
     ======================================================== */
  --postac-w: clamp(13rem, min(100vw, var(--container)) * 0.25, 20rem);
  /* Odległość od krawędzi okna do krawędzi kontenera. Dla warstw
     dekoracyjnych, które leżą POZA kontenerem i mają się zatrzymać
     na linii treści.

     Pasy otwierające podstrony już tego nie używają — postać kotwiczy
     się tam krawędzią od strony tekstu, nie od strony okna. Token
     zostaje, bo liczy rzecz, której inaczej nie da się napisać
     w jednej deklaracji.

     Musi być zmienną, nie wpisanym wprost wyrażeniem: sass upraszcza
     `calc()` wewnątrz `max()` w zwykłej deklaracji i przeglądarka
     odrzuca wynik, przez co max() bierze sam gutter. W deklaracji
     custom property calc zostaje nietknięty. */
  --krawedz-kontenera: max(var(--gutter), calc((100vw - var(--container)) / 2));
  /* Tokenu na postać w pasie otwierającym podstronę tu nie ma.
     Stała szerokość nie działała: zostawiała między ramieniem
     a kolumną tekstu od 240 do 290 px pustego papieru, zależnie od
     monitora. Te pasy mierzą postać wysokością sekcji i ramką rozpiętą
     do linii kolumny — patrz _components.scss, „pas otwierający”. */
  /* Interlinia */
  --leading-none: 1;
  --leading-tight: 1.06;
  --leading-snug: 1.2;
  --leading-mid: 1.35;
  --leading-copy: 1.5;
  --leading-normal: 1.6;
  --leading-loose: 1.75;
  /* Światło międzyliterowe — nagłówki chodzą ze skalą */
  --tracking-h1: -0.03em;
  --tracking-h2: -0.028em;
  --tracking-h3: -0.024em;
  --tracking-h4: -0.02em;
  --tracking-h5: -0.018em;
  --tracking-h6: -0.01em;
  --tracking-tight: -0.022em;
  --tracking-normal: 0;
  --tracking-num: 0.01em;
  --tracking-slight: 0.02em;
  --tracking-wide: 0.06em;
  --tracking-widest: 0.16em;
  /* ========================================================
     CIENIE — miękkie i ciepłe, bez czerni
     ======================================================== */
  --shadow-xs: 0 1px 2px rgb(var(--ink-700-rgb) / 0.06);
  --shadow-s: 0 2px 6px rgb(var(--ink-700-rgb) / 0.07), 0 1px 2px rgb(var(--ink-700-rgb) / 0.05);
  --shadow-m: 0 6px 20px rgb(var(--ink-700-rgb) / 0.09), 0 2px 6px rgb(var(--ink-700-rgb) / 0.05);
  --shadow-l: 0 18px 48px rgb(var(--ink-700-rgb) / 0.13), 0 4px 12px rgb(var(--ink-700-rgb) / 0.06);
  --shadow-navy: 0 10px 28px rgb(var(--navy-900-rgb) / 0.22);
  --shadow-on-navy: 0 18px 48px rgb(var(--navy-950-rgb) / 0.42);
  /* Aliasy pod nazewnictwo motywu */
  --shadow-sm: var(--shadow-s);
  --shadow-md: var(--shadow-m);
  --shadow-lg: var(--shadow-l);
  --shadow-ring: 0 0 0 3px rgb(var(--brass-500-rgb) / 0.35);
  /* ========================================================
     RUCH I WARSTWY
     ======================================================== */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --dur-fast: 140ms;
  --dur: 260ms;
  --dur-slow: 620ms;
  --z-base: 1;
  --z-sticky: 100;
  --z-header: 200;
  --z-drawer: 300;
  --z-modal: 400;
  /* Wysokość linijki księgowej — tła „w kratkę" */
  --ledger-line: 2rem;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 1ms;
    --dur: 1ms;
    --dur-slow: 1ms;
  }
}
/* ============================================================
   TYPOGRAFIA — QTA Grupa.

   Podział, którego trzymamy się bez wyjątków:

   • ROZMIAR nadaje PRESET z theme.json. WP wypuszcza go z !important
     (sprawdzone: `.has-text-font-size{font-size:var(--…) !important}`),
     więc żaden font-size wpisany tutaj dla klasy .has-*-font-size
     i tak by nie zadziałał. Dlatego ich tu NIE MA.
     Preset dostaje tu wyłącznie krój, interlinię i światło.

   • ŻADNA klasa w tym pliku nie ustawia font-size dla presetu. Stopnie
     (has-heading-N, has-text-*) rozdaje WP z theme.json — globalnie
     i z !important. Tutaj jest tylko to, co presetem nie jest: krój,
     interlinia, światło międzyliterowe, barwa.

   • WARSTWA TEKSTU (.lead, .note, .micro, .label, .cell-text, .col-head)
     to role, nie stopnie. Blok przypina klasę przez className i dokłada
     najwyżej max-width oraz margines.
   ============================================================ */
body {
  /* ========================================================
     STOPNIE NAGŁÓWKÓW — krój, interlinia, światło. Bez rozmiaru.

     `has-heading-N-font-size` to preset z theme.json, więc dokładnie
     ta klasa wychodzi z Gutenberga, kiedy w edytorze wybierze się
     „Rozmiar liter”. Tej samej używamy w znacznikach PHP — jedno
     nazewnictwo dla nagłówka wyklikanego i napisanego ręcznie.

     Rozmiaru tu NIE MA i nie wolno go dopisywać: WP wypuszcza go
     globalnie i z !important —

       .has-heading-1-font-size{font-size: var(--wp--preset--font-size--heading-1) !important}

     — więc każda nasza deklaracja font-size i tak by przegrała.
     Źródłem prawdy dla stopni jest theme.json, nie ten plik.

     Warunek: stopnie muszą stać w theme.json w GLOBALNYM
     `settings.typography.fontSizes`. Kiedy siedziały pod
     `settings.blocks."core/heading"`, WP zawężał i zmienną, i regułę
     do `.wp-block-heading` — nagłówek pisany w PHP zostawał bez
     rozmiaru, a pole „Wielkość liter” przy akapicie w ogóle ich nie
     znało. Nie przenoś ich z powrotem.
     ======================================================== */
}
body .has-heading-1-font-size,
body .has-heading-2-font-size,
body .has-heading-3-font-size,
body .has-heading-4-font-size,
body .has-heading-5-font-size,
body .has-heading-6-font-size {
  font-family: var(--ffont);
  font-weight: 700;
  line-height: var(--leading-tight);
  text-wrap: balance;
  /* Barwa DZIEDZICZY. Wpisany tu granat wygrywał z sekcjami na ciemnym
     tle (stopka, karta CTA) przez remis specyficzności, bo global styles
     i arkusze sekcji mają po 0,1,1. Domyślną barwę daje body. */
  color: inherit;
}
body .has-heading-1-font-size {
  letter-spacing: var(--tracking-h1);
}
body .has-heading-2-font-size {
  letter-spacing: var(--tracking-h2);
}
body .has-heading-3-font-size {
  letter-spacing: var(--tracking-h3);
}
body .has-heading-4-font-size {
  letter-spacing: var(--tracking-h4);
}
body .has-heading-5-font-size {
  letter-spacing: var(--tracking-h5);
}
body .has-heading-6-font-size {
  letter-spacing: var(--tracking-h6);
}
body {
  /* ========================================================
     PRESETY TEKSTU — tylko krój i interlinia.
     ======================================================== */
}
body .has-text-xs-font-size,
body .has-text-sm-font-size,
body .has-text-font-size,
body .has-text-lg-font-size,
body .has-text-xl-font-size,
body .has-text-xxl-font-size {
  font-family: var(--sfont);
}
body .has-text-xs-font-size,
body .has-text-sm-font-size,
body .has-text-font-size {
  line-height: var(--leading-normal);
}
body .has-text-lg-font-size {
  line-height: var(--leading-copy);
}
body .has-text-xl-font-size,
body .has-text-xxl-font-size {
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
}
body {
  /* ========================================================
     WARSTWA TEKSTU — ROLE, nie stopnie.

     Te klasy mówią, CZYM jest tekst (akapit wprowadzający, drobne
     pismo, rubryka wersalikami), a nie JAK duży ma być. Rozmiaru
     tu NIE MA i nie wolno go dopisywać: nadaje go wyłącznie preset —
     w bloku atrybut `fontSize`, w znacznikach PHP klasa
     `has-<slug>-font-size`.

     Powód jest praktyczny, nie estetyczny: kiedy rozmiar siedział
     w klasie roli, pole „Wielkość liter” w edytorze pokazywało
     „Domyślne”, choć tekst miał swój stopień. Panel kłamał, a klient
     nie miał czym tego zmienić.

     Dobór presetu do roli (te same wartości, co wcześniej):
       .lead        → text        .lead--lg      → text-lg
       .note        → text-sm     .micro         → text-xs
       .cell-text   → text        .cell-text--sm → text-sm
       .col-head    → text-sm     .label         → text-xs
       .eyebrow     → text-sm     (patrz _components.scss)

     Modyfikator --invert przestawia barwę na granatowe tło.
     ======================================================== */
  /* Akapit wprowadzający pod nagłówkiem sekcji */
}
body .lead {
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}
body .lead--lg { /* gdy akapit jest jedyną treścią obok hasła */
  line-height: var(--leading-copy);
}
body .lead--loose { /* dłuższa nota o nas */
  line-height: var(--leading-loose);
}
body .lead--invert {
  color: var(--paper-200);
}
body {
  /* Drobne pismo: opisy kart, podpisy pod kadrem, listy w stopce */
}
body .note {
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}
body .note--tight {
  line-height: var(--leading-mid);
}
body .note--invert {
  color: var(--fg-invert-muted);
}
body .note--light {
  color: var(--fg-invert);
}
body {
  /* Stanowisko pod nazwiskiem — mosiądz odróżnia je od zwykłego opisu */
}
body .note--brass {
  color: var(--brass-700);
}
body {
  /* Najdrobniejsze: etykiety kolumn, jednostki, numery pozycji */
}
body .micro {
  color: var(--fg-subtle);
}
body .micro--invert {
  color: var(--fg-invert-muted);
}
body .micro--light {
  color: var(--fg-invert);
}
body .micro--brass {
  color: var(--brass-600);
}
body .micro--brass-light {
  color: var(--brass-300);
}
body {
  /* Zdanie w komórce zestawienia: krótkie, więc na ciasnej interlinii */
}
body .cell-text {
  line-height: var(--leading-snug);
}
body {
  /* Główka kolumny i temat wiersza: krój nagłówkowy, stopień z presetu */
}
body .col-head {
  font-family: var(--ffont);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
}
body {
  /* Rubryka wersalikami w mosiądzu, jak główka kolumny w formularzu */
}
body .label {
  font-weight: 600;
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--brass-700);
}
body .label--invert {
  color: var(--brass-300);
}
body {
  /* Liczby zawsze tabelarycznie, jak w zestawieniu obrotów */
}
body .num {
  font-feature-settings: "tnum" 1, "zero" 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-num);
}
body {
  /* Tekst na granacie — wrapper zdejmujący domyślne barwy */
}
body .on-navy {
  color: var(--fg-invert);
}
body .on-navy .has-heading-1-font-size,
body .on-navy .has-heading-2-font-size,
body .on-navy .has-heading-3-font-size,
body .on-navy .has-heading-4-font-size,
body .on-navy .has-heading-5-font-size,
body .on-navy .has-heading-6-font-size {
  color: var(--paper-000);
}

/* ============================================================
   PROZA — jedyny zakres, w którym stylujemy GOŁE tagi.

   Treść wpisu przychodzi z edytora (a przy migracji ze starego
   serwisu — z cudzego edytora) i nie ma na sobie klas presetów.
   Nagłówek jest tam po prostu <h2>, nie <h2 class="has-…">.
   Reset zeruje tagom wszystko, więc bez tego bloku wpis czyta się
   jak surowy HTML.

   Reguła „rozmiar nadaje preset" NIE jest tu łamana: sięgamy po te
   same zmienne --step-*, którymi karmione są presety. Zmienia się
   tylko haczyk — tag zamiast klasy — bo klasy w tej treści nie ma.

   Kolumna jest wąska (--layout-narrow ≈ 68 znaków), bo to jedyna
   szerokość, przy której dłuższy tekst czyta się bez gubienia wiersza.
   ============================================================ */
body {
  /* Treść wpisu i podstrony. Sama ustawia swoje szerokości, więc nie
     potrzebuje opakowania w .container — inaczej mierzylibyśmy tę samą
     rzecz dwa razy, a każde wyjście poza kolumnę tekstu trzeba było
     ratować marginesem ujemnym.

     Trzy tory siatki: „content” to kolumna tekstu (68ch), „wide” sięga
     szerokości sekcji na stronie (1280px), „full” do krawędzi ekranu.
     Blok wybiera tor klasą, którą nadaje mu edytor: bez klasy leci
     w kolumnie tekstu, „Szeroki” w torze wide, „Pełna szerokość”
     w torze full. Żadnych stylów wpisywanych w znacznik. */
}
body .prose {
  --prose-pas: calc((var(--layout-content) - var(--layout-narrow)) / 2);
  display: grid;
  grid-template-columns: [full-start] minmax(var(--gutter), 1fr) [wide-start] minmax(0, var(--prose-pas)) [content-start] min(var(--layout-narrow), 100% - var(--gutter) * 2) [content-end] minmax(0, var(--prose-pas)) [wide-end] minmax(var(--gutter), 1fr) [full-end];
  font-size: var(--step-0);
  line-height: var(--leading-copy);
  color: var(--fg);
}
body .prose > * {
  grid-column: content;
}
body .prose {
  /* Zerowanie marginesów przez :where() — specyficzność 0, żeby reguła
     rytmu „> * + *” niżej zawsze wygrywała. Wcześniej „.prose p { margin: 0 }”
     (0,1,2) przebijało rytm (0,1,1) i akapity się sklejały. */
}
body .prose :where(h2, h3, h4, h5, h6, p, ul, ol, figure, blockquote, hr) {
  margin: 0;
}
body .prose > .alignwide {
  grid-column: wide;
}
body .prose > .alignfull {
  grid-column: full;
}
body .prose {
  /* W siatce marginesy się nie zlewają, więc rytm nadaje wyłącznie
     odstęp górny kolejnego elementu — inaczej odległość między
     akapitami byłaby sumą dwóch marginesów. */
}
body .prose > * {
  margin-block: 0;
}
body .prose > * + * {
  margin-top: var(--space-s);
}
body .prose > * + :is(h2, h3, h4, h5, h6),
body .prose > * + :is(.alignwide, .alignfull),
body .prose > :is(.alignwide, .alignfull) + * {
  margin-top: var(--space-xl);
}
body .prose h2, body .prose h3, body .prose h4, body .prose h5, body .prose h6 {
  font-family: var(--ffont);
  font-weight: 700;
  line-height: var(--leading-tight);
  text-wrap: balance;
  color: var(--navy-900);
}
body .prose h2 {
  font-size: var(--step-3);
  letter-spacing: var(--tracking-h3);
}
body .prose h3 {
  font-size: var(--step-2);
  letter-spacing: var(--tracking-h4);
}
body .prose h4 {
  font-size: var(--step-1);
  letter-spacing: var(--tracking-h5);
}
body .prose h5,
body .prose h6 {
  font-size: var(--step-0);
  letter-spacing: var(--tracking-h6);
}
body .prose ul,
body .prose ol {
  padding-left: var(--space-m);
}
body .prose li + li {
  margin-top: var(--space-2xs);
}
body .prose {
  /* Wewnątrz cytatu, elementu listy czy komórki tabeli siatka już nie
     sięga, więc rytm trzyma tam zwykły odstęp górny. */
}
body .prose :is(blockquote, li, td, th, figure) > * + * {
  margin-top: var(--space-s);
}
body .prose li::marker {
  color: var(--brass-500);
}
body .prose {
  /* Odnośnik w prozie musi być widoczny bez najeżdżania myszą —
     w tekście ciągłym sama barwa to za mało. */
}
body .prose a {
  color: var(--brass-700);
  text-decoration: underline;
  text-decoration-color: var(--brass-300);
}
body .prose a:hover {
  text-decoration-color: currentColor;
}
body .prose strong,
body .prose b {
  color: var(--navy-900);
}
body .prose img,
body .prose figure img {
  border-radius: var(--radius-m);
}
body .prose figcaption {
  margin-top: var(--space-2xs);
  font-size: var(--step--1);
  color: var(--fg-subtle);
}
body .prose {
  /* Cytat jak dopisek na marginesie dokumentu */
}
body .prose blockquote {
  padding-left: var(--space-m);
  border-left: 3px solid var(--brass-500);
  font-size: var(--step-1);
  line-height: var(--leading-copy);
  color: var(--navy-800);
}
body .prose hr {
  border: 0;
  border-top: 1px solid var(--line);
}
body .prose {
  /* Tabela ucieka poza wąską kolumnę, bo zestawienie liczb rzadko
     mieści się w 68 znakach. Przewija się w swojej ramce, nie
     rozpycha strony. */
}
body .prose .wp-block-table,
body .prose figure.wp-block-table {
  overflow-x: auto;
}
body .prose table {
  border-collapse: collapse;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}
body .prose th,
body .prose td {
  padding: var(--space-2xs) var(--space-xs);
  border-bottom: 1px solid var(--line);
  text-align: left;
}
body .prose th {
  font-weight: 600;
  color: var(--navy-900);
}
body {
  /* Fotografia i tabela idą torem szerszym niż kolumna tekstu, nawet gdy
     redaktor nie ustawił im wyrównania — obraz w 68 znakach wygląda jak
     znaczek pocztowy, a zestawienie liczb rzadko się w nich mieści.
     Blok z własnym wyrównaniem tego nie łapie, bo tam decyduje edytor. */
}
body .prose > :is(.wp-block-image, figure, .wp-block-table):not(.alignwide):not(.alignfull):not(.alignleft):not(.alignright) {
  grid-column: wide;
}
body {
  /* Obraz zostaje w swoim naturalnym rozmiarze — rozciąganie małego pliku
     na szerokość toru dałoby rozmytą plamę. Tor tylko przestaje go dusić. */
}
body .prose > figure img {
  max-width: 100%;
}

/* ============================================================
   PRZYCISKI — klawisz kalkulatora biurowego.

   Konstrukcja: twarda krawędź 2px pod spodem (--btn-lift), światło na górnej
   fasce, wciśnięcie dopiero na kliknięciu. Hover zmienia wyłącznie barwę —
   klawisza nie da się unieść.

   DWA TORY, JEDNA BRYŁA:
     • core/button w edytorze → .wp-block-button.is-style-<wariant>
     • przycisk w szablonie PHP (stopka, szuflada) → a.btn.btn--<wariant>
   Wariant ustawia tylko zmienne --btn-*, więc oba tory dzielą całą resztę.
   Warianty: granat (domyślny) · papier · mosiadz · jasny.
   Rejestracja stylów bloku: includes/cli/button-styles.php

   Modyfikatory (w edytorze: „Zaawansowane → dodatkowe klasy CSS”):
     btn--phone   ikona słuchawki odcięta pionową kreską
     btn--arrow   strzałka wysuwa się na hover
     btn--sm      niższy
     btn--lg      wyższy, do zamknięć sekcji
   ============================================================ */
body {
  /* --- Zmienne wariantu: dziedziczą w dół, więc mogą siedzieć
         na wrapperze bloku albo na samym <a class="btn"> ---------- */
}
body .wp-block-button,
body .btn {
  --btn-bg: var(--navy-800);
  --btn-fg: var(--paper-000);
  --btn-edge: var(--navy-950);
  --btn-lift: 2px;
}
body {
  /* --- Bryła klawisza ------------------------------------------- */
}
body .wp-block-button .wp-block-button__link,
body .btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7em;
  padding: 0.62rem 1.15rem;
  min-height: 2.75rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 0;
  border-radius: var(--radius-s);
  font-family: var(--sfont);
  font-size: var(--step--1);
  font-weight: 500;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-normal);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgb(var(--white-rgb)/0.13), 0 var(--btn-lift) 0 var(--btn-edge), 0 calc(var(--btn-lift) + 2px) 7px rgb(var(--ink-700-rgb)/0.11);
  transition: transform 90ms var(--ease-out), box-shadow 90ms var(--ease-out), background-color var(--dur) var(--ease-out);
}
body .wp-block-button .wp-block-button__link:active,
body .btn:active {
  --btn-lift: 0px;
  transform: translateY(2px);
  box-shadow: inset 0 1px 2px rgb(var(--ink-900-rgb)/0.22), 0 1px 2px rgb(var(--ink-700-rgb)/0.14);
}
body .wp-block-button .wp-block-button__link:focus-visible,
body .btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
body .btn__icon {
  flex: none;
  width: 1.05em;
  height: 1.05em;
}
body {
  /* ========================================================
     WARIANTY
     ======================================================== */
  /* --- Granat: klawisz podstawowy ------------------------------ */
}
body .wp-block-button.is-style-granat .wp-block-button__link:hover,
body .btn--granat:hover {
  --btn-bg: var(--navy-700);
}
body {
  /* --- Papier: ten sam klawisz odlany w papierze --------------- */
}
body .wp-block-button.is-style-papier,
body .btn--papier {
  --btn-bg: var(--paper-000);
  --btn-fg: var(--navy-800);
  --btn-edge: var(--paper-500);
}
body .wp-block-button.is-style-papier .wp-block-button__link,
body .btn--papier {
  box-shadow: inset 0 0 0 1px var(--line-strong), 0 var(--btn-lift) 0 var(--btn-edge), 0 calc(var(--btn-lift) + 2px) 7px rgb(var(--ink-700-rgb)/0.09);
}
body .wp-block-button.is-style-papier .wp-block-button__link:hover,
body .btn--papier:hover {
  --btn-bg: var(--white);
  --btn-fg: var(--navy-900);
  --btn-edge: var(--paper-600);
}
body .wp-block-button.is-style-papier .wp-block-button__link:active,
body .btn--papier:active {
  box-shadow: inset 0 0 0 1px var(--line-strong), inset 0 1px 2px rgb(var(--ink-700-rgb)/0.16);
}
body {
  /* --- Mosiądz: akcent w granatowych panelach ------------------ */
}
body .wp-block-button.is-style-mosiadz,
body .btn--mosiadz {
  --btn-bg: var(--brass-700); /* 5,25:1 z jasnym tekstem */
  --btn-fg: var(--paper-000);
  --btn-edge: var(--brass-900);
}
body .wp-block-button.is-style-mosiadz .wp-block-button__link:hover,
body .btn--mosiadz:hover {
  --btn-bg: var(--brass-800);
}
body {
  /* --- Jasny: biel na granacie --------------------------------- */
}
body .wp-block-button.is-style-jasny,
body .btn--jasny {
  --btn-bg: var(--paper-000);
  --btn-fg: var(--navy-900);
  --btn-edge: var(--paper-600);
}
body .wp-block-button.is-style-jasny .wp-block-button__link:hover,
body .btn--jasny:hover {
  --btn-bg: var(--white);
}
body {
  /* ========================================================
     MODYFIKATORY

     Klasa modyfikatora z edytora ląduje na KONTENERZE bloku
     (div.wp-block-button), nie na samym klawiszu. Dlatego wariant dla
     szablonów PHP celuje w `.btn.btn--x`, a nie w gołe `.btn--x` —
     inaczej ten sam pseudoelement rysuje się dwa razy: raz w klawiszu
     z bloku, raz na jego kontenerze, obok przycisku.
     ======================================================== */
  /* Ikona w klawiszu — jeden element i jedna reguła.

     Ikonę wstawia szablon PHP albo filtr render_block dla core/button
     (includes/cli/button-styles.php), więc w obu wypadkach jest to zwykłe
     <svg class="btn__icon"> i kreska odcinająca ją od etykiety może być
     jego obramowaniem. Wcześniej blok dostawał ikonę maską CSS, a `mask`
     przycina element razem z ramką — kreskę trzeba było wrysowywać
     w ikonę i nic się nie zgadzało. */
}
body .btn__icon {
  flex: none;
  width: 1.25em;
  height: 1.25em;
  padding-inline-end: 0.7em;
  border-inline-end: 1px solid currentColor;
  box-sizing: content-box;
  opacity: 0.55;
}
body {
  /* Wariant po prawej stronie etykiety (strzałka): kreska po drugiej stronie. */
}
body .btn__icon--po {
  padding-inline: 0.7em 0;
  border-inline-start: 1px solid currentColor;
  border-inline-end: 0;
  transition: transform var(--dur) var(--ease-out);
}
body .wp-block-button.btn--phone .wp-block-button__link,
body .btn.btn--phone {
  font-feature-settings: "tnum" 1;
  letter-spacing: var(--tracking-slight);
}
body {
  /* Strzałka wysuwa się w hoverze */
}
body .wp-block-button.btn--arrow .wp-block-button__link:hover .btn__icon--po,
body .btn.btn--arrow:hover .btn__icon--po {
  transform: translateX(3px);
}
body .wp-block-button.btn--sm .wp-block-button__link,
body .btn.btn--sm {
  min-height: 2.4rem;
  padding: 0.4rem 0.9rem;
  font-size: var(--step--2);
}
body .wp-block-button.btn--lg,
body .btn--lg {
  --btn-lift: 3px;
}
body .wp-block-button.btn--lg .wp-block-button__link,
body .btn.btn--lg {
  min-height: 3.4rem;
  padding: 0.85rem 1.6rem;
  font-size: var(--step-0);
  font-weight: 600;
}

/* ============================================================
   KOMPONENTY WSPÓŁDZIELONE — elementy wracające w wielu sekcjach.
   Wszystko na tokenach z _tokens.scss. Zero sztywnych px poza
   optycznym justowaniem (wyrównanie ikon do linii bazowej).
   ============================================================ */
body {
  /* ========================================================
     KONTENER — jedyne miejsce, które ustawia szerokość treści.
     Schemat sekcji: section > .container > .<blok>__content
     Ta sama wartość dla nagłówka, hero, sekcji i stopki, więc
     wszystko zaczyna treść na tym samym x.
     ======================================================== */
}
body .container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
body {
  /* Warstwy dekoracyjne (__bg, __media, __person) leżą poza kontenerem,
     bo z definicji sięgają krawędzi ekranu. */
  /* ========================================================
     ODBICIE LUSTRZANE OBRAZU

     Wycinki postaci są robione w jedną stronę, więc przy przeciwnej
     krawędzi sekcji człowiek odwraca się od treści. Zamiast drugiego
     pliku w bibliotece obracamy go stylem bloku: w panelu „Style” →
     „Odbicie lustrzane”, powrót tym samym kliknięciem. Rejestracja
     wariantu: includes/cli/image-styles.php.

     Druga klasa, `odbicie`, jest dla wpisania ręcznie w „Dodatkowe
     klasy CSS”. Style bloku wykluczają się wzajemnie, więc bez niej
     nie dałoby się złożyć odbicia z innym stylem obrazu.
     ======================================================== */
}
body .wp-block-image.is-style-odbicie img,
body .wp-block-image.odbicie img,
body .wp-block-cover.is-style-odbicie > .wp-block-cover__image-background,
body .wp-block-cover.odbicie > .wp-block-cover__image-background {
  transform: scaleX(-1);
}
body {
  /* ========================================================
     RUBRYKA SEKCJI — etykieta z odhaczonym znacznikiem.
     Ten sam znak wraca przy każdym eyebrow na stronie.
     ======================================================== */
  /* Rozmiaru tu nie ma — nadaje go preset (text-sm). Patrz komentarz
     przy warstwie tekstu w _typography.scss. */
}
body .eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-normal);
  color: var(--navy-800);
}
body .eyebrow--invert {
  color: var(--fg-invert-muted);
}
body {
  /* Znacznik jako tło pseudoelementu — dla tekstu, który w edytorze ma
     zostać czystym tekstem (nagłówek Gutenberga nie uniesie inline SVG).
     Dwie barwy zapieczone w data-URI, bo maska uniosłaby tylko jedną. */
}
body .has-mark::before {
  content: "";
  flex: none;
  width: 1.2rem;
  height: 1.2rem;
  background: var(--icon-mark) center/contain no-repeat;
}
body .has-mark {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}
body .eyebrow--invert.has-mark::before,
body .on-navy .has-mark::before {
  background-image: var(--icon-mark-invert);
}
body {
  /* Wariant z inline SVG — tam, gdzie znacznik siedzi w szablonie PHP */
}
body .mark {
  --mark-tick: var(--paper-000);
  display: block;
  flex: none;
  width: 1.2rem;
  height: 1.2rem;
  color: var(--brass-700);
}
body .mark__box {
  fill: currentColor;
}
body .mark__tick {
  stroke: var(--mark-tick);
}
body .eyebrow--invert .mark {
  --mark-tick: var(--navy-950);
  color: var(--brass-300);
}
body {
  /* ========================================================
     TŁA PAPIEROWE
     ======================================================== */
  /* Ziarno papieru: fraktalny szum, jeden inline SVG, zero requestów */
}
body .paper-grain::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: var(--texture-grain);
}
body {
  /* Linie księgi rachunkowej, jak w zeszycie kancelaryjnym */
}
body .ledger-lines {
  position: relative;
}
body .ledger-lines::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.4;
  background-image: repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--ledger-line) - 1px), var(--line) calc(var(--ledger-line) - 1px), var(--line) var(--ledger-line));
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 78%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 78%, transparent);
}
body {
  /* ========================================================
     KLAWISZE KARUZELI — ten sam klawisz co przyciski, tylko kwadratowy
     i odlany w papierze. Wyłączony gaśnie i opada o 1px zamiast znikać,
     żeby pasek nie skakał na końcu taśmy.
     ======================================================== */
}
body .carousel-btn {
  --btn-lift: 2px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  background: var(--paper-000);
  color: var(--navy-800);
  border: 0;
  border-radius: var(--radius-s);
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--line-strong), 0 var(--btn-lift) 0 var(--paper-500), 0 calc(var(--btn-lift) + 2px) 7px rgb(var(--ink-700-rgb)/0.09);
  transition: transform 90ms var(--ease-out), box-shadow 90ms var(--ease-out), background-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
body .carousel-btn svg {
  width: 1.15rem;
  height: 1.15rem;
}
body .carousel-btn:hover:not(:disabled) {
  background: var(--white);
  color: var(--navy-900);
}
body .carousel-btn:active:not(:disabled) {
  --btn-lift: 0px;
  transform: translateY(2px);
  box-shadow: inset 0 0 0 1px var(--line-strong), inset 0 1px 2px rgb(var(--ink-900-rgb)/0.16), 0 1px 2px rgb(var(--ink-700-rgb)/0.12);
}
body .carousel-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
body .carousel-btn:disabled {
  --btn-lift: 1px;
  color: var(--paper-600);
  cursor: default;
  box-shadow: inset 0 0 0 1px var(--line), 0 1px 0 var(--paper-400);
}
body {
  /* ========================================================
     ZNAK FIRMOWY — logo klienta przemalowane maską na granat
     ======================================================== */
}
body .logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--navy-900);
  transition: color var(--dur) var(--ease-out);
}
body .logo:hover {
  color: var(--navy-700);
}
body .logo__mark {
  display: block;
  width: 4.5rem;
  height: 4.5rem;
  background-color: currentColor;
  -webkit-mask: var(--logo-src) center/contain no-repeat;
  mask: var(--logo-src) center/contain no-repeat;
  transition: width var(--dur) var(--ease-out), height var(--dur) var(--ease-out);
}
body {
  /* ========================================================
     POMOCNICZE
     ======================================================== */
}
body .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
body .skip-link {
  position: absolute;
  top: var(--space-2xs);
  left: var(--space-2xs);
  z-index: var(--z-modal);
  padding: 0.7rem 1.1rem;
  background: var(--navy-900);
  color: var(--paper-050);
  font-size: var(--step--1);
  border-radius: var(--radius-s);
  transform: translateY(-160%);
  transition: transform var(--dur) var(--ease-out);
}
body .skip-link:focus-visible {
  transform: translateY(0);
}

/* Znacznik sekcji jako data-URI. Dwie wersje, bo na granacie odwraca się
   układ barw: mosiądz jaśnieje, ptaszek idzie w granat. */
:root {
  /* Ziarno papieru: fraktalny szum, jeden inline SVG, zero requestów */
  --texture-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E");
  --icon-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Crect x='1.6' y='1.6' width='14.8' height='14.8' rx='2' fill='%238a6428'/%3E%3Cpath d='m5.4 9.1 2.5 2.5 4.7-5.2' fill='none' stroke='%23fffdf9' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --icon-mark-invert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Crect x='1.6' y='1.6' width='14.8' height='14.8' rx='2' fill='%23d9bd8c'/%3E%3Cpath d='m5.4 9.1 2.5 2.5 4.7-5.2' fill='none' stroke='%23071424' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* Słuchawka i koperta do MASKI, nie do tła: barwę daje
     `background-color` elementu, więc znak chodzi z kolorem tekstu.

     Pliki dostały `xmlns`, którego wcześniej nie miały. Reszta ikon
     w assets/svg/ui/ też go nie ma i nie musi — motyw wstawia je
     inline przez tb_icon(), a w znaczniku strony namespace jest zbędny.
     Ale plik wciągnięty przez url() jest osobnym dokumentem: bez xmlns
     przeglądarka go odrzuca i maska wychodzi pusta, bez śladu w konsoli.
     Ikony w menu-icons/ mają xmlns od początku i dlatego działają. */
  --icon-phone: url("assets/svg/ui/phone.svg");
  --icon-mail: url("assets/svg/ui/mail.svg");
}

/* ============================================================
   STYK SEKCJI

   Sekcje stykają się prostą linią. Prototyp miał tu eliptyczny łuk
   (--arc), ale został odrzucony — stąd brak zaokrągleń, ujemnych
   marginesów i drabinki z-index, która była potrzebna tylko po to,
   żeby wybrzuszenie jednej sekcji nie chowało się pod następną.

   Zostaje position: relative, bo warstwy tła sekcji (postacie, ziarno,
   fotografie) siedzą na position: absolute i muszą mieć się od czego
   odbić. Za stos wewnątrz sekcji odpowiada isolation: isolate w jej
   własnym arkuszu.
   ============================================================ */
body main > * {
  position: relative;
}

/* ============================================================
   WRAPPERY SIATKOWE A blockGap GUTENBERGA

   Nasze wrappery (główki sekcji, lista kroków) są zbudowane z core/group,
   ale układ robi im grid albo flex z własnym gapem. Gutenberg dokłada do
   nich rytm przepływu:

       :root :where(.is-layout-flow) > * { margin-block-start: 24px }

   Pierwsze dziecko dostaje 0, reszta 24px — w siatce nie rozsuwa to niczego,
   tylko spycha kolumny 2 i 3 w dół i skraca je o te 24px, więc karty
   przestają być równej wysokości.

   Zerujemy to tam, gdzie odstępy nadaje gap. Specyficzność 0,1,1 wygrywa
   z 0,1,0 reguły layoutu.
   ============================================================ */
body .steps__list > *,
body .services__head > *,
body .comparison__head > *,
body .program__items > *,
body .vs__head > * {
  margin-top: 0;
  margin-bottom: 0;
}

/* ============================================================
   KAFEL WPISU — wraca na liście bloga, w pasie „Przeczytaj też”
   i na stronie 404. Dlatego stoi tutaj, nie w arkuszu listy.

   Klikalny jest cały kafel: odnośnik w tytule rozciąga się
   pseudoelementem na całą kartę. Jeden link zamiast trzech —
   czytnik ekranu ma co przeczytać, a nie trzy razy to samo.
   ============================================================ */
body {
  /* Odnośnik ze strzałką — ten sam gest co „Poznaj ofertę” na kaflu usługi.
     Strzałka znakiem, nie plikiem: wchodzi też tam, gdzie nie ma jak wstawić
     inline SVG (InnerBlocks, treść z panelu). */
}
body .link-arrow,
body .service__more .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  color: var(--navy-800);
  font-weight: 600;
}
body .link-arrow::after,
body .service__more .wp-block-button__link::after {
  content: "→";
  transition: transform var(--dur) var(--ease-out);
}
body {
  /* Kiedy odnośnikiem jest przycisk z bloku (core/button na kaflu usługi),
     trzeba mu zdjąć wygląd klawisza — inaczej zostaje tło wariantu, a napis
     w barwie odnośnika znika na granacie. */
}
body .service__more .wp-block-button__link {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  font-family: inherit;
  /* Ten sam stopień co „Czytaj artykuł” na blogu — odnośnik ma być
     dopiskiem pod opisem, nie drugim nagłówkiem karty. */
  font-size: var(--step--1);
  line-height: var(--leading-mid);
  letter-spacing: inherit;
  text-decoration: none;
}
body a.link-arrow:hover,
body .post-card:hover .link-arrow,
body .service:hover .service__more .wp-block-button__link {
  color: var(--brass-700);
}
body a.link-arrow:hover::after,
body .post-card:hover .link-arrow::after,
body .service:hover .service__more .wp-block-button__link::after {
  transform: translateX(3px);
}
body .post-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  background: var(--paper-000);
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
body .post-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-m);
}
body .post-card:has(.post-card__link:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
body .post-card__media {
  position: relative;
  overflow: hidden;
  background: var(--paper-200);
  aspect-ratio: 3/2;
}
body .post-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
body .post-card:hover .post-card__img {
  transform: scale(1.03);
}
body {
  /* Wpis bez miniatury dostaje linie księgi zamiast szarej dziury */
}
body .post-card__placeholder {
  display: block;
  width: 100%;
  height: 100%;
  background-image: repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--ledger-line) - 1px), var(--line) calc(var(--ledger-line) - 1px), var(--line) var(--ledger-line));
  opacity: 0.6;
}
body {
  /* Kategoria jako papierowa naklejka na fotografii: ten sam papier,
     ta sama kreska i ten sam mosiądz co reszta motywu. Ciemny żeton
     z mosiężnym pismem odstawał od wszystkiego dookoła i przy każdym
     zdjęciu wyglądał inaczej. Ikona metki, żeby nie trzeba było czytać
     etykiety, by wiedzieć, że to kategoria. */
}
body .post-card__cat {
  position: absolute;
  left: var(--space-s);
  top: var(--space-s);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: var(--space-3xs) var(--space-2xs);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: rgb(var(--paper-000-rgb)/0.94);
  color: var(--navy-900);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  box-shadow: var(--shadow-xs);
  backdrop-filter: blur(2px);
}
body .post-card__cat-icon {
  flex: none;
  width: 0.85rem;
  height: 0.85rem;
  color: var(--brass-700);
}
body .post-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-m);
}
body {
  /* Tytuł do dwóch wierszy, zajawka do trzech. Wielokropek dokłada
     przeglądarka, więc nie trzeba go liczyć w PHP, a kafle w rzędzie
     kończą się na tej samej wysokości niezależnie od długości tekstu.
     `line-clamp` bez prefiksu jest już standardem, `-webkit-` zostaje
     dla starszych Safari — obie własności wymagają box-orient. */
}
body .post-card__title {
  display: -webkit-box;
  margin: 0;
  color: var(--navy-900);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
body {
  /* Rozciągnięty odnośnik. ::after łapie kliknięcie na całym kaflu,
     więc w środku nie może być drugiego linku. */
}
body .post-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}
body .post-card__excerpt {
  display: -webkit-box;
  margin: 0;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
body .post-card__more {
  flex: none;
  margin: 0;
}
body {
  /* Stopka zawsze przy dolnej krawędzi — rząd kafli kończy się równo,
     nawet gdy tytuły mają różną liczbę wierszy. Data po lewej, odnośnik
     po prawej; przy ciasnym kaflu zawijają się jeden pod drugi. */
}
body .post-card__foot {
  display: flex;
  flex-wrap: nowrap; /* odnośnik zostaje w linii z datą */
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-s);
  margin: auto 0 0;
  padding-top: var(--space-xs);
}
body {
  /* Cała stopka trzyma się jednej linii: data w zapisie cyfrowym,
     czas czytania i odnośnik obok siebie. Stąd nowrap w obu miejscach. */
}
body .post-card__meta {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-2xs);
  min-width: 0;
  margin: 0;
  color: var(--fg-subtle);
  white-space: nowrap;
}
body .post-card__meta > * + *::before {
  content: "·";
  margin-right: var(--space-2xs);
}
body {
  /* Kafel wiodący: fotografia obok tekstu, na całą szerokość siatki */
}
@media (min-width: 62rem) {
  body .post-card--lead {
    flex-direction: row;
  }
  body .post-card--lead .post-card__media {
    flex: 0 0 52%;
    aspect-ratio: auto;
  }
  body .post-card--lead .post-card__body {
    justify-content: center;
    padding: var(--space-xl);
    gap: var(--space-xs);
  }
  body .post-card--lead {
    /* Kafel wiodący ma miejsce, więc tytuł idzie w całości, a
       zajawka do pięciu wierszy zamiast trzech. */
  }
  body .post-card--lead .post-card__title {
    display: block;
    overflow: visible;
  }
  body .post-card--lead .post-card__excerpt {
    -webkit-line-clamp: 5;
    line-clamp: 5;
  }
}
body {
  /* ========================================================
     ŻETON — filtr kategorii i tag pod wpisem.
     ======================================================== */
}
body .chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-3xs) var(--space-xs);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--paper-000);
  color: var(--navy-800);
  font-size: var(--step--1);
  font-weight: 500;
  line-height: var(--leading-mid);
  transition: var(--transition);
}
body .chip:hover {
  border-color: var(--brass-500);
  color: var(--brass-700);
}
body .chip--on {
  border-color: var(--navy-900);
  background: var(--navy-900);
  color: var(--paper-000);
}
body .chip--on:hover {
  border-color: var(--navy-900);
  color: var(--paper-000);
}
body .chip__count {
  color: var(--fg-subtle);
  font-size: var(--step--2);
}
body .chip--on .chip__count {
  color: var(--brass-300);
}
body {
  /* ========================================================
     PAGINACJA — te same klawisze co karuzele sekcji.
     ======================================================== */
}
body .pager {
  margin-top: var(--space-2xl);
}
body .pager__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
body .pager .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding-inline: var(--space-2xs);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--paper-000);
  color: var(--navy-800);
  font-variant-numeric: tabular-nums;
  transition: var(--transition);
}
body .pager .page-numbers:hover {
  border-color: var(--brass-500);
  color: var(--brass-700);
}
body .pager .page-numbers.current {
  border-color: var(--navy-900);
  background: var(--navy-900);
  color: var(--paper-000);
}
body .pager .page-numbers.dots {
  border-color: transparent;
  background: none;
}
body .pager__icon {
  width: 1rem;
  height: 1rem;
}
body {
  /* Strzałka „wstecz” to ta sama ikona obrócona — jeden plik SVG */
}
body .pager__icon--prev {
  transform: rotate(180deg);
}

/* ============================================================
   NAGŁÓWEK PODSTRONY — pas otwierający każdą stronę poza główną.

   Ten sam układ na liście wpisów, pojedynczym wpisie, archiwum,
   podstronie z treścią i na 404: okruchy, tytuł, akapit wprowadzający,
   ewentualna meta i przyciski. Rubryki nad tytułem nie ma — zwykłe
   podstrony jej nie miały, a reszta widoków ma wyglądać tak samo.

   Znaczniki: templates/default/naglowek/naglowek.php
   ============================================================ */
body {
  /* Nagłówek strony leży pod paskiem nawigacji, który jest
     `position: absolute` na całym serwisie — także tutaj, tak jak na
     stronie głównej. Miejsce pod pasek robi górny padding liczony z
     `--header-h`; `position: relative` zostaje wyłącznie po to, żeby
     ziarno papieru (`.page-head__grain`) miało do czego się przypiąć. */
}
body .page-head {
  position: relative;
  isolation: isolate;
  padding-block: calc(var(--header-h) + var(--space-2xl)) var(--space-xl);
  background: linear-gradient(to bottom, var(--paper-000), var(--paper-050));
  border-bottom: 1px solid var(--line);
}
body .page-head__grain {
  position: absolute;
  inset: 0;
  z-index: -1;
}
body {
  /* Okruchy zawijają się na wąskim ekranie zamiast rozpychać stronę */
}
body .page-head__crumbs-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--fg-subtle);
}
body .page-head__crumbs-list a:hover {
  color: var(--brass-700);
}
body .page-head__crumbs-list {
  /* Separator rysuje CSS, żeby w PHP została sama lista kroków */
}
body .page-head__crumbs-list > li + li::before {
  content: "›";
  margin-right: var(--space-2xs);
  color: var(--line-strong);
}
body .page-head__crumbs-list > li {
  display: flex;
  align-items: center;
}
body .page-head__crumbs-list [aria-current=page] {
  color: var(--navy-800);
}
body .page-head__body {
  max-width: var(--container-text);
  margin-top: var(--space-m);
}
body .page-head__title {
  margin: 0;
  color: var(--navy-900);
}
body {
  /* Akapit wprowadzający bierze się z zajawki wpisu albo strony — ten sam
     tekst, który idzie do opisu w wynikach wyszukiwania. Jedno pole,
     dwa zastosowania, więc nie ma jak się rozjechać. */
}
body .page-head__lead {
  margin-top: var(--space-m);
}
body .page-head__lead > :first-child {
  margin-top: 0;
}
body .page-head__lead > :last-child {
  margin-bottom: 0;
}
body .page-head__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: var(--space-m);
  color: var(--fg-subtle);
}
body .page-head__meta > * + *::before {
  content: "·";
  margin-right: var(--space-2xs);
}
body .page-head__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs);
  margin-top: var(--space-l);
}

/* ============================================================
   FORMULARZ — wspólny panel dla wszystkich sekcji z Contact Form 7.

   Wnętrze panelu to znaczniki CF7, więc sięgamy po gołe tagi pól, tak
   jak w .prose po gołe nagłówki treści. Zakres zamyka się w .tb-form,
   nic nie wycieka na resztę strony.

   Klasa siedzi tutaj, a nie w arkuszu jednego bloku, bo formularz stoi
   w dwóch sekcjach (blok „Formularz” i kolumna w bloku „Kontakt”)
   i pola mają w obu wyglądać tak samo.
   ============================================================ */
body .tb-form {
  padding: var(--space-l);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  background: var(--paper-000);
  box-shadow: var(--shadow-m);
}
body .tb-form p {
  margin: 0 0 var(--space-xs);
}
body .tb-form label {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--navy-900);
}
body .tb-form input[type=text],
body .tb-form input[type=email],
body .tb-form input[type=tel],
body .tb-form input[type=url],
body .tb-form input[type=number],
body .tb-form input[type=date],
body .tb-form select,
body .tb-form textarea {
  width: 100%;
  margin-top: var(--space-3xs);
  padding: var(--space-2xs) var(--space-xs);
  border: 1px solid var(--line-field);
  border-radius: var(--radius-s);
  background: var(--paper-050);
  color: var(--fg);
  font-family: inherit;
  font-size: var(--step-0);
  line-height: var(--leading-normal);
  transition: var(--transition);
}
body .tb-form input[type=text]::placeholder,
body .tb-form input[type=email]::placeholder,
body .tb-form input[type=tel]::placeholder,
body .tb-form input[type=url]::placeholder,
body .tb-form input[type=number]::placeholder,
body .tb-form input[type=date]::placeholder,
body .tb-form select::placeholder,
body .tb-form textarea::placeholder {
  color: var(--fg-subtle);
}
body .tb-form input[type=text]:hover,
body .tb-form input[type=email]:hover,
body .tb-form input[type=tel]:hover,
body .tb-form input[type=url]:hover,
body .tb-form input[type=number]:hover,
body .tb-form input[type=date]:hover,
body .tb-form select:hover,
body .tb-form textarea:hover {
  border-color: var(--brass-700);
}
body .tb-form input[type=text]:focus,
body .tb-form input[type=email]:focus,
body .tb-form input[type=tel]:focus,
body .tb-form input[type=url]:focus,
body .tb-form input[type=number]:focus,
body .tb-form input[type=date]:focus,
body .tb-form select:focus,
body .tb-form textarea:focus {
  border-color: var(--brass-500);
  background: var(--paper-000);
  outline: none;
  box-shadow: 0 0 0 3px rgb(var(--brass-500-rgb)/0.18);
}
body .tb-form textarea {
  min-height: 6rem;
  resize: vertical;
}
body .tb-form {
  /* Dwa krótkie pola w jednym rzędzie (imię + telefon). Klasa idzie
     z szablonu formularza w CF7, bo tylko tam da się dołożyć własny
     znacznik wokół pól. */
}
body .tb-form .tb-form__rzad {
  display: grid;
  gap: 0 var(--space-s);
  grid-template-columns: 1fr;
}
@media (min-width: 30rem) {
  body .tb-form .tb-form__rzad {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
body .tb-form {
  /* Zgoda RODO: kwadracik obok tekstu, nie nad nim */
}
body .tb-form .wpcf7-acceptance .wpcf7-list-item {
  margin: 0;
}
body .tb-form .wpcf7-acceptance label {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  font-size: var(--step--2);
  font-weight: 400;
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}
body .tb-form {
  /* Kwadrat rysujemy sami: systemowy checkbox wygląda inaczej
     w każdym silniku i przy papierowej palecie motywu odstawał
     jak wklejony z innej strony. Ptaszek to tło SVG, więc chodzi
     z każdym rozmiarem pola. */
}
body .tb-form input[type=checkbox] {
  flex: none;
  appearance: none;
  -webkit-appearance: none;
  width: 1.15rem;
  height: 1.15rem;
  margin: 0.12em 0 0;
  border: 1px solid var(--line-field);
  border-radius: var(--radius-s);
  background: var(--paper-000);
  cursor: pointer;
  transition: var(--transition);
}
body .tb-form input[type=checkbox]:hover {
  border-color: var(--brass-700);
}
body .tb-form input[type=checkbox]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgb(var(--brass-500-rgb)/0.18);
}
body .tb-form input[type=checkbox]:checked {
  border-color: var(--navy-900);
  background-color: var(--navy-900);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.4l3.4 3.4L13 5'/%3E%3C/svg%3E");
  background-size: 0.72rem;
  background-position: center;
  background-repeat: no-repeat;
}
body .tb-form {
  /* Klawisz wysyłki bierze wygląd przycisku motywu. CF7 renderuje
     <input type="submit">, więc klasy .btn nie da się na nim
     powiesić bez edycji formularza — stąd selektor po typie. */
}
body .tb-form input[type=submit],
body .tb-form .wpcf7-submit {
  width: 100%;
  margin-top: var(--space-s);
  padding: var(--space-xs) var(--space-m);
  border: 0;
  border-radius: var(--radius-s);
  background: var(--navy-900);
  color: var(--paper-000);
  font-family: var(--ffont);
  font-size: var(--step-0);
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}
body .tb-form input[type=submit]:hover,
body .tb-form .wpcf7-submit:hover {
  background: var(--navy-800);
}
body .tb-form {
  /* Kręciołek CF7 stoi w linii z klawiszem, nie pod nim */
}
body .tb-form .wpcf7-spinner {
  margin-inline: var(--space-2xs);
  vertical-align: middle;
}
body .tb-form .wpcf7-not-valid-tip {
  margin-top: var(--space-3xs);
  font-size: var(--step--2);
  color: var(--stamp-600);
}
body .tb-form .wpcf7-not-valid {
  border-color: var(--stamp-500);
}
body .tb-form .wpcf7-response-output {
  margin: var(--space-s) 0 0;
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-size: var(--step--1);
}
body .tb-form form.sent .wpcf7-response-output {
  border-color: var(--ledger-500);
  background: var(--ledger-100);
  color: var(--ledger-600);
}
body .tb-form form.invalid .wpcf7-response-output,
body .tb-form form.failed .wpcf7-response-output {
  border-color: var(--stamp-500);
  background: var(--stamp-100);
  color: var(--stamp-600);
}
@media (max-width: 40rem) {
  body .tb-form {
    padding: var(--space-m);
  }
}

/* ============================================================
   POROZMAWIAJMY — granatowy kadr z numerem telefonu.

   Sekcja jest blokiem „Okładka” z rdzenia. Przejście z granatu na postać
   jest wpalone w samą fotografię, więc nad zdjęciem nie ma zasłony —
   tylko ziarno. Lewa połowa kadru jest z założenia pusta i tam siedzi
   treść.
   ============================================================ */
body .call {
  position: relative;
  isolation: isolate;
  background: var(--navy-950);
  color: var(--fg-invert);
}
body {
  /* Okładka celuje w 430 px; tu wysokość jest częścią kadru, więc
     podajemy własną. Pionowe środkowanie zostaje — treść ma stać
     w połowie fotografii. */
}
body .call.wp-block-cover {
  /* Górny pułap wyższy niż 40rem z prototypu: przy szerokim oknie
     kadr robił się na tyle płaski, że `cover` ścinał go w pionie
     o kilkaset pikseli i zabierał postaci czubek głowy. */
  min-height: clamp(28rem, 44vw, 44rem);
  padding: var(--section-y) 0;
}
body {
  /* Kadr jest przesunięty w prawo: postać stoi po prawej, lewa połowa
     zostaje pusta pod tekst. */
  /* Kadr przesunięty w prawo (postać stoi po prawej, lewa połowa zostaje
     pusta pod tekst) i wyraźnie do góry. Głowa siedzi na wysokości 13%
     oryginału, więc przy środkowaniu w pionie wchodziła pod krawędź. */
}
body .call > .wp-block-cover__image-background {
  object-position: 72% 22%;
}
body {
  /* Ziarno nad zdjęciem. Powód, dla którego idzie ::after a nie ::before,
     ten sam co przy karcie CTA. */
}
body .call.wp-block-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--texture-grain);
}
body {
  /* Poniżej 56 rem tekst nie ma gdzie zejść z postaci, a zasłony
     w fotografii nie ma — dokładamy granat, żeby dało się to czytać. */
}
@media (max-width: 55.999rem) {
  body .call.wp-block-cover::after {
    background: var(--texture-grain), linear-gradient(rgb(var(--navy-950-rgb)/0.72), rgb(var(--navy-950-rgb)/0.72));
  }
}
body .call > .wp-block-cover__inner-container {
  position: relative;
  /* z-index jawnie, bo rdzeń nadaje go tylko na froncie: cały ten
     blok reguł ma selektor body:not(.editor-styles-wrapper). W canvasie
     kontener zostawał na `auto` i warstwa ::after wchodziła na treść.
     Na froncie ta sama wartość co w rdzeniu, więc nic nie zmienia. */
  z-index: 1;
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
body .call__content {
  max-width: 34rem;
}
@media (min-width: 56rem) {
  body .call__content {
    width: 52%;
    max-width: 38rem;
  }
}
body .call__title {
  margin-top: var(--space-s);
  color: var(--paper-000);
}
body .call__lead {
  max-width: 34ch;
  margin-top: var(--space-m);
}
body .call__actions {
  margin-top: var(--space-l);
}
body {
  /* Pasek trzech zdań pod numerem. Kreski rysuje CSS, bo treść jest
     zwykłym akapitem bloku i nie da się w niej trzymać znaczników. */
}
body .call__marks {
  margin-top: var(--space-m);
}

/* ============================================================
   KARTA CTA — fotografia biurka pod granatową powłoką.

   Dwa znaczniki, jeden wygląd. W treści strony karta jest blokiem
   „Okładka” z rdzenia: zdjęcie niesie sam blok, a powłokę i ziarno
   rysują pseudoelementy. Przy zamknięciu pojedynczego wpisu karta
   przychodzi z szablonu PHP, gdzie te same warstwy leżą osobnymi
   divami (__media / __overlay / __grain). Stąd podwójne selektory.
   ============================================================ */
body .cta-card {
  position: relative;
  isolation: isolate;
  margin-top: 0.75rem;
  padding: clamp(2rem, 1.4rem + 2.2vw, 3.2rem) clamp(1.5rem, 1rem + 2.2vw, 3rem);
  border-radius: var(--radius-l);
  overflow: hidden;
  background-color: var(--navy-900);
  color: var(--fg-invert);
}
body {
  /* Okładka celuje w 430 px wysokości i środkuje treść w pionie.
     Kartę ma rozpychać treść, więc znosimy jedno i drugie. */
}
body .cta-card.wp-block-cover {
  display: block;
  min-height: 0;
}
body {
  /* --- Warstwa nad zdjęciem: wersja blokowa ---------------------------
     Granat i ziarno idą jednym pseudoelementem, dwiema warstwami tła.
     Nie da się tu rozdzielić ich na ::before i ::after: zdjęcie niesie
     sam blok okładki, rdzeń trzyma je na z-index 0 selektorem, z którym
     nie ma sensu się ścigać, a przy remisie o kolejność malowania
     decyduje miejsce w drzewie — ::before stoi PRZED zdjęciem, więc
     schowałby się pod nim. Treść zostaje na wierzchu, bo rdzeń daje
     kontenerowi okładki z-index 1.
     -------------------------------------------------------------- */
}
body .cta-card.wp-block-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
body {
  /* --- Warstwy: wersja z szablonu wpisu -------------------------------
     Tu treść jest zwykłym blokiem w przepływie, więc warstwy schodzą
     pod nią ujemnym z-indexem, a nie ponad nią dodatnim.
     -------------------------------------------------------------- */
}
body .cta-card__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
body .cta-card__media picture,
body .cta-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
body .cta-card__grain {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.32;
}
body .cta-card__overlay {
  position: absolute;
  inset: 0;
  z-index: -1;
}
body {
  /* Granat gęstszy w środku, gdzie leży tekst. W wersji blokowej ziarno
     jedzie tą samą deklaracją, jako pierwsza warstwa tła. */
}
body .cta-card.wp-block-cover::after {
  background: var(--texture-grain), radial-gradient(120% 95% at 50% 50%, rgb(var(--navy-950-rgb)/0.8) 0%, rgb(var(--navy-900-rgb)/0.87) 48%, rgb(var(--navy-950-rgb)/0.93) 100%), linear-gradient(180deg, rgb(var(--navy-950-rgb)/0.26), rgb(var(--navy-950-rgb)/0.44));
}
body .cta-card__overlay {
  background: radial-gradient(120% 95% at 50% 50%, rgb(var(--navy-950-rgb)/0.8) 0%, rgb(var(--navy-900-rgb)/0.87) 48%, rgb(var(--navy-950-rgb)/0.93) 100%), linear-gradient(180deg, rgb(var(--navy-950-rgb)/0.26), rgb(var(--navy-950-rgb)/0.44));
}
body {
  /* --- Treść -----------------------------------------------------------
     W wersji blokowej rolę .cta-card__content gra kontener okładki —
     nie da się mu dopisać klasy, więc jedzie w tej samej regule.
     -------------------------------------------------------------- */
}
body .cta-card__content,
body .cta-card > .wp-block-cover__inner-container {
  position: relative;
  /* z-index jawnie, bo rdzeń nadaje go tylko na froncie: cały ten
     blok reguł ma selektor body:not(.editor-styles-wrapper). W canvasie
     kontener zostawał na `auto` i warstwa ::after wchodziła na treść.
     Na froncie ta sama wartość co w rdzeniu, więc nic nie zmienia. */
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-m);
}
@media (min-width: 50rem) {
  body .cta-card__content,
  body .cta-card > .wp-block-cover__inner-container {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xl);
  }
}
body {
  /* Układ „przepływ” z rdzenia dokłada dzieciom margines górny. Przy
     flexie rozpychałby wiersz — odstęp niesie gap. */
}
body .cta-card > .wp-block-cover__inner-container > * {
  margin-block: 0;
}
body .cta-card__title {
  max-width: 30ch;
  color: var(--paper-000);
  text-wrap: balance;
}
body .cta-card .btn,
body .cta-card .wp-block-buttons {
  flex: none;
}

/* ============================================================
   O NAS — okładka z arkuszem księgowym w tle, portretem i rejestrem.

   Sekcja jest złożona z bloków rdzenia (okładka + obraz + grupa +
   lista + przyciski), więc jej styl musi być w arkuszu globalnym.
   ============================================================ */
body .expert {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--paper-050);
  border-top: 1px solid var(--line);
  /* Okładka z rdzenia zakłada zdjęcie pod spodem i wypisuje treść
     na biało. Tu arkusz jest jasny, więc wracamy do barwy tekstu. */
  color: var(--fg);
}
body {
  /* Jak w karcie CTA: znosimy 430 px i pionowe środkowanie okładki.
     Całą wyściółkę bierze na siebie kontener, nie sekcja — inaczej
     kontener kończyłby się --section-y nad dolną krawędzią, a razem
     z nim postać, która ma na tej krawędzi stać. */
}
body .expert.wp-block-cover {
  display: block;
  min-height: 0;
  padding: 0;
}
body {
  /* Przygaszenie arkusza i ziarno jedną warstwą nad zdjęciem — powód
     ten sam co przy karcie CTA. */
  /* Arkusz przygaszony mocniej niż w usługach, bo tu leży pod pełnym
     akapitem, a nie pod kartami */
}
body .expert.wp-block-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--texture-grain), linear-gradient(rgb(var(--paper-050-rgb)/0.4), rgb(var(--paper-050-rgb)/0.4));
}
body .expert > .wp-block-cover__inner-container {
  position: relative;
  /* z-index jawnie, bo rdzeń nadaje go tylko na froncie: cały ten
     blok reguł ma selektor body:not(.editor-styles-wrapper). W canvasie
     kontener zostawał na `auto` i warstwa ::after wchodziła na treść.
     Na froncie ta sama wartość co w rdzeniu, więc nic nie zmienia. */
  z-index: 1;
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-block: var(--section-y);
  padding-inline: var(--gutter);
}
body {
  /* --- Postać ---------------------------------------------------------
     Wycinek stoi w lewym dolnym rogu kontenera, obok kolumny tekstu.
     -------------------------------------------------------------- */
  /* Wszędzie .expert .expert__figure, nie samo .expert__figure. Edytor
     trzyma każdy blok na `position: relative` regułą
     .block-editor-block-list__layout .block-editor-block-list__block
     (0-2-0), która biła `body .expert__figure` (0-1-1) — portret zostawał
     w przepływie i lądował NAD tekstem zamiast obok. Na froncie nic to
     nie zmienia, ta sama deklaracja wygrywała już wcześniej. */
}
body .expert .expert__figure {
  margin: 0;
}
body .expert .expert__figure img {
  display: block;
  width: 100%;
  height: auto;
}
@media (min-width: 62rem) {
  body .expert .expert__figure {
    position: absolute;
    /* Postać wychodzi poza kontener, w margines strony — inaczej
       stoi tuż przy kolumnie tekstu. Wartość środkowa to odległość
       od krawędzi kontenera do krawędzi okna (ujemna), więc na
       wąskim ekranie zjazd sam schodzi do zera. */
    left: clamp(-6rem, (var(--container) - 100vw) / 2, 0rem);
    bottom: 0;
    /* Ramka, w którą postać ma się zmieścić. `contain` bierze
       mniejszy z wymiarów, więc na wąskim ekranie ogranicza
       szerokość, na szerokim wysokość, i nigdy nie wchodzi na
       kolumnę tekstu. Wąziej niż w prototypie, bo treść siedzi
       w kontenerze strony, a nie na pełnej szerokości okładki. */
    width: min(46%, 36rem);
    height: 96%;
  }
  body .expert .expert__figure img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: bottom left;
  }
}
body {
  /* Poniżej 62 rem postać wraca do przepływu i otwiera sekcję */
}
@media (max-width: 61.999rem) {
  body .expert .expert__figure {
    max-width: 20rem;
    margin: 0 auto var(--space-l);
  }
}
body {
  /* --- Treść ----------------------------------------------------------- */
}
body .expert .expert__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
@media (min-width: 62rem) {
  body .expert .expert__content {
    width: 54%;
    max-width: 44rem;
    margin-inline-start: auto;
  }
}
body .expert__title {
  margin-top: var(--space-m);
}
body {
  /* Druga linia hasła w mosiądzu */
}
body .expert__title b {
  display: block;
  font-weight: inherit;
  color: var(--brass-700);
}
body .expert__lead {
  max-width: 56ch;
  margin-top: var(--space-l);
}
body {
  /* --- Rejestr odznak --------------------------------------------------
     Dwie kolumny: cztery pozycje po lewej, trzy po prawej. Każda dostaje
     włosową kreskę u góry, więc obie kolumny zaczynają się na jednej
     linii i czytają jak zestawienie, a nie jak kafelki.
     -------------------------------------------------------------- */
  /* Rejestr zamknięty z obu stron: kreska nad każdą pozycją, a pod całą
     siatką jedna wspólna. Kolumny mają różną liczbę pozycji, więc bez
     tej dolnej zestawienie kończyło się urwane w połowie. */
}
body .expert__creds {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin: var(--space-l) 0 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 40rem) {
  body .expert__creds {
    /* Wiersz ma wspólną wysokość w obu kolumnach, więc kreski
       stoją w jednej linii nawet gdy jedna pozycja łamie się
       na dwa wiersze, a sąsiednia nie. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(4, minmax(2.75rem, auto));
    grid-auto-flow: column;
    column-gap: var(--space-2xl);
  }
}
body .expert__creds li {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  margin: 0;
  padding-block: var(--space-2xs);
  border-top: 1px solid var(--line);
  line-height: var(--leading-mid);
  color: var(--fg-muted);
}
body {
  /* Ikonę niesie maska, nie inline SVG: lista jest blokiem rdzenia,
     a ten wycina znaczniki z treści pozycji. Plik ten sam co w menu,
     barwę nadaje background-color. */
}
body .expert__creds li::before {
  content: "";
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  background-color: var(--brass-600);
  -webkit-mask: var(--cred-ikona, none) center/contain no-repeat;
  mask: var(--cred-ikona, none) center/contain no-repeat;
}
body .expert__creds li:nth-child(1) {
  --cred-ikona: url("assets/svg/menu-icons/cred-1.svg");
}
body .expert__creds li:nth-child(2) {
  --cred-ikona: url("assets/svg/menu-icons/cred-2.svg");
}
body .expert__creds li:nth-child(3) {
  --cred-ikona: url("assets/svg/menu-icons/cred-3.svg");
}
body .expert__creds li:nth-child(4) {
  --cred-ikona: url("assets/svg/menu-icons/cred-4.svg");
}
body .expert__creds li:nth-child(5) {
  --cred-ikona: url("assets/svg/menu-icons/cred-5.svg");
}
body .expert__creds li:nth-child(6) {
  --cred-ikona: url("assets/svg/menu-icons/cred-6.svg");
}
body .expert__creds li:nth-child(7) {
  --cred-ikona: url("assets/svg/menu-icons/cred-7.svg");
}
body {
  /* Klawisz zamyka blok, pod rejestrem */
}
body .expert__actions {
  margin-top: var(--space-l);
}

/* ============================================================
   PASY STRONY „PIERWSZA FIRMA” — wspólny szkielet.

   Trzy sekcje tej podstrony (ból i odpowiedź, program, prowadzący)
   trzymają się schematu z góry tego arkusza:

       section > .container > .<blok>__content

   czyli zwykły section z bloków rdzenia (core/group z tagName=section),
   gotowa klasa .container na treści i warstwy dekoracyjne poza nią.
   Nie ma tu okładki z rdzenia: cover zawsze wypuszcza <div>, narzuca
   430 px i pionowe środkowanie, a jego kontener trzeba było prostować
   trzema deklaracjami i jawnym z-index dla canvasu. Zdjęcie w tle jest
   zwykłym blokiem „Obraz” z klasą __bg, więc dalej wymienia się je
   w panelu, a znaczniki zostają czyste.

   Wszystkie selektory warstw idą przez rodzica (.problem .problem__bg,
   nie samo .problem__bg): edytor trzyma każdy blok na position: relative
   regułą .block-editor-block-list__layout .block-editor-block-list__block
   (0-2-0), która biłaby `body .problem__bg` (0-1-1) i warstwa lądowałaby
   w przepływie zamiast pod treścią.
   ============================================================ */
body {
  /* --- Wspólne dla trzech pasów ---------------------------------------- */
}
body .problem,
body .program,
body .instructor {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: var(--section-y);
}
body {
  /* Zdjęcie w tle sięga krawędzi ekranu, więc leży poza kontenerem */
}
body .problem .problem__bg,
body .program .program__bg,
body .instructor .instructor__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  margin: 0;
  pointer-events: none;
}
body .problem .problem__bg img,
body .program .program__bg img,
body .instructor .instructor__bg img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
body {
  /* Ziarno nad zdjęciem, pod treścią */
}
body .problem::after,
body .program::after,
body .instructor::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
body {
  /* Postać stoi na dolnej krawędzi sekcji, obok kolumny tekstu. Też poza
     kontenerem, bo wychodzi w margines strony. */
}
body .problem .problem__figure,
body .instructor .instructor__figure {
  margin: 0;
}
body .problem .problem__figure img,
body .instructor .instructor__figure img {
  display: block;
  width: 100%;
  height: auto;
}
@media (min-width: 62rem) {
  body {
    /* Ramka rozpięta od krawędzi okna do linii, na której zaczyna się
       kolumna tekstu, z odstępem --space-l. Kolumna to 52% wnętrza
       kontenera dosunięte do prawej, więc jej start liczy się z tych
       samych trzech rzeczy, co sam kontener: wolne pole poza nim
       (100% - C)/2, gutter i 48% wnętrza (C - 2·gutter), gdzie C to
       min(100vw, --container). Procent rozwiązuje się w `right`/`left`
       figury, czyli względem szerokości pasa.

       Wcześniej ramka kończyła się na 50% + 5rem i nie znała kolumny:
       przy 1920 wchodziła 100 px pod tekst, więc postać nie mogła
       urosnąć (przy 80% głowa wchodziła w akapit wiodący) i przy
       74% wysokości nad nią zostawało 300 px pustego papieru, a przy
       868 px kolumny sylwetka czytała się jak mała wklejka obok
       ściany tekstu. Teraz ramka kończy się PRZED kolumną, więc
       wysokość może iść wysoko, a `contain` i tak ogranicza szerokością,
       gdy sylwetka nie mieści się w ramce (1440: 664 px szerokości). */
  }
  body .problem,
  body .instructor {
    --kolumna-start: calc(
        (100% - min(100vw, var(--container))) / 2
        + var(--gutter)
        + 0.48 * (min(100vw, var(--container)) - 2 * var(--gutter))
    );
  }
  body .problem .problem__figure,
  body .instructor .instructor__figure {
    position: absolute;
    bottom: 0;
    height: 88%;
  }
  body .problem .problem__figure img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: bottom right;
  }
  body .instructor .instructor__figure img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: bottom left;
  }
  body {
    /* Odbicie lustrzane obraca CAŁY element, więc razem z obrazkiem
       obraca kotwicę `object-position`. Postać, która miała stać przy
       wewnętrznej krawędzi ramki, po odbiciu lądowała przy zewnętrznej
       — u prowadzącego robiło to 292 px dziury zamiast 56 px odstępu.
       Dla odbitych wycinków kotwica idzie więc na odwrót.

       Obie klasy, bo styl bloku i ręczne `odbicie` z „Dodatkowych klas
       CSS” muszą działać tak samo (patrz ODBICIE LUSTRZANE wyżej). */
  }
  body .problem .problem__figure:is(.is-style-odbicie, .odbicie) img {
    object-position: bottom left;
  }
  body .instructor .instructor__figure:is(.is-style-odbicie, .odbicie) img {
    object-position: bottom right;
  }
  body {
    /* Postać stoi POZA kontenerem, w marginesie strony, kotwiczona
       krawędzią OKNA. Kolumna treści zostaje na siatce kontenera
       i nic jej nie rusza. U prowadzącego lustrzanie: kolumna po
       lewej kończy się w 100% - --kolumna-start, więc wyrażenie
       jest to samo, tylko w `left`. */
  }
  body .problem .problem__figure {
    left: 0;
    right: calc(100% - var(--kolumna-start) + var(--space-l));
  }
  body .instructor .instructor__figure {
    right: 0;
    left: calc(100% - var(--kolumna-start) + var(--space-l));
  }
}
body {
  /* Poniżej 62 rem postać wraca do przepływu i otwiera sekcję */
}
@media (max-width: 61.999rem) {
  body .problem .problem__figure,
  body .instructor .instructor__figure {
    max-width: 18rem;
    margin: 0 auto var(--space-l);
  }
}
body {
  /* Kolumna treści zajmuje nieco ponad połowę pasa — resztę bierze postać */
}
body .problem .problem__content,
body .instructor .instructor__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
@media (min-width: 62rem) {
  body .problem .problem__content,
  body .instructor .instructor__content {
    width: 52%;
    max-width: 44rem;
  }
}

/* ============================================================
   BÓL I ODPOWIEDŹ — pas otwierający stronę „Pierwsza firma”.

   Postać stoi w lewym dolnym rogu, kolumna treści po prawej — tak jak
   „O nas” na stronie głównej. Pod spodem ten sam arkusz księgowy,
   przygaszony, żeby uniósł pełny akapit.

   Wobec „O nas” zmienia się koniec kolumny: zamiast rejestru odznak
   stoi granatowy panel z odpowiedzią i klawiszem telefonu.
   ============================================================ */
body .problem {
  background: var(--paper-050);
  border-bottom: 1px solid var(--line);
}
body {
  /* Arkusz przygaszony tak samo jak w „O nas” (0.4), bo leży pod pełnym
     akapitem, a nie pod kartami */
}
body .problem::after {
  background: var(--texture-grain), linear-gradient(rgb(var(--paper-050-rgb)/0.4), rgb(var(--paper-050-rgb)/0.4));
}
@media (min-width: 62rem) {
  body {
    /* Kolumna trzyma się prawej krawędzi kontenera */
  }
  body .problem .problem__content {
    margin-inline-start: auto;
  }
}
body .problem__title {
  max-width: 22ch;
  margin-top: var(--space-m);
}
body .problem__lead {
  max-width: 52ch;
  margin-top: var(--space-m);
  color: var(--fg-muted);
}
body {
  /* --- Odpowiedź -------------------------------------------------------
     Granatowy panel zamyka kolumnę: pytanie zostaje na papierze,
     odpowiedź dostaje własne tło i klawisz telefonu. Ten sam granat
     i to samo ziarno co w karcie CTA.
     -------------------------------------------------------------- */
}
body .problem__answer {
  position: relative;
  isolation: isolate;
  /* Kolumna jest kolumną fleksa wyrównaną do lewej, więc panel bez
     tego zwęziłby się do własnej treści zamiast trzymać szerokość. */
  align-self: stretch;
  margin-top: var(--space-xl);
  padding: clamp(2rem, 1.4rem + 2.2vw, 3.2rem) clamp(1.5rem, 1rem + 2.2vw, 3rem);
  border-radius: var(--radius-l);
  overflow: hidden;
  background: var(--navy-900);
  color: var(--fg-invert);
  box-shadow: var(--shadow-on-navy);
}
body {
  /* Ziarno na granacie, tak samo jak na karcie CTA */
}
body .problem__answer::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--texture-grain);
}
body {
  /* Bez max-width na miarę wiersza: panel stoi w kolumnie szerokiej na
     52%, więc to on wyznacza długość wiersza. Osobne ograniczenie tylko
     by się z nim biło. */
}
body .problem__answer-title {
  color: var(--paper-000);
  text-wrap: balance;
}
body .problem__answer-text {
  max-width: 52ch;
  margin-top: var(--space-m);
}
body .problem__actions {
  margin-top: var(--space-l);
}

/* ============================================================
   PROGRAM SZKOLENIA — granatowy pas z rejestrem czterech punktów.

   Granat przerywa dwa jasne pasy z góry strony (nagłówek podstrony
   i „ból i odpowiedź”). Pod spodem leży własny kadr biurka
   (qta-tlo-program.jpg): ten sam zapis co pod porównaniem na stronie
   głównej — widok z góry, wszystko w jednym granacie, kanty obrysowane
   mosiądzem — tylko rekwizyty inne (notes, teczki, kubek, pióro), żeby
   podstrona nie powtarzała kadru z głównej. Środek kadru jest pusty
   i ciemny (#0c182c), więc rejestr nie potrzebuje zasłony pod spodem.

   Punkty czytają się jak rejestr, nie jak kafelki: włosowa kreska nad
   każdą pozycją, wspólna pod całą siatką, numer w mosiądzu przed nazwą.
   Ten sam zapis co przy krokach na stronie głównej — numer rysuje licznik
   CSS, więc nie ma go w treści i przestawienie pozycji przenumerowuje
   je od razu.
   ============================================================ */
body .program {
  background: var(--navy-900);
  color: var(--fg-invert);
}
body {
  /* Samo ziarno, bez przygaszenia: biurko na zdjęciu jest już granatowe,
     a druga warstwa granatu zjadałaby z niego spinacze i pióro. */
}
body .program::after {
  opacity: 0.4;
  background: var(--texture-grain);
}
body .program__title {
  max-width: 20ch;
  margin-top: var(--space-s);
  color: var(--paper-000);
}
body {
  /* --- Rejestr punktów -------------------------------------------------
     Dwie kolumny po dwie pozycje. Wiersz siatki ma wspólną wysokość, więc
     kreski nad pozycjami stoją w jednej linii nawet gdy jedna nazwa łamie
     się na dwa wiersze, a sąsiednia nie.
     -------------------------------------------------------------- */
}
body .program__items {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin-top: var(--space-2xl);
  border-bottom: 1px solid var(--line-invert);
  /* Numeracja licznikiem — przestawienie pozycji w edytorze
     przenumerowuje je od razu, bez zapisu strony. */
  counter-reset: punkt;
}
@media (min-width: 56rem) {
  body .program__items {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-2xl);
  }
}
body .program__item {
  counter-increment: punkt;
  padding-block: var(--space-m);
  border-top: 1px solid var(--line-invert);
}
body .program__name {
  max-width: 30ch;
  color: var(--paper-000);
}
body {
  /* Numer pozycji jako pseudoelement nagłówka — nagłówek jest blokiem
     rdzenia i nie ma w nim gdzie wstawić <span>, a numer i tak nie jest
     treścią. Mosiądz jaśniejszy niż przy krokach, bo tu leży na granacie. */
}
body .program__name::before {
  content: counter(punkt, decimal-leading-zero);
  margin-inline-end: 0.35rem;
  color: var(--brass-300);
  font-variant-numeric: tabular-nums;
}
body .program__desc {
  max-width: 46ch;
  margin-top: var(--space-xs);
}

/* ============================================================
   PROWADZĄCY — pas z Marcinem, odbity względem „bólu i odpowiedzi”.

   Ten sam szkielet i ten sam arkusz pod spodem, tylko lustrzanie:
   postać stoi w PRAWYM dolnym rogu, kolumna treści idzie po lewej.
   Między nimi leży granatowy program, więc strona czyta się jako
   postać z lewej, granat, postać z prawej, a nie jako dwa razy to samo.

   Cytat to blok „Cytat” z rdzenia w tym samym zapisie, co cytat w prozie
   wpisu (_typography.scss): mosiężna kreska z lewej, jak dopisek na
   marginesie dokumentu.
   ============================================================ */
body .instructor {
  background: var(--paper-050);
  border-top: 1px solid var(--line);
}
body .instructor::after {
  background: var(--texture-grain), linear-gradient(rgb(var(--paper-050-rgb)/0.4), rgb(var(--paper-050-rgb)/0.4));
}
body {
  /* Ramka i wielkość postaci są wspólne z „bólem i odpowiedzią”, tylko
     odbite: kolumna po lewej, sylwetka po prawej. Wszystko siedzi
     w bloku wspólnym wyżej, tutaj nie ma czego dokładać. */
  /* Rytm kolumny idzie taktami, nie równym krokiem. Cztery rzeczy stoją
     pod sobą: metryczka (rubryka + nazwisko + stanowisko), nota, cytat
     i pasek dorobku. W środku taktu odstępy są ciasne, między taktami
     szerokie — inaczej wszystko czyta się jak jedna lista akapitów.

     Wcześniej stało tu 16 / 8 / 24 / 32 / 32 px, czyli krok prawie
     równy, i nota z cytatem zlewały się w jeden szary blok. */
}
body .instructor__title {
  margin-top: var(--space-s);
}
body {
  /* Stanowisko należy do nazwiska, więc zostaje przy nim blisko */
}
body .instructor__role {
  margin-top: var(--space-xs);
}
body .instructor__bio {
  max-width: 52ch;
  margin-top: var(--space-l);
}
body {
  /* Cytat jako kartka odłożona na biurko: biały papier na kremowym pasie,
     mosiężna krawędź od strony marginesu, zaokrąglenie tylko z prawej —
     tak jakby lewa strona była przycięta przy grzbiecie.

     Sam zapis z prozy wpisu (goła kreska z lewej) tutaj nie działał:
     kolumna miała pod sobą trzy różne traktowania lewej krawędzi
     i cytat czytał się jak przypadkowy wtręt, a nie jak puenta.
     Wyróżnienie niesie więc karta, nie stopień pisma — puenta zostaje
     na `text-lg`, tym samym co w prozie wpisu.

     Kartę niesie ten sam zestaw co granatowy panel w „bólu i odpowiedzi”
     — promień, cień i tło z tokenów — tylko odwrócony na papier, żeby
     strona nie pokazała dwa razy tego samego granatu.

     `balance` jak przy pozostałych hasłach w motywie: bez niego ostatni
     wiersz puenty zostawał na dwóch słowach. */
}
body .instructor__quote {
  /* Kolumna jest fleksem wyrównanym do lewej, więc bez stretch
     karta zwęziłaby się do własnej treści. Miara ta sama co nota,
     dzięki czemu kolumna ma jedną prawą krawędź. */
  align-self: stretch;
  max-width: 52ch;
  margin: var(--space-xl) 0 0;
  padding: var(--space-l);
  border-left: 3px solid var(--brass-500);
  border-radius: 0 var(--radius-m) var(--radius-m) 0;
  background: var(--paper-000);
  box-shadow: var(--shadow-s);
  color: var(--navy-800);
  line-height: var(--leading-copy);
  text-wrap: balance;
}
body {
  /* Pasek dorobku zamyka kolumnę. Kropki rozdzielające są w treści,
     bo to jeden akapit z warsztatu, a nie lista.

     Miara ma dobić do prawej krawędzi noty, nie do krawędzi kolumny.
     Liczba jest inna niż tam (62 zamiast 52), bo `ch` mierzy się
     pismem SWOJEGO elementu, a dorobek idzie stopień niżej — tych
     samych 620 px to przy drobnym piśmie o dziesięć znaków więcej.

     Kreski nad paskiem nie ma, choć wcześniej była. Odkąd cytat jest
     kartą, jej dolna krawędź zamyka blok, a druga linia 40 px niżej
     robiła z końca kolumny drabinkę. Rozdziela sam odstęp. */
}
body .instructor__creds {
  max-width: 62ch;
  margin-top: var(--space-l);
}

/* ============================================================
   ZESPÓŁ — kartoteka ludzi na „O nas”.

   Sekcja jest złożona z bloków rdzenia, jak reszta strony: grupa
   z tagName=section, w środku kontener, siatka grup i w każdej
   „Obraz” + „Akapit” + „Szczegóły”.

   Nazwisko niesie PODPIS OBRAZKA. Tam jest już wpisane przy pliku
   w bibliotece mediów, więc po wstawieniu zdjęcia w edytorze przychodzi
   samo i nie trzeba go przepisywać drugi raz do nagłówka.

   Rozwijanie wizytówki robi blok „Szczegóły” z rdzenia, czyli
   <details>. Otwieranie, zamykanie, obsługa klawiatury i czytnika
   ekranu idą z przeglądarki — zero JavaScriptu i działa też
   w edytorze.
   ============================================================ */
body .team {
  padding-block: var(--section-y);
  background: var(--paper-050);
  border-top: 1px solid var(--line);
}
body .team__title {
  margin-top: var(--space-s);
  max-width: 24ch;
  text-wrap: balance;
}
body {
  /* --- Jedna siatka -----------------------------------------------------
     W treści zespół siedzi w dwóch grupach (czoło i reszta), bo tak go
     redaktor kiedyś rozbił. Na ekranie ma być jeden ciąg kart: cztery
     w linii, bez przerwy i bez dziury po niepełnym rzędzie założycieli.

     Siatką jest więc kontener sekcji, a obie grupy dostają
     `display: contents` — znikają jako pudełka i wypuszczają karty
     prosto do siatki rodzica. Bez tego kart z dwóch osobnych gridów
     nie da się ustawić w jednym rzędzie.
     ------------------------------------------------------------------ */
}
body .team > .container {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-m);
}
body {
  /* Nagłówek sekcji nie jest kartą — bierze całą szerokość siatki. */
}
body .team > .container > :is(.eyebrow, .team__title) {
  grid-column: 1/-1;
}
body {
  /* Odstęp pod tytułem większy niż między rzędami kart: `gap` daje
     wszystkim wierszom po równo, resztę dokłada margines tytułu. */
}
body .team__title {
  margin-bottom: calc(var(--space-xl) - var(--space-m));
}
body .team__grid {
  display: contents;
}
body {
  /* Układ „przepływ” z rdzenia dokłada każdemu dziecku poza pierwszym
     margines górny. W siatce ten margines nie rozpycha, tylko ZJADA
     wysokość: karta rozciągnięta do wiersza kurczy się o tyle, ile ma
     marginesu, więc pierwsza karta stała o 24 px wyżej od pozostałych.
     Odstęp niesie `gap`, więc marginesy są tu zbędne. */
}
body .team__grid > * {
  margin-block: 0;
}
body {
  /* Cztery kolumny od tabletu w górę. Sztywna liczba, nie `auto-fill`:
     przy 1440 auto-fill wypuszczał sześć kart w linii. */
}
@media (min-width: 46rem) {
  body .team > .container {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
body {
  /* --- Karta ------------------------------------------------------------
     Kartoteka pracownicza: papierowy prostokąt, portret u góry, podpis
     pod spodem. Zdjęcie idzie od krawędzi do krawędzi, więc odstęp
     niesie każdy element tekstowy osobno, a nie wspólny padding karty.
     ------------------------------------------------------------------ */
}
body .team__item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--paper-000);
  box-shadow: var(--shadow-xs);
}
body .team__item > * {
  margin-block: 0;
}
body {
  /* Wycinki mają przezroczyste tło, więc kadr dostaje własny papier,
     ciemniejszy niż karta — inaczej sylwetka zlewa się z podpisem. */
}
body .team__photo {
  margin: 0;
  background: var(--paper-100);
}
body {
  /* Proporcja z ramki, nie ze zdjęcia: portrety są kadrowane różnie,
     a rząd ma mieć jedną linię głów. `top` zamiast środka, bo przy
     cięciu w pionie zostać ma głowa, nie marynarka. */
}
body .team__photo img {
  display: block;
  width: 100%;
  aspect-ratio: 4/5;
  object-fit: cover;
  object-position: top center;
}
body {
  /* Podpis obrazka gra rolę nazwiska, więc gubi wygląd podpisu spod
     zdjęcia (drobne, wyśrodkowane, przygaszone) i dostaje wygląd
     nagłówka karty. Stopnia pisma nie ustawiamy — podpis dziedziczy
     stopień bazowy, a to jest dokładnie ten, którego chcemy. */
}
body .team__photo figcaption {
  margin: 0;
  padding: var(--space-m) var(--space-m) 0;
  border-top: 1px solid var(--line);
  /* Własne tło, choć podpis siedzi w <figure> razem ze zdjęciem:
     bez tego nazwisko leżałoby na papierze kadru (--paper-100),
     a ma leżeć na papierze karty razem ze stanowiskiem. */
  background: var(--paper-000);
  font-weight: 700;
  font-size: inherit;
  line-height: var(--leading-snug);
  text-align: left;
  color: var(--navy-900);
}
body .team__grid--czolo .team__photo figcaption,
body .team__grid--reszta .team__photo figcaption {
  padding: var(--space-s) var(--space-s) 0;
}
body .team__role {
  padding: var(--space-3xs) var(--space-m) var(--space-m);
  line-height: var(--leading-mid);
  color: var(--fg-muted);
}
body .team__grid--czolo .team__role,
body .team__grid--reszta .team__role {
  padding: var(--space-3xs) var(--space-s) var(--space-s);
}
body {
  /* --- Wizytówka w oknie ------------------------------------------------
     Treść wizytówki leży w karcie jako zwykła grupa bloków rdzenia,
     więc redaktor pisze bio i kontakt w edytorze. Na froncie grupa jest
     schowana, a okno bierze z niej kopię przy otwarciu (assets/js/zespol.js).

     Klapki <details> tu nie ma, choć rdzeń daje gotowy blok: rozwijana
     karta rozpychała rząd i spychała siatkę w dół, a wizytówka ma
     przykryć stronę, nie przestawić ją.
     ------------------------------------------------------------------ */
}
body .team__popup {
  display: none;
}
body {
  /* Karta z wizytówką zachowuje się jak przycisk. Rolę i tabindex nadaje
     JS, bo bloki rdzenia nie wypuszczą <button> wokół zdjęcia. */
}
body .team__item--klik {
  cursor: pointer;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
body .team__item--klik:hover,
body .team__item--klik:focus-visible {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-m);
}
body .team__item--klik:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
body {
  /* --- Okno ------------------------------------------------------------- */
}
body .team__modal {
  width: min(34rem, 100vw - 2 * var(--gutter));
  max-height: min(42rem, 100vh - 2 * var(--gutter));
  padding: 0;
  border: 0;
  border-radius: var(--radius-l);
  background: var(--paper-000);
  color: var(--fg);
  box-shadow: var(--shadow-l);
}
body .team__modal::backdrop {
  background: rgb(var(--navy-950-rgb)/0.55);
}
body .team__modal-inner {
  position: relative;
  padding: var(--space-xl);
}
body {
  /* Krzyżyk to klawisz karuzeli z komponentów współdzielonych — ten sam
     kwadratowy odlew w papierze, z gotowym stanem wciśnięcia i obwódką
     skupienia. Okno dokłada tylko miejsce, w którym ma stać. */
}
body .team__modal-close {
  position: absolute;
  top: var(--space-s);
  right: var(--space-s);
}
body .team__modal-head {
  display: flex;
  align-items: center;
  gap: var(--space-m);
  /* Miejsce na krzyżyk, żeby długie nazwisko pod niego nie weszło */
  padding-right: var(--space-xl);
}
body .team__modal-photo {
  flex: none;
  display: block;
  width: 5rem;
  overflow: hidden;
  border-radius: var(--radius-m);
  background: var(--paper-100);
}
body .team__modal-photo img {
  display: block;
  width: 100%;
  aspect-ratio: 1/1;
  object-fit: cover;
  object-position: top center;
}
body .team__modal-ident {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
}
body .team__modal-name {
  line-height: var(--leading-tight);
  color: var(--navy-900);
}
body {
  /* Kopia wizytówki wraca do widoczności — schowana jest tylko
     ta w karcie. */
}
body .team__modal .team__popup {
  display: block;
  margin-top: var(--space-l);
}
body .team__bio {
  margin-top: var(--space-s);
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}
body {
  /* Telefon i mail jako para z ikoną. Flex, nie zwykły akapit: odstęp
     niesie `gap`, więc w treści nie trzeba stawiać kropki rozdzielającej
     ani twardej spacji, a odnośniki nie sklejają się przy zawijaniu. */
}
body .team__contact {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-l);
  margin-top: var(--space-l);
  padding-top: var(--space-m);
  border-top: 1px solid var(--line);
}
body {
  /* Ikonę wybiera protokół odnośnika, nie klasa: redaktor wpisuje
     w edytorze zwykły link `tel:` albo `mailto:` i słuchawka czy koperta
     dokłada się sama. Maska, nie <img>, żeby znak brał barwę tekstu
     razem z hoverem. */
}
body .team__contact a::before {
  content: "";
  flex: none;
  width: 1.15em;
  height: 1.15em;
  background-color: currentColor;
  -webkit-mask: var(--ikona) center/contain no-repeat;
  mask: var(--ikona) center/contain no-repeat;
}
body .team__contact a[href^="tel:"] {
  --ikona: var(--icon-phone);
}
body .team__contact a[href^="mailto:"] {
  --ikona: var(--icon-mail);
}
body .team__contact a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-weight: 600;
  color: var(--navy-800);
  text-decoration: none;
  /* --line-field, nie --line-strong: granica, która niesie znaczenie
     („to jest odnośnik”), potrzebuje 3:1 wobec tła — WCAG 1.4.11.
     --line-strong dawał 1,9:1, --line-field daje 3,3:1. */
  border-bottom: 1px solid var(--line-field);
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
body .team__contact a:hover {
  color: var(--navy-700);
  border-bottom-color: var(--brass-500);
}
body {
  /* Na telefonie okno siada na dole i bierze pełną szerokość: kciuk
     sięga tam, gdzie krzyżyk, a wyśrodkowane okno na 390 px i tak
     zajęłoby prawie cały ekran, tylko z paskami po bokach. */
}
@media (max-width: 40rem) {
  body .team__modal {
    width: 100%;
    max-width: 100%;
    max-height: 88vh;
    margin: auto 0 0;
    border-radius: var(--radius-l) var(--radius-l) 0 0;
  }
  body .team__modal-inner {
    padding: var(--space-l);
  }
}

/* ============================================================
   HISTORIA — oś czasu „Skąd się wzięło QTA” na „O nas”.

   Główka dwukolumnowa jak wszędzie: rubryka z hasłem po lewej,
   akapit wprowadzający po prawej. Pod spodem oś czasu: cztery
   przystanki, każdy z fotografią sceny, etykietą epoki, tytułem
   i akapitem.

   Wąsko: linia przy lewej krawędzi, kropka na wysokości etykiety,
   treść wcięta w prawo, zdjęcie nad tekstem. Od 62 rem linia staje
   na środku, przystanki przeplatają strony: zdjęcie po jednej,
   tekst po drugiej, kropka na przecięciu.
   ============================================================ */
body .story {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: var(--section-y);
  border-top: 1px solid var(--line);
}
body .story__head {
  display: grid;
  gap: var(--space-m);
  align-items: end;
  margin-bottom: var(--space-2xl);
}
@media (min-width: 56rem) {
  body .story__head {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--space-2xl);
  }
}
body .story__head-main > * + * {
  margin-top: var(--space-s);
}
body .story__title {
  max-width: 16ch;
}
body .story__lead {
  max-width: 46ch;
}
body {
  /* Oś. Linia rysowana na pseudoelemencie kontenera, kropki na
     pseudoelementach przystanków — markup zostaje czystymi blokami
     rdzenia. */
}
body .story__timeline {
  --story-dot: 1.1rem;
  position: relative;
  display: grid;
  gap: var(--space-2xl);
}
body {
  /* Linia wygasa na końcach zamiast urywać się twardo — ostatni
     przystanek nie zostaje z ogonem. */
}
body .story__timeline::before {
  content: "";
  position: absolute;
  top: var(--space-2xs);
  bottom: var(--space-2xs);
  left: calc(var(--story-dot) / 2 - 1px);
  width: 2px;
  background: linear-gradient(to bottom, transparent, var(--line-strong) 6%, var(--line-strong) 88%, transparent);
}
body .story__item {
  position: relative;
  display: grid;
  gap: var(--space-m);
  padding-left: calc(var(--story-dot) + var(--space-l));
}
body {
  /* Kropka: mosiężne koło z papierową obwódką, przykrywa linię. */
}
body .story__item::before {
  content: "";
  position: absolute;
  top: 0.2em;
  left: 0;
  width: var(--story-dot);
  height: var(--story-dot);
  background: var(--brass-500);
  border: 3px solid var(--paper-050);
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--line-strong);
}
body .story__media {
  margin: 0;
  border-radius: var(--radius-m);
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-s);
}
body .story__media img {
  display: block;
  width: 100%;
  height: auto;
}
body {
  /* Etykieta epoki — mosiądz przyciemniony do 4,8:1 na papierze,
     wersaliki jak rubryka, ale bez znaku sekcji. */
}
body .story__era {
  color: var(--brass-700);
  font-weight: 700;
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
}
body .story__item-title {
  margin-top: var(--space-2xs);
}
body .story__item-text {
  max-width: 52ch;
  margin-top: var(--space-xs);
  color: var(--fg-muted);
}
body {
  /* Szeroko: linia na środku, strony w przeplocie. Zdjęcie i tekst
     wyrównane do góry przystanku, kropka na linii tytułu. */
}
@media (min-width: 62rem) {
  body .story__timeline::before {
    left: 50%;
    transform: translateX(-50%);
  }
  body .story__item {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--space-3xl);
    align-items: center;
    padding-left: 0;
  }
  body .story__item::before {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  body .story__item > .story__media {
    grid-row: 1;
    grid-column: 1;
  }
  body .story__item > .story__body {
    grid-row: 1;
    grid-column: 2;
  }
  body .story__item:nth-child(even) > .story__media {
    grid-column: 2;
  }
  body .story__item:nth-child(even) > .story__body {
    grid-column: 1;
    justify-self: end;
    text-align: right;
  }
  body .story__item:nth-child(even) .story__item-text {
    margin-left: auto;
  }
}

/* ============================================================
   CERTYFIKATY — pas „Certyfikaty i standardy” na „O nas”.

   Trzy karty w rzędzie, każda ze znakiem z tego samego kompletu, co
   rejestr odznak przy Marcinie na stronie głównej (menu-icons/cred-*).
   Znak niesie maska, nie inline SVG: karta jest grupą bloków rdzenia,
   a ta wycina znaczniki wpisane w treść.

   Podglądu skanów tu nie ma, choć warsztat go przewiduje: w bibliotece
   mediów nie leży ani jeden plik z certyfikatem. Gdy dojdą, karta
   dostanie pod tekstem odnośnik do pliku.
   ============================================================ */
body .certs {
  padding-block: var(--section-y);
  border-top: 1px solid var(--line);
}
body .certs__head {
  display: grid;
  gap: var(--space-m);
  align-items: end;
}
@media (min-width: 56rem) {
  body .certs__head {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--space-2xl);
  }
}
body .certs__head-main > * + * {
  margin-top: var(--space-s);
}
body .certs__title {
  max-width: 16ch;
  text-wrap: balance;
}
body .certs__lead {
  max-width: 46ch;
}
body .certs__grid {
  display: grid;
  counter-reset: certyfikat;
  grid-template-columns: 1fr;
  gap: var(--space-m);
  margin-top: var(--space-xl);
}
body {
  /* Układ „przepływ” z rdzenia dokłada dzieciom margines górny, a ten
     w siatce zjada wysokość zamiast rozpychać. Odstęp niesie `gap`. */
}
body .certs__grid > * {
  margin-block: 0;
}
@media (min-width: 46rem) {
  body .certs__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
body {
  /* Karta echo karty usługi ze strony głównej: w górnym rzędzie znak
     po lewej i mosiężny numer po prawej, pod nimi nazwa i opis.
     Siatka, nie flex w kolumnie, bo znak i numer muszą stanąć obok
     siebie, a oba są pseudoelementami — nie da się ich owinąć
     wspólnym rodzicem bez pustego bloku w treści. */
}
body .certs__item {
  display: grid;
  grid-template-columns: auto 1fr;
  align-content: start;
  gap: var(--space-xs) var(--space-s);
  counter-increment: certyfikat;
  padding: var(--space-l);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--paper-000);
  box-shadow: var(--shadow-xs);
}
body .certs__item > * {
  margin-block: 0;
}
body .certs__item::before {
  content: "";
  /* Wiersz jawnie, nie z automatu: `::after` jest w kolejności
     ostatnim dzieckiem, więc bez tego siatka wrzucała numer pod
     opis zamiast obok znaku. */
  grid-row: 1;
  grid-column: 1;
  width: 2.6rem;
  height: 2.6rem;
  background-color: var(--brass-600);
  -webkit-mask: var(--cred-ikona, none) center/contain no-repeat;
  mask: var(--cred-ikona, none) center/contain no-repeat;
}
body {
  /* Numer pozycji, jak na kartach usług. Nie jest treścią, więc idzie
     pseudoelementem — kolejność kart zmienia się przeciąganiem, a numery
     przeliczają się same. */
}
body .certs__item::after {
  content: counter(certyfikat, decimal-leading-zero);
  grid-row: 1;
  grid-column: 2;
  justify-self: end;
  align-self: start;
  color: var(--brass-600);
  font-size: var(--step--2);
  font-variant-numeric: tabular-nums;
}
body .certs__name,
body .certs__desc {
  grid-column: 1/-1;
}
body .certs__name {
  margin-top: var(--space-s);
}
body .certs__item:nth-child(1) {
  --cred-ikona: url("assets/svg/menu-icons/cred-3.svg");
}
body .certs__item:nth-child(2) {
  --cred-ikona: url("assets/svg/menu-icons/cred-4.svg");
}
body .certs__item:nth-child(3) {
  --cred-ikona: url("assets/svg/menu-icons/cred-5.svg");
}
body .certs__name {
  line-height: var(--leading-snug);
  color: var(--navy-900);
  text-wrap: balance;
}
body .certs__desc {
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}

/* ============================================================
   ZASADY — pas „Jak pracujemy” na „O nas”.

   Trzy zasady numerowane licznikiem CSS, tak jak program szkolenia na
   „Pierwszej firmie”: kreska u góry pozycji, numer mosiądzem przed
   nazwą. Kart tu nie ma celowo — nad tym pasem stoją trzy karty
   certyfikatów i drugi rząd pudełek czytałby się jak to samo jeszcze raz.

   Numer jest pseudoelementem nagłówka, nie treścią: nagłówek to blok
   rdzenia i nie ma w nim gdzie wstawić <span>, a numeracja i tak
   wynika z kolejności, więc nie powinna siedzieć w tekście.
   ============================================================ */
body .values {
  padding-block: var(--section-y);
  background: var(--paper-050);
  border-top: 1px solid var(--line);
}
body .values__title {
  margin-top: var(--space-s);
  max-width: 18ch;
  text-wrap: balance;
}
body .values__lead {
  max-width: 52ch;
  margin-top: var(--space-m);
}
body .values__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-l);
  margin-top: var(--space-xl);
  counter-reset: zasada;
}
body {
  /* Układ „przepływ” z rdzenia dokłada dzieciom margines górny, a ten
     w siatce zjada wysokość zamiast rozpychać. Odstęp niesie `gap`. */
}
body .values__grid > * {
  margin-block: 0;
}
@media (min-width: 46rem) {
  body .values__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-xl);
  }
}
body .values__item {
  counter-increment: zasada;
  padding-top: var(--space-m);
  border-top: 2px solid var(--brass-500);
}
body .values__item > * {
  margin-block: 0;
}
body .values__name {
  line-height: var(--leading-snug);
  color: var(--navy-900);
  text-wrap: balance;
}
body .values__name::before {
  content: counter(zasada, decimal-leading-zero);
  margin-inline-end: 0.4rem;
  color: var(--brass-700);
  font-variant-numeric: tabular-nums;
}
body .values__desc {
  max-width: 42ch;
  margin-top: var(--space-s);
  line-height: var(--leading-normal);
  color: var(--fg-muted);
}

/* ============================================================
   KSIĘGA ZAKRESU — pas „Co obejmuje pełna księgowość” na
   podstronie usługi.

   Zakres podany jak pozycje w księdze rachunkowej, na fizycznym
   arkuszu: biała karta z cieniem, gruba granatowa kreska otwarcia,
   poziome linie między wierszami i pionowa mosiężna linia marginesu
   oddzielająca kolumnę numerów — jak w zeszycie księgowym.

   Wiersz to grupa bloków rdzenia: akapit z numerem (pisze go
   redagujący, nie licznik CSS — pozycje księgi się nie przestawiają),
   nagłówek H3 i akapit opisu.
   ============================================================ */
body .ksiega {
  padding-block: var(--section-y);
  border-top: 1px solid var(--line);
  background: var(--paper-050);
}
body .ksiega__head {
  display: grid;
  gap: var(--space-m);
  align-items: end;
  margin-bottom: var(--space-xl);
}
@media (min-width: 56rem) {
  body .ksiega__head {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--space-2xl);
  }
}
body .ksiega__head-main > * + * {
  margin-top: var(--space-s);
}
body .ksiega__title {
  max-width: 20ch;
}
body .ksiega__lead {
  max-width: 46ch;
}
body {
  /* Biały panel z siatką pozycji: hairline'y między polami, w każdym
     polu okrągła plakietka z ikoną, mosiężny numer, nazwa i opis. */
}
body .ksiega__list {
  display: grid;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-m);
  overflow: hidden;
}
body {
  /* Lista jest grupą o układzie „flow”, więc Gutenberg dokłada każdemu
     kolejnemu polu margin-block-start (blockGap). W siatce ten margines
     nie znika: pola 02..06 stały 24 px niżej niż pierwsze, a plakietki
     w jednym rzędzie nie trzymały linii. */
}
body .ksiega__list > .ksiega__row {
  margin-block: 0;
}
body {
  /* Pole siatki. Plakietkę i ikonę niosą pseudoelementy: ::before jest
     elementem siatki (koło w lewej kolumnie, przez trzy rzędy treści),
     ::after leży na nim absolutnie — spod tej samej pary
     padding + rozmiar, więc środki się pokrywają. Ikona maską, jak
     w rejestrze odznak (.expert__creds): blok rdzenia wycina inline
     SVG z treści, plik z assets/ go zastępuje. */
}
body .ksiega__row {
  --ksiega-plakietka: 4.75rem;
  position: relative;
  display: grid;
  grid-template-columns: var(--ksiega-plakietka) minmax(0, 1fr);
  grid-template-rows: auto auto 1fr;
  column-gap: var(--space-m);
  row-gap: var(--space-3xs);
  padding: var(--space-l);
}
body .ksiega__row::before {
  content: "";
  grid-row: 1/span 3;
  width: var(--ksiega-plakietka);
  height: var(--ksiega-plakietka);
  background: var(--paper-100);
  border-radius: 50%;
}
body .ksiega__row::after {
  content: "";
  position: absolute;
  top: var(--space-l);
  left: var(--space-l);
  width: var(--ksiega-plakietka);
  height: var(--ksiega-plakietka);
  background-color: var(--navy-800);
  -webkit-mask: var(--ksiega-ikona, none) center/44% no-repeat;
  mask: var(--ksiega-ikona, none) center/44% no-repeat;
}
body .ksiega__row:nth-child(1) {
  --ksiega-ikona: url("assets/svg/menu-icons/pelna-ksiegowosc.svg");
}
body .ksiega__row:nth-child(2) {
  --ksiega-ikona: url("assets/svg/menu-icons/vs-cena.svg");
}
body .ksiega__row:nth-child(3) {
  --ksiega-ikona: url("assets/svg/menu-icons/cfo.svg");
}
body {
  /* Nie vs-dokumenty: teczka w małej skali czyta się jak słuchawki. */
}
body .ksiega__row:nth-child(4) {
  --ksiega-ikona: url("assets/svg/ui/faktura.svg");
}
body .ksiega__row:nth-child(5) {
  --ksiega-ikona: url("assets/svg/menu-icons/vs-kontrola.svg");
}
body .ksiega__row:nth-child(6) {
  --ksiega-ikona: url("assets/svg/ui/panel.svg");
}
body {
  /* Hairline'y: wąsko lista jest słupkiem, linia tylko między polami.
     Progi siatki niżej nadpisują je na kratkę 2 i 3 kolumn. */
}
body .ksiega__row:not(:last-child) {
  border-bottom: 1px solid var(--line);
}
@media (min-width: 48rem) and (max-width: 71.999rem) {
  body .ksiega__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  body .ksiega__row:not(:last-child) {
    border-bottom: none;
  }
  body .ksiega__row:nth-child(-n+4) {
    border-bottom: 1px solid var(--line);
  }
  body .ksiega__row:nth-child(odd) {
    border-right: 1px solid var(--line);
  }
}
@media (min-width: 72rem) {
  body .ksiega__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  body .ksiega__row:not(:last-child) {
    border-bottom: none;
  }
  body .ksiega__row:nth-child(-n+3) {
    border-bottom: 1px solid var(--line);
  }
  body .ksiega__row:not(:nth-child(3n)) {
    border-right: 1px solid var(--line);
  }
}
body {
  /* brass-600, nie -500: na bieli jaśniejszy mosiądz schodzi do 3,2:1,
     a numer to duży stopień, więc 3,8:1 z -600 domyka WCAG z zapasem. */
}
body .ksiega__no {
  color: var(--brass-600);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-num);
  line-height: var(--leading-tight);
}
body .ksiega__name {
  margin: 0;
}
body .ksiega__desc {
  grid-column: 2;
  max-width: 34ch;
  margin-top: var(--space-2xs);
  color: var(--fg-muted);
}

/* ============================================================
   SEKCJA TEKSTOWA — proza redakcyjna na podstronach usług.

   Rubryka z tytułem w lewej kolumnie (przykleja się przy scrollu),
   proza w prawej. Wyróżnik (.tekst__box) to akapit z mosiężną
   krawędzią — na pytanie z telefonem albo rejestr znaków.

   Modyfikator --raised podnosi tło o stopień, żeby sąsiednie
   sekcje tekstowe się nie zlewały.
   ============================================================ */
body .tekst {
  padding-block: var(--section-y);
  border-top: 1px solid var(--line);
}
body .tekst--raised {
  background: var(--paper-050);
}
body .tekst__grid {
  display: grid;
  gap: var(--space-l);
  align-items: start;
}
@media (min-width: 62rem) {
  body .tekst__grid {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: var(--space-3xl);
  }
  body .tekst__head {
    position: sticky;
    top: calc(var(--header-h) + var(--space-m));
  }
}
body .tekst__head > * + * {
  margin-top: var(--space-s);
}
body .tekst__title {
  max-width: 16ch;
}
body .tekst__body > * + * {
  margin-top: var(--space-m);
}
body .tekst__body p {
  max-width: 58ch;
}
body .tekst__box {
  max-width: none;
  margin-top: var(--space-l);
  padding: var(--space-m) var(--space-l);
  background: var(--paper-050);
  border-left: 3px solid var(--brass-500);
  border-radius: var(--radius-s);
}
body .tekst--raised .tekst__box {
  background: var(--white);
}
body {
  /* PODSTRONY LOKALNE („Usługi księgowe {miejscowość}”) — długi tekst
     pod wyszukiwarkę na typografii .prose z bloga: siatka z torami
     content/wide/full, nagłówki, listy, zdjęcia z podpisami. Sekcja daje
     tylko oddech pionowy; tor i gutter liczy sama .prose. */
}
body .lokalny {
  padding-block: var(--space-xl) var(--space-2xl);
}
body {
  /* Jedna szerokość dla wszystkiego: tekst, listy, zdjęcia i podpisy.
     Siatka .prose (tor content 68ch, tor wide dla obrazów) dawała tu
     obraz na 1000 px nad akapitem na 830 px, a podpis pod obrazem
     szerszy niż tekst. Proza leci zwykłym przepływem w standardowym
     .container i trzyma jego lewą krawędź — wycentrowany kontener
     56 rem zaczynał tekst ok. 150 px w prawo od nagłówka strony,
     pasa „program” i FAQ, więc nic się nie licowało. Miarę wiersza
     daje token --layout-narrow, ten sam co kolumna tekstu na blogu.
     Klasa .lokalny__intro zostaje w treści dwunastu podstron, ale
     stylu już nie ma: intro to zwykły akapit prozy, bez trzeciego
     kroju na tym samym tle. */
}
body .lokalny .lokalny__prose {
  display: block;
  max-width: var(--layout-narrow);
}
body .lokalny .lokalny__prose > * {
  grid-column: auto;
  max-width: none;
}
body .lokalny .lokalny__prose > figure img {
  display: block;
  width: 100%;
  height: auto;
}
body {
  /* Odnośniki w opisach pozycji „ksiega” i „program” (podstrony lokalne
     linkują z nich do usług) dostają ten sam mosiężny podkreślnik co
     tekst akapitowy — bez tego nie odróżniały się od zwykłego tekstu. */
}
body .ksiega__desc a,
body .program__desc a,
body .tekst__body a,
body .tekst__box a {
  color: var(--navy-800);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--brass-500);
}
body .program__desc a {
  color: inherit;
}
body .ksiega__desc a:hover,
body .program__desc a:hover,
body .tekst__body a:hover,
body .tekst__box a:hover {
  color: var(--navy-700);
}
body {
  /* Rejestr znaków pod prozą — kropkowany pasek jak w okładkach. */
}
body .tekst__marks {
  margin-top: var(--space-l);
  color: var(--fg-subtle);
}

/* --logo-src ustawia PHP (includes/add-theme-assets.php) jako adres BEZWZGLĘDNY.
   Względny nie zadziała: url() w zmiennej CSS rozwiązuje się względem arkusza,
   który jej UŻYWA, więc stopka szukałaby logo w templates/default/footer/. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}
body {
  min-height: 100svh;
  background-color: var(--bg);
  color: var(--fg);
  font-family: var(--sfont);
  font-size: var(--step-0);
  line-height: var(--leading-normal);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
body img,
body picture,
body svg,
body video,
body canvas {
  display: block;
  max-width: 100%;
}
body img,
body video {
  height: auto;
}
body a {
  color: inherit;
  text-decoration: none;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
body p,
body li,
body figcaption {
  text-wrap: pretty;
}
body ol {
  list-style-type: auto;
  padding-left: 15px;
  margin: 15px 0;
}
body ul {
  padding-left: 15px;
  list-style-type: disc;
  margin: 15px 0;
}
body {
  /* Bez margin: 0. Selektor z atrybutem ma 0,1,2 i bił własne marginesy
     list w blokach (0,1,1) — np. odstęp nad odznakami w „O nas”.
     Zerowanie marginesu i tak robi reset w global.css. */
}
body ul[role=list],
body ol[role=list] {
  list-style: none;
  padding: 0;
}
body table {
  width: 100%;
}
body strong,
body b {
  font-weight: 700;
}
body {
  /* Cyfry tabelaryczne wszędzie tam, gdzie stoją w zestawieniu */
}
body ::selection {
  background: var(--brass-300);
  color: var(--navy-950);
}
body :focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}
body .on-navy :focus-visible {
  outline-color: var(--brass-300);
}
