/*
  AUXERIA — style strony.
  Wszystkie kolory/fonty przez zmienne z tokens.css (patrz design-system/components.md).

  KOREKTA ZAKRESU (2026-09-20, patrz docs/decisions.md i komentarz w
  index.html): cała strona to wyłącznie interfejs czatowy — usunięte
  martwe reguły po starym navie i sekcjach (Problem/Approach/Services/
  Process/Who it's for/About/FAQ/Contact/stopka). Poprzednia,
  wieloszekcyjna wersja stylów zarchiwizowana w
  design-system/concepts/site-full-page-backup-2026-09-20/styles.css.
*/

* { box-sizing: border-box; }

/* [hidden] musi wygrywać nad display:flex zadeklarowanym na
   .chat-empty/.chat-active/.chat-suggestions (te same klasy niosą zarówno
   layout jak i widoczność) — bez tego przeglądarka pokazuje oba stany
   naraz, bo reguła klasy ma tę samą swoistość co [hidden] i jest
   zadeklarowana później. */
[hidden] { display: none !important; }

/* Maciek + niezależnie jego chrześniak, na Chrome-iOS: cała strona dała
   się przewijać (pionowo I poziomo), mimo że to ma być zablokowany,
   jednoekranowy interfejs — dowód (dotknięcie+przeciągnięcie w górę
   pokazywało z powrotem pasek narzędzi przeglądarki) że to BODY strony
   się scrollowało, nie tylko wewnętrzny .chat-transcript. Przyczyna:
   html/body nie miały żadnego ograniczenia wysokości ani overflow —
   .hero-chat samo w sobie jest 100dvh, ale nic nie stało na przeszkodzie,
   żeby strona urosła i stała się przewijalna, jeśli COKOLWIEK w środku
   (fixed input przy klawiaturze, dropdown sugestii) na moment
   wystawało poza widoczny obszar choć o piksel. overflow:hidden na
   html/body ucina taki nadmiar zamiast pozwalać całej stronie się
   przewijać — jedyne scrollowalne obszary to celowe wewnętrzne
   kontenery (.chat-transcript, dropdowny sugestii), każdy ze swoim
   własnym overflow-y:auto. overscroll-behavior:none jako dodatkowe
   zabezpieczenie przed "gumowym" efektem odbicia na iOS. */
html, body {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

/* Strefa pod przypiętym nagłówkiem, gdzie przewijana treść znika
   (Runda 23, 2026-09-29) — JEDNO źródło dla .chat-transcript (homepage)
   i .service-content-scroll (strona usługi), plus anchorToTop() w
   homepage-chat.js czyta padding-top zamiast trzymać własną liczbę.
   --scroll-clip: twarde obcięcie (clip-path) — nic nie renderuje się
     wyżej, łącznie z cieniem kart (powód clipa z Rundy 10).
   --scroll-fade: miękkie wygaszanie tuż pod clipem (gradient ::after).
   --scroll-safe-top: padding-top kontenerów — pierwsza treść w spoczynku
     startuje PONIŻEJ końca fade'a (clip+fade=10 < 12), z 10px zapasu nad
     clipem. Wcześniej (Rundy 16/22) dokładaliśmy padding pod 28px clipem,
     co tylko powiększało "za wysoki nagłówek" i dalej ucinało zaokrągloną
     górę czarnego dymka (8px), bo liczyliśmy od tekstu, nie od krawędzi
     pigułki. Mniejsza strefa rozwiązuje oba problemy naraz. */
:root {
  --scroll-clip: 2px;
  --scroll-fade: 8px;
  --scroll-safe-top: 12px;
  /* Wysokość .chat-topbar ustalona jawnie (2026-09-29), nie wynikająca z
     metryk czcionki — bottom sheet na stronie usługi zaczyna się
     dokładnie na tej linii (service-page.css), więc obie strony muszą
     czytać tę samą liczbę. 18 (padding-top) + 36 (Menu/telefon) + 12
     (padding-bottom); na mobile 4 zamiast 12, patrz @media niżej. */
  --topbar-h: calc(66px + env(safe-area-inset-top));
}

/* Pływające kółko Cookiebota ukryte na wszystkich stronach (decyzja
   Maćka, 2026-09-29) — zajmowało miejsce i nachodziło na treść. Baner
   zgody przy pierwszym wejściu (#CybotCookiebotDialog, inny id) zostaje
   nietknięty. Zmiana zgody dalej jest równie łatwa: Menu → Cookies
   wywołuje Cookiebot.renew() (homepage-chat.js). !important, bo widget
   wstrzykuje własne style inline. */
#CookiebotWidget { display: none !important; }

body {
  margin: 0;
  background: var(--color-paper-secondary);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-weight: var(--weight-body-regular);
  font-size: 16px;
  line-height: 1.5;
}

h1 {
  font-family: var(--font-heading);
  color: var(--color-ink);
  margin: 0;
}

a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-ink); }

