/* style.css — arkusz BASE: tokeny, reset, dostępność, typografia, .container,
   siatka (sekcja 7), header/footer. CSS pojedynczych bloków siedzi w <style>
   ich snippetów; tu wracają tylko style renderowane z ≥2 miejsc (sekcje 10–16). */

/* 0. FONT — Anek Latin (variable): oś wght 100–700, oś wdth 75–125%, 1:1 z fvar.
   "font" to celowy alias — podmiana fontu = zmiana w jednym miejscu. */
@font-face {
  font-family: "font";
  src: url("../fonts/AnekLatin.woff2") format("woff2-variations");
  font-weight: 100 700;
  font-stretch: 75% 125%;
  font-display: swap;
}

/* 1. TOKENY */

:root {
  --font-body: "font", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-heading: var(--font-body);

  /* grubość (oś wght) */
  --wght-s:  300;
  --wght-m:  400;
  --wght-l:  600;
  --wght-xl: 700;

  /* szerokość (oś wdth) */
  --wdth-s:  100%;
  --wdth-m:  105%;
  --wdth-l:  112.5%;
  --wdth-xl: 125%;

  /* font-size — tekst */
  --fs:    clamp(.938rem, calc(.0653vw + .9184rem), 1rem);
  --fs-xs: calc(var(--fs) * 0.6);
  --fs-s:  calc(var(--fs) * 0.9);
  --fs-m:  var(--fs);
  --fs-l:  calc(var(--fs) * 1.2);
  --fs-xl: calc(var(--fs) * 1.45);
  --fs-pl: 1.05em;
  --fs-mn: 0.95em;

  /* font-size — nagłówki */
  --hs: clamp(1rem, 0.85rem + 0.66vw, 1.25rem);
  --hs-1: calc(var(--hs) * 1.7);
  --hs-2: calc(var(--hs) * 1.3);
  --hs-3: calc(var(--hs) * 1.1);
  --hs-4: calc(var(--hs) * 1);
  --hs-5: calc(var(--hs) * 0.9);
  --hs-6: calc(var(--hs) * 0.8);

  /* line-height */
  --lh-s: 1.1;
  --lh-m: 1.5;
  --lh-l: 1.7;

  /* kolory — 10 tokenów. --co-accent #FFA300 = pomarańcz marketingu,
     ~2:1 na bieli/szarym — ŚWIADOMIE poniżej WCAG AA (decyzja marketingu,
     nie błąd); na ciemnym tle (granat/deep) 7.5–8.2:1, czytelny z zapasem.
     --co-error/--co-success: rezerwa.
     --co-logo #1A2EF0 = kolor z logo (eyebrow, tytuły kart), 7.8:1 na bieli /
     7.1:1 na szarym — na ciemnym granacie/deep przełącza się na biel
     (sekcja 10, jak --link; na tych tłach sam --co-logo miałby ~2:1). */
  --co-brand:   #0F1757;
  --co-accent:  #FFA300;
  --co-logo:    #1A2EF0;

  --co-bg:      #ffffff;
  --co-soft:    #f4f4f5;
  --co-deep:    #26262b;
  --co-ink:     #141414;

  --co-mix:     color-mix(in srgb, currentColor 15%, transparent);

  --co-error:   #b3261e;
  --co-success: #1e7d34;

  /* kolor linku treści — alias; sekcja 10 przestawia go na --co-bg na ciemnym tle */
  --link: var(--co-logo);

  --panel-radius: 1.25rem;

  /* panel tła kontenera (sekcja 10). --panel-overlap MUSI być ≥ 2× --panel-radius. */
  --panel-wide:     calc(var(--sp-l) * 2);
  --panel-edge-gap: 0.5rem;
  --panel-overlap:  calc(var(--panel-radius) * 2);

  /* wariant "Wysoki" — dolny próg (min-height), nic nie przycina */
  --kontener-h-wysoki: clamp(22rem, 50dvh, 40rem);

  /* odstępy sekcji — dolny próg 1.75rem (2026-09-15, było 1.5rem): trochę
     więcej „powietrza" na wąskich ekranach. Płynna część (calc) i górny próg
     (3rem) bez zmian — podniesienie samego minimum tylko przesuwa punkt, w
     którym krzywa przestaje być płaska (dawniej ~480px, teraz ~733px
     szerokości viewportu), nie zmienia nachylenia skalowania. */
  --sp:    clamp(1.75rem, calc(1.5789vw + 1.0263rem), 3rem);
  --sp-xs: calc(var(--sp) * 0.4);
  --sp-s:  calc(var(--sp) * 0.6);
  --sp-m:  var(--sp);
  --sp-l:  calc(var(--sp) * 1.5);
  --sp-xl: calc(var(--sp) * 3);

  /* gapy siatki — aliasy skali odstępów */
  --gap-s: var(--sp-xs);
  --gap-m: var(--sp-m);
  --gap-l: var(--sp-l);

  /* szerokość treści */
  --wd-s: 45ch;
  --wd-m: 65ch;
  --wd-l: 80ch;

  /* radius */
  --rd:      1rem;
  --rd-s:    calc(var(--rd) * 0.5);
  --rd-m:    calc(var(--rd) * 1.5);
  --rd-l:    calc(var(--rd) * 3);
  --rd-full: 999px;

  --content-width: 78rem;
  --gutter:        clamp(2rem, calc(2.1053vw + 1.3684rem), 4rem);

  /* z-index */
  --z-header:  10;
  --z-overlay: 100;
  --z-skip:    1000;

  --transition: 200ms ease;

  color-scheme: light;
}


/* 2. RESET */

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

/* hidden musi realnie chować — komponenty z własnym display nadpisują display:none */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-m);
  font-weight: var(--wght-m);
  font-stretch: var(--wdth-m);
  line-height: var(--lh-m);
  color: var(--co-ink);
  background: var(--co-bg);
  font-synthesis: none;
  overflow-x: hidden;
}

/* sticky footer */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

.page > main {
  flex: 1 1 auto;
}

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

h1, h2, h3, h4, h5, h6, p, blockquote, figure {
  margin: 0;
  padding: 0;
}

ul, ol {
  margin: 0;
}


/* 3. ACCESSIBILITY */

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--sp-xs);
  z-index: var(--z-skip);
  padding: var(--sp-xs) var(--sp-s);
  background: var(--co-bg);
  color: var(--co-ink);
  border: 1px solid var(--co-mix);
  transition: top var(--transition);
}

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

:focus-visible {
  outline: 2px solid var(--co-accent);
  outline-offset: 2px;
}


/* 4. REDUCED MOTION */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* 5. NAGŁÓWKI I LINKI */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--font-heading);
  font-weight: var(--wght-l);
  font-stretch: var(--wdth-l);
  line-height: var(--lh-s);
  color: var(--co-brand);
  max-width: 30ch;
}

