/* ══════════════════════════════════════════════════════════════════════════════
   RDZEŃ — style wspólne dla WSZYSTKICH stron docelowych.            WERSJA: 10
   ══════════════════════════════════════════════════════════════════════════════
   ⛔ TU NIE MA WYGLĄDU. Zero kolorów marki, zero krojów pisma, zero układu.
      Dwie strony docelowe mają się RÓŻNIĆ — to jest sens, za który klient płaci.

   Jest tu wyłącznie to, czego nigdy nie projektujemy od nowa:
   dostępność, czytelność, stany interakcji, zachowanie przy ruchu.
   Wszystko sterowane zmiennymi, żeby każda strona nadała temu swój wygląd.

   Wpinać PRZED `app.css` strony:
     <link rel="stylesheet" href="assets/rdzen.css?v=10">
     <link rel="stylesheet" href="assets/app.css?v=N">

   Poprawka idzie do tego pliku, nie do kopii w repo klienta.
   ══════════════════════════════════════════════════════════════════════════════ */

:root{
  /* hover zdjęć — lekcja 2026-08-04-001: scale(1.05) skakał kadrem i wyglądał tanio */
  --img-zoom:1.02;
  --img-rest:brightness(.95) saturate(.99);
  --img-hot:brightness(1.06) saturate(1.05);
  --img-dur:.55s;
  --ease:cubic-bezier(.2,.7,.3,1);
  /* cień pod napisem leżącym na zdjęciu — lekcja 2026-08-06-004.
     Wartości dobrane tak, żeby ratować czytelność, a nie przyciemniać kadru. */
  --cien-na-zdjeciu:0 1px 2px rgba(0,0,0,.58),0 2px 22px rgba(0,0,0,.46);
  --cien-na-zdjeciu-lekki:0 1px 2px rgba(0,0,0,.55),0 1px 12px rgba(0,0,0,.4);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* 🔴 PŁYNNE PRZEWIJANIE TYLKO POD MYSZĄ (K. 11.09.2026: „przy scrollowaniu na telefonie
   czasami tak się przesuwa niekontrolowanie"). Na ekranie dotykowym `scroll-behavior:smooth`
   bije się z bezwładnością palca: przeglądarka animuje swoje przewinięcie, a palec w tym
   czasie prowadzi własne — strona dojeżdża sama albo szarpie po puszczeniu. Na myszy
   efekt jest potrzebny (kotwice w menu), bo tam nie ma czego zakłócać.
   ⛔ Nie przenoś `scroll-behavior` z powrotem na goły `html`. */
@media (pointer:fine){html{scroll-behavior:smooth}}
img{max-width:100%;height:auto;display:block}
a{color:inherit}

/* ── DOSTĘPNOŚĆ ──────────────────────────────────────────────────────────── */
/* obrys focusa MUSI zostać — bez niego strona jest nieobsługiwalna z klawiatury */
:focus-visible{outline:2.5px solid currentColor;outline-offset:3px;border-radius:2px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;padding:12px 18px;z-index:200}
.skip:focus{left:12px;top:12px}

/* ── ŁAMANIE TEKSTU ──────────────────────────────────────────────────────────
   Lekcja 2026-08-06-003: „wodno-kanalizacyjne” pękało po dywizie i druga linia
   zaczynała się od końcówki wyrazu. Generator owija takie wyrazy w .nw. */
.nw{white-space:nowrap}
h1,h2,h3{text-wrap:balance}          /* bez tego zostaje sierota w ostatniej linii */
p,li{text-wrap:pretty}

/* ── NAPISY NA ZDJĘCIU ───────────────────────────────────────────────────────
   Lekcja 2026-08-06-001 i 2026-08-07-015: biały tekst na jasnym kadrze znika,
   a bramka nie policzy kontrastu z kodu, bo tłem jest fotografia.
   Każdy napis leżący na zdjęciu dostaje cień — kosztuje nic, ratuje czytelność. */
.na-zdjeciu,.hero h1,.hero-lead,.hero .kicker,.hero-cap{text-shadow:var(--cien-na-zdjeciu)}
.na-zdjeciu-lekko{text-shadow:var(--cien-na-zdjeciu-lekki)}

/* ── STANY ─────────────────────────────────────────────────────────────────── */
/* pojawianie się sekcji; klasa is-in dokładana przez rdzen.js z bezpiecznikami */
.rv{opacity:0;transform:translateY(14px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.rv.is-in{opacity:1;transform:none}
/* 🔴 NA DOTYKU SEKCJA SIĘ TYLKO POJAWIA, NIE DOJEŻDŻA (K. 11.09.2026: „treść podskakuje,
   gdy sekcja się pojawia"). Te 14 px w pionie na laptopie czyta się jak głębia, bo kadr
   stoi. Na telefonie czytelnik przewija w tym samym czasie, w którym element dojeżdża —
   więc tekst rusza się pod wzrokiem i gubi się miejsce, w którym się czytało.
   Zostaje samo przenikanie: efekt jest, a nic się nie przesuwa. */
@media (pointer:coarse){
  .rv{transform:none;transition:opacity .5s var(--ease)}
}
/* BEZ JAVASCRIPTU treść musi po prostu BYĆ — klasę `js` dokłada rdzeń w pierwszej
   linijce, więc gdy skrypt nie wystartuje (blokada, błąd sieci, stara przeglądarka),
   nic nie zostaje ukryte. Bez tego strona bywa PUSTA i nikt tego nie widzi. */
html:not(.js) .rv,html:not(.js) .kaskada>*,html:not(.js) .proces-line > li{opacity:1!important;transform:none!important;animation:none!important}
/* górny pasek chowany przy przewijaniu w dół */
.top.is-hidden{transform:translateY(-102%)}

/* hover zdjęć w galeriach i kafelkach */
.tile img,.mosaic img,.gateway img,.m-tile img,.galeria img{
  transition:transform var(--img-dur) var(--ease),filter var(--img-dur) var(--ease)}
@media (hover:hover){
  .tile img,.mosaic img,.gateway img,.m-tile img,.galeria img{filter:var(--img-rest)}
  .tile:hover img,.mosaic a:hover img,.gateway:hover img,.m-tile:hover img,.galeria a:hover img,.galeria figure:hover img{
    transform:scale(var(--img-zoom));filter:var(--img-hot)}
}

/* ── OSADZENIA ŁADOWANE PO KLIKNIĘCIU ────────────────────────────────────────
   Decyzja K. 07.08.2026: mapa łączy się z Google dopiero po kliknięciu, więc
   strona nie potrzebuje banera cookies. Zasłona ma wyglądać jak część strony,
   nie jak błąd — kolory i kroje dokłada `app.css`. */
[data-po-kliknieciu]{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;text-align:center;padding:28px;width:100%}
.pk-btn{cursor:pointer;border:0}

/* ── RUCH PRZY PRZEWIJANIU (blok 10 rdzen.js) ────────────────────────────────
   Tu siedzi wyłącznie MECHANIKA: rytm, czasy, sposób wchodzenia. Kolory,
   grubości i kształty dokłada `app.css` każdej strony z osobna. */

/* KASKADA — dzieci wchodzą po kolei; `--i` ustawia rdzeń.
   Krok 70 ms: przy 5 pozycjach ostatnia rusza po 0,35 s, więc oko wodzi po
   sekcji, a nikt nie czeka na treść.

   🔴 WEJŚCIE ROBI `animation`, NIE `transition` (naprawa 16.08.2026, PEC STAL).
   Poprzednia wersja stała na `transition` + `transition-delay` — i to były DWIE
   ciche wady naraz, obie na KAŻDEJ naszej stronie:
     1. `.kaskada>*` (0,1,1) bije specyficznością zwykłą klasę kafla (0,1,0), więc
        NADPISYWAŁA cały `transition` dziecka. Kafel, któremu `app.css` ustawił
        reakcję na kursor w 0,12 s, i tak dostawał 0,55 s.
     2. Gorsze: `transition-delay` z kaskady zostaje na elemencie NA ZAWSZE i dotyczy
        każdej późniejszej zmiany. Ósmy kafel w siatce miał `--i:7`, czyli 490 ms —
        po najechaniu podświetlenie zapalało się z pół sekundy później (K. zgłaszał
        „opóźnienie na hoverze" DWA razy; za pierwszym skróciłem czas przejścia,
        co nie mogło pomóc, bo winny był delay z zupełnie innej reguły).
   `animation` nie dotyka `transition` dziecka, a `backwards` trzyma stan początkowy
   tylko w czasie oczekiwania — po zakończeniu wjazdu element wraca pod kontrolę
   reguł niżej i reaguje natychmiast. */
.kaskada>*{opacity:0;transform:translateY(16px)}
.kaskada.is-in>*{opacity:1;transform:none;
  animation:kaskada-wjazd .55s var(--ease) backwards;
  animation-delay:calc(var(--i,0) * 70ms)}
@keyframes kaskada-wjazd{from{opacity:0;transform:translateY(16px)}}

/* PASEK POSTĘPU CZYTANIA — wygląd (kolor, wysokość) należy do app.css */
.postep{position:fixed;top:0;left:0;right:0;height:2px;z-index:120;
  transform:scaleX(0);transform-origin:left center;pointer-events:none;
  transition:transform .1s linear}

/* OŚ PROCESU (blok 11) — TYLKO mechanika stanów. Kolory, odstępy, kształt
   numerów i kreski należą do `app.css` każdej strony z osobna.
   `os-on` na <html> dokłada skrypt: bez niego kroki są po prostu widoczne. */
.os-on .proces-line > li{opacity:0;transform:translateY(14px);
  transition:opacity .55s var(--ease),transform .55s var(--ease),color .35s ease}
.os-on .proces-line > li.os-seen{opacity:1;transform:none}
.proc-bar > i{transition:width .25s linear}
/* wypełnienie osi rośnie płynnie razem z przewijaniem; kolor i grubość w app.css */
.proces-line{position:relative}
.proces-line::before{content:"";position:absolute;left:0;top:0;width:1px;
  height:var(--os-fill,0);transition:height .25s linear;pointer-events:none}

/* PARALAKSA — element musi mieć własną warstwę, inaczej przeglądarka
   przerysowuje przy każdym przewinięciu i strona zaczyna się szarpać */
[data-paralaksa]{will-change:transform}

/* PRZEJŚCIE MIĘDZY PODSTRONAMI — TYLKO ZANIK PRZY WYJŚCIU.
   ⛔ Nie dokładaj tu reguły chowającej stronę przy WEJŚCIU (stała tu
   `.przejscie-wejscie body{opacity:0}`, usunięta 11.09.2026). Strona jest gotowa
   w chwili renderu; chowanie jej po fakcie dawało na telefonie: mignięcie treści
   → biały ekran → treść. Powód i pełny przebieg w `rdzen.js`, blok 10e. */
body{opacity:1;transition:opacity .22s var(--ease)}
.przejscie-wyjscie body{opacity:0}

/* Kto prosi system o mniej animacji, ma je dostać wyłączone — inaczej strona
   potrafi wywołać mdłości. Treść zostaje widoczna. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
  .rv{opacity:1!important;transform:none!important}
  .kaskada>*,.os-on .proces-line > li{opacity:1!important;transform:none!important;animation:none!important}
  body{opacity:1!important}
  .postep{display:none}
}

/* ── NAWIGACJA: rozwijane listy i sygnał „to jest klikalne" ──────────────────
   MECHANIKA, nie wygląd. Kolory bierze ze zmiennych strony (--akcent), rozmiary
   i kroje ustawia app.css. Wzorzec zamówiony przez K. 16.08.2026 na podstawie
   anthropic.com: lista rozwija się NA NAJECHANIE, a każda pozycja menu - także ta
   bez podmenu - musi dawać widoczny znak, że jest odnośnikiem.

   Wymagany HTML:
     <li class="ma-podmenu">
       <a href="..." aria-haspopup="true">Usługi <svg class="strzalka">…</svg></a>
       <ul class="podmenu"> <li><a href="…">…</a></li> </ul>
     </li>                                                                      */

.ma-podmenu { position: relative; }
.ma-podmenu { position: relative; }
/* ⚠️ Ten sam typ wyświetlania na WSZYSTKICH pozycjach menu. Gdy tylko pozycja ze
   strzałką dostaje inline-flex, a reszta zostaje inline, linia bazowa się rozjeżdża
   i ta jedna siada niżej od pozostałych (wpadka GastroHelp 16.08.2026). */
.nawigacja > ul { display: flex; align-items: center; }
.nawigacja a:not(.btn) { display: inline-flex; align-items: center; gap: .5rem; }

.podmenu {
  position: absolute; top: 100%; left: 0;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s ease;
  list-style: none; margin: 0;
}
.ma-podmenu:hover .podmenu,
.ma-podmenu:focus-within .podmenu { opacity: 1; visibility: visible; transform: none; }

/* ⚠️ Mostek nad listą. Bez niego kursor idący od pozycji w dół mija szczelinę,
   hover gaśnie i lista znika w pół drogi. Wysokość musi pokryć odstęp z app.css. */
.podmenu::before { content: ''; position: absolute; left: 0; right: 0; top: -10px; height: 10px; }

/* strzałka obraca się, gdy lista jest otwarta */
.strzalka { flex: none; transition: transform .18s ease; }
.ma-podmenu:hover > a .strzalka,
.ma-podmenu:focus-within > a .strzalka { transform: rotate(180deg); }

/* Podkreślenie wyjeżdżające od lewej. Dotyczy KAŻDEJ pozycji menu, nie tylko
   aktywnej - sama zmiana koloru tekstu jest za słabym sygnałem, żeby zauważyć
   ją w locie. Kolor i grubość nadpisuje app.css. */
.nawigacja a:not(.btn) { position: relative; }
.nawigacja a:not(.btn)::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform .18s ease;
}
.nawigacja a:not(.btn):hover::after,
.nawigacja a:not(.btn):focus-visible::after,
.nawigacja a:not(.btn)[aria-current="page"]::after { transform: scaleX(1); }
.ma-podmenu:hover > a:not(.btn)::after,
.ma-podmenu:focus-within > a:not(.btn)::after { transform: scaleX(1); }
/* w rozwiniętej liście podkreślenie przy każdej pozycji byłoby szumem */
.podmenu a::after { display: none; }

/* ── DRUK ────────────────────────────────────────────────────────────────────
   Klienci drukują ofertę i kontakt. Bez tego wychodzą puste sekcje i menu. */
@media print{
  .top,.burger,.lb,.skip,[data-po-kliknieciu]{display:none!important}
  .rv,.kaskada>*,.proces-line > li{opacity:1!important;transform:none!important;animation:none!important}
  body{opacity:1!important;background:#fff;color:#000}
  .postep{display:none!important}
}

/* ── PLAKIETKA OPINII GOOGLE ──────────────────────────────────────────────
   Wyjątek od zasady „tu nie ma wyglądu" i to świadomy: to nie jest wygląd
   NASZEJ strony, tylko cudzy znak firmowy (Google) plus dowód zaufania, który
   ma być rozpoznawalny wszędzie tak samo - jak logotyp, nie jak nasza typografia.
   Decyzja K. 13.08.2026: „jak dajemy gdzieś na hero info o opiniach z Google,
   róbmy to wszędzie w obu silnikach tak, jak zrobił to Marceli".
   Wygląd i tak zostaje w rękach strony: tło i obwódka liczą się z KOLORU TEKSTU
   (currentColor), a rozmiar, promień i krój dziedziczą się z otoczenia -
   zmienne poniżej można nadpisać w app.css.
   HTML (gwiazdki wypełnia się szerokością prostokąta w clipPath - patrz SKILL.md).
   ──────────────────────────────────────────────────────────────────────── */
:root{
  --gb-tlo:color-mix(in srgb,currentColor 8%,transparent);
  --gb-obwodka:color-mix(in srgb,currentColor 20%,transparent);
  --gb-gwiazdka:#FBBC04;              /* kolor gwiazdek z systemu Google */
  --gb-promien:999px;
}
.g-badge{
  display:inline-flex;align-items:center;gap:.62em;
  padding:.52em 1em;border-radius:var(--gb-promien);
  background:var(--gb-tlo);border:1px solid var(--gb-obwodka);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  font-size:.98rem;line-height:1;font-weight:500;letter-spacing:.01em;
  white-space:nowrap;vertical-align:middle;max-width:100%}
.g-badge .gb-ico,.g-badge .gb-stars{flex:none}
.g-badge .gb-ocena{font-weight:700;font-size:1.08em}
.g-badge .gb-txt{opacity:.92}
.g-badge .gb-stars .gb-peln{fill:var(--gb-gwiazdka)}
.g-badge .gb-stars .gb-pusta{fill:currentColor;opacity:.26}
@media(max-width:560px){
  .g-badge{gap:.45em;padding:.45em .8em;font-size:.86rem}
  .g-badge .gb-stars{width:62px;height:12.4px}
  .g-badge .gb-ico{width:16px;height:16px}
}