/* Buttons */

.btn-primary {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: var(--weight-body-medium);
  font-size: 15px;
  color: var(--color-paper);
  background: var(--color-accent);
  border: none;
  /* Pełna pigułka wszędzie (2026-09-28, Runda 7 — Maciek: niespójne
     kształty między "Book a call" w czacie (już pigułka, patrz
     .hero-chat .btn-primary niżej) i na stronie usługi (był
     prostokąt z border-radius:6px, z poprzedniego, usuniętego
     wielosekcyjnego designu)). */
  border-radius: 999px;
  padding: 14px 26px;
  cursor: pointer;
  transition: opacity .15s ease;
}

.btn-primary:hover {
  opacity: .88;
  color: var(--color-paper);
}

/* Hero-chat — jedyna treść strony (port z Claude Design, patrz
   komentarz w index.html i site/js/homepage-chat.js).
   --shadow-ink/--shadow-accent: rgb-tripletowe zmienne do użycia w
   rgba() cieni w dwóch odcieniach (ink, accent). */

.hero-chat {
  --shadow-ink: 16, 11, 0;
  --shadow-accent: 0, 111, 112;
  display: flex;
  flex-direction: column;
  /* 100vh na iOS Safari = LARGE viewport height (chrome w pełni
     zwinięte) — przy świeżo załadowanej stronie, zanim ktokolwiek
     scrollnął (pasek adresu + toolbar w pełni rozwinięte), realnie
     widoczne okno jest NIŻSZE niż 100vh. .chat-empty centruje treść w
     tym za wysokim boksie, więc widoczny jest tylko górny fragment —
     treść wygląda na "zepchniętą w dół" (mniej miejsca pod nią niż nad
     nią), dokładnie zrzut od Maćka. 100dvh śledzi REALNIE widoczną
     wysokość na bieżąco (kurczy/rośnie z pokazywaniem/chowaniem paska
     Safari), więc przy starcie strony pokrywa się z tym, co faktycznie
     widać. Zostawione 100vh jako fallback dla przeglądarek bez dvh —
     nieznana jednostka jest po prostu ignorowana, poprzednia deklaracja
     w mocy. */
  height: 100vh;
  height: 100dvh;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
  position: relative;
}

/* Topbar: logo (= start over) + Menu (About/Contact/email) — jedyny
   header na stronie, patrz komentarz w index.html. */

.chat-topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 0 12px;
  /* Bufor pod notch/wysepkę/pasek Safari (2026-09-28, Runda 16 — Maciek
     na prawdziwym iPhone: logo+Menu wyglądają na ucięte w połowie
     wysokości, na mobile. Nie mogliśmy tego potwierdzić przez DOM
     inspection (geometria w naszym browser tool wygląda poprawnie) —
     może to być natywne UI Safari nakładające się wizualnie, czego nie
     widać przez inspekcję DOM na desktopie/emulacji. env() zwraca 0 na
     urządzeniach bez notcha/wysepki (zero zmiany tam), a na urządzeniach
     z nią dodaje realny, potrzebny odstęp — bezpieczne, defensywne
     dodanie niezależnie od tego, czy to faktyczna przyczyna zgłoszonego
     problemu. Wymaga retestu na prawdziwym telefonie, nie mogliśmy tego
     zweryfikować sami. */
  padding-top: calc(18px + env(safe-area-inset-top));
  height: var(--topbar-h);
  flex: 0 0 auto;
  position: relative;
  /* z-index: żeby ::after (gradient) faktycznie leżał NAD transkryptem —
     .chat-topbar jest PIERWSZYM dzieckiem .hero-chat, więc bez tego
     .chat-active (dalej w DOM-ie) malowałby się nad nim, chowając
     gradient pod przewijaną treścią zamiast nad nią. */
  z-index: 2;
}

/* Miękkie zniknięcie treści transkryptu pod topbarem podczas scrolla
   (2026-09-28 — Maciek: "czat główny to ma", odwrócone lustro
   .chat-bottom::before poniżej, które robi to samo na dole paska
   input/pigułek). Bez tego treść ucinała się na twardo pod topbarem. */
.chat-topbar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  /* Runda 23 (2026-09-29): mała strefa zamiast 28px clip + 64px fade.
     Gradient zaczyna się na dolnej krawędzi topbara, jest pełny do
     --scroll-clip (tam i tak nic nie ma — clip-path na .chat-transcript),
     potem wygasza przez --scroll-fade. Wartości na :root, wspólne ze
     stroną usługi (.service-sticky-header::after). */
  top: 100%;
  height: calc(var(--scroll-clip) + var(--scroll-fade));
  background: linear-gradient(to bottom, var(--color-paper-secondary) 0, var(--color-paper-secondary) var(--scroll-clip), transparent calc(var(--scroll-clip) + var(--scroll-fade)));
  pointer-events: none;
  /* Dodatkowe zabezpieczenie NA WSZELKI WYPADEK (Runda 20) — logo/Menu
     mają już własny z-index:1, co samo w sobie wystarcza (spec: dziecko
     z z-index:1 zawsze maluje się nad rodzeństwem z z-index:auto,
     niezależnie od silnika), ale to POD SPÓD zamiast tylko NAD jest
     tańsze koncepcyjnie do zweryfikowania na oko przy przyszłych zmianach. */
  z-index: -1;
}