h1, .h1 { font-size: var(--hs-1); font-weight: var(--wght-xl); font-stretch: var(--wdth-xl); }
h2, .h2 { font-size: var(--hs-2); }
h3, .h3 { font-size: var(--hs-3); }
h4, .h4 { font-size: var(--hs-4); }
h5, .h5 { font-size: var(--hs-5); }
h6, .h6 { font-size: var(--hs-6); letter-spacing: 0.05em; }

/* wyróżnienie w treści — 600, nie domyślne przeglądarkowe 700 */
b, strong { font-weight: var(--wght-l); }

/* mniej sierotek, ignorowane bez wsparcia */
h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
p, li, span, blockquote { text-wrap: pretty; }

/* linki treści — kolor przez --link; podkreślenie zostaje (afordancja nie tylko kolorem) */
a {
  color: var(--link);
  text-underline-offset: 0.15em;
}

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


/* 6. UTILITIES */

.container {
  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
  /* kontekst pozycjonowania/stackowania dla .background* i .shift-* (sekcja 10) */
  position: relative;
  z-index: 1;
}

/* .container nie ma własnego padding-block — te klasy go ustawiają (header/footer) */
.row-padding-s { padding-block: var(--sp-s); }
.row-padding-l { padding-block: var(--sp-l); }

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

/* flow (owl selector) — pionowy rytm; --flow-space nadpisywalny per para */
.flow > * + * {
  margin-block-start: var(--flow-space, var(--sp-s));
}


/* 7. GRID SYSTEM
   Utility-first; renderowany przez site/snippets/blocks/kontener.php.
   Progi: desktop (.dN), tablet ≤991px (.tN), mobile ≤576px (.mN). */

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--gap-m);
}
.grid > * {
  min-width: 0;
}

.grid + .grid {
  margin-top: var(--gap-m);
}

/* gaps */
.gap-n { gap: 0; }
.gap-s { gap: var(--gap-s); }
.gap-m { gap: var(--gap-m); }
.gap-l { gap: var(--gap-l); }

/* siatka / całe rzędy */
.v-start    { align-items: start; }
.v-center   { align-items: center; }
.v-end      { align-items: end; }
.v-stretch  { align-items: stretch; }

.h-start    { justify-items: start; }
.h-center   { justify-items: center; }
.h-end      { justify-items: end; }
.h-stretch  { justify-items: stretch; }

/* pojedynczy item / komórka */
.iv-start   { align-self: start; }
.iv-center  { align-self: center; }
.iv-end     { align-self: end; }
.iv-stretch { align-self: stretch; }

.ih-start   { justify-self: start; }
.ih-center  { justify-self: center; }
.ih-end     { justify-self: end; }
.ih-stretch { justify-self: stretch; }

/* desktop */
.d1  { grid-column: span 1; }
.d2  { grid-column: span 2; }
.d3  { grid-column: span 3; }
.d4  { grid-column: span 4; }
.d5  { grid-column: span 5; }
.d6  { grid-column: span 6; }
.d7  { grid-column: span 7; }
.d8  { grid-column: span 8; }
.d9  { grid-column: span 9; }
.d10 { grid-column: span 10; }
.d11 { grid-column: span 11; }
.d12 { grid-column: 1 / -1; }

/* tablet */
@media (max-width: 991px) {
  .t1  { grid-column: span 1; }
  .t2  { grid-column: span 2; }
  .t3  { grid-column: span 3; }
  .t4  { grid-column: span 4; }
  .t5  { grid-column: span 5; }
  .t6  { grid-column: span 6; }
  .t7  { grid-column: span 7; }
  .t8  { grid-column: span 8; }
  .t9  { grid-column: span 9; }
  .t10 { grid-column: span 10; }
  .t11 { grid-column: span 11; }
  .t12 { grid-column: 1 / -1; }

  .order-tp { order: -1; }
  .order-to { order: 13; }
}

/* mobile */
@media (max-width: 576px) {
  .m1  { grid-column: span 1; }
  .m2  { grid-column: span 2; }
  .m3  { grid-column: span 3; }
  .m4  { grid-column: span 4; }
  .m5  { grid-column: span 5; }
  .m6  { grid-column: span 6; }
  .m7  { grid-column: span 7; }
  .m8  { grid-column: span 8; }
  .m9  { grid-column: span 9; }
  .m10 { grid-column: span 10; }
  .m11 { grid-column: span 11; }
  .m12 { grid-column: 1 / -1; }

  .order-mp { order: -1; }
  .order-mo { order: 13; }

  /* reverseMobile (fields/row-reverse-mobile) — na telefonie kolumny wiersza
     są i tak pełnej szerokości (.m12), więc grid przełączamy na flex
     column-reverse: odwraca kolejność dla dowolnej liczby kolumn, bez
     ruszania DOM (Tab / czytnik ekranu idą jak w Panelu). gap dziedziczy. */
  .grid-reverse-m {
    display: flex;
    flex-direction: column-reverse;
  }
}

/* flex helpers — kontener.php łączy .flex.col z .flow na komórce siatki */
.flex      { display: flex; }
.col       { flex-direction: column; }
.grow      { flex-grow: 1; }
.no-shrink { flex-shrink: 0; }


/* 8. HEADER / FOOTER — .container/.row-padding-* robią szerokość/odstęp */

/* header jest przezroczysty (--co-bg nigdzie nie ustawiony na .header-bar) —
   sekcja hero z "Połączenie: nachodzi" (base/blocks.php) celowo podsuwa się
   POD niego (--panel-overlap, ujemny margines), żeby jej kolor/zdjęcie
   prześwitywało za logo/nawigacją. Ale ta sekcja dostaje .shift-front
   (z-index: 3, sekcja 10) i bez własnego z-index header — jako zwykły,
   wcześniejszy element w DOM — przegrywał kolejność malowania: hero
   (późniejszy w DOM) renderował się NAD headerem, zakrywając rozwijane
   panele nawigacji/kontaktu (sekcja 20). --z-header (token zdefiniowany w
   sekcji 1, wcześniej nigdzie nie użyty) naprawia to bez ruszania
   przezroczystości — header nadal przepuszcza kolor hero, tylko jego WŁASNA
   zawartość zawsze maluje się na wierzchu. */
header {
  position: relative;
  z-index: var(--z-header);
}

.header-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-s);
}

.header-logo {
  display: flex;
  align-items: center;
}

.header-logo img {
  height: 2.5rem;
  width: auto;
}

.nav-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-s);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-list a {
  color: var(--co-logo);
  font-size: var(--fs-mn);
  font-weight: 550;
  font-stretch: var(--wdth-m);
  text-transform: uppercase;
  text-decoration: none;
}

/* przycisk hamburgera (mobile-nav.php) — wygląd w sekcji 20, tu tylko
   przełącznik z poziomą listą */
.nav-toggle-wrap {
  display: none;
}

/* ≤991px (próg jak .t* w sekcji 7): pozioma nawigacja znika, wraca jako hamburger */
@media (max-width: 991px) {
  .nav-list {
    display: none;
  }

  .nav-toggle-wrap {
    display: inline-flex;
  }
}


