/* ==========================================================================
   Big Idea Studio — kierunek K5a.3
   Tokeny pochodzą z księgi znaku. Nie dopisujemy tu nowych kolorów marki.
   ========================================================================== */

:root{
  /* paleta z księgi */
  --bis-ink:       #0F1115;
  --bis-accent:    #2B3AFF;   /* Ultra — akcent na jasnym tle */
  --bis-accent-lt: #6E78FF;   /* Ultra Light — akcent na ciemnym tle */

  /* Jeden krój na całej stronie. Inter zszedł — Familjen niesie i nagłówki, i tekst ciągły. */
  --font:"Familjen Grotesk",system-ui,-apple-system,"Segoe UI",sans-serif;
  --bis-mist:      #E6E7EB;
  --bis-grey:      #6B6F76;
  --bis-paper:     #FFFFFF;

  /* Grey #6B6F76 daje na Mist tylko 4,0:1 — poniżej progu AA dla drobnego tekstu.
     Na polach Mist tekst drugorzędny jest przyciemniony do 5,6:1. */
  --bis-grey-mist: #575B62;

  /* moduł konstrukcyjny znaku: X = średnica kropki.
     Ten sam moduł niesie rytm strony, więc odstępy nie są przypadkowe. */
  --x: 9px;

  --gutter: clamp(20px, 5vw, 64px);
  --maxw: 1180px;

  /* skala typograficzna */
  --t-hero: clamp(2.1rem, 5.6vw, 3.75rem);   /* trzy linie hero w wysokości dawnych dwóch */
  --t-h2:   clamp(2.1rem, 5.4vw, 4.4rem);
  --t-lead: clamp(1.1rem, 1.9vw, 1.45rem);
  --t-item: clamp(1.15rem, 2vw, 1.5rem);
  --t-body: 1.0625rem;

  /* role kolorystyczne pola — nadpisywane przez klasy .band--* */
  --bg: var(--bis-paper);
  --fg: var(--bis-ink);
  --fg-2: var(--bis-grey);
  --accent: var(--bis-accent);
  --rule: rgba(15,17,21,.14);

  /* Tylko jasny zestaw — telefon w trybie ciemnym ma widzieć te same pola co desktop. */
  color-scheme: only light;
}

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

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

body{
  margin:0;
  background:var(--bis-paper);
  color:var(--bis-ink);
  font-family:var(--font);
  font-size:var(--t-body);
  line-height:1.55;          /* Familjen ma wyższe x-height niż Inter — 1,62 rozrzedzało akapity */
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

img{max-width:100%;height:auto;display:block}

a{color:inherit;text-underline-offset:.22em;text-decoration-thickness:1px}

:focus-visible{
  outline:2px solid currentColor;
  outline-offset:3px;
}

/* --------------------------------------------------------------------------
   Znak
   -------------------------------------------------------------------------- */

/* Litery biorą currentColor, akcent zmienną --bis-accent.
   Podpinamy ją pod akcent pola, więc jeden znak obsługuje wszystkie sześć tł. */
.bis-logo{display:inline-block;color:var(--fg);--bis-accent:var(--accent)}
.bis-logo svg{display:block;width:200px;height:auto}   /* nigdy poniżej 160 px */

@media (max-width:760px){
  .bis-logo svg{width:168px}
}

/* --------------------------------------------------------------------------
   Pola (bands) — sześć ekranów, sześć ról kolorystycznych
   -------------------------------------------------------------------------- */

.band{
  background:var(--bg);
  color:var(--fg);
  padding-block:calc(var(--x) * 11);
  scroll-margin-top:calc(var(--x) * 8);   /* wysokość paska przyklejonego + luz */
}

/* Telefon: 90 px zamiast 63 px — w tym odstępie treść zostaje w tyle przy głębi (app.js, 6a). */
@media (max-width:760px){
  .band{padding-block:calc(var(--x) * 10)}
}

/* Desktop: szerszy oddech między polami. Głębia (app.js, punkt 6a) przesuwa treść tylko w obrębie
   tego odstępu, więc większy odstęp = wyraźniejsza paralaksa bez zasłaniania tekstu. */
@media (min-width:1100px){
  .band{padding-block:calc(var(--x) * 16)}
}

.band--ultra{
  --bg:var(--bis-accent);
  --fg:#fff;
  --fg-2:rgba(255,255,255,.78);
  /* na polu akcentu akcent jest zrównany z resztą — różnicę niesie krój */
  --accent:#fff;
  --rule:rgba(255,255,255,.28);
}

/* Grafit z Ultra Light: 5,2:1 — przechodzi AA także dla drobnego tekstu.
   Czysta Ultra na grafit ma 2,8:1 i gaśnie, dlatego jej tu nie ma. */
.band--ink{
  --bg:var(--bis-ink);
  --fg:var(--bis-accent-lt);
  --fg-2:var(--bis-accent-lt);
  --accent:var(--bis-accent-lt);
  --rule:rgba(110,120,255,.28);
}

/* Scena: gdy skrypt działa, tło i kolory trzymają trzy ostatnie sekcje wspólnie.
   Wartości liczy app.js klatka po klatce z pozycji przewinięcia i wpisuje w zmienne sceny —
   kolor idzie za palcem, bez przejść czasowych. Sekcje oddają swoje zmienne rodzicowi przez inherit.
   Reguła z data-ton-now obsługuje tylko ograniczony ruch: tam ton przełącza się skokowo. */
.scena.is-live{
  --bg:var(--bis-accent);
  --fg:#fff;
  --fg-2:rgba(255,255,255,.78);
  --accent:#fff;
  --rule:rgba(255,255,255,.28);
  background:var(--bg);
}

.scena.is-live[data-ton-now="ink"]{
  --bg:var(--bis-ink);
  --fg:var(--bis-accent-lt);
  --fg-2:var(--bis-accent-lt);
  --accent:var(--bis-accent-lt);
  --rule:rgba(110,120,255,.28);
}

.scena.is-live > .band{
  --bg:inherit;
  --fg:inherit;
  --fg-2:inherit;
  --accent:inherit;
  --rule:inherit;
  background:transparent;
}

.band--mist{
  --bg:var(--bis-mist);
  --fg:var(--bis-ink);
  --fg-2:var(--bis-grey-mist);
  --accent:var(--bis-accent);
  --rule:rgba(15,17,21,.16);
}

.band--paper{
  --bg:var(--bis-paper);
  --fg:var(--bis-ink);
  --fg-2:var(--bis-grey);
  --accent:var(--bis-accent);
  --rule:rgba(15,17,21,.14);
}

.wrap{
  width:100%;
  max-width:var(--maxw);
  margin-inline:auto;
  padding-inline:var(--gutter);
}

/* --------------------------------------------------------------------------
   Typografia
   -------------------------------------------------------------------------- */

h1,h2,h3{
  font-weight:600;
  letter-spacing:-.015em;   /* było -.025: „wy”, „ko” stykały się przy 600 */
  line-height:1.02;
  margin:0;
  text-wrap:balance;
}

.h-hero{font-size:var(--t-hero)}
.h-sec{font-size:var(--t-h2);line-height:1.02}

/* Sekcje bez siatki redakcyjnej (koła, kontakt) — nagłówek bierze całą szerokość pola. */
.h-sec--wide{max-width:18ch}

/* Bez etykiet sekcji nagłówek stoi pierwszy w polu — odstęp pod nim niesie już treść. */
.h-sec + .prose{margin-top:calc(var(--x) * 5)}

/* Teza: jedno zdanie w skali planszy, krojem nagłówkowym.
   Waga 500, nie 600 — przy siedmiu linijkach display 600 robi się plamą.
   Miara 30 znaków: dłuższy wiersz przestaje się czytać jednym rzutem oka. */
.prose--stmt{
  margin-top:calc(var(--x) * 4);
  font-weight:500;
  font-size:clamp(1.75rem, 4.6vw, 3.75rem);
  line-height:1.14;
  letter-spacing:-.015em;   /* było -.03: „ty”, „wy” stykały się w zdaniach tezy */
  max-width:30ch;
  text-wrap:pretty;
}

/* Pusta kolumna po lewej — oś tekstu wchodzi w pole na wysokości jednej czwartej.
   Tylko na szerokich ekranach: niżej strona musi mieć jedną oś, nie dwie. */
@media (min-width:1100px){
  .prose--stmt{margin-left:24%}
}

.lead{
  font-size:var(--t-lead);
  line-height:1.42;
  max-width:34ch;
  margin:calc(var(--x) * 3) 0 0;
  text-wrap:pretty;
}

.prose{max-width:56ch}
.prose p{margin:0 0 1.15em}
.prose p:last-child{margin-bottom:0}

/* --------------------------------------------------------------------------
   Belka górna i pasek przyklejony
   -------------------------------------------------------------------------- */

.sticky{
  position:fixed;
  inset:0 0 auto 0;
  z-index:50;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--gutter);
  padding:calc(var(--x) * 1.4) var(--gutter);
  /* Ultra z bielą (6,7:1). Znak w całości biały: --accent też jest bielą, więc „idea” i kropka
     nie przechodzą w Ultra Light, która na Ultra traci kontrast.
     Linia pod paskiem oddziela go od pól Ultra, nad którymi przejeżdża. */
  background:var(--bis-accent);
  color:#fff;
  --fg:#fff;
  --accent:#fff;
  box-shadow:0 1px 0 rgba(255,255,255,.24);
  transform:translateY(-110%);   /* zapas na linię pod paskiem — przy -101% wystawała */
  transition:transform .35s ease;
}