.chat-topbar-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--color-ink);
  font: inherit;
  /* Własny stacking context NAD .chat-topbar::after (2026-09-28, Runda 20
     — PRAWDZIWA przyczyna, znaleziona przez CC-Design i udowodniona
     eksperymentem: gradient ::after, jako generowana treść, maluje się PO
     (czyli NAD) rzeczywistymi dziećmi .chat-topbar w normalnym porządku,
     bo idzie jako "ostatnie dziecko" w kolejności dokumentu — logo/Menu
     nie miały własnego z-indexu, więc nic ich nie chroniło. Pierwsze 28px
     gradientu to pełna nieprzezroczystość w kolorze tła strony
     (--color-paper-secondary) — DOKŁADNIE tym samym co tło pod logo —
     więc zasłonięcie kamuflowało się jako "logo ucięte", nie jako
     oczywisty prostokąt na wierzchu. Trzy poprzednie rundy (safe-area,
     SVG height, scrollTo) celowały w złą warstwę problemu. */
  position: relative;
  z-index: 1;
}

/* display:block + height jawny w markupie (2026-09-28, Runda 18 — Maciek
   na prawdziwym iPhone: logo+Menu wyglądają na ucięte, stabilnie, od
   pierwszego malowania, nie znika po scrollu/odświeżeniu — wyklucza
   teorię paska Safari z Rundy 16, wskazuje na realną niespójność
   cross-engine w liczeniu wysokości. SVG bez display:block jest
   traktowane jako inline-level (mimo blockifikacji jako flex-item, WebKit
   potrafi zostawić rezerwę na "descender" typową dla inline-replaced
   elementów), a bez jawnego height auto-wysokość z proporcji (width:34 /
   viewBox 1320:800 = 20.6px) może być liczona nieidentycznie między
   silnikami w kontekście konkretnego flex-rzędu). Obie własności usuwają
   zależność od auto-obliczeń, niezależnie od silnika. */
.chat-topbar-mark { flex: 0 0 auto; display: block; }

.chat-topbar-word {
  font-family: var(--font-heading);
  font-weight: var(--weight-heading-bold);
  font-size: 15px;
  letter-spacing: 0.2em;
  /* line-height:1, nie "normal" (Runda 18) — "normal" liczy się z
     wewnętrznych metryk fontu (ascent/descent/line-gap w tabeli fontu),
     które Chrome i WebKit potrafią interpretować różnie dla tego samego
     pliku fontu (Plus Jakarta Sans), dając różną wysokość linii tekstu
     mimo identycznego font-size. line-height:1 = dokładnie font-size,
     bez zależności od tabeli metryk. */
  line-height: 1;
}

/* Wrapper na ikonkę telefonu (mobile-only) + Menu, przesuwa OBIE do
   prawej krawędzi topbara (2026-09-29 — margin-left:auto przeniesiony
   tu z .chat-menu, żeby dało się wstawić .chat-topbar-call PRZED Menu z
   małym gap zamiast maksymalnego rozepchnięcia). */
.chat-topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Ikonka telefonu w topbarze — WYŁĄCZNIE mobile (2026-09-29 — Maciek:
   pływający pasek "Book a call" u dołu strony głównej zajmował za dużo
   miejsca na mobile; zastąpiony małą, zawsze widoczną ikonką obok Menu.
   Na desktopie .chat-float-cta zostaje bez zmian, ta ikonka ukryta. */
.chat-topbar-call { display: none; }

.chat-menu {
  position: relative;
  /* z-index nad .chat-topbar::after (Runda 20) — patrz komentarz przy
     .chat-topbar-logo, ten sam powód. */
  z-index: 1;
}

.chat-menu-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: var(--weight-body-medium);
  color: var(--color-ink);
  background: var(--color-paper);
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  /* Jawne 16px zamiast "normal" (metryka czcionki, inna w WebKit) —
     przycisk ma równe 36px, tyle co ikonka telefonu obok i tyle, ile
     zakłada --topbar-h. */
  line-height: 16px;
  cursor: pointer;
  box-shadow: 0 6px 16px -10px rgba(var(--shadow-ink), 0.5);
  transition: background-color .15s ease, color .15s ease;
}

.chat-menu-btn:hover { background: var(--color-ink); color: var(--color-paper); }