/* 9. TREŚĆ — LISTY
   main ul/ol: natywny list-style zdjęty, marker w ::before — ul em-dash "—",
   ol licznik "01" (decimal-leading-zero). Kolor markera adaptacyjny.
   Oba tagi dostają role="list" (petroff_role_list) — list-style:none gubi
   semantykę w Safari+VoiceOver. */
main ul,
main ol {
  list-style: none;
  padding-left: 0;
}

main ol {
  counter-reset: lista;
}

main ul li,
main ol li {
  position: relative;
  padding-left: 2em;
}

main ol li {
  counter-increment: lista;
}

main ul li::before,
main ol li::before {
  position: absolute;
  left: 0;
  color: color-mix(in srgb, currentColor 55%, transparent);
}

main ul li::before {
  content: "\2014";
  font-weight: var(--wght-s);
}

main ol li::before {
  content: counter(lista, decimal-leading-zero);
  font-weight: var(--wght-m);
}

main li {
  padding-bottom: 1em;
}


/* 10. KONTENER — WARIANTY (kontener.yml pola settings; render: base/blocks.php).
   .background* / .eyebrow używa też realizacja.php wprost — stąd w tym arkuszu. */

.kontener {
  padding: var(--gutter);
  /* kolumna flex → pole "valign" (fields/row-align-vertical) steruje
     justify-content inline z base/blocks.php. Bez wolnej przestrzeni (czyli bez
     .kontener-wysoki) bez efektu wizualnego — wiersze .grid i tak układają się
     w pionie jeden pod drugim. .background jest position:absolute, poza flow. */
  display: flex;
  flex-direction: column;
}

.kontener-wysoki {
  min-height: var(--kontener-h-wysoki);
}

.background {
  position: absolute;
  inset-block: 0;
  /* trzyma --panel-edge-gap od krawędzi okna na wąskich ekranach */
  inset-inline: max(0px, calc(var(--panel-edge-gap) - (50vw - 50%)));
  z-index: -1;
  border-radius: var(--panel-radius);
  border: 1px solid transparent;
  overflow: hidden;
}

/* "Szeroka" — panel poza kontener o --panel-wide, nie na pełną szerokość okna */
.background-szeroka {
  inset-inline: max(
    calc(50% - 50vw + var(--panel-edge-gap)),
    calc(-1 * var(--panel-wide))
  );
}

.background-niebieski { background-color: var(--co-brand); border-color: var(--co-brand); }
.background-szary     { background-color: var(--co-soft);  border-color: var(--co-soft); }
.background-ciemny    { background-color: var(--co-deep);  border-color: var(--co-deep); }

/* biały panel na białej stronie — odróżnia go tylko adaptacyjny border */
.background-bialy {
  background-color: var(--co-bg);
  border-color: var(--co-mix);
}

/* ciemne tło → biały tekst treści (rodzeństwo idące PO .background) */
.background-niebieski ~ *,
.background-ciemny ~ * {
  color: var(--co-bg);
  --link: var(--co-bg);
  --co-logo: var(--co-bg);
}

/* nagłówki mają jawny color (sekcja 5) — potrzebują osobnej reguły */
.background-niebieski ~ :is(h1, h2, h3, h4, h5, h6),
.background-niebieski ~ * :is(h1, h2, h3, h4, h5, h6),
.background-ciemny ~ :is(h1, h2, h3, h4, h5, h6),
.background-ciemny ~ * :is(h1, h2, h3, h4, h5, h6) {
  color: var(--co-bg);
}

.background-niebieski ~ .eyebrow,
.background-niebieski ~ * .eyebrow,
.background-ciemny ~ .eyebrow,
.background-ciemny ~ * .eyebrow {
  color: var(--co-accent);
}

/* POŁĄCZENIE (fields/row-connect) — klasy atomowe składane w base/blocks.php.
   .shift-up na <section> (rodzeństwo w <main>); reszta na .kontener. */
section.shift-up { margin-block-start: calc(-1 * var(--panel-overlap)); }

.shift-front { z-index: 3; }
.shift-back  { z-index: 0; }

/* zakryta krawędź: +--panel-overlap, żeby widoczny odstęp treści wrócił do --gutter */
.kontener.shift-pad-top    { padding-block-start: calc(var(--gutter) + var(--panel-overlap)); }
.kontener.shift-pad-bottom { padding-block-end:   calc(var(--gutter) + var(--panel-overlap)); }

/* ODSTĘP (fields/row-gap) — przeciwieństwo shift-up: sekcje domyślnie stykają
   się bez marginesu, to dokłada widoczną przerwę między dwoma panelami. */
section.gap-up { margin-block-start: var(--sp-m); }

/* zdjęcie w tle — grayscale + brightness(0.85) = delikatna warstwa
   przyciemniająca u źródła. Krótko było 0.7 (mocniejszy kontrast pod białym H1
   hero), cofnięte do 0.85 na życzenie — zdjęcie w tle ma być wyraźniejsze.
   Overlay koloru sekcji (.background-overlay-*) zostaje na opacity 0.8. */
.background-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.85);
}

/* ton NAD zdjęciem, w kolorze wybranego "Tła" */
.background-overlay {
  position: absolute;
  inset: 0;
}

.background-overlay-niebieski { background-color: var(--co-brand); opacity: 0.8; }
.background-overlay-szary     { background-color: var(--co-soft);  opacity: 0.8; }
.background-overlay-bialy     { background-color: var(--co-bg);    opacity: 0.8; }
.background-overlay-ciemny    { background-color: var(--co-deep);  opacity: 0.72; }


/* 11. EYEBROW — .eyebrow też ręcznie w realizacja.php (stąd tu, nie w snippecie) */
.eyebrow {
  font-family: var(--font-heading);
  font-size: var(--fs-s);
  font-weight: 500;
  font-stretch: var(--wdth-l);
  letter-spacing: 0.05em;
  color: var(--co-logo);
  text-transform: uppercase;
}

/* eyebrow przyklejony do nagłówka pod nim */
.flow > .eyebrow + :is(h1, h2, h3, h4, h5, h6) {
  --flow-space: 0.25em;
}


/* 12. PRZYCISK (.btn) — blok "Przyciski" ORAZ przycisk "Wyślij" formularza.
   :focus-visible pokryte globalnie (sekcja 3). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.7em 1.5em;
  border: 1px solid transparent;
  border-radius: var(--rd-full);
  font-family: var(--font-body);
  font-size: var(--fs-s);
  font-weight: var(--wght-l);
  font-stretch: var(--wdth-l);
  line-height: var(--lh-s);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--transition), color var(--transition), border-color var(--transition);
}

/* podstawowy — pełne wypełnienie akcentem */
.btn-primary {
  background-color: var(--co-accent);
  /* Ciemny tekst na pomarańczu: biały dawał ok. 2:1 (WCAG 1.4.3 wymaga 4,5:1);
     --co-brand na --co-accent ≈ 7:1. */
  color: var(--co-brand);
}