.sticky.is-on{transform:translateY(0)}
.sticky .bis-logo svg{width:150px}   /* pasek jest wyjątkiem: sygnetu tu nie ma, skala techniczna */

/* Obrys w kształcie pigułki — ta sama kategoria co „Umówmy rozmowę”: koło to reguła dla akcji.
   Wersaliki robi CSS, w kodzie zostaje „Kontakt”, żeby czytnik ekranu nie literował słowa. */
.sticky-cta{
  display:inline-flex;
  align-items:center;
  padding:calc(var(--x) * .9) calc(var(--x) * 2.4);
  border:1.5px solid #fff;
  border-radius:999px;
  font-size:.8125rem;
  font-weight:600;
  line-height:1;
  letter-spacing:.12em;
  text-transform:uppercase;
  text-decoration:none;
  white-space:nowrap;
  transition:background-color .3s var(--ease-out),color .3s var(--ease-out);
}

.sticky-cta:hover,
.sticky-cta:focus-visible{background:#fff;color:var(--bis-accent)}

@media (max-width:760px){
  .sticky .bis-logo svg{width:120px}
  .sticky-cta{padding:calc(var(--x) * .8) calc(var(--x) * 1.8);font-size:.75rem}
}

/* --------------------------------------------------------------------------
   Plansza wejściowa
   -------------------------------------------------------------------------- */

.hero{padding-block:0}               /* padding siedzi w .hero-inner, żeby plansza miała równo 100svh */

.hero-inner{
  min-height:100svh;                 /* svh, bo na telefonie pasek przeglądarki zjada vh */
  padding-block:calc(var(--x) * 3);
  display:flex;
  flex-direction:column;
  gap:calc(var(--x) * 4);
}

@supports not (height:100svh){
  .hero-inner{min-height:100vh}
}

.hero-inner > .bis-logo{align-self:flex-start}

.hero-text{min-width:0}              /* bez tego długie słowo rozpycha kolumnę siatki */

.hero-body{
  flex:1;
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:calc(var(--x) * 5);
}

/* Tekst zawsze pierwszy w kodzie i w kolejności czytania.
   Od 1100 px forma z portretem stoi obok tekstu; poniżej portret jest tylko awatarem w podpisie. */
@media (min-width:1100px){
  .hero-body{
    display:grid;
    /* 1,35 : 0,65 — najdłuższy wiersz nagłówka („Prowadzony osobiście.”) mieści się w kolumnie,
       a portret ma szerokość formy ze znaku. */
    grid-template-columns:minmax(0,1.35fr) minmax(0,.65fr);
    align-items:center;
    gap:calc(var(--x) * 6);
  }
}

/* Eyebrow nad nagłówkiem: segment i kategorie w jednym wierszu. Półgruby zamiast wersalików —
   przy ponad 50 znakach rozstrzelone wersaliki czytały się jak baner, nie jak etykieta. */
.hero-eyebrow{
  margin:0 0 calc(var(--x) * 2.5);
  max-width:62ch;
  font-size:clamp(.9375rem, 1.2vw, 1.0625rem);
  font-weight:600;
  line-height:1.4;
  letter-spacing:.01em;
  color:#fff;
  text-wrap:balance;
}

/* Trzy linie zamiast dwóch przy tej samej wysokości bloku co wcześniej (1440 × 900: ok. 223 px),
   więc stopień hero zszedł z 86 do ok. 60 px. Cały nagłówek w czystej bieli: „Prowadzony osobiście"
   to wyróżnik oferty, nie dopowiedzenie — przygaszony czytał się jak przypis. */

/* Lead w hero: tłumaczy nazwę usługi. Szersza miara niż .lead, bo 34ch dawało
   siedem wierszy i spychało przycisk pod pierwszy ekran. */
.hero-lead{
  max-width:46ch;
  margin-top:calc(var(--x) * 3.5);
}

.hero-lead + .btn-connect{margin-top:calc(var(--x) * 3.5)}

/* --- przycisk „Umówmy rozmowę” ------------------------------------------ */

/* Drugi wyjątek od border-radius:0 po kołach kompetencji, tym razem świadomie
   dwudzielny: kant zostaje regułą dla treści, koło — regułą dla akcji i dla
   własnego motywu marki (kropka w znaku, blob, koła). Przycisk i strzałka
   w nim to pierwsza akcja na stronie, więc dostają tę drugą kategorię. */
.btn-connect{
  display:inline-flex;
  align-items:center;
  gap:calc(var(--x) * 1.6);
  margin-top:calc(var(--x) * 4);
  padding:calc(var(--x) * 1.1) calc(var(--x) * .6) calc(var(--x) * 1.1) calc(var(--x) * 2.2);
  background:#fff;
  color:var(--bis-ink);
  font-weight:500;
  font-size:1.0625rem;
  text-decoration:none;
  border-radius:999px;
  transition:background .3s var(--ease-out),color .3s var(--ease-out);
}

.btn-connect svg{
  flex-shrink:0;
  width:calc(var(--x) * 4);
  height:calc(var(--x) * 4);
  padding:calc(var(--x) * 1);
  border-radius:50%;
  background:var(--bis-ink);
  color:#fff;
  transition:transform .35s var(--ease-out),background .3s var(--ease-out),color .3s var(--ease-out);
}

.btn-connect:hover{background:var(--bis-accent);color:#fff}
.btn-connect:hover svg{background:#fff;color:var(--bis-accent);transform:translateX(15%)}

/* --- scena w hero: portret przed formą ze znaku ------------------------- */

/* Poniżej 1100 px duży portret schodzi ze strony: stał pod przyciskiem na 40svh, po CTA wyglądał
   na doklejony i dokładał ekran przewijania. Twarz niesie awatar w podpisie nad nagłówkiem. */
.hero-scena{
  display:none;
  position:relative;
}

.hero-form{display:none}

.hero-portret{display:block;position:relative}

/* Podpis: portret w kole obok eyebrow, jak przy autorze tekstu — twarz przy „Prowadzony osobiście”,
   zanim ktoś przeczyta nagłówek. W jednym rzędzie z eyebrow kosztuje ok. 20 px wysokości, więc
   przycisk zostaje na pierwszym ekranie także na 375 × 667. Koło ze znaku, białe jak forma na desktopie.
   Kadr: głowa i ramiona z pliku 1044 × 1518 — kwadrat 760 px od góry, oś twarzy na środku koła. */
.hero-podpis{
  display:flex;
  align-items:center;
  gap:calc(var(--x) * 1.8);
  margin:0 0 calc(var(--x) * 2.5);
}

.hero-podpis .hero-eyebrow{margin:0}

.hero-awatar{
  position:relative;
  flex:none;
  width:clamp(72px, 20vw, 96px);
  aspect-ratio:1;
  border-radius:50%;
  overflow:hidden;
  background:#fff;
}

.hero-awatar img{
  position:absolute;
  top:4%;                  /* oddech nad czubkiem głowy */
  left:-18.4%;             /* 140 / 760 */
  width:137.4%;            /* 1044 / 760 */
  max-width:none;
  height:auto;
}

@media (max-width:760px){
  .hero-inner{gap:calc(var(--x) * 1.5)}
  /* Bez dużego portretu pod przyciskiem treść stoi w środku pola — wcześniej przy górnej krawędzi
     zostawiała na 390 × 844 ok. 240 px pustego pasa pod CTA. Na niskich ekranach i tak wypełnia pole. */
  .hero-body{
    gap:calc(var(--x) * 3);
    justify-content:center;
    padding-top:clamp(calc(var(--x) * 1.5), 3svh, calc(var(--x) * 5));
  }
}

/* Od 1100 px: forma ze znaku jako tło, portret przed nią. Kolumna sceny schodzi do dołu pola
   i wychodzi poza siatkę w margines strony (min. 32 px do krawędzi ekranu).
   Szerokość ograniczona też wysokością ekranu: portret nie może wejść pod logo. */
@media (min-width:1100px){
  .hero-body{align-items:center}
  .hero-podpis{display:block}
  .hero-awatar{display:none}          /* na desktopie twarz niesie duży portret obok */
  .hero-scena{
    display:block;
    margin-bottom:calc(var(--x) * -3);   /* dół portretu na krawędzi pola */
    align-self:end;
    justify-self:end;
    margin-top:0;
    width:clamp(260px, min(32vw, calc((100svh - 150px) * .688)), 480px);
    margin-right:calc(-1 * clamp(0px, (100vw - 1180px) / 2 - 32px, 110px));
  }
  /* Forma ze znaku za portretem wyłączona: przy portrecie mono biała koszulka zlewała się z białą formą
     i sylwetka traciła kontur. Portret stoi wprost na Ultra. Powrót: display:block.
     Pętla animacji w app.js (punkt 8) sama staje, bo ukryty kształt nie przecina ekranu. */
  .hero-form{
    display:none;
    position:absolute;
    left:-6%;
    top:-2%;
    width:112%;
  }
  .hero-portret img{width:100%;height:auto}
}

.hero-form svg{
  display:block;
  width:100%;
  height:auto;
  overflow:visible;
}

/* Pojawia się po tekście, nie przed nim. Kształt i obrót liczy app.js (punkt 8):
   animacja CSS atrybutu d nie działa w Safari, a wcześniejsze klatki blob-morph
   nigdy nie zostały zdefiniowane — dlatego forma stała. */
.blob{animation:blob-in 1.1s ease-out .35s both}

@keyframes blob-in{from{opacity:0}to{opacity:1}}

/* --------------------------------------------------------------------------
   Kurtyna: hero stoi, „Punkt wyjścia” wjeżdża na nie od dołu
   -------------------------------------------------------------------------- */

/* --hero-top podaje app.js: 0, gdy hero mieści się w oknie; ujemne, gdy jest wyższe
   (niskie telefony) — wtedy hero najpierw przewija się do końca, a dopiero potem staje.
   --cover (0–1) to postęp zasłaniania: hero lekko ciemnieje i odsuwa się w głąb. */
.hero{position:relative}

.kurtyna.is-live .hero{
  position:sticky;
  top:var(--hero-top,0px);
  z-index:0;
}

.kurtyna.is-live .hero::after{
  content:"";
  position:absolute;
  inset:0;
  background:var(--bis-ink);
  opacity:calc(var(--cover,0) * .32);   /* mocniej — biel w hero szarzała */
  pointer-events:none;
}

.kurtyna.is-live .hero-inner{
  transform:translate3d(0,calc(var(--cover,0) * -6vh),0) scale(calc(1 - var(--cover,0) * .05));
  transform-origin:50% 100%;
}

/* Paralaksa portretu: gdy „Punkt wyjścia” wjeżdża na hero, portret unosi się szybciej niż tekst
   (-6vh w .hero-inner), a forma ze znaku wolniej — trzy warstwy, trzy prędkości.
   Dół portretu odsłania się zawsze niżej niż czoło zasłony, więc cięcie w pasie nigdy nie wychodzi na wierzch.
   Na telefonie twarz przesuwa się w obrębie koła. Bez kurtyny (ograniczony ruch) wszystko stoi. */
.kurtyna.is-live .hero-portret{transform:translate3d(0,calc(var(--cover,0) * -16vh),0)}
.kurtyna.is-live .hero-form{transform:translate3d(0,calc(var(--cover,0) * -7vh),0)}
.kurtyna.is-live .hero-awatar img{transform:translate3d(0,calc(var(--cover,0) * -9%),0)}

.kurtyna.is-live .punkt{position:relative;z-index:1}

/* Teza ma co najmniej wysokość ekranu — inaczej nie zasłoniłaby hero w całości. */
.punkt{
  min-height:100svh;
  display:flex;
  align-items:center;
}

@supports not (height:100svh){
  .punkt{min-height:100vh}
}

.punkt .prose--stmt{margin-top:0}

/* Tekst spod belek (app.js, punkt 7a). Każde słowo ma trzy stany:
   ukryte → zasłonięte grafitową belką → jawne. Czoło odsłaniania idzie za przewijaniem,
   więc przed nim zawsze stoi kilka belek — jak zaczernienia w dokumencie.
   Tekst jest cały czas w drzewie dostępności: znika tylko kolor, nie treść. */
.slowo{position:relative}
.is-redact .slowo{color:transparent;transition:color .22s ease .12s}
.is-redact .slowo.is-jawne{color:inherit}

/* Belka nie miga, tylko jedzie: wsuwa się nad słowo od lewej, a przy odsłonięciu
   zjeżdża w prawo — tekst wyłania się spod niej, a nie pojawia skokiem. */
/* Góra belki 0,24em pod górą słowa: przy interlinii 1,14 zostaje ok. 0,16em światła
   pod „p”, „y”, „ą” z wiersza wyżej. Przy 0,12em belka stała tuż pod nimi i litery
   wyglądały na ucięte od dołu. */
.is-redact .slowo::after{
  content:"";
  position:absolute;
  inset:.24em 0 .02em;
  background:var(--fg);
  transform:scaleX(0);
  transform-origin:0 50%;
  transition:transform .32s var(--ease-out);
}

.is-redact .slowo.is-blok::after{transform:scaleX(1)}
.is-redact .slowo.is-jawne::after{transform-origin:100% 50%}

/* Kanały jako etykiety pod opisem — pięć osobnych pozycji na liście
   rozbiłoby hierarchię pięciu obszarów. */
.comp-tags{
  margin:calc(var(--x) * 3) 0 0;
  padding:0;
  list-style:none;
  display:flex;
  flex-wrap:wrap;
  gap:calc(var(--x) * .8);
}

.comp-tags li{
  font-size:.8125rem;
  letter-spacing:.02em;
  color:var(--fg-2);
  padding:calc(var(--x) * .5) calc(var(--x) * 1.2);
  border:1px solid var(--rule);
}

/* --------------------------------------------------------------------------
   Dla kogo — dwie listy warunków w układzie tabeli wyników
   -------------------------------------------------------------------------- */

.kwal-blok{margin-top:calc(var(--x) * 8)}
.kwal-blok + .kwal-blok{margin-top:calc(var(--x) * 11)}

/* Etykieta kolumny — nagłówek listy. Skala tuż pod pozycjami listy (2,3rem), waga 700:
   czyta się jako tytuł, nie jako podpis. Wcześniej 1,25rem ginęło obok dużej listy. */
.kwal-etykieta{
  margin:0;
  font-size:clamp(1.5rem, 2.2vw, 2rem);
  font-weight:700;
  line-height:1.15;
  letter-spacing:-.012em;
}

.kwal-lista{
  margin:calc(var(--x) * 3) 0 0;
  padding:0;
  list-style:none;
}

/* Duża skala, dwie wagi: pogrubienie w kolorze tekstu, dopowiedzenie w drugorzędnym
   (#575B62 na Mist = 5,6:1). Bez drugiego kroju — różnicę niesie sama waga.
   Poziomy padding z ujemnym marginesem: tekst stoi na osi kolumny,
   a zaznaczenie po najechaniu ma zapas z obu stron. */
.kwal-lista li{
  position:relative;
  margin-inline:calc(var(--x) * -2);
  padding:calc(var(--x) * 3.2) calc(var(--x) * 2);
  font-size:clamp(1.35rem, 2.55vw, 2.3rem);
  line-height:1.2;
  letter-spacing:-.01em;    /* było -.022: pogrubienia 700 zlewały „ty”, „ry” */
  color:var(--fg-2);
  text-wrap:pretty;
  /* Zaznaczenie jako tło rosnące od dołu — gradient, bo ::before niesie już kreskę. */
  background:linear-gradient(var(--fg), var(--fg)) 0 100% / 100% 0 no-repeat;
  transition:background-size .35s var(--ease-out),color .25s ease;
}

.kwal-lista strong{
  font-weight:700;
  color:var(--fg);
  transition:color .25s ease;
}

/* Kreska jako osobny element, żeby mogła rysować się od lewej. Stoi na osi tekstu,
   nie na krawędzi zaznaczenia. */
.kwal-lista li + li::before{
  content:"";
  position:absolute;
  top:0;
  left:calc(var(--x) * 2);
  right:calc(var(--x) * 2);
  height:1px;
  background:var(--fg);
  opacity:.3;
  transform-origin:0 50%;
}

/* Po najechaniu: pełny grafit, tekst w kolorze tła (na Mist 16:1).
   Tylko z kursorem — na dotyku hover przykleja się po tapnięciu. */
@media (hover:hover){
  .kwal-lista li:hover{
    background-size:100% 100%;
    color:var(--bg);
  }
  .kwal-lista li:hover strong{color:var(--bg)}
  .kwal-lista li:hover::before,
  .kwal-lista li:hover + li::before{opacity:0}
}

@media (min-width:1100px){
  .kwal-blok{
    display:grid;
    grid-template-columns:minmax(0,4fr) minmax(0,8fr);
    gap:calc(var(--x) * 6);
    align-items:start;
  }
  /* Etykieta na wysokości pierwszego wiersza listy, nie nad jego zaznaczeniem. */
  .kwal-etykieta{position:sticky;top:calc(var(--x) * 12);padding-top:calc(var(--x) * 3.2 + .1em)}
  .kwal-lista{margin-top:0}
}

/* Wejście: kreski rysują się, pozycje podjeżdżają kaskadą. Ukrywamy dopiero,
   gdy skrypt uzbroił listę (is-armed) — bez JS lista stoi w całości. */
.kwal-lista.is-armed li{
  opacity:0;
  transform:translateY(28px);
  transition:opacity .9s var(--ease-out) calc(var(--i,0) * 110ms),
             transform .9s var(--ease-out) calc(var(--i,0) * 110ms),
             background-size .35s var(--ease-out),
             color .25s ease;
}

.kwal-lista.is-armed li::before{
  transform:scaleX(0);
  transition:transform 1.2s var(--ease-out) calc(var(--i,0) * 110ms),opacity .25s ease;
}

.kwal-lista.is-armed.is-in li{opacity:1;transform:none}
.kwal-lista.is-armed.is-in li::before{transform:scaleX(1)}

/* --------------------------------------------------------------------------
   O mnie — portret na kole ze znaku
   -------------------------------------------------------------------------- */

/* Od 1100 px dół pola bez paddingu: portret stoi na krawędzi sekcji. */
.omnie{
  position:relative;
  overflow:hidden;
}

@media (max-width:1099px){
  .omnie-scena{width:min(100%, 360px);margin-inline:0;border-bottom:1px solid var(--rule)}
}

.omnie-uklad{
  position:relative;
  display:grid;
  gap:calc(var(--x) * 6);
}

/* Poniżej 1100 px portret przed tekstem, nad nagłówkiem „Odpowiadałem za wynik.”
   Pole wraca wtedy do zwykłego dolnego odstępu, a cięcie portretu w pasie domyka kreska. */
.omnie-tekst{order:2}

.omnie-scena{
  order:1;
  position:relative;
  width:min(100%, 420px);
  margin-inline:auto;
}

/* Koło: kropka ze znaku w skali portretu. Zewnętrzna ramka niesie paralaksę,
   wewnętrzna — skalę wejścia; jedna transformacja nadpisywałaby drugą. */
.omnie-kolo-px{
  position:absolute;
  left:2%;
  top:8%;
  width:96%;
  aspect-ratio:1;
}

.omnie-kolo{
  display:block;
  width:100%;
  height:100%;
  border-radius:50%;
  background:var(--bis-accent);
}

.omnie-portret{position:relative;display:block}
.omnie-portret img{width:100%}

.js .omnie-kolo{
  transform:scale(.5);
  opacity:0;
  transition:transform 1.6s var(--ease-out),opacity .8s ease;
}

.js .omnie-portret{
  clip-path:inset(100% 0 0 0);
  transition:clip-path 1.5s var(--ease-out) .3s;
}

.omnie-scena.is-in .omnie-kolo{transform:none;opacity:1}
.omnie-scena.is-in .omnie-portret{clip-path:inset(0)}

@media (min-width:1100px){
  .omnie{padding-bottom:0}
  .omnie-uklad{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:calc(var(--x) * 8);
    align-items:end;
  }
  .omnie-scena{order:0;width:100%;max-width:540px;margin:0}
  .omnie-tekst{align-self:center;padding-bottom:calc(var(--x) * 11)}
}

.omnie-lead{max-width:30ch}

/* Nazwy z łącznikiem (E-commerce) nie mogą się łamać na „E-” / „commerce”.
   Znak U+2011 odpada — Familjen Grotesk go nie ma. */
.bez-lamania{white-space:nowrap}

.omnie-proza{margin-top:calc(var(--x) * 4)}

.omnie-proza p{
  margin:0;
  color:var(--fg-2);
}

.omnie-proza p + p{margin-top:calc(var(--x) * 2)}

/* Dorobek: dwa bloki danych pod prozą. Każdy otwiera kreska i etykieta wersalikami —
   ten sam zapis co etykiety w stopce, więc czyta się jako metryczka, nie jako treść. */
.omnie-dorobek{margin-top:calc(var(--x) * 5)}

.omnie-blok{
  padding-top:calc(var(--x) * 2.5);
  border-top:1px solid var(--rule);
}

.omnie-blok + .omnie-blok{margin-top:calc(var(--x) * 4)}

.omnie-etykieta{
  margin:0 0 calc(var(--x) * 1.5);
  font-size:.8125rem;
  font-weight:500;
  letter-spacing:.14em;
  line-height:1.5;
  text-transform:uppercase;
  color:var(--fg-2);
}

/* Etykieta-zdanie („Wcześniej, w agencji…”): bez wersalików i rozstrzelenia —
   przy pełnym zdaniu wersaliki czytały się jak krzyk, nie jak metryczka. */
.omnie-etykieta--zdanie{
  font-size:.9375rem;
  letter-spacing:0;
  text-transform:none;
}

/* Firmy: nazwa pogrubiona, dopowiedzenie w drugorzędnym kolorze, wiersze rozdzielone kreską. */
.omnie-firmy{
  margin:0;
  padding:0;
  list-style:none;
}

.omnie-firmy li{
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  align-items:baseline;
  gap:0 calc(var(--x) * 2);
  padding-block:calc(var(--x) * 1.2);
  line-height:1.4;
}

.omnie-firmy li + li{border-top:1px solid var(--rule)}
.omnie-firmy strong{font-weight:600;color:var(--fg)}
.omnie-firmy span{color:var(--fg-2)}

/* Marki: jeden ciąg nazw z ukośnikami — ukośnik w drugorzędnym kolorze, żeby nie konkurował z nazwą.
   Ukośnik stoi ZA nazwą, więc przy łamaniu kończy wiersz, a nie zaczyna następny. */
.omnie-marki{
  margin:0;
  padding:0;
  list-style:none;
  display:flex;
  flex-wrap:wrap;
  font-weight:600;
  line-height:1.6;
  color:var(--fg);
}

.omnie-marki li{white-space:nowrap}

.omnie-marki li:not(:last-child)::after{
  content:"/";
  margin-inline:.45em;
  font-weight:400;
  color:var(--fg-2);
}

/* --------------------------------------------------------------------------
   Plansza typograficzna — jedno zdanie na pełny ekran
   -------------------------------------------------------------------------- */

.plansza{padding-block:0}   /* padding siedzi w .plansza-inner, żeby pole miało równo 100svh */

.plansza-inner{
  min-height:100svh;
  padding-block:calc(var(--x) * 8);
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:center;
  text-align:center;
}

@supports not (height:100svh){
  .plansza-inner{min-height:100vh}
}

.plansza-line{
  font-weight:600;
  font-size:clamp(1.82rem,7.56vw,6.58rem);   /* 70% poprzedniej skali — zdanie ma oddech, nie ścianę */
  line-height:.95;
  letter-spacing:-.02em;
  /* Plansza jedzie z paralaksą (data-px), więc jej ramka też musi mieścić dół ostatniej linii.
     Zapas w paddingu, zwrócony ujemnym marginesem — położenie tekstu bez zmian. */
  padding-block:.12em .3em;
  margin:-.12em 0 -.3em;
  text-wrap:balance;
}

/* Telefon: 7,56vw dawało ok. 29 px — mniej niż nagłówki sekcji. Tu zdanie jest całym polem. */
@media (max-width:759px){
  .plansza-line{font-size:clamp(2.4rem, 11.5vw, 3.6rem)}
}

/* --------------------------------------------------------------------------
   Schemat układu — koła ze znaku
   -------------------------------------------------------------------------- */

/* Siatka sześciu torów po pół koła: górny rząd zajmuje tory 1–2, 3–4, 5–6,
   dolny 2–3 i 4–5, więc wsuwa się dokładnie w połowę. Tor ma szerokość (K − zakładka) / 2,
   koło jest szersze niż swoje dwa tory i nachodzi na sąsiada o zakładkę.
   Siódmy tor to sama zakładka ostatniego koła — dzięki niemu całość stoi na środku.
   Jedna formuła K obsługuje desktop i mobile: 280 px albo tyle, ile zmieszczą trzy koła. */
.kola{
  --k:min(280px, calc((100vw - 2 * var(--gutter)) / 2.78));
  --ov:calc(var(--k) * .11);
  margin:calc(var(--x) * 7) 0 0;
  padding:0;
  list-style:none;
  display:grid;
  grid-template-columns:repeat(6, calc((var(--k) - var(--ov)) / 2)) var(--ov);
  justify-content:center;
}

.kola li{
  width:var(--k);
  aspect-ratio:1;
  grid-column:span 2;
  border:1px solid var(--fg);
  border-radius:50%;                    /* jedyny wyjątek od border-radius:0 — kropka ze znaku */
  display:grid;
  place-items:center;
  padding:.8em;
  text-align:center;
  font-size:clamp(.78rem, calc(var(--k) * .078), 1.35rem);
  line-height:1.15;
  letter-spacing:-.015em;
  position:relative;
  background:transparent;
}

/* Kolejność w kodzie: hub, Kampanie, Sklep, Strategia, Kreacja — tak czyta czytnik ekranu.
   Pozycja na ekranie jest przypisana jawnie: Kampanie po lewej od huba, bo to pierwsza usługa po nim. */
.kola li:nth-child(1){grid-column:3 / span 2;grid-row:1}
.kola li:nth-child(2){grid-column:1 / span 2;grid-row:1}
.kola li:nth-child(3){grid-column:5 / span 2;grid-row:1}
.kola li:nth-child(4){grid-column:2 / span 2;grid-row:2}
.kola li:nth-child(5){grid-column:4 / span 2;grid-row:2}

/* Dolny rząd podjeżdża o 22% średnicy: odległość środków do górnych sąsiadów spada
   do ok. 0,9 średnicy — każde koło zachodzi na hub i na sąsiada tak samo jak w górnym rzędzie.
   Ujemny margines, bo row-gap nie przyjmuje wartości ujemnych. */
.kola li:nth-child(4),
.kola li:nth-child(5){margin-top:calc(var(--k) * -.22)}

/* Pole nadrzędne: wypełnione na stałe, więc samo wskazuje środek układu. */
.kola .is-hub{
  background:var(--accent);
  border-color:var(--accent);
  color:#fff;
  font-weight:500;
  z-index:1;
}

/* Najechanie wypełnia koło tym samym kolorem co pole nadrzędne — jak na benchmarku.
   Tylko dla urządzeń z kursorem: na dotyku stan hover przykleja się po tapnięciu. */
@media (hover:hover){
  .kola li:hover{
    background:var(--accent);
    border-color:var(--accent);
    color:#fff;
    z-index:2;
  }
}

/* Zdanie pod schematem na jego osi — domyka układ kół. */
.kola-note{
  max-width:40ch;
  margin:calc(var(--x) * 7) auto 0;
  text-align:center;
  text-wrap:balance;
}

/* --------------------------------------------------------------------------
   Zakres usług — akordeon od 760 px (app.js, punkt 4)
   · bez skryptu i poniżej 760 px: wszystkie opisy rozwinięte, rozdzielone kreską
   · od 760 px: nagłówek jest przyciskiem, zwinięty opis ma zerową wysokość i visibility:hidden
   -------------------------------------------------------------------------- */

.obszary-tytul{
  font-size:var(--t-h2);
  font-weight:600;
  line-height:1.02;
  padding-bottom:.06em;
}

.obszary-akordeon{margin-top:calc(var(--x) * 4)}

.obszar{
  border-top:1px solid var(--rule);
  padding-block:calc(var(--x) * 4);
}

.obszar:last-child{border-bottom:1px solid var(--rule)}

/* Interlinia 1,12 i zapas pod spodem — przy 1,02 Familjen gubił dół „ę”, „ą” i „j”. */
.obszar h3{
  font-size:clamp(1.5rem, 2.6vw, 2.25rem);
  letter-spacing:-.015em;
  line-height:1.12;
  padding-bottom:.06em;
}

.obszar p{
  margin:calc(var(--x) * 2) 0 0;
  max-width:60ch;
  color:var(--fg-2);
}

/* Pierwsze zdanie w kolorze tekstu głównego — czyta się samo, reszta dopowiada. */
.obszar p strong{font-weight:600;color:var(--fg)}

@media (min-width:760px){
  .obszary-akordeon{margin-top:calc(var(--x) * 6)}
  .obszar{padding-block:0}
  .obszar h3{font-size:clamp(1.75rem, 3.2vw, 3rem)}
  .obszary:not(.is-akordeon) .obszar{padding-block:calc(var(--x) * 4)}

  /* Cały wiersz jest przyciskiem: nazwa po lewej, kółko z plusem po prawej.
     Koło to reguła dla akcji na tej stronie (przycisk w hero, LinkedIn, „Kontakt” w pasku). */
  .obszar-przycisk{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:calc(var(--x) * 3);
    width:100%;
    margin:0;
    padding:calc(var(--x) * 3.5) 0;
    background:none;
    border:0;
    color:inherit;
    font:inherit;
    letter-spacing:inherit;
    line-height:inherit;
    text-align:left;
  }

  .obszar-przycisk:focus-visible{outline-offset:6px}

  .obszar-znak{
    position:relative;
    flex:none;
    width:calc(var(--x) * 5.5);
    height:calc(var(--x) * 5.5);
    border:1.5px solid currentColor;
    border-radius:50%;
    transition:background-color .3s var(--ease-out),color .3s var(--ease-out);
  }

  /* Plus z dwóch kresek; pionowa składa się przy otwarciu, zostaje minus. */
  .obszar-znak::before,
  .obszar-znak::after{
    content:"";
    position:absolute;
    left:50%;
    top:50%;
    width:36%;
    height:1.5px;
    background:currentColor;
    transform:translate(-50%,-50%);
    transition:transform .35s var(--ease-out);
  }

  .obszar-znak::after{transform:translate(-50%,-50%) rotate(90deg)}
  .obszar.is-otwarty .obszar-znak::after{transform:translate(-50%,-50%) rotate(0deg)}

  @media (hover:hover){
    .obszar-przycisk:hover .obszar-znak{background:var(--bis-accent);border-color:var(--bis-accent);color:#fff}
  }

  /* Zwijanie przez wysokość wiersza siatki 0fr → 1fr — płynnie, bez mierzenia w JS.
     visibility z opóźnieniem: zwinięty opis znika z tabulacji i dla czytnika dopiero po animacji. */
  .is-akordeon .obszar-tresc{
    display:grid;
    grid-template-rows:0fr;
    visibility:hidden;
    transition:grid-template-rows .5s var(--ease-out),visibility 0s linear .5s;
  }

  .is-akordeon .obszar.is-otwarty .obszar-tresc{
    grid-template-rows:1fr;
    visibility:visible;
    transition:grid-template-rows .5s var(--ease-out),visibility 0s linear 0s;
  }

  .is-akordeon .obszar-tresc-in{min-height:0;overflow:hidden}

  .is-akordeon .obszar p{
    margin-top:0;
    font-size:1.125rem;
    line-height:1.5;
  }

  .is-akordeon .obszar-tresc-in > :last-child{margin-bottom:calc(var(--x) * 4)}

  /* Opisy pod nazwą, ale w prawej części wiersza — nazwy tworzą czytelną kolumnę po lewej. */
  .is-akordeon .obszar-tresc-in{padding-left:min(24%, 260px)}
}

/* --------------------------------------------------------------------------
   Współpraca — typografia jako grafika (wzór: basicagency.com)
   -------------------------------------------------------------------------- */

/* Więcej powietrza nad i pod sekcją — dłuższa droga dla przejścia koloru w obie strony.
   Kompensuje start przejścia dopiero po planszy w czystej Ultra. */
.wspolpraca{padding-block:calc(var(--x) * 26)}

@media (max-width:760px){
  .wspolpraca{padding-block:calc(var(--x) * 18)}
}

/* Skala nagłówka od szerokości kolumny: najdłuższy wiersz wypełnia połowę pola.
   Najdłuższy jest „• OD ROZMOWY” — kropka (0,84em) + 5,98em = 6,82em (Familjen 700, wersaliki, -0,045em).
   Dzielnik 6,9 zostawia margines na hinting.
   Mobile: jedna kolumna, więc słowo bierze całą szerokość. Zmiana tekstu = nowy pomiar. */
.wsp-tytul{
  --wsp-w:calc(min(100vw, var(--maxw)) - 2 * var(--gutter));
  display:grid;
  gap:calc(var(--x) * 3);
  font-weight:700;
  font-size:calc(var(--wsp-w) / 6.9);
  line-height:.9;
  letter-spacing:-.045em;
  text-transform:uppercase;
  text-wrap:nowrap;
}

/* Każda połowa wjeżdża osobno (data-reveal). Przy interlinii 0,9 przecinek i dół liter
   wystawały z ramki — zapas w paddingu, zwrócony ujemnym marginesem. */
.wsp-pol{display:block;padding-block:.1em .2em;margin-block:-.1em -.2em}

/* Kropka ze znaku, w kolorze tekstu — otwiera drugą połowę zdania. */
.wsp-kropka{
  display:inline-block;
  width:.62em;
  height:.62em;
  border-radius:50%;
  background:currentColor;
  margin-right:.22em;
  vertical-align:.06em;
}

@media (min-width:760px){
  .wsp-tytul{
    grid-template-columns:1fr 1fr;
    column-gap:calc(var(--x) * 4);
    row-gap:0;
    font-size:calc((var(--wsp-w) - var(--x) * 4) / 2 / 6.9);
  }

  /* druga połowa schodzi o dwie linie — oko przeskakuje przez pole po przekątnej */
  .wsp-pol--2{margin-top:1.8em}   /* 1,9em minus 0,1em zapasu z paddingu powyżej */
}

.steps{
  margin:calc(var(--x) * 10) 0 0;
  padding:0;
  list-style:none;
  display:grid;
  gap:calc(var(--x) * 5);
}

@media (min-width:760px){
  .steps{grid-template-columns:repeat(3,1fr);gap:calc(var(--x) * 5)}
}

.steps h3{
  font-size:clamp(1.5rem, 2.4vw, 2.25rem);
  font-weight:700;
  letter-spacing:-.03em;
  line-height:1;
  text-transform:uppercase;
}

/* Opis krojem nagłówkowym i w dużym stopniu — kolumna ma się czytać jak blok graficzny,
   nie jak przypis. */
.steps p{
  margin:calc(var(--x) * 2) 0 0;
  font-weight:500;
  font-size:clamp(1.125rem, 1.55vw, 1.5rem);
  line-height:1.3;
  letter-spacing:-.01em;
  color:var(--fg);
  text-wrap:pretty;
}

/* Ramy kroku: czas i forma rozliczenia. Skala podpisu, żeby nie konkurowała z opisem.
   Selektor z .steps, bo reguła .steps p ustawia opisom inny stopień i odstęp. */
.steps p.steps-meta{
  margin:calc(var(--x) * 1.4) 0 0;
  font-size:.8125rem;
  font-weight:500;
  letter-spacing:.14em;
  line-height:1.4;
  text-transform:uppercase;
  color:var(--fg-2);
}

/* --------------------------------------------------------------------------
   Kontakt — pole akcentu zamyka stronę
   -------------------------------------------------------------------------- */

/* Zdanie zamiast jednego słowa: skala planszy, zwykłe litery, łamanie z balance.
   Stopień dobrany pomiarem: maks. 2 linie przy 1440 px, maks. 3 przy 390 px. */
.kontakt-tytul{
  margin-left:-.04em;
  max-width:14ch;
  font-size:clamp(2.6rem, 8.4vw, 7.25rem);
  font-weight:700;
  letter-spacing:-.035em;
  line-height:.95;
  text-wrap:balance;
}

/* Hierarchia: tytuł (grafika) → adres e-mail (działanie) → instrukcja (tekst).
   Wcześniej instrukcja miała 44 px przy 58 px adresu i trzy poziomy walczyły ze sobą;
   na telefonie instrukcja i adres miały po 24 px. Teraz instrukcja ma skalę leadu. */
.kontakt-lead{
  margin:calc(var(--x) * 5) 0 0;
  max-width:40ch;
  font-weight:500;
  font-size:var(--t-lead);
  line-height:1.4;
  letter-spacing:-.01em;
  text-wrap:pretty;
}

/* Mail i telefon jeden pod drugim, bez linii i kolumn — dwie linie jednego bloku.
   Waga 500, nie 600: pod tytułem w 700 adres ma być czytelny, nie krzyczeć. */
.kontakt-kanaly{margin-top:calc(var(--x) * 6)}

.kontakt-glowny{
  margin:0;
  font-weight:500;
  font-size:clamp(1.5rem, 6.8vw, 3.6rem);   /* 360 px: adres mieści się w jednej linii */
  letter-spacing:-.025em;
  line-height:1.15;
}

/* Linia rysuje się od lewej po najechaniu albo przy fokusie — w spoczynku tekst stoi czysty. */
.kontakt-link{
  text-decoration:none;
  overflow-wrap:anywhere;
  padding-bottom:.04em;
  background:linear-gradient(currentColor, currentColor) 0 100% / 0 2px no-repeat;
  transition:background-size .5s var(--ease-out);
}

.kontakt-link:focus-visible{background-size:100% 2px}

@media (hover:hover){
  .kontakt-link:hover{background-size:100% 2px}
}

/* tekst tylko dla czytników ekranu */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Co najmniej wysokość ekranu. Treść u góry, znak w tle dociśnięty do dołu. */
.kontakt{
  position:relative;
  overflow:hidden;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  padding-bottom:calc(var(--x) * 4);
}

.kontakt > .wrap{
  flex:1 0 auto;
  display:flex;
  flex-direction:column;
}

@supports not (height:100svh){
  .kontakt{min-height:100vh}
}

/* Wolne miejsce dzielone po połowie: nad tytułem i nad znakiem. Treść stoi w środku pola,
   zamiast wisieć u góry nad pustym pasem (na telefonie ok. 260 px pustki). */
.kontakt-tytul{margin-top:auto}

/* Znak w całości, na szerokość siatki. Ramka przycina — znak wysuwa się spod jej dolnej krawędzi. */
.sygnatura-rama{
  margin-top:auto;
  padding-top:calc(var(--x) * 10);
  overflow:hidden;
}

.sygnatura{
  display:block;
  width:100%;
  height:auto;
  opacity:.2;
  pointer-events:none;
}

.js .sygnatura{
  transform:translate3d(0,110%,0);
  transition:transform 1.6s var(--ease-out);
}

.sygnatura-rama.is-in .sygnatura{transform:none}

/* --------------------------------------------------------------------------
   Stopka — nawigacja, kanały, dane firmy
   -------------------------------------------------------------------------- */

.stopka{
  background:var(--bis-ink);
  color:#fff;
  padding-block:calc(var(--x) * 10) calc(var(--x) * 4);
  font-size:.9375rem;
}

.stopka a{text-decoration:none}

.stopka-gora{
  display:grid;
  gap:calc(var(--x) * 7);
}

@media (min-width:900px){
  .stopka-gora{
    grid-template-columns:minmax(0,5fr) minmax(0,3.5fr) minmax(0,3.5fr);
    gap:calc(var(--x) * 6);
  }
}

.stopka-logo{display:inline-block}
.stopka-logo img{width:200px;height:auto}   /* minimum z księgi: 160 px */

/* rgba(255,255,255,.66) na grafit = ok. 9:1 */
.stopka-motto{
  margin:calc(var(--x) * 3) 0 0;
  max-width:32ch;
  color:rgba(255,255,255,.66);
  font-size:1.0625rem;
  line-height:1.45;
}

.stopka-etykieta{
  margin:0 0 calc(var(--x) * 2.5);
  font-size:.8125rem;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:rgba(255,255,255,.6);
}

.stopka-nav ul{
  margin:0;
  padding:0;
  list-style:none;
  display:grid;
  gap:calc(var(--x) * 1.6);
}

.stopka-nav a,
.stopka-gora-link{
  display:inline-block;
  font-weight:500;
  letter-spacing:-.01em;
}

.stopka-nav a{font-size:clamp(1.125rem, 1.6vw, 1.375rem)}

/* Po najechaniu linia rośnie od lewej — ten sam ruch co przy adresie e-mail. */
.stopka-nav a span,
.stopka-gora-link span{
  background:linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition:background-size .45s var(--ease-out);
  padding-bottom:.1em;
}

.stopka-nav a:hover span,
.stopka-nav a:focus-visible span,
.stopka-gora-link:hover span,
.stopka-gora-link:focus-visible span{background-size:100% 1px}

/* Mail i telefon jeden pod drugim, w tym samym stylu. */
.stopka-kontakt{display:grid;justify-items:start;align-content:start;gap:calc(var(--x) * 1.2)}

.stopka-mail{
  font-size:clamp(1.125rem, 1.6vw, 1.375rem);
  font-weight:500;
  letter-spacing:-.01em;
  background:linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition:background-size .45s var(--ease-out);
  padding-bottom:.1em;
  word-break:break-word;
}

@media (min-width:900px){
  .stopka-mail{white-space:nowrap;word-break:normal}
}

.stopka-mail:hover,
.stopka-mail:focus-visible{background-size:100% 1px}

.stopka-dol{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:calc(var(--x) * 2.5) calc(var(--x) * 4);
  margin-top:calc(var(--x) * 10);
  padding-top:calc(var(--x) * 3.5);
  border-top:1px solid rgba(255,255,255,.16);
}

.stopka-social{display:flex;gap:calc(var(--x) * 1.2)}

.stopka-ikona{
  display:inline-grid;
  place-items:center;
  width:calc(var(--x) * 5.5);
  height:calc(var(--x) * 5.5);
  border:1px solid rgba(255,255,255,.3);
  border-radius:50%;
  transition:background-color .3s var(--ease-out),border-color .3s var(--ease-out);
}

.stopka-ikona svg{width:19px;height:19px}

.stopka-ikona:hover,
.stopka-ikona:focus-visible{background:var(--bis-accent);border-color:var(--bis-accent)}

.stopka-prawne{
  margin:0;
  font-size:.8125rem;
  color:rgba(255,255,255,.6);
}

.stopka-gora-link{font-size:.9375rem}

@media (max-width:760px){
  .stopka-dol{flex-direction:column;align-items:flex-start}
}

/* --------------------------------------------------------------------------
   Kursor nad elementami, które reagują: kropka Ultra z białym obrysem
   -------------------------------------------------------------------------- */

/* Kropka ze znaku jako kursor — ten sam motyw co koła i forma w hero.
   Biały obrys 2,5 px trzyma ją widoczną także na polach Ultra i na graficie.
   SVG w data URI, bez skryptu: przeglądarka rysuje kursor sama, bez opóźnienia.
   Punkt aktywny w środku koła (12 12). Druga wartość to zapas, gdy SVG nie wejdzie:
   pointer dla odnośników, zwykła strzałka dla elementów, które tylko reagują ruchem.
   Tylko mysz i gładzik — na dotyku kursora nie ma. */
@media (hover:hover) and (pointer:fine){
  :root{
    --kursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='9' fill='%232B3AFF' stroke='%23fff' stroke-width='2.5'/%3E%3C/svg%3E") 12 12;
  }

  a,
  button,
  summary{cursor:var(--kursor), pointer}

  .hero-scena,
  .kola li,
  .kwal-lista li,
  .omnie-scena,
  .comp-tags li{cursor:var(--kursor), default}
}

/* --------------------------------------------------------------------------
   Ruch
   -------------------------------------------------------------------------- */

/* Wspólne wyprowadzenie ruchu: to samo easing dla wszystkiego, co wchodzi na ekran.
   Krzywa startuje szybko i długo wytraca — stąd wrażenie ciężaru, a nie skoku. */
:root{--ease-out:cubic-bezier(.16,1,.3,1)}

/* Stan startowy tylko pod .js — bez skryptu cała treść stoi widoczna (wcześniej znikała). */
.js [data-reveal]{
  opacity:0;
  transform:translateY(18px);
  transition:opacity 1s var(--ease-out),transform 1s var(--ease-out);
}

.js [data-reveal].is-in{opacity:1;transform:none}

/* Nagłówki wjeżdżają linia po linii spod krawędzi maski.
   Zapas góra/dół oddany ujemnym marginesem. Dół 0,3em: Familjen ma głębokie
   wydłużenia dolne (ok. 0,18em pod linią pisma), a nagłówki mają interlinię 0,9–1,05.
   Zapas siedzi w animowanym wierszu (i), nie w masce: ramka, która się przesuwa, musi
   obejmować całe litery — inaczej Safari ucina dół „g”, „p”, „j” i ogonki „ę”, „ą”.
   Wysokość maski bez zmian, więc układ zostaje co do piksela. */
.mask{
  display:block;
  overflow:hidden;
  margin:-.12em 0 -.3em;
}

.mask > i{
  display:block;
  padding:.12em 0 .3em;
  font-style:normal;
  transform:translateY(115%);
  transition:transform 1.15s var(--ease-out);
  transition-delay:var(--d,0ms);
}

[data-mask].is-in .mask > i{transform:none}

/* Koła startują rozsunięte (--tx/--ty liczy JS: wektor od huba) i zjeżdżają się
   w jeden układ — schemat pokazuje to, co mówi zdanie pod nim. */
.js [data-kola] li{
  opacity:0;
  transform:translate3d(var(--tx,0px),var(--ty,0px),0) scale(.88);
  /* opóźnienie kaskady dotyczy tylko wejścia — kolor po najechaniu reaguje od razu */
  transition:
    opacity .9s var(--ease-out) var(--d,0ms),
    transform 1.5s var(--ease-out) var(--d,0ms),
    background-color .35s ease,
    border-color .35s ease,
    color .35s ease;
}

.js [data-kola].is-in li{opacity:1;transform:none}

/* Nic nie wystaje poza szerokość ekranu. Koła w „Pięciu obszarach” startują rozsunięte
   na boki i przed wejściem wychodziły 23 px za prawą krawędź telefonu — strona robiła się
   szersza od ekranu i przy przewijaniu kołysała się na boki. clip, nie hidden:
   nie tworzy kontenera przewijania, więc elementy przyklejone (sticky) działają dalej. */
main{overflow-x:clip}

/* Paralaksa: przesunięcie wpisuje app.js wprost w styl elementu (punkt 6). */
[data-px]{will-change:transform}

/* Głębia między sekcjami (desktop, app.js punkt 6a). Przesuwa się tylko .wrap,
   tło sekcji stoi. Każde pole leży warstwę wyżej niż poprzednie (kolejność z kodu),
   więc treść, która przy wyjściu zostaje w tyle, chowa się pod następnym polem,
   zamiast na nie wchodzić. Desktop i telefon mają osobne proporcje ruchu (app.js). */
.glebia .band,
.glebia .scena{position:relative;z-index:1}

/* Przesunięcie, skalę (tylko telefon) i krycie wpisuje app.js wprost w styl .wrap.
   Oś u dołu treści: treść maleje do własnej dolnej krawędzi, więc nie wychodzi na następne pole. */
.warstwa{
  transform-origin:50% 100%;
  will-change:transform,opacity;
}

/* --------------------------------------------------------------------------
   Intro z logo (app.js, punkt 10; wzór: lepont.pl)
   Biała plansza, znak na całą szerokość wysuwa się od dołu. Potem od dołu wjeżdża
   pole Ultra, a znak w tym samym ruchu maleje i ląduje dokładnie na miejscu znaku w hero,
   przechodząc z grafitu i Ultra w biel. Plansza znika bez śladu — pod spodem stoi to samo.
   -------------------------------------------------------------------------- */

/* Zasłona do chwili, w której skrypt zbuduje intro. Bezpiecznik: gdyby app.js się
   nie wczytał, zasłona sama znika po 3 s, więc strona nigdy nie zostaje pusta. */
html.intro:not(.intro-gotowe) body::after{
  content:"";
  position:fixed;
  inset:0;
  z-index:100;
  background:var(--bis-paper);
  animation:intro-bezpiecznik 0s linear 3s forwards;
}

@keyframes intro-bezpiecznik{to{visibility:hidden}}

/* Animacje hero czekają pod planszą i ruszają dopiero, gdy ona zniknie. */
html.intro .hero .mask > i{transform:translateY(115%)}
html.intro .hero [data-reveal]{opacity:0;transform:translateY(18px)}
html.intro .blob{animation:none;opacity:0}

/* Plansza intro ma własną klasę. Wcześniej nazywała się tak samo jak znacznik html.intro,
   więc na czas intro cały dokument dostawał position:fixed i overflow:hidden. */
.intro-ekran{
  position:fixed;
  inset:0;
  z-index:90;                 /* nad paskiem przyklejonym (50) */
  background:var(--bis-paper);
  overflow:hidden;
  transition:opacity .35s ease;
}

.intro-ekran.is-koniec{opacity:0}

.intro-panel{
  position:absolute;
  inset:0;
  background:var(--bis-accent);
  transform:translate3d(0,100%,0);
}

/* Znak startuje w kolorach na jasnym tle: grafit + Ultra. Kończy w bieli, jak w hero. */
.intro-logo{
  position:fixed;
  overflow:hidden;            /* maska: znak wysuwa się spod dolnej krawędzi */
  transform-origin:0 0;
  color:var(--bis-ink);
  --bis-accent:#2B3AFF;
}

.intro-logo svg{
  display:block;
  width:100%;
  height:100%;
  transform:translate3d(0,105%,0);
}

.intro-ekran.is-1 .intro-logo svg{
  transform:none;
  transition:transform .9s var(--ease-out);
}

/* Faza 2: pole wjeżdża, znak leci na swoje miejsce. Jedna krzywa dla obu —
   ruszają i hamują razem, więc czytają się jako jeden gest. */
.intro-ekran.is-2 .intro-panel{
  transform:none;
  transition:transform 1.1s cubic-bezier(.76,0,.24,1);
}

.intro-ekran.is-2 .intro-logo{
  transform:none !important;  /* !important: pozycję startową wpisuje skrypt w atrybut style */
  color:#fff;
  --bis-accent:#fff;
  transition:transform 1.1s cubic-bezier(.76,0,.24,1),color .8s ease .25s;
}

.intro-ekran.is-2 .intro-logo path{transition:fill .8s ease .25s}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;   /* wyłączamy ruch, nie znaczenie */
    transition-duration:.01ms !important;
  }
  [data-reveal]{opacity:1;transform:none}
  .mask > i{transform:none}
  [data-kola] li{opacity:1;transform:none}
  .sygnatura,
  .omnie-kolo-px,
  .omnie-kolo{transform:none}
  .omnie-kolo{opacity:1}
  .omnie-portret{clip-path:none}
  .kwal-lista.is-armed li{opacity:1;transform:none}
  .kwal-lista.is-armed li::before{transform:none}
  .sticky{transition:none}
  html{scroll-behavior:auto}
  .blob{animation:none;opacity:1}           /* kształt zostaje w klatce spoczynkowej */
  .btn-connect:hover svg{transform:none}
}