.chat-menu-panel {
  position: absolute;
  top: 48px;
  right: 0;
  z-index: 30;
  background: var(--color-paper);
  border-radius: 16px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  /* 240px, nie 190px (2026-09-28, Runda 16 — redesign z podtytułami pod
     Services potrzebuje więcej szerokości niż płaska lista tekstowa). */
  min-width: 240px;
  box-shadow: 0 24px 48px -24px rgba(var(--shadow-ink), 0.5);
  animation: ax-rise .18s ease both;
}

/* Runda 16 — przebudowa panelu Menu wg zatwierdzonego redline:
   design-system/concepts/menu-redesign/index.html. Zastępuje płaską
   listę .chat-menu-item (usunięte, nieużywane od tej rundy) sekcjami z
   ikonkami w stylu .msg-item-icon (szary kwadrat z zaokrągleniem). */
.menu-v2-section + .menu-v2-section {
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px solid rgba(var(--shadow-ink), 0.14);
}
.menu-v2-label {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: var(--weight-body-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
  padding: 6px 14px 4px;
}
.menu-v2-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-ink);
  background: transparent;
  border: none;
  text-decoration: none;
  padding: 8px 10px;
  border-radius: 10px;
  cursor: pointer;
}
.menu-v2-item:hover { background: var(--color-paper-secondary); }
.menu-v2-item:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.menu-v2-icon {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--color-paper-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-ink);
}
.menu-v2-icon svg { width: 16px; height: 16px; }
.menu-v2-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.menu-v2-title { font-weight: var(--weight-body-medium); line-height: 1.3; }
.menu-v2-sub { font-size: 11.5px; color: var(--color-ink-muted); line-height: 1.3; }
/* "Cookies" — jedyny item z tym wariantem: ikonka bez tła kwadratu (sam
   glif), całość na opacity:0.62 inline w markupie — celowo przyciszone,
   ma być obecne, nie rzucać się w oczy (redline + Maciek). */
.menu-v2-item--plain .menu-v2-icon { background: transparent; color: var(--color-ink-muted); }

/* Stan pusty */

.chat-empty {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 34px;
  padding: 24px 0 48px;
  overflow: hidden;
}

.chat-dots-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.chat-empty-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 34px;
  width: 100%;
}

.chat-empty h1 {
  font-size: clamp(30px, 4.4vw, 46px);
  line-height: 1.08;
  letter-spacing: -0.03em;
  max-width: 24ch;
  text-align: center;
  text-wrap: balance;
}

/* "Product"/"Design" — słowa kluczowe do szybkiego skanowania, ten sam
   accent co "CORE SERVICES" nad pigułkami (spójność, nie nowy kolor). */
.hl-word { color: var(--color-accent); }

.chat-inputzone {
  width: 100%;
  max-width: 660px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative;
}

.chat-pills-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.chat-pills-label {
  font-size: 11.5px;
  font-weight: var(--weight-body-medium);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.chat-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}

.pill {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: var(--weight-body-medium);
  color: var(--color-ink);
  border: 1px solid rgba(var(--shadow-ink), 0.18);
  border-radius: 999px;
  padding: 13px 24px;
  cursor: pointer;
  background: var(--color-paper-secondary);
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.pill:hover {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-paper);
}

/* Kontekstowe sugestie pod najnowszą kartą odpowiedzi (2026-09-29,
   redline design-system/concepts/contextual-suggestions/) — zastępują
   globalny pasek pigułek w .chat-bottom. Budowane w homepage-chat.js
   (appendSuggestionsEl), zawsze tylko jeden rządek: pod aktualnym
   tematem. Zawija się do kolejnych linii, bez przewijania w bok. */
.msg-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  /* 2px + gap:22px z .chat-transcript-inner = 24px od karty (Maciek:
     "nie za daleko, nie za blisko"). */
  margin-top: 2px;
  animation: ax-rise .3s ease both;
}
.msg-suggestion-pill {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: var(--weight-body-medium);
  color: var(--color-ink);
  border: 1px solid rgba(var(--shadow-ink), 0.18);
  border-radius: 999px;
  padding: 10px 18px;
  cursor: pointer;
  /* Tło jak .pill w hero (Maciek po teście na telefonie, 2026-09-29) —
     rozmiar zostaje mniejszy. */
  background: var(--color-paper-secondary);
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.msg-suggestion-pill:hover {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-paper);
}
.msg-suggestion-pill:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.chat-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--color-paper);
  border-radius: 999px;
}

/* Widoczny fokus (2026-09-28, Runda 16 — CC-Design: .chat-input ma
   outline:none i ZERO zamiennika, całkowity brak wskaźnika fokusu dla
   klawiatury). Ring na .chat-bar (rodzicu), nie na .chat-input samym w
   sobie — input nie ma własnego tła/obrysu (jest częścią pigułki), więc
   outline wprost na nim wyglądałby jak prostokąt wewnątrz zaokrąglonej
   pigułki. :focus-within przenosi widoczność na całą pigułkę, śledzi
   border-radius:999px (nowoczesne przeglądarki respektują radius dla
   outline). */