.btn-primary:hover {
  background-color: color-mix(in srgb, var(--co-accent) 88%, var(--co-brand));
}

/* drugorzędny — pigułka bez wypełnienia, tekst dziedziczy kolor kontekstu */
.btn-secondary {
  background-color: transparent;
  color: inherit;
  border-color: var(--co-mix);
}

.btn-secondary:hover {
  border-color: color-mix(in srgb, currentColor 40%, transparent);
}

/* wrapper bloku — odstęp MIĘDZY przyciskami; rytm pionowy daje .flow rodzica */
.przyciski {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-s);
}


/* 13. FORMULARZ (.formularz*) — markup w blocks/formularz.php; dzieli .btn (sekcja 12).
   Pola adaptacyjne do jasności sekcji: color: inherit + tło/obwódka z currentColor.
   --field-line / --field-fill = jedyne regulatory. */
.formularz {
  /* width:100% — inaczej kurczy się do max-content siatki (poziomy scroll ~330px) */
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  /* BEZ `margin: 0` — nadpisywałoby margin-block-start z .flow > * + * (odstęp
     od nagłówka/bloku nad formularzem w kolumnie); usunięte 2026-09-30 */
  --flow-space: var(--gap-m);
}

.formularz {
  --field-fill: color-mix(in srgb, currentColor 7%, transparent);
  --field-line: color-mix(in srgb, currentColor 30%, transparent);
}

/* odstęp między rzędami pól — węższy niż domyślne .grid + .grid (--gap-m);
   opis i przycisk nadal na --flow-space / własnym marginesie */
.formularz .grid + .grid {
  margin-top: var(--gap-s);
}

.formularz-field {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
}

.formularz-label {
  font-size: var(--fs-s);
  font-weight: 500; /* font zmienny 100–700 — pośrednia grubość między --wght-m a --wght-l */
  font-stretch: var(--wdth-m);
}

.formularz-input {
  display: block;
  width: 100%;
  padding: 0.8em 1em;
  border: 1px solid var(--field-line);
  border-radius: var(--rd-s);
  background: var(--field-fill);
  font-family: var(--font-body);
  font-size: var(--fs-s);
  font-weight: var(--wght-m);   /* wpisywany tekst = 400, jak domyślnie w witrynie */
  font-stretch: var(--wdth-m);
  color: inherit;
}

.formularz-req {
  margin-inline-start: 0.15em;
}

.formularz-input::placeholder {
  color: inherit;
  opacity: 0.65;
}

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

.formularz .formularz-note {
  /* odstęp od pola treści (zmniejszony z --gap-l, 2026-09-30) */
  margin: var(--gap-s) 0 0;
  font-size: var(--fs-s);
}

.formularz-error {
  margin: 0;
  font-size: var(--fs-s);
  font-weight: var(--wght-l);
}

.formularz-input[aria-invalid="true"] {
  border-color: currentColor;
  border-width: 2px;
}

.formularz-status {
  margin: 0;
  padding: 0.8em 1em;
  border: 1px solid var(--field-line);
  border-left-width: 4px;
  border-radius: var(--rd-s);
  background: var(--field-fill);
  font-size: var(--fs-s);
}

.formularz-status:focus {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* Honeypot — poza ekranem (nie display:none: część botów pomija takie pola);
   ukryty też przed AT (aria-hidden w markupie) i poza kolejnością fokusu. */
.formularz-hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.formularz-submit {
  display: flex;
  justify-content: flex-end;
}


/* 14. KARTA (site/snippets/card.php) — blok "Podstrony"/"Karta" + moduły.
   Karta-duch: przezroczyste tło, kolory treści dziedziczone z kontenera —
   na panelu Niebieski/Ciemny tekst i border same jaśnieją (sekcja 10 + --co-mix
   liczony z currentColor). Tytuł na `var(--link)`: granat na jasnym, biały na
   ciemnym — ten sam przełącznik co linki treści. Klik w kartę: .card-link::after.

   Układ: flexbox pionowy. .card-body u góry (tytuł → stat → treść);
   .card-media (obraz, proporcje 16:9, cover) na dole — renderowana tylko gdy
   jest zdjęcie. Bez zdjęcia .card-body jest jedynym dzieckiem flexa
   → 100% wysokości (moduły „Dlaczego"/„Liczby" jak wcześniej). Flex lokalny
   dla karty — NIE system .grid/.dN. */

/* Listing kart — flexbox z deterministyczną liczbą kolumn per próg
   (2026-09-15, druga iteracja; 2026-09-25 — 2 kolumny jako domyślne wszędzie).
   Poprzedni wariant (flex-basis:17rem + flex-grow + max-width) był wciąż
   „intrinsic" — przeglądarka liczy zawinięcie wiersza na bazie flex-basis
   PRZED zastosowaniem grow/max-width, więc przy pewnych szerokościach mieściła
   się dodatkowa karta, zanim urosła/skurczyła się do docelowego rozmiaru.
   Procentowy flex-basis + flex-grow:0 eliminuje zgadywanie — liczba kolumn to
   wprost 2/2/1 (karty, każde .lista bez modyfikatora — Podstrony, Dlaczego,
   Powiązane) i 4/2/1 (.lista-stat) na progu .mN (sekcja 7: 576px). 2 kolumny
   testowane najpierw na listingu „Rozwiązania" (.lista-2, do 2026-09-25,
   dziś usunięte jako zbędne — stały się domyślnym zachowaniem .lista). Bez
   osobnego max-width: karta na mobile ma pełną szerokość, spójną z resztą
   treści, zamiast być ograniczana do sztywnego maksimum.
   justify-content:flex-start = domyślnie karty do lewej; modyfikator
   .lista-center dokłada wyśrodkowanie niepełnego ostatniego wiersza tam, gdzie
   wygląda to lepiej (np. modul-dlaczego.php). */
.lista {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  /* kolumna .flex.col.v-start (base/layout.php) ma align-items:start → bez tego
     ul kurczy się do szerokości treści (ten sam powód co width:100% w .info,
     sekcja 18) */
  width: 100%;
  /* var(--sp-s) zamiast var(--gap-s) (2026-09-15) — nieco większy odstęp
     między kartami niż domyślny gap systemu siatki */
  gap: var(--sp-s);
  list-style: none;
  padding-left: 0;
}

.lista-center {
  justify-content: center;
}

/* zeruje marker "—" list treści (sekcja 9); min-width:0 = długi tytuł bez
   spacji nie rozpycha karty ponad wyliczoną szerokość kolumny. 2 kolumny na
   desktop I tablet (ten sam wynik na obu progach — patrz media query niżej,
   tylko ≤576px zbija do 1 kolumny), stąd bez osobnej reguły na 991px. */
.lista > li {
  min-width: 0;
  padding-left: 0;
  flex: 0 1 calc((100% - var(--sp-s)) / 2);
}
.lista > li::before {
  content: none;
}

/* moduł „Petroff w liczbach" — małe kafelki ze statystyką, gęściej niż listing treści */
.lista-stat > li {
  flex-basis: calc((100% - 3 * var(--sp-s)) / 4);
}

@media (max-width: 991px) {
  .lista-stat > li {
    flex-basis: calc((100% - var(--sp-s)) / 2);
  }
}
@media (max-width: 576px) {
  .lista > li,
  .lista-stat > li {
    flex-basis: 100%;
  }
}

.card {
  position: relative;
  display: flex;
  height: 100%;
  overflow: hidden;
  /* przezroczysta — tło i kolor treści z kontenera; wyróżnia ją tylko
     lewy akcent (--co-mix = currentColor 16%, jaśnieje na ciemnym).
     padding jednolity na WSZYSTKICH krawędziach (2026-09-15) — wcześniej tylko
     padding-left, a .card-body miał własny padding do tekstu; obraz w
     .card-media (bez paddingu) dotykał prawej/dolnej krawędzi karty. gap
     zastępuje dawne padding-block na .card-body — odstęp tekst↔obraz. */
  border-left: 1px solid var(--co-mix);
  border-radius: var(--panel-radius);
  padding: var(--sp-s);
  gap: var(--sp-s);
  flex-direction: column;
}

/* pas obrazu (tylko gdy karta ma zdjęcie) — stałe proporcje 16:9 zamiast
   wysokości zależnej od treści, więc siatka kart nie „skacze" przy różnych
   długościach tytułu/treści. Obraz position:absolute (jak .background-image,
   sekcja 10) wypełnia ten pas przez cover. Własny border-radius (mniejszy niż
   --panel-radius karty) — odkąd obraz jest inset (padding karty), a nie
   dociąga do krawędzi, potrzebuje zaokrąglenia samodzielnie. */
.card-media {
  flex: 0 0 auto;
  width: 100%;
  aspect-ratio: 32 / 9;
  position: relative;
  overflow: hidden;
  border-radius: var(--rd-s);
}

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

.card-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(var(--sp-xs) * 0.9);
}

/* duża liczba w karcie modułu "Petroff w liczbach" — nie nagłówek, do lewej */
.card .card-stat {
  display: block;
  font-size: var(--hs-2);
  font-weight: var(--wght-xl);
  font-stretch: var(--wdth-xl);
  line-height: var(--lh-s);
  color: var(--co-accent);
}

/* tytuł karty — NIE nagłówek (patrz card.php): własna typografia zamiast klasy
   .h4. font-size o krok mniejszy niż dawne --hs-4 (--hs * 0.9) */
.card .card-title {
  font-family: var(--font-heading);
  font-size: calc(var(--hs) * 0.88);
  font-weight: var(--wght-l);
  font-stretch: var(--wdth-l);
  line-height: var(--lh-s);
  /* niebieski z logo na jasnym, biały na ciemnym — sekcja 10 przełącza
     --co-logo na panelu Niebieski/Ciemny (tytuł jest linkiem: obejmuje .card-link) */
  color: var(--co-logo);
  transition: color var(--transition);
}

.card:hover .card-title {
  color: var(--co-accent);
}

.card-link {
  color: inherit;
  text-decoration: none;
}

.card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card:has(.card-link:focus-visible) {
  outline: 2px solid var(--co-accent);
  outline-offset: 2px;
}

.card .card-text {
  font-size: var(--fs-s);
  color: inherit;
  padding-right: 5%;
}

/* moduł „Petroff w liczbach" — etykieta stylem jak .eyebrow (sekcja 11:
   uppercase, letter-spacing, font-size/weight/stretch), ale w kolorze sekcji
   zamiast --co-accent — jedyny kolorowy element karty zostaje liczba
   (.card-stat, wyżej), etykieta nie jest linkiem/nagłówkiem. */
.lista-stat .card-title {
  font-size: var(--fs-s);
  font-weight: var(--wght-m);
  font-stretch: var(--wdth-l);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: inherit;
}

.lista-stat .card:hover .card-title {
  color: inherit;
}

/* Wariant numerowany karty (2026-09-16, poprawiony) — opt-in przez param
   `numer` w card.php, włączany przełącznikiem „Numerowana" w bloku
   „Podstrony" (blocks/lista.yml), per wstawienie bloku — nie jest zaszyty
   w typie podstrony. Bez `numer` te reguły się nie stosują — reszta kart
   (Realizacje, Branże, blok „Karta", moduły) wygląda jak dotychczas.
   Cyfra i linia siedzą w `.card-numer` z aria-hidden="true" (czysto
   wizualny akcent — pozycję w liście i tak niesie <ul role="list">). */
.card-numer {
  display: flex;
  align-items: center;
  gap: var(--sp-xs);
}

/* ta sama wielkość co .card-title — numer ma wagę tytułu, nie osobny,
   większy akcent; jedyna różnica to kolor (akcent zamiast --co-logo) */
.card-numer-cyfra {
  font-family: var(--font-heading);
  font-size: calc(var(--hs) * 0.88);
  font-weight: var(--wght-xl);
  font-stretch: var(--wdth-xl);
  color: var(--co-accent);
}

/* krótka kreska obok cyfry — stała szerokość (NIE flex:1 na całą resztę
   rządka), czysto dekoracyjny akcent, jak we wzorze */
.card-numer-linia {
  flex: 0 0 auto;
  width: 3rem;
  height: 1px;
  background: var(--co-mix);
}

/* „Więcej…" na dole KAŻDEJ klikalnej karty (2026-09-16, poszerzone z wariantu
   numerowanego na wszystkie — patrz `url` w card.php). Wcześniej
   margin-top:auto (dociągało do dołu .card-body niezależnie od długości
   treści) — dawało zbyt duży, zmienny odstęp nad przyciskiem; zamienione
   (2026-09-25) na stały, mały padding-top (--sp-s), spójny z resztą
   odstępów w karcie. Bez ikony strzałki — świadomie usunięta. */
.card-cta-text {
  font-size: calc(var(--fs-s) * 0.9);
  font-weight: var(--wght-m);
  color: inherit;
  opacity: 0.7;
  transition: color var(--transition), opacity var(--transition);
}

/* hover całej karty (nie tylko tekstu) — spójnie z .card:hover .card-title;
   --co-logo zamiast --co-accent, celowo inny akcent niż tytuł */
.card:hover .card-cta-text {
  color: var(--co-logo);
  opacity: 1;
}