.chat-bar:focus-within {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.chat-bar-lg {
  padding: 10px 10px 10px 26px;
  box-shadow: 0 22px 44px -26px rgba(var(--shadow-ink), 0.55), 0 2px 6px -3px rgba(var(--shadow-ink), 0.16);
}

.chat-bar-sm {
  padding: 6px 6px 6px 22px;
  box-shadow: 0 16px 34px -24px rgba(var(--shadow-ink), 0.55), 0 2px 5px -3px rgba(var(--shadow-ink), 0.14);
}

.chat-input {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--font-body);
  color: var(--color-ink);
}

.chat-bar-lg .chat-input { font-size: 17px; padding: 13px 0; }
/* 16px, nie 15px (Runda 23): iOS WebKit (Safari i Chrome iOS) przybliża
   całą stronę przy focusie inputu z font-size < 16px — Menu/wyślij
   uciekały za prawą krawędź, sugestie poza ekran. Globalnie, nie tylko
   ≤720px, bo iPad też to robi. NIE przez maximum-scale/user-scalable=no
   (blokuje pinch-zoom — dostępność). */
.chat-bar-sm .chat-input { font-size: 16px; padding: 10px 0; }

.chat-send {
  flex: 0 0 auto;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: none;
  background: var(--color-ink);
  color: var(--color-paper);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color .15s ease;
}

.chat-send:hover { background: var(--color-accent); }
.chat-send-sm { width: 38px; height: 38px; }

.chat-suggestions {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 10px);
  z-index: 28;
  background: var(--color-paper);
  border: 1px solid rgba(var(--shadow-ink), 0.14);
  border-radius: 20px;
  padding: 8px;
  max-height: 32vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  box-shadow: 0 28px 56px -28px rgba(var(--shadow-ink), 0.5), 0 2px 6px -4px rgba(var(--shadow-ink), 0.14);
  animation: ax-open .2s ease both;
}

.chat-suggestions-up {
  top: auto;
  bottom: calc(100% + 10px);
  max-height: 42vh;
}

.chat-suggestion {
  text-align: left;
  font-family: var(--font-body);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 11px 14px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--color-ink);
  width: 100%;
}

.chat-suggestion:hover { background: var(--color-paper-secondary); }
.chat-suggestion-text { flex: 1 1 auto; min-width: 0; font-size: 14.5px; line-height: 1.4; }
.chat-suggestion-label { flex: 0 0 auto; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-accent); }

/* 2026-09-22: było position:absolute — zakotwiczone do najbliższego
   pozycjonowanego przodka (rośnie/przewija się z KONTENEREM), nie do
   widocznego okna. Na telefonie, gdzie dynamiczne paski Safari zmieniają
   dostępną wysokość, "26px od dołu kontenera" mogło wylądować POD tym,
   co faktycznie widać na starcie — Maciek: przycisk "daleko na dole,
   trzeba przewijać". fixed pozycjonuje względem widocznego viewportu,
   niezależnie od wysokości treści czy scrolla. */
.chat-float-cta {
  position: fixed;
  right: 24px;
  bottom: 26px;
  z-index: 25;
  box-shadow: 0 16px 34px -16px rgba(var(--shadow-accent), 0.75);
  transition: opacity .15s ease;
}

/* .hero-chat .btn-primary: nadpisanie na ink/paper (nie accent/paper jak
   domyślnie) — dotyczy pływającego CTA w stanie pustym i CTA w kartach
   odpowiedzi (sekcja Contact), zgodnie z referencją Claude Design.
   border-radius: 999px teraz już w bazowym .btn-primary (Runda 7) —
   nic tu do nadpisania, zostaje tylko kolor. */
.hero-chat .btn-primary {
  background: var(--color-ink);
  color: var(--color-paper);
}

.hero-chat .btn-primary:hover { background: var(--color-accent); }

/* Tryb czatu */