/* Wariant "Kafelek" (2026-09-29 — treść/ikona/numer/zdjęcie) — samodzielna
   karta BEZ powiązania ze stroną, BEZ tytułu (site/snippets/kafelek.php,
   bloki „Kafelek"/„Lista kafelków"). Współdzieli .card/.card-body z kartą
   standardową —
   różni ją obramowanie na WSZYSTKICH krawędziach (.card odsłania je tylko
   po lewej, `border-left`) i .card-kafelek-ikona (ikonka LUB numer) NAD
   treścią — ten sam wzorzec co .card-numer nad .card-title w karcie
   standardowej (card.php), zamiast osobnej lewej kolumny (czwarta wersja,
   wiersz — porzucona, patrz git). Selektor .card.card-kafelek
   (specificity 0,2,0), żeby nadpisać border-left samego .card — wzorzec
   jak .info.info-* (sekcja 18). Bez .card-link/.card-cta/.card-title —
   kafelek nie ma `url` ani nagłówka, nie jest klikalny, więc bez efektu
   hover. */
.card.card-kafelek {
  border: 1px solid var(--co-mix);
}

/* .card-body domyślnie jest kolumną (karta standardowa) — kafelek zostaje
   przy tym (bez nadpisania na wiersz, w odróżnieniu od czwartej wersji):
   ikonka/numer, potem treść, jedno pod drugim. gap: var(--sp-s)
   (2026-09-28) — ten sam odstęp co padding karty (.card, wyżej) między
   krawędzią a treścią, żeby odstęp ikonka↔treść wizualnie odpowiadał
   odstępowi treść↔krawędź. Nadpisuje mniejszy domyślny gap .card-body
   (calc(var(--sp-xs)*0.9), używany do pionowego odstępu tytuł/treść
   w karcie standardowej). */
.card-kafelek .card-body {
  gap: var(--sp-s);
}

/* Wariant obrazowy kafelka (2026-09-29, pole „Zdjęcie") — CAŁA karta to
   zdjęcie, bez .card-body/treści. padding: 0 nadpisuje padding .card (wyżej)
   — inaczej obraz miałby ramkę pustego tła dookoła zamiast dotykać krawędzi.
   ŚWIADOMIE bez aspect-ratio (wcześniej 1/1, porzucone — obraz robił się
   wyższy niż sąsiednie kafelki z treścią, zamiast się do nich dopasować).
   .lista-kafelki to flex row z domyślnym align-items:stretch (sekcja 7) —
   wiersz i tak dostaje wysokość od "zwykłych" kafelków (treść w normalnym
   przepływie), a .card (height:100%, sekcja 14 wyżej) obrazowego kafelka
   po prostu ją PRZEJMUJE przez stretch, nie narzuca własnej. min-height —
   WYŁĄCZNIE floor na wypadek, gdyby w wierszu nie było ŻADNEGO kafelka
   z treścią (sam obrazowy, lub kilka obrazowych obok siebie) — inaczej <img
   position:absolute (site/snippets/image.php, ratio:"full") wypadłby
   z przepływu i .card zapadłby się do 0px. Nie ogranicza wysokości w górę,
   tylko w dół. */
.card-kafelek-obraz {
  padding: 0;
  min-height: 10rem;
}

/* Treść kafelka — DEDYKOWANA klasa (2026-09-28), NIE .card-text karty
   standardowej. Wcześniej kafelek dziedziczył .card .card-text (sekcja 14
   wyżej): font-size: var(--fs-s) (0.9×) i padding-right: 5% — ustawienia
   dobrane pod kartę z obrazem/CTA, przypadkowe dla dwukolumnowego wiersza
   kafelka. Własna klasa = własny, świadomy zestaw stylów:
   - font-size: var(--fs-m) — domyślny rozmiar tekstu strony (--fs), NIE
     pomniejszony jak w karcie; kafelek nie ma tytułu, który by go wybijał,
     więc tekst ma wyglądać jak zwykła treść, nie jak podpis;
   - BEZ padding-right — kolumna tekstu i tak kończy się na krawędzi karty
     (padding niesie już .card), dodatkowy zapas z prawej nie miał tu funkcji.
   Odstęp MIĘDZY akapitami (.flow, kafelek.php) węższy niż domyślny --sp-s
   (.flow > * + *, sekcja 6) — kafelek to mały, gęsty element, nie długa
   treść strony. Stała 1em (zamiast fluid --sp-s) — skaluje się z rozmiarem
   czcionki, celowo bez responsywnego szybowania. */
.card-kafelek-tresc {
  font-size: var(--fs-m);
  color: inherit;
  --flow-space: 1em;
}

/* Rozmiar stały (1.5em × 1.5em) niezależnie od reszty treści karty. */
.card-icon {
  display: block;
  width: 1.5em;
  height: 1.5em;
  /* jasny/żywy niebieski z logo (sekcja 2) — SVG wewnątrz dziedziczy go przez
     currentColor (kod ikony ma już podmienione #000000 → currentColor,
     patrz kafelek.php). */
  color: var(--co-logo);
}

/* Rozmiar SVG dziedziczony z .card-icon (span). ŚWIADOMIE bez `fill:
   currentColor` tutaj — te ikony są konturowe (fill="none" na korzeniu
   pliku), a CSS na `<svg>` wygrywa z JEGO WŁASNYM atrybutem `fill`, więc
   taka reguła nadpisywałaby "none" na kolor marki i dzieci bez własnego
   fill dziedziczyłyby wypełnienie zamiast zostać samą kreską (błąd
   naprawiony 2026-09-28 — patrz komentarz w kafelek.php). Kolor niesie
   wyłącznie podmiana na currentColor w źródle SVG + `color` powyżej. */
.card-icon svg {
  width: 100%;
  height: 100%;
}

/* Wariant numerowany kafelka (2026-09-28, pole „Numerowana" w bloku „Lista
   kafelków") — cyfra w TYM SAMYM miejscu co .card-icon, NAD treścią
   (kafelek.php: jedno z dwóch, nigdy oba naraz). font-size: 1em, ŚWIADOMIE
   mniejszy niż width/height: 1.5em ikony (wyżej) — przy równym 1.5em cyfra
   optycznie wyglądała na większą od ikony (pełny kwadrat glifu vs. cienki
   kontur SVG), 1em lepiej się bilansuje. line-height:1 trzyma jej wysokość
   ciasno wokół cyfry, żeby odstęp do treści pod spodem nie skakał między
   kafelkami numerowanymi i tymi z ikoną. font-weight: 500 — świadomie
   WŁASNA wartość (poza tokenami --wght-*, sekcja 1: 300/400/600/700),
   pośrednia, mniej ciężka niż pogrubienie .card-numer-cyfra karty
   standardowej — na tle samej ikonki (bez tytułu obok) pełne pogrubienie
   robiło się zbyt krzykliwe. */
.card-kafelek-numer {
  display: block;
  font-family: var(--font-heading);
  font-size: 1em;
  font-weight: 500;
  font-stretch: var(--wdth-xl);
  line-height: 1;
  color: var(--co-accent);
}

/* Siatka bloku "Lista kafelków" (site/snippets/blocks/lista-kafelkow.php)
   (2026-09-28, liczba kolumn wybierana w Panelu) — modyfikator .lista-kafelki
   na tym samym .lista co „Podstrony" (flexbox, sekcja 14 wyżej). Liczbę
   kolumn niosą custom properties `--kafelki-desktop`/`--kafelki-tablet`,
   ustawione inline na <ul> (blocks/lista-kafelkow.php) z pól „Kolumny
   (komputer)"/„Kolumny (tablet)" — jeden wzór flex-basis obsługuje dowolną
   wybraną wartość, bez generowania klasy na każdą kombinację. Fallbacki
   (3/2) na wypadek starszej treści bez zapisanych properties. Smartfon
   ZAWSZE 1 kolumna — bez pola w Panelu, to standard całej strony (zwykłe
   .lista). Kafelki mają stały, naturalny rozmiar; niepełny ostatni wiersz
   centruje `.lista-center` (w markupie). */
.lista-kafelki > li {
  --kafelki-cols: var(--kafelki-desktop, 3);
  flex-basis: calc((100% - (var(--kafelki-cols) - 1) * var(--sp-s)) / var(--kafelki-cols));
}

@media (max-width: 991px) {
  .lista-kafelki > li {
    --kafelki-cols: var(--kafelki-tablet, 2);
  }
}
@media (max-width: 576px) {
  .lista-kafelki > li {
    flex-basis: 100%;
  }
}

/* Wariant „dopełniaj" (pole „Niepełny ostatni wiersz" w bloku, włączone) —
   flex-grow:1 zamiast domyślnego 0 (z bazowej reguły .lista > li). Pełne
   wiersze i tak sumują flex-basis do ~100% szerokości, więc grow nie ma
   z czego korzystać; na NIEPEŁNYM ostatnim wierszu zostaje wolne miejsce,
   które te kilka kafelków dzieli między siebie i rośnie, żeby razem
   wypełnić całą szerokość — zamiast zostać naturalnego rozmiaru
   i wyśrodkować się (`.lista-center`, wariant domyślny). */
.lista-kafelki.lista-kafelki-dopelniaj > li {
  flex-grow: 1;
}


/* 15. BANER ZGÓD COOKIES (cookie-banner.php, render base/foot.php; logika cookies.js).
   .cookie-banner = scrim blokujący; .cookie-banner-panel = pływająca karta u dołu. */
.cookie-banner {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: var(--sp-s);
  background: color-mix(in srgb, var(--co-ink) 55%, transparent);
}

.cookie-banner-panel {
  margin-block-start: auto;
  margin-inline: auto;
  width: 100%;
  max-width: var(--content-width);
  display: flex;
  flex-direction: column;
  padding: var(--sp-s) var(--gutter);
  background: var(--co-bg);
  color: var(--co-ink);
  border: 1px solid var(--co-mix);
  border-radius: var(--panel-radius);
  box-shadow: 0 0.5rem 2rem color-mix(in srgb, var(--co-ink) 25%, transparent);
}

.cookie-banner-panel > * {
  margin: 0;
}

.cookie-banner-desc {
  margin-block-start: var(--sp-xs);
}

.cookie-banner-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-block-start: var(--sp-xs);
}

@media (min-width: 48rem) {
  .cookie-banner-panel {
    padding-block: var(--sp-m);
  }
}


/* 16. PLACEHOLDER YOUTUBE (blocks/video.php; podmiana w youtube.js) —
   miniaturka + overlay + przycisk zamiast <iframe>. */
.yt-embed {
  width: 100%;
  margin: 0;
}

.yt-embed-trigger {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 15rem; /* dłuższa informacja o zgodzie nie może być ucięta na wąskich ekranach */
  padding: 0;
  border: 1px solid var(--co-mix);
  border-radius: var(--panel-radius);
  overflow: hidden;
  background: var(--co-deep);
  color: var(--co-bg);
  font: inherit;
  cursor: pointer;
}

.yt-embed-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.yt-embed-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-xs);
  padding: var(--sp-m);
  text-align: center;
  background: color-mix(in srgb, var(--co-deep) 72%, transparent);
}

.yt-embed-play {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-xs);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.yt-embed-note a {
  color: inherit;
  text-decoration: underline;
}

.yt-embed-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--rd-full);
  background: var(--co-accent);
  color: var(--co-bg);
  transition: background-color var(--transition);
}

.yt-embed-trigger:hover .yt-embed-icon,
.yt-embed-play:focus-visible .yt-embed-icon {
  background: var(--co-brand);
}

.yt-embed-label {
  font-weight: var(--wght-l);
  font-stretch: var(--wdth-l);
  font-size: var(--fs-l);
}

.yt-embed-note {
  max-width: 46ch;
  margin: 0;
  font-size: var(--fs-s);
}

.yt-embed-iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: var(--panel-radius);
}

.yt-embed figcaption {
  margin-block-start: var(--sp-xs);
  text-align: center;
  font-size: var(--fs-s);
  color: var(--co-ink);
  opacity: 0.75;
}


/* 17. MEDIA TREŚCI — obraz / wideo w treści strony.
   Domyślny wygląd: wszystkie rogi zaokrąglone tym samym promieniem co panel
   tła kontenera (--panel-radius, sekcja 10) — spójność wizualna zdjęć,
   galerii i ramek wideo z „kafelkami" tła i kartami.

   ŹRÓDŁO markupu jest OSOBNO (wzorzec „prezentacja w CSS"): plik wybiera
   redaktor w Panelu, <img> renderuje site/snippets/image.php (webp + srcset),
   a bloki „Obraz" / „Galeria" / „Wideo" (site/snippets/blocks/*.php) owijają
   je w <figure>. Ta sekcja NIE dotyka tych plików — tylko nakłada domyślny
   promień na każde <img>/<video>/<iframe> siedzące w <figure> w <main>.

   Świadomie POZA regułą (własny promień / brak):
   - logo w <header>/<footer> — poza <main>,
   - tło kontenera .background-image — przycięte przez .background { overflow:hidden },
   - obraz karty — .card-media ma własny (mniejszy) border-radius, sekcja 14,
   - placeholder YouTube .yt-embed — komplet stylów w sekcji 16 (stąd :not). */
main figure:not(.yt-embed) :is(img, video, iframe) {
  border-radius: var(--panel-radius);
}

/* Blok „Obraz", ratio "full" (site/blueprints/blocks/image.yml pkt 4).
   DWIE POPRZEDNIE WERSJE zawodziły (height:100% zapadało się do zera; potem
   flex-grow + aspect-ratio nie było wiarygodnie przenoszone przez zagnieżdżony
   flex-column w praktyce — figure lądowała na zapasowym 4:3, nie rosła).

   Trzecie podejście: TEN SAM mechanizm co .background/.background-image
   (sekcja 10) — position:absolute + inset:0 względem rodzica, nie żadna
   procentowa/flex kalkulacja. Rodzic (kolumna .dN „Kontenera" — ALE też
   każdy inny bezpośredni rodzic, gdyby blok trafił w inny kontekst, stąd
   uniwersalny selektor :has() niżej, nie ".dN" wprost) dostaje
   position:relative + min-height jako podłogę: bez sąsiada/w podglądzie
   Panelu ma z czego zbudować własną wysokość (16rem), z sąsiadem — CSS Grid
   naturalnie rozciąga go (align-items:stretch, domyślne dla .grid, sekcja 7)
   wyżej niż ta podłoga, a figure wypełnia dokładnie tyle, ile rodzic
   faktycznie ma. Figure nie ma już WŁASNEJ wysokości do policzenia z niczego
   — stąd koniec z zapadaniem się i z rozjazdem szerokości. */