.chat-active {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.chat-transcript {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Strefa clip/fade i padding-top ze wspólnych zmiennych na :root
     (Runda 23) — patrz komentarz tam. Pierwszy dymek w spoczynku
     startuje na --scroll-safe-top, czyli poniżej końca fade'a. */
  padding: var(--scroll-safe-top) 2px 16px;
  /* anchorToTop() w homepage-chat.js robi scrollIntoView na nowej
     wiadomości usera (kotwica do góry nowej tury, nie do dołu
     transkryptu) — scroll-behavior:smooth daje temu płynną animację. */
  scroll-behavior: smooth;
  /* Twarde obcięcie (Runda 10): usuwa treść RAZEM z cieniem kart —
     sam gradient nie maskował równo cienia zaokrąglonych rogów .msg-agent
     ("półksiężyce"). */
  clip-path: inset(var(--scroll-clip) 0 0 0);
}

.chat-transcript-inner {
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

/* Bez tego bufora, gdy nowa wiadomość usera jest ostatnim elementem,
   scrollTop potrzebny żeby podbić ją pod górę viewportu przekracza
   maksymalny scrollHeight - clientHeight w danym momencie (odpowiedź
   agenta jeszcze nie doszła) i przeglądarka po prostu ucina scroll —
   stąd wcześniejsze "skakanie" w losowe miejsce zamiast pod górę.
   Wysokość ustawiana z JS na clientHeight #chatTranscript (patrz
   syncSpacerHeight w homepage-chat.js), żeby każda wiadomość, nawet
   ta ostatnia, miała fizyczny zapas do przescrollowania pod górę. */
.chat-transcript-spacer {
  flex: none;
}

/* Odstęp od góry przy scrollIntoView({block:'start'}), żeby nowa
   wiadomość nie lądowała dosłownie na krawędzi kontenera. */
.msg-user, .msg-agent { scroll-margin-top: 8px; }

.msg-user { display: flex; justify-content: flex-end; }

.msg-user-bubble {
  background: var(--color-ink);
  color: var(--color-paper);
  font-size: 15.5px;
  line-height: 1.5;
  padding: 13px 20px;
  border-radius: 20px 20px 6px 20px;
  max-width: 78%;
  animation: ax-rise .3s ease both;
}

.msg-agent {
  background: var(--color-paper);
  border-radius: 22px 22px 22px 6px;
  padding: 28px 30px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  box-shadow: 0 26px 54px -32px rgba(var(--shadow-ink), 0.55), 0 2px 6px -4px rgba(var(--shadow-ink), 0.14);
  animation: ax-rise .3s ease both;
  /* Ring "to tutaj" przy powrocie do już pokazanego tematu — używany tylko
     w wariancie REVISIT_MODE='scroll' (homepage-chat.js; domyślny 'move'
     go nie potrzebuje, zostaje dla jednokrokowego cofnięcia):.is-revisit zapala go bez przejścia, zdjęcie
     klasy wygasza go przez transition. Outline zamiast animation —
     podmiana `animation` zrestartowałaby ax-rise całej karty. */
  outline: 2px solid transparent;
  outline-offset: 4px;
  transition: outline-color .55s ease-out;
}
.msg-agent.is-revisit { outline-color: var(--color-accent); transition: none; }
@media (prefers-reduced-motion: reduce) {
  .msg-agent { transition: none; }
}

.msg-agent-head { display: flex; flex-direction: column; gap: 9px; }
.msg-agent-title { font-family: var(--font-heading); font-weight: var(--weight-heading-bold); font-size: 21px; letter-spacing: -0.015em; }
.msg-agent-intro { font-size: 15.5px; line-height: 1.6; opacity: 0.78; }

.msg-items { display: flex; flex-direction: column; }
.msg-item { border-top: 1px solid rgba(var(--shadow-ink), 0.1); transition: border-top-color .15s ease; animation: ax-rise .32s ease both; }

.msg-item-row {
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 15px 12px 15px 8px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  gap: 16px;
  color: var(--color-ink);
}

/* Podświetlenie wiersza (2026-09-29, Maciek po teście na telefonie):
   trzymane przez stan rozwinięcia (aria-expanded, ustawiane w
   homepage-chat.js), a :hover tylko na urządzeniach z prawdziwym
   kursorem — na iOS hover "przykleja się" po tapnięciu i zostawał
   nawet po zwinięciu wiersza. */
.msg-item-row[aria-expanded="true"] { background: rgba(var(--shadow-ink), 0.035); }

/* Separatory przylegające do podświetlonego bloku znikają (linia
   dotykająca zaokrąglonego tła wyglądała nieestetycznie): ten nad
   wierszem zawsze, ten pod nim tylko gdy wiersz nie jest rozwinięty
   (rozwinięty ma pod sobą szczegóły, więc linia go nie dotyka).
   :has — Safari 15.4+. */
.msg-item:has(> .msg-item-row[aria-expanded="true"]) { border-top-color: transparent; }

@media (hover: hover) {
  .msg-item-row:hover { background: rgba(var(--shadow-ink), 0.035); }
  .msg-item:has(> .msg-item-row:hover) { border-top-color: transparent; }
  .msg-item:has(> .msg-item-row:hover[aria-expanded="false"]) + .msg-item { border-top-color: transparent; }
}

.msg-item-icon {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background: var(--color-paper-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
}

.msg-item-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.msg-item-title { font-family: var(--font-heading); font-weight: var(--weight-heading-bold); font-size: 15.5px; }
.msg-item-desc { font-size: 13.5px; line-height: 1.5; opacity: 0.68; }

.msg-item-sign {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-paper-secondary);
  color: var(--color-accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.msg-item-detail {
  padding: 2px 12px 20px 56px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  animation: ax-open .26s ease both;
}

.msg-item-loading { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--color-accent); }
.msg-item-loading-dots { display: flex; gap: 5px; }
.msg-item-loading-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-accent); animation: ax-dot 1.1s infinite; }
.msg-item-loading-dot:nth-child(2) { animation-delay: .18s; }
.msg-item-loading-dot:nth-child(3) { animation-delay: .36s; }

.msg-item-text-detail { font-size: 14.5px; line-height: 1.65; opacity: 0.84; max-width: 62ch; animation: ax-open .3s ease both; }

/* "Read full details" — patrz design-system/concepts/service-page-redline/
   transition-prototype.html. Prawdziwy <a>, nie przycisk JS — tylko dla
   pozycji z dedykowaną stroną usługi (it.servicePage w TOPICS). Wariant
   outline .btn-primary: te same proporcje, obrys zamiast wypełnienia.
   align-self:flex-start — .msg-item-detail to flex column BEZ własnego
   align-items (czyli domyślne stretch), więc bez tego przycisk
   rozciągał się na pełną szerokość rodzica zamiast trzymać naturalną,
   kompaktową szerokość swojej treści (2026-09-28, zgłoszone po żywym
   teście jako "pełna szerokość i kwadratowy"). */
.btn-outline {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-weight: var(--weight-body-medium);
  font-size: 14px;
  color: var(--color-ink);
  background: transparent;
  border: 1.5px solid rgba(var(--shadow-ink), 0.3);
  /* Pełna pigułka, spójnie z .btn-primary (Runda 7). */
  border-radius: 999px;
  padding: 9px 16px;
  cursor: pointer;
  text-decoration: none;
  animation: ax-open .3s ease both;
  transition: border-color .15s ease;
}
.btn-outline:hover { border-color: var(--color-ink); }

.msg-item-media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
  border: 1px dashed rgba(var(--shadow-ink), 0.22);
  border-radius: 14px;
  font-size: 12.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  animation: ax-open .3s ease both;
}

.msg-proof {
  border-top: 1px solid rgba(var(--shadow-ink), 0.1);
  padding-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  animation: ax-rise .32s ease both;
}

.msg-proof-figure { font-family: var(--font-heading); font-weight: var(--weight-heading-black); font-size: 30px; line-height: 1; color: var(--color-accent); white-space: nowrap; }
.msg-proof-text { font-size: 13.5px; line-height: 1.55; opacity: 0.76; max-width: 52ch; }

.msg-cta {
  border-top: 1px solid rgba(var(--shadow-ink), 0.1);
  padding-top: 20px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Wyśrodkowane jak blok .msg-proof ("30 min") nad nim. */
  justify-content: center;
  gap: 18px;
  animation: ax-rise .32s ease both;
}

.msg-cta-email { font-family: var(--font-heading); font-weight: var(--weight-heading-bold); font-size: 17px; color: var(--color-accent); text-decoration: none; }
/* accent (nie accent-light) — accent-light jako kolor tekstu na jasnym
   tle ma tylko 2.57:1 kontrastu, poniżej progu WCAG AA nawet dla dużego
   tekstu (3:1). accent już przechodzi 5.76:1 (2026-09-28, Runda 17 —
   CC-Design, audyt kontrastu). */
.msg-cta-email:hover { color: var(--color-accent); }

.msg-thinking { display: flex; gap: 6px; padding: 4px; }
.msg-thinking-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--color-ink); animation: ax-dot 1.1s infinite; }
.msg-thinking-dot:nth-child(2) { animation-delay: .18s; }
.msg-thinking-dot:nth-child(3) { animation-delay: .36s; }

.chat-bottom {
  flex: 0 0 auto;
  position: relative;
  padding: 18px 0;
  background: var(--color-paper-secondary);
}

.chat-bottom::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  /* Przesunięte W DÓŁ o połowę wysokości, top:-14px zamiast -28px
     (2026-09-28, Runda 15 — lustro .chat-topbar::after powyżej, ten sam
     powód: połowa gradientu NAKŁADA SIĘ na .chat-bottom samo w sobie
     (tam tło już jest nieprzezroczyste, zero różnicy wizualnej), tylko
     druga połowa faktycznie wystaje NAD .chat-bottom do treści —
     mniejszy łączny footprint bar+fade przy tej samej miękkości). */
  top: -14px;
  height: 28px;
  background: linear-gradient(to bottom, transparent, var(--color-paper-secondary));
  pointer-events: none;
}

.chat-bottom-inner {
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative;
}

/* Kontener tylko dla paska inputu (bez pigułek nad nim), żeby dropdown
   sugestii (.chat-suggestions-up, bottom:100%+10px) kotwiczył się do
   WYSOKOŚCI SAMEGO INPUTU, nie całego .chat-bottom-inner (pigułki +
   input). Wcześniej lądował w pustej przestrzeni NAD pigułkami — Maciek:
   pigułki i tak nie są wtedy istotne, dropdown może je swobodnie
   przykryć. */