.grid > *:has(> .image-full) {
  position: relative;
  min-height: 16rem;
}

.image-full {
  position: absolute;
  inset: 0;
}


/* 18. INFO (.info) — notatka na marginesie: blok „Info" (blocks/info.php).
   CSS tutaj, nie w <style> snippetu (wzorzec jak .eyebrow sekcja 11,
   memory-blueprint.md §5).

   Bez tła i ramki dookoła — wyróżnia ją tylko pionowa kreska 1px po lewej +
   rozmiar S. width:100% — <aside> siedzi w kolumnie .flex.col z
   align-items:flex-start, bez tego kurczy się do szerokości treści i kreska
   nie idzie pełną wysokością. */
.info {
  width: 100%;
  border-inline-start: 1px solid var(--co-mix);
  padding-inline-start: var(--sp-s);
  font-size: var(--fs-s);
}

/* Warianty koloru kreski — ta SAMA właściwość co skrót w .info
   (border-inline-start-color) + selektor .info.info-* (0,2,0), żeby wariant
   pewnie wygrał ze skrótem bazowym. */
.info.info-domyslny  { border-inline-start-color: var(--co-mix); }
.info.info-niebieski { border-inline-start-color: var(--co-brand); }
.info.info-akcent    { border-inline-start-color: var(--co-accent); }


/* 19. REALIZACJA — oś czasu zleceń (templates/realizacja.php, sekcja 2).
   Lista rok → zakres w kolumnie 3/4 kontenera. Wiersze rozdziela sam gap
   (--gap-s, mniejszy niż siatka --gap-m) — bez linii, bez markera „—" list
   treści (sekcja 9): zerujemy ::before i pad-left/pad-bottom z tamtej sekcji.
   Rok w kolorze akcentu. */
.realizacje-zlecenia {
  width: 100%;
  display: grid;
  gap: var(--gap-s);
}

.realizacje-zlecenia > li {
  display: grid;
  grid-template-columns: 4rem 1fr;
  gap: var(--gap-m);
  align-items: baseline;
  padding-left: 0;
  padding-bottom: 0;
}

.realizacje-zlecenia > li::before {
  content: none;
}

.realizacje-zlecenia-rok {
  font-family: var(--font-heading);
  font-weight: var(--wght-l);
  font-variant-numeric: tabular-nums;
  color: var(--co-accent);
}


/* 20. NAWIGACJA MOBILNA — hamburger + rozwijany panel (mobile-nav.php),
   ≤991px. Panel "wysuwa się" z przycisku: górny prawy róg panelu pokrywa się
   z górnym prawym rogiem przycisku (ten sam prostokąt 2.6rem), więc przycisk
   zostaje na miejscu i ląduje w rogu rozwiniętego panelu. Logika
   otwierania/zamykania, pułapka focusa: assets/js/nav.js. */

.nav-toggle-wrap {
  position: relative;
  flex: 0 0 auto;
  /* własny kontekst stackowania — bez tego przycisk mógłby się znaleźć pod
     sekcją hero (patrz też --z-header, sekcja 8) mimo z-index panelu poniżej */
  isolation: isolate;
}

.nav-toggle {
  position: relative;
  z-index: 21;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 1px solid var(--co-mix);
  border-radius: var(--rd-full);
  background: var(--co-logo);
  cursor: pointer;
  transition: border-color var(--transition);
}

/* otwarty — bez obwódki, kółko wtapia się w panel pod spodem (ten sam kolor) */
.nav-toggle[aria-expanded="true"] {
  border-color: transparent;
}

.nav-toggle .bars {
  position: relative;
  width: 1.15rem;
  height: 0.8rem;
}

.nav-toggle .bars span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: #fff;
  transition: transform var(--transition), opacity var(--transition), top var(--transition);
}

.nav-toggle .bars span:nth-child(1) { top: 0; }
.nav-toggle .bars span:nth-child(2) { top: 50%; margin-top: -1px; }
.nav-toggle .bars span:nth-child(3) { top: 100%; margin-top: -2px; }

.nav-toggle[aria-expanded="true"] .bars span:nth-child(1) {
  top: 50%; margin-top: -1px;
  transform: rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .bars span:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .bars span:nth-child(3) {
  top: 50%; margin-top: -1px;
  transform: rotate(-45deg);
}

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

/* niewidzialna warstwa na cały viewport — zamyka klikiem poza panelem,
   bez przyciemnienia reszty strony */
.mobile-nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 19;
  background: transparent;
  pointer-events: none;
}

.mobile-nav.is-open .mobile-nav-scrim {
  pointer-events: auto;
}

.mobile-nav-panel {
  position: absolute;
  z-index: 20;
  top: 0;
  right: 0;
  left: auto;
  width: max-content;
  /* prawa krawędź ma już zapas z paddingu headera (--gutter, .container
     sekcja 6) — tu pilnujemy tylko minimalnego luzu od LEWEJ krawędzi
     ekranu; na bardzo wąskich telefonach panel może więc podejść blisko
     pełnej szerokości, ale nigdy jej nie dotknąć. */
  max-width: calc(100vw - var(--gutter) - 0.75rem);
  background: var(--co-logo);
  color: #fff;
  border-radius: var(--panel-radius);
  /* góra: miejsce na przycisk (2.6rem) + odstęp nad linkami */
  padding: calc(2.6rem + 0.65rem) 1.05rem 0.9rem;
  transform-origin: top right;
  transform: scale(0.94);
  opacity: 0;
  pointer-events: none;
  transition: transform var(--transition), opacity var(--transition);
}

.mobile-nav.is-open .mobile-nav-panel {
  transform: scale(1);
  opacity: 1;
  pointer-events: auto;
}

.mobile-nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.mobile-nav-list a {
  display: block;
  padding: 0.9rem 2.1rem;
  color: #fff;
  font-size: 0.92rem;
  font-weight: 600;
  /* duże litery — spójnie z .nav-list a na desktopie (sekcja 8) */
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  border-radius: calc(var(--panel-radius) * 0.55);
}

.mobile-nav-list a:hover,
.mobile-nav-list a:focus-visible {
  color: var(--co-accent);
}

.mobile-nav-list a[aria-current="page"] {
  color: var(--co-accent);
}

@media (prefers-reduced-motion: reduce) {
  .mobile-nav-panel,
  .nav-toggle .bars span {
    transition-duration: 0.01ms;
  }
}