.chat-input-wrap { position: relative; }

@keyframes ax-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes ax-open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@keyframes ax-dot { 0%, 60%, 100% { opacity: 0.22; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* Responsive */

@media (max-width: 720px) {
  /* 16px→20px (2026-09-28, Runda 12 — Maciek: porównując homepage z
     bottom sheetem na stronie usługi (tam .service-content ma
     padding:0 20px 40px), margines krawędź-ekranu→krawędź-karty
     wychodził inny (16px vs 20px) mimo że .msg-agent nie ma własnego
     marginesu poziomego. Ujednolicone do 20px jako wartości "prawidłowej"
     wg Maćka. */
  .hero-chat { padding: 0 20px; }
  /* Mniejszy dolny odstęp topbara (Runda 23 — Maciek: przypięty nagłówek
     zjadał za dużo ekranu). Razem z --scroll-safe-top daje ~16px od dołu
     Menu do pierwszego dymka zamiast 32px. */
  .chat-topbar { padding-bottom: 4px; }
  :root { --topbar-h: calc(58px + env(safe-area-inset-top)); }
  .chat-empty { padding: 20px 0 32px; gap: 24px; }
  .chat-bar-lg { padding: 8px 8px 8px 20px; }
  /* 16px — próg auto-zoomu iOS, patrz .chat-bar-sm .chat-input. */
  .chat-bar-lg .chat-input { font-size: 16px; }
  /* Usunięty na mobile (2026-09-29 — Maciek: pływający pasek "Book a
     call" u dołu zajmował za dużo miejsca; zastąpiony małą ikonką
     telefonu obok Menu w topbarze, patrz .chat-topbar-call niżej).
     Zostaje bez zmian na desktopie. */
  .chat-float-cta { display: none; }
  /* Mała czarna okrągła ikonka ze słuchawką, ten sam rozmiar co
     .service-sheet-close (36px) dla spójności z resztą projektu. */
  .chat-topbar-call {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--color-ink);
    color: var(--color-paper);
  }
  /* Maciek (doprecyzowanie, mocniejsza wersja): przy otwartej klawiaturze
     w stanie pustym input jest najważniejszy — slogan i pigułki usług
     znikają, a input dostaje position:fixed przyklejony do góry viewportu.
     Zwykły reflow (flex-start zamiast center) NIE wystarczał — Maciek
     zgłosił, że różne rzeczy (pasek Cookiebota, autofill) dalej potrafiły
     go przesłonić. position:fixed + wysoki z-index to twarda gwarancja:
     input siedzi na wierzchu niezależnie od tego, co się dzieje wokół,
     zamiast polegać na kolejności w normalnym układzie. */
  .chat-empty.is-keyboard-open h1,
  .chat-empty.is-keyboard-open .chat-pills-wrap {
    display: none;
  }
  /* top: 12px zasłaniało logo/Menu w topbarze (Maciek: "muszę mieć
     widoczne logo, muszę mieć widoczne menu") — .chat-topbar ma ~66.5px
     wysokości (zmierzone), +12px odstępu. env(safe-area-inset-top) na
     wypadek notcha/wysepki (topbar sam go nie uwzględnia, więc licząc
     "pod topbarem" trzeba go doliczyć osobno). */
  .chat-empty.is-keyboard-open .chat-inputzone {
    position: fixed;
    top: calc(env(safe-area-inset-top) + 78px);
    left: 16px;
    right: 16px;
    width: auto;
    max-width: none;
    z-index: 60;
  }
  /* Maciek: dropdown sugestii, kiedy klawiatura aktywna, ma priorytet nad
     resztą — niech rośnie maksymalnie w dostępnej przestrzeni (do dołu
     widocznego obszaru), a nie sztywny max-height. --kb-input-bottom
     ustawiane z JS (updateKeyboardState) na realny dolny brzeg inputu w
     px względem viewportu, więc to działa niezależnie od wysokości
     topbaru/inputu. position:fixed (nie odziedziczone position:absolute)
     bo inaczej top/bottom liczyłyby się względem małego .chat-inputzone,
     nie względem całego viewportu. */
  .chat-empty.is-keyboard-open .chat-suggestions {
    position: fixed;
    top: calc(var(--kb-input-bottom, 100%) + 10px);
    bottom: 16px;
    left: 16px;
    right: 16px;
    max-height: none;
  }
  .msg-agent { padding: 20px 18px; }
  .msg-item-detail { padding: 2px 8px 18px 16px; }
  .msg-item-row { padding: 13px 6px; gap: 12px; }
  /* Było 64px — rezerwa pod pływający widget Cookiebota. Widget ukryty
     (#CookiebotWidget, patrz wyżej), więc zwykły odstęp + safe-area
     (pasek home na iPhonie). */
  .chat-bottom { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
}
