
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;--anchor-gap:104px}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
/* KOTWICE FORMULARZY (user 2026-08-02: "tylko nie tak blisko").
   Naglowek jest przyklejony (.site{position:sticky;top:0}, min-height 66px),
   wiec bez zapasu formularz wjezdza pod niego i klei sie do gornej krawedzi
   ekranu. Zapas ok. 100 px zostawia nad polami widoczna gorna krawedz karty
   i oddech pod naglowkiem. Selektory: kotwica formularza kontaktowego,
   kotwica panelu zapytania na LP oraz kazdy formularz leada z wlasnym id
   (zeby nowe formularze dostawaly to samo bez dopisywania regul). */
#kontakt-form,#zapytanie,[id][data-lead-form],[id][data-qx2-form]{
  scroll-margin-top:var(--anchor-gap,104px)}
body{margin:0;overflow-x:hidden;background:var(--bg);color:var(--ink);
  font-family:var(--font);font-size:clamp(16px,1rem + .15vw,17.5px);line-height:1.6;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3,p,ul,ol,figure{margin:0}
ul,ol{padding:0;list-style:none}
a{color:inherit;text-decoration:none}
img,svg,canvas,video{display:block;max-width:100%;height:auto}
button{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
.ico{width:1.2em;height:1.2em;flex:0 0 auto}
.vh{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:12px;top:-60px;z-index:200;background:var(--accent);
  color:#fff;padding:10px 16px;border-radius:8px;transition:top .2s}
.skip:focus{top:12px}
.wrap{width:100%;max-width:var(--maxw,1140px);margin-inline:auto;
  padding-inline:clamp(18px,5vw,40px)}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  padding:.85em 1.4em;border:1px solid transparent;border-radius:var(--btn-r,12px);
  font-weight:600;line-height:1;cursor:pointer;text-align:center;
  transition:transform .18s ease,box-shadow .25s ease,background .25s ease,border-color .25s ease;
  will-change:transform}
.btn--sm{padding:.6em 1em;font-size:.92rem}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0)}
.btn .ico{width:1.05em;height:1.05em}

/* ---- animowana obwodka przycisku: PRZENIESIONA 1:1 Z LABY ----
   Zrodlo: trash/obwodki.html, sekcja "Wersja finalna do zatwierdzenia"
   (klasy .fin-otoczka / .fin-btn / .fg / .fg1 / .fg2). User: "ma sie to
   zachowywac identycznie, tak jak jest tam, co do znaku".

   Wczesniejsze podejscia PRZEPISYWALY ten efekt po swojemu (warstwa pod
   przyciskiem, background-clip, wlasne krzywe wygaszania) i za kazdym razem
   roznily sie w czyms, czego nie bylo widac w pomiarach. Teraz reguly sa
   przeniesione doslownie; zmienione sa WYLACZNIE nazwy klas i zmiennych,
   zeby nie kolidowaly z reszta serwisu.

   JEDYNE ODSTEPSTWO OD LABY: po animacji JS zdejmuje klase, wiec przycisk
   wraca do zupelnie normalnego wygladu (jawne zyczenie usera). W labie
   gradientowy border zostaje na stale, bo animacja ma `fill: both`.

   SKUTEK, KTORY JEST W LABIE I ZOSTAJE: na czas animacji obramowanie
   przycisku rosnie z 1 na 2 px. Wczesniej probowalem to obejsc warstwa
   pozycjonowana - to wlasnie bylo zrodlo roznic. Ruch jest o jeden piksel
   i wystepuje raz.

   PULAPKA: w skroconym zapisie `background` kolor wolno podac WYLACZNIE
   w ostatniej warstwie. "#fff padding-box, conic(...) border-box" jest
   nieprawidlowe i CALE TLO ZNIKA. Dlatego wypelnienie zawsze jako gradient. */
@property --btnglow-a{syntax:"<angle>";inherits:false;initial-value:0deg}
/* Kat jest SKROCONY PROPORCJONALNIE do czasu trwania, zeby tempo obrotu
   zostalo takie samo: 720 st. w 3,5 s to 205,7 st./s, a 617 st. w 3,0 s to
   205,7 st./s. Samo skrocenie czasu bez kata przyspieszyloby obrot. */
@keyframes btnglow-spin{to{--btnglow-a:617deg}}
/* Sekunda narastania, sekunda pelnej mocy, sekunda gasniecia (user
   2026-08-03: "robimy od razu i przez sekunde fade in"). Przy 3 s
   calosci 33% to rowno 1 s. Wczesniej efekt pojawial sie skokiem po
   opoznieniu, teraz narasta od zera. */
@keyframes btnglow-gasnie{0%{opacity:0}33%,67%{opacity:var(--btnglow-o,.6)}100%{opacity:0}}
/* Szara kreska przycisku wraca DOKLADNIE ta sama krzywa, ktora gasi gradient,
   wiec zamiast twardego ciecia jest przenikanie. */
@keyframes btnglow-kreska{0%{border-color:var(--line)}33%,67%{border-color:transparent}100%{border-color:var(--line)}}
.btnglow{position:relative;display:inline-flex;border-radius:12px}
.btnglow .btnglow__ring{position:absolute;pointer-events:none;z-index:0;opacity:0}
.btnglow .btnglow__fg{position:absolute;border-radius:16px;pointer-events:none;z-index:0;opacity:0;
 background:conic-gradient(from var(--btnglow-a),#2563eb,#06b6d4,#fbbf24,#f59e0b,#2563eb)}
/* ZEWNETRZNY PIKSEL OBWODKI. Razem z 1 px w obramowaniu przycisku daje
   2 px gradientu, ale BEZ dotykania grubosci obramowania - dzieki temu
   wnetrze przycisku nie kurczy sie ani o piksel. Nie rozmywamy jej i nie
   wygaszamy w polowie: kontur ma byc ostry do konca, tak jak w labie. */
.btnglow .btnglow__ring{inset:-1px;border-radius:calc(var(--btn-r,12px) + 1px);--btnglow-o:1;
 background:conic-gradient(from var(--btnglow-a),#2563eb,#06b6d4,#fbbf24,#f59e0b,#2563eb)}
.btnglow .btnglow__fg1{inset:-4px;filter:blur(9px);--btnglow-o:.62}
.btnglow .btnglow__fg2{inset:-11px;filter:blur(19px);--btnglow-o:.46}
/* `.btn` ma w serwisie `transition:...background .25s,border-color .25s`, przez
   co gradient WTAPIALBY sie przez cwierc sekundy zamiast pojawic od razu.
   W labie zadnego przejscia nie ma. Podniesienie na hover zostaje. */
/* Owijka bierze na siebie miejsce przycisku w ukladzie. Gdy rodzic ja
   rozciaga (grid albo flex ze stretch), przycisk musi ja wypelnic -
   inaczej obwodka rysuje sie wokol pustego miejsca. Na panelu wyceny
   Zscalera owijka miala 709 px przy przycisku 209 px. W ukladach
   inline (hero) nic sie nie zmienia, bo owijka i tak ma szerokosc
   przycisku. */
.btnglow>.btn{width:100%;position:relative;z-index:1;transition:transform .18s ease,box-shadow .25s ease}
/* ZERO ZMIANY GEOMETRII, DO PIKSELA.
   Droga do tego stanu, zeby nie wracac do zlych pomyslow:
   (1) laba pogrubia obramowanie z 1 na 2 px - `.btn` jest `inline-flex`
       o szerokosci "shrink to fit" (tresc + padding + obramowanie), a
       `box-sizing:border-box` tu NIE POMAGA, bo dziala na ZADANA szerokosc,
       ktorej nie ma. Przycisk rosl o 2 px i kurczyl sie na koncu, przesuwajac
       sasiadow;
   (2) kompensacja paddingu (`calc(.85em - 1px)`) zatrzymala pudelko i napis,
       ale WNETRZE dalej kurczylo sie o 1 px z kazdej strony, bo obramowanie
       zabieralo pikselaz padding-boxu. Zmierzone: biale wnetrze 148x48 ->
       146x46. Layout Shift byl zerowy (CLS 0.000000), a mimo to bylo widac
       delikatne pulsowanie - user zglosil to trzykrotnie i mial racje;
   (3) teraz obramowanie NIE ZMIENIA GRUBOSCI. Zostaje 1 px, zmienia sie
       wylacznie jego KOLOR (gradient przez tlo border-box), a drugi piksel
       obwodki doklada warstwa `.btnglow__ring` lezaca 1 px NA ZEWNATRZ.
       Warstwa jest absolutnie pozycjonowana, wiec nie istnieje dla ukladu.
       Nie zmienia sie ani pudelko, ani padding, ani wnetrze, ani napis.
   NIE WRACAC do zmiany `border-width` ani `padding` na tym przycisku. */
/* CALY gradient siedzi teraz na warstwie `.btnglow__ring`, a nie w obramowaniu
   przycisku. Dzieki temu da sie go WYGASZAC przez opacity razem z poswiatami -
   wczesniej kontur byl tlem samego przycisku, wiec nie mial jak przygasnac
   i po zniknieciu poswiat zostawal goly, gruby, kolorowy rant, ktory potem
   znikal skokiem (user 2026-08-03).
   Przycisk tylko ODSLANIA pierscien: obramowanie zostaje 1 px (zero zmiany
   geometrii), traci kolor, a `background-clip:padding-box` sprawia, ze tlo
   przestaje malowac sie pod obramowaniem. 1 px na zewnatrz + 1 px w miejscu
   obramowania = 2 px gradientu na krawedzi. */
.btnglow.is-glowing>.btn{border-color:transparent;background-clip:padding-box}
.btnglow.is-glowing>.btn--ghost{animation:btnglow-kreska 3s linear 1 both}
.btnglow.is-glowing .btnglow__fg{animation:btnglow-spin 3s linear 1 both,btnglow-gasnie 3s linear 1 both}
.btnglow.is-glowing .btnglow__ring{animation:btnglow-spin 3s linear 1 both,btnglow-gasnie 3s linear 1 both}
@media (prefers-reduced-motion:reduce){
 .btnglow.is-glowing>.btn,.btnglow.is-glowing>.btn--ghost,
 .btnglow.is-glowing .btnglow__fg,
 .btnglow.is-glowing .btnglow__ring{animation:none!important}
 .btnglow .btnglow__fg,.btnglow .btnglow__ring{opacity:0!important}}

/* MOBILE: odstep nad trescia hero o POLOWE mniejszy (user 2026-08-03).
   Na 844 px wysokosci `8vh` dawalo 67,5 px pustki miedzy naglowkiem
   a pierwsza linia tekstu. Dolny odstep zostaje bez zmian, bo pod
   trescia jest grafika i to nie uwiera. */
@media (max-width:700px){
  /* Na telefonie hero NIE centruje tresci w pionie. Przy min-height
     rownym wysokosci ekranu centrowanie spychalo pierwsza linijke
     ok. 80 px w dol, a na malym ekranie kazdy piksel nad zgieciem
     jest cenny. Tresc startuje od gory, z krotkim odstepem. */
  /* SELEKTOR MUSI BYC MOCNIEJSZY niz `.hero--aurora`, bo ta regula stoi
     w arkuszu WCZESNIEJ niz definicja hero (motyw dopisywany jest po
     BASE_CSS), a @media nie dodaje wagi. Przy rownej wadze wygrywa
     regula pozniejsza - i przez to caly ten blok byl bezczynny. */
  .hero.hero--aurora{justify-content:flex-start;padding-top:clamp(18px,3vh,36px)}
}

/* header */
.site{position:sticky;top:0;z-index:60;background:var(--header-bg);
  backdrop-filter:saturate(140%) blur(14px);-webkit-backdrop-filter:saturate(140%) blur(14px);
  border-bottom:1px solid var(--header-line);transition:box-shadow .3s,background .3s,border-color .3s}
.site.is-scrolled{box-shadow:0 10px 40px -22px var(--shadow)}
.site__row{display:flex;align-items:center;justify-content:space-between;gap:18px;min-height:66px}
.brand{display:inline-flex;align-items:baseline;font-weight:800;letter-spacing:.01em;font-size:1.22rem}
.brand__mark{display:inline-flex;align-items:center;justify-content:center;color:var(--accent)}
.brand__word{color:var(--ink)}
.nav{display:flex;align-items:center;gap:clamp(6px,1.4vw,22px)}
.nav__link{position:relative;padding:.5em .2em;font-weight:500;color:var(--muted);
  transition:color .2s}
.nav__link::after{content:"";position:absolute;left:.2em;right:.2em;bottom:.15em;height:2px;
  background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .25s ease}
.nav__link:hover,.nav__link.is-active{color:var(--ink)}
.nav__link:hover::after,.nav__link.is-active::after{transform:scaleX(1)}
/* rozwijane menu (Uslugi / Projekty) */
.nav__item{position:relative;display:flex;align-items:center}
.nav__item .nav__link{display:inline-flex;align-items:center}
.nav__chev{width:13px;height:13px;margin-left:.28em;flex:none;transition:transform .2s ease}
.nav__item:hover .nav__chev,.nav__item:focus-within .nav__chev{transform:rotate(180deg)}
.nav__dd{position:absolute;top:100%;left:50%;min-width:250px;padding:8px;z-index:70;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 28px 60px -30px var(--shadow);display:grid;gap:2px;
  opacity:0;visibility:hidden;transform:translate(-50%,12px);
  transition:opacity .18s ease,transform .18s ease,visibility .18s}
.nav__dd::before{content:"";position:absolute;left:0;right:0;top:-12px;height:12px}
.nav__item:hover .nav__dd,.nav__item:focus-within .nav__dd{opacity:1;visibility:visible;transform:translate(-50%,6px)}
.nav__dd-link{display:block;padding:.6em .9em;border-radius:10px;color:var(--ink);
  font-weight:500;font-size:.92rem;transition:background .15s,color .15s}
.nav__dd-link:hover{background:var(--accent-soft);color:var(--accent)}
.site__cta{display:flex;align-items:center;gap:12px}
/* numer telefonu w naglowku: nigdy sie nie lamie i nie zwezaja go sasiedzi */
.site__tel{flex:none}
.site__tel-num{white-space:nowrap}
.langswitch{display:inline-flex;align-items:center;justify-content:center;width:38px;height:34px;
  border:1px solid var(--line);border-radius:8px;font-size:.78rem;font-weight:700;color:var(--muted);
  letter-spacing:.04em;transition:color .2s,border-color .2s}
.langswitch:hover{color:var(--ink);border-color:var(--accent)}
.burger{display:none;width:42px;height:38px;border:1px solid var(--line);border-radius:10px;
  background:transparent;position:relative;cursor:pointer}
.burger span:not(.vh){position:absolute;left:9px;right:9px;height:2px;background:var(--ink);
  border-radius:2px;transition:transform .25s,opacity .2s}
.burger span:nth-child(1){top:12px}.burger span:nth-child(2){top:18px}.burger span:nth-child(3){top:24px}
.site[data-open] .burger span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.site[data-open] .burger span:nth-child(2){opacity:0}
.site[data-open] .burger span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

@media (max-width:900px){
  /* Tlo NIEPRZEZROCZYSTE. Wczesniej bylo var(--header-bg), czyli
     rgba(247,250,255,.78) - przez rozwiniete menu przeswiecalo kolorowe hero
     (gradienty aurora) i tekst tracil kontrast. Pasek naglowka zostaje
     przezroczysty z blurem, ale ROZWINIETY panel menu musi byc kryjacy. */
  .nav{position:absolute;left:0;right:0;top:100%;flex-direction:column;align-items:stretch;
    gap:2px;padding:14px clamp(18px,5vw,40px) 22px;background:var(--panel);
    border-bottom:1px solid var(--header-line);
    transform:translateY(-12px);opacity:0;visibility:hidden;transition:.28s ease;
    box-shadow:0 24px 50px -28px var(--shadow);pointer-events:none}
  .site[data-open] .nav{transform:none;opacity:1;visibility:visible;pointer-events:auto}
  .nav__link{padding:.85em .2em;font-size:1.05rem;border-bottom:1px solid var(--header-line)}
  .nav__link::after{display:none}
  .nav__item{position:static;display:block}
  .nav__item .nav__link{display:flex;align-items:center;width:100%}
  .nav__chev{margin-left:auto}
  /* visibility:INHERIT, nie "visible". Dziecko z visibility:visible ODSLANIA
     sie wewnatrz rodzica z visibility:hidden - przy ZAMKNIETYM menu ten panel
     zostawal klikalny i lapal dotkniecia w hero (niewidzialny obszar
     ~351x266 px nad kafelkami uslug). Zlapane przez usera 2026-07-27. */
  .nav__dd{position:static;opacity:1;visibility:inherit;transform:none;border:0;border-radius:0;
    box-shadow:none;background:none;min-width:0;padding:2px 0 10px 14px;gap:0}
  .nav__dd::before{display:none}
  .nav__dd-link{padding:.55em .2em;color:var(--muted);font-size:.98rem}
  .burger{display:block}
  /* Numer telefonu ZOSTAJE na telefonie. Wczesniej bylo tu
     .site__cta .btn{display:none}, czyli jedyna akcja kontaktowa z naglowka
     znikala dokladnie na urzadzeniu, z ktorego dzwoni sie najlatwiej.
     Przycisk dostaje ciasniejszy padding, zeby zmiescic sie obok logo,
     przelacznika jezyka i burgera. */
  .site__cta .btn{padding:.55em .8em}
}
/* Ponizej 380 px w rzedzie naglowka brakuje miejsca na 11 znakow numeru
   (logo + langswitch + przycisk + burger). Chowamy sam TEKST numeru; link
   dziala dalej, a caly numer czyta czytnik ekranu z aria-label. */
@media (max-width:379px){
  .site__tel-num{display:none}
  .site__tel{padding-inline:.7em}
}

/* sections */
.sec{padding:clamp(56px,8vw,108px) 0}
.sec--page-head{padding-top:clamp(48px,7vw,84px);padding-bottom:clamp(20px,3vw,32px)}
.sec__head{max-width:min(640px,100%);margin-bottom:clamp(28px,4vw,52px)}
.eyebrow{display:inline-flex;align-items:center;gap:.55em;font-size:.8rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent);margin-bottom:1em}
.sec__title{font-size:clamp(1.7rem,1.1rem + 2.4vw,2.7rem);line-height:1.1;letter-spacing:-.02em;
  font-family:var(--display,var(--font))}
.sec__lead{margin-top:.8em;color:var(--muted);font-size:1.08rem;max-width:54ch}

/* generic grids */
.grid{display:grid;gap:clamp(14px,1.6vw,22px)}
.grid--cards{grid-template-columns:1fr}
@media(min-width:600px){.grid--cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.grid--cards{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* Siatka zakresu przy CZTERECH kartach: 3 + 1 zostawialo sierotke w drugim
   rzedzie (LP maja po 4 sekcje, Zscaler ma 6 i wychodzi 3+3). 2x2 jest rowne. */
@media(min-width:1000px){.grid--cards--4{grid-template-columns:repeat(2,minmax(0,1fr))}}
.grid--proj{grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr))}
.grid--posts{grid-template-columns:repeat(auto-fit,minmax(min(100%,270px),1fr))}
.grid--posts-2{grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}

/* service card */
.card{position:relative;display:flex;flex-direction:column;gap:.55em;padding:clamp(20px,2.4vw,30px);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);
  color:var(--ink);overflow:hidden;transition:transform .28s ease,box-shadow .3s ease,border-color .3s ease}
.card__num{font-size:.78rem;font-weight:700;letter-spacing:.1em;color:var(--muted);opacity:.7}
.card__ico{display:inline-flex;align-items:center;justify-content:center;width:46px;height:46px;
  border-radius:12px;color:var(--accent);background:var(--accent-soft);margin:.1em 0 .2em}
.card__ico .ico{width:24px;height:24px}
.card__h{font-size:1.2rem;letter-spacing:-.01em}
.card__p{color:var(--muted);font-size:.98rem}
.card__go{margin-top:auto;display:inline-flex;align-items:center;gap:.4em;font-weight:600;
  color:var(--accent);font-size:.92rem;padding-top:.6em}
.card__go .ico{transition:transform .25s}
.card:hover{transform:translateY(-4px);border-color:var(--accent)}
.card:hover .card__go .ico{transform:translateX(4px)}

/* process steps */
.steps{display:grid;gap:clamp(10px,1.4vw,16px);counter-reset:s}
@media(min-width:760px){.steps{grid-template-columns:repeat(5,1fr)}}
.step{display:flex;gap:14px;align-items:flex-start;padding:clamp(16px,2vw,22px);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px)}
@media(min-width:760px){.step{flex-direction:column}}
.step__n{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex:none;
  border-radius:50%;background:var(--accent);color:var(--on-accent,#fff);font-weight:700}
.step__h{font-size:1.05rem;margin-bottom:.25em}
.step__p{color:var(--muted);font-size:.92rem}

/* process path (journey - scroll down) */
.path{position:relative;max-width:760px;margin-inline:auto;list-style:none;padding:0;
  --path-pad:clamp(20px,3.4vw,40px)}
/* Kreska laczaca kropki. Rysujemy ja PER KROK, nie raz na cala liste.
   Poprzednia wersja miala staly odstep 16px od gory i dolu `.path`, a kropki sa
   wysrodkowane w krokach o ROZNEJ wysokosci, wiec kreska nigdy nie konczyla sie
   na kropce: raz wystawala przed pierwsza i za ostatnia, raz nie dochodzila.
   Teraz pierwszy krok zaczyna kreske dokladnie w srodku swojej kropki
   (top = (wysokosc kroku - jego dolny padding) / 2), a ostatni konczy ja w srodku
   swojej (padding-bottom jest tam zerowy, wiec srodek kropki to rowne 50%).
   Kropka ma position:relative i stoi w DOM za pseudoelementem, wiec zaslania
   kreske soba - widac ja tylko MIEDZY kropkami. */
.path__step::before{content:"";position:absolute;left:19px;top:0;bottom:0;width:2px;
  background:linear-gradient(var(--accent),var(--accent-2));opacity:.35}
.path__step:first-child::before{top:calc((100% - var(--path-pad)) / 2)}
.path__step:last-child::before{bottom:50%}
.path__step{position:relative;display:grid;grid-template-columns:40px 1fr;column-gap:24px;align-items:center;padding:0 0 var(--path-pad)}
.path__step:last-child{padding-bottom:0}
.path__node{position:relative;width:40px;height:40px;border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;font-weight:700;
  background:var(--accent);color:var(--on-accent,#fff);box-shadow:0 0 0 6px var(--accent-soft)}
.path__card{background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);
  padding:clamp(14px,2vw,20px) clamp(16px,2.4vw,24px);transition:transform .25s ease,border-color .25s ease}
.path__card:hover{transform:translateX(3px);border-color:var(--accent)}
.path__h{font-size:1.12rem;letter-spacing:-.01em;margin-bottom:.3em}
.path__p{color:var(--muted);font-size:.97rem}

/* proof */
.proof{display:flex;flex-direction:column;gap:clamp(18px,2.4vw,28px)}
.proof__title{font-size:clamp(1.3rem,1rem + 1.4vw,1.9rem);font-family:var(--display,var(--font));letter-spacing:-.01em}
.proof__list{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.proof__item{display:flex;align-items:center;gap:.6em;padding:.9em 1.1em;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--card-r,14px);font-weight:600;font-size:.98rem}
.proof__dot{width:9px;height:9px;border-radius:50%;background:var(--accent);flex:none;box-shadow:0 0 0 4px var(--accent-soft)}

/* projects */
.proj{display:flex;flex-direction:column;gap:.6em;padding:clamp(22px,2.6vw,30px);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);
  transition:transform .28s,border-color .3s}
.proj:hover{transform:translateY(-4px);border-color:var(--accent)}
.proj__tag{align-self:flex-start;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent);background:var(--accent-soft);padding:.4em .8em;border-radius:999px}
.proj__h{font-size:1.22rem;letter-spacing:-.01em}
.proj__p{color:var(--muted);font-size:.97rem}

/* posts */
.post{display:flex;flex-direction:column;gap:.5em;padding:clamp(20px,2.4vw,28px);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);color:var(--ink);
  transition:transform .28s,border-color .3s}
.post:hover{transform:translateY(-4px);border-color:var(--accent)}
.post__kick{font-size:.75rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--accent)}
.post__h{font-size:1.2rem;letter-spacing:-.01em}
.post__p{color:var(--muted);font-size:.96rem}
.post__go{margin-top:auto;display:inline-flex;align-items:center;gap:.4em;font-weight:600;color:var(--accent);padding-top:.5em}
/* data na karcie indeksu bloga: lista idzie od najnowszych, wiec data musi
   byc widoczna, inaczej kolejnosc jest nieczytelna [user 2026-07-30] */
.lnews__date{margin-right:auto;color:var(--muted);font-weight:500;font-size:.88rem}
.post--mini{min-height:120px;justify-content:center}

/* faq - flat full-width questions (user decision 2026-06-09) */
.faq{display:grid;gap:clamp(18px,2.6vw,30px)}
.faq .sec__head{margin-bottom:0}
.faq__list{display:flex;flex-direction:column;gap:10px}
.faq__item{background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,14px);
  padding:2px 18px;overflow:hidden;transition:border-color .25s}
/* Pytanie FAQ JEST klikalne (<details>), a nie dawalo zadnego sygnalu pod
   kursorem - uwaga z przegladu 2026-07-30. Sam kolor obramowania, bez lift:
   to pozycja listy, nie karta. */
.faq__item:hover{border-color:var(--accent)}
.faq__item summary{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:1.05em 0;font-weight:600;cursor:pointer;list-style:none}
.faq__item summary::-webkit-details-marker{display:none}
.faq__plus{position:relative;width:16px;height:16px;flex:none}
.faq__plus::before,.faq__plus::after{content:"";position:absolute;background:var(--accent);border-radius:2px;
  transition:transform .25s}
.faq__plus::before{left:0;right:0;top:7px;height:2px}
.faq__plus::after{top:0;bottom:0;left:7px;width:2px}
.faq__item[open] .faq__plus::after{transform:scaleY(0)}
.faq__item p{padding:0 0 1.1em;color:var(--muted)}

/* CTA band */
.sec--band{position:relative;overflow:hidden;background:var(--band-bg);padding-block:clamp(36px,5vw,56px)}
.band{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:24px;position:relative;z-index:1}
.band__h{font-size:clamp(1.4rem,1rem + 1.7vw,2.1rem);font-family:var(--display,var(--font));
  letter-spacing:-.01em;color:var(--band-ink,var(--ink));max-width:22ch}
.band__p{margin-top:.5em;color:var(--band-muted,var(--muted));max-width:42ch}
.band .hero__cta{margin-top:0}

/* page head + legal + article
   (page-head celowo BEZ max-width: pelna szerokosc daje .wrap,
   ktorego capu nie wolno nadpisywac - patrz decyzja "na szerokosc headera")

   WPIS BLOGOWY to wyjatek [user 2026-07-30]: "tekst blogu ma byc
   wysrodkowany, nie do lewej". Tekst zostaje wyrownany do lewej, ale CALA
   kolumna czytania jest wysrodkowana - przy 1140 px wrapa i akapicie 80ch
   tresc lezala przy lewej krawedzi, a po prawej zostawal pusty pas.
   860 px to ta sama miara, ktora ma juz .pfx (historia projektu), wiec
   serwis zyskuje jedna szerokosc czytania zamiast dwoch.
   UWAGA: selektor musi byc MOCNIEJSZY niz .wrap (ta sama specyficznosc =
   wygrywa pozniejsza regula, a tego nie chcemy zostawiac przypadkowi). */
.sec--article .article{max-width:min(860px,100%);margin-inline:auto}
/* Powiazane wpisy: ta sama kolumna co tekst + wyrazny odstep, zeby przycisk
   "Zobacz strone tego projektu" nie przyklejal sie do pierwszej karty. */
.article__more{max-width:min(860px,100%);margin-inline:auto;
  margin-top:clamp(34px,5vw,58px);padding-top:clamp(22px,3vw,34px);
  border-top:1px solid var(--line)}
.page-head__h1{font-size:clamp(2rem,1.3rem + 3vw,3.4rem);line-height:1.05;letter-spacing:-.025em;
  font-family:var(--display,var(--font));margin:.2em 0 .35em}
.page-head__lead{color:var(--muted);font-size:1.12rem;max-width:72ch}
.legal{display:grid;gap:22px;max-width:min(760px,100%)}
.legal__b h2{font-size:1.2rem;margin-bottom:.4em}
.legal__b p{color:var(--muted)}
/* CSS sekcji doswiadczen (.exp*) USUNIETY 2026-07-30 razem z sekcja.
   Zapis danych: project/research/doswiadczenia-projektowe-2026-07-28.md */

/* /projekty/ - zrealizowany projekt jako BOHATER strony (wariant B).
   Pelna szerokosc, twarde liczby, dwa wyjscia: strona projektu i wpis na blogu.
   Koncepty schodza nizej do zwyklej siatki kart. */
/* Lista projektow: kazdy jako szeroki blok, naprzemiennie grafika lewo/prawo. */
.sec--hproj{display:grid;gap:clamp(18px,2.6vw,30px)}
.hproj--flip .hproj__media{order:2}
@media(max-width:899px){.hproj--flip .hproj__media{order:0}}
.hproj{display:grid;gap:clamp(20px,3vw,40px);align-items:center;
  background:var(--panel);border:1px solid var(--line);border-radius:calc(var(--card-r,16px) + 6px);
  padding:clamp(20px,3vw,38px);box-shadow:0 26px 60px -44px var(--shadow)}
@media(min-width:900px){.hproj{grid-template-columns:.95fr 1.05fr}}
.hproj__media{background:var(--accent-soft);border-radius:var(--card-r,16px);overflow:hidden;
  display:grid;place-items:center;padding:clamp(10px,1.6vw,18px)}
.hproj__media img{width:100%;height:auto;display:block}
.hproj__copy{display:grid;gap:.7em;align-content:center}
.hproj__h{font-size:clamp(1.5rem,1.1rem + 1.6vw,2.2rem);line-height:1.15;letter-spacing:-.02em;
  font-family:var(--display,var(--font));margin:0}
.hproj__p{color:var(--muted);margin:0;max-width:56ch}
.hproj__stats{display:flex;flex-wrap:wrap;gap:clamp(16px,3vw,34px);margin:.5em 0 .3em;
  padding:.9em 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.hproj__stat{display:grid;gap:.1em}
.hproj__n{font-size:clamp(1.5rem,1.2rem + 1vw,2rem);font-weight:800;line-height:1;
  font-family:var(--display,var(--font));
  background:var(--grad-accent);-webkit-background-clip:text;background-clip:text;color:transparent}
.hproj__l{font-size:.84rem;color:var(--muted);max-width:18ch;line-height:1.35}
.hproj__cta{display:flex;gap:10px;flex-wrap:wrap;margin-top:.3em}

/* 404 - prawdziwa strona bledu (bez auto-przekierowania). Ma dac wyjscie:
   sekcje serwisu + telefon + kontakt. Wysokosc liczona tak, zeby stopka nie
   wjezdzala do gory przy krotkiej tresci. */
.sec--nf{min-height:calc(100svh - 220px);display:grid;align-items:center}
.nf{max-width:760px}
.nf__h1{font-size:clamp(2rem,1.4rem + 2.8vw,3.2rem);line-height:1.06;letter-spacing:-.02em;
  font-family:var(--display,var(--font));margin:.15em 0 .35em;
  background:var(--grad-hero);-webkit-background-clip:text;background-clip:text;color:transparent;
  padding-bottom:.18em;margin-bottom:-.18em}
.nf__lead{color:var(--muted);font-size:1.1rem;max-width:62ch;margin-bottom:1.6em}
.nf__links{list-style:none;display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));
  margin:0 0 1.8em;padding:0}
.nf__link{display:flex;align-items:center;gap:.6em;padding:12px 16px;border:1px solid var(--line);
  border-radius:12px;background:var(--panel);color:var(--ink);font-weight:600}
.nf__link:hover{border-color:var(--accent);color:var(--accent)}
.nf__link .ico{color:var(--accent);flex:none}
.nf__cta{display:flex;gap:12px;flex-wrap:wrap}
/* OKRUSZKI NAWIGACYJNE (Z7). Drobny tekst nad naglowkiem strony: w hero stoja
   nad nadtytulem (wewnatrz kolumny hero, wiec nie zmieniaja jego wysokosci),
   na wpisach i stronach prawnych nad H1. Sciezka jest ta sama, co
   BreadcrumbList w danych strukturalnych.
   PONIZEJ 560 px zwijamy do JEDNEGO POZIOMU WSTECZ (zostaje sam link do
   strony nadrzednej): pelna sciezka z tytulem wpisu brala tam dwie, a bywalo
   ze trzy linie. Cel: :nth-last-child(2) to zawsze ostatni LINK, bo ostatnia
   pozycja listy jest biezaca strona. */
.crumbs{margin:0 0 1.1em}
.crumbs__list{display:flex;flex-wrap:wrap;align-items:center;gap:.45em;
  list-style:none;margin:0;padding:0;font-size:.82rem;line-height:1.45;color:var(--muted)}
.crumbs__i{display:inline-flex;align-items:center;gap:.45em;min-width:0;
  overflow-wrap:break-word;hyphens:none}
.crumbs__i a{color:var(--accent);font-weight:600}
.crumbs__i a:hover{text-decoration:underline}
.crumbs__i--cur span{color:var(--muted)}
.crumbs__sep{color:var(--muted);opacity:.55;flex:none}
@media (max-width:560px){
  .crumbs__list{flex-wrap:nowrap}
  .crumbs__i{display:none}
  .crumbs__i:nth-last-child(2){display:inline-flex}
  .crumbs__i:nth-last-child(2) .crumbs__sep{display:none}
}
.back{display:inline-flex;align-items:center;gap:.5em;color:var(--muted);font-weight:600;font-size:.92rem;margin-bottom:1.4em}
.back .ico{transform:rotate(180deg)}
.back:hover{color:var(--accent)}
.article__h1{font-size:clamp(1.9rem,1.3rem + 2.6vw,3rem);line-height:1.08;letter-spacing:-.02em;
  font-family:var(--display,var(--font));margin:.2em 0 .5em}
.article__lead{font-size:1.18rem;color:var(--ink);margin-bottom:1.4em}
.article__body{display:grid;gap:1.1em;color:var(--muted);font-size:1.06rem}
.article__body p{max-width:80ch}

/* wyliczenia w tresci: prawdziwa lista, zamiast akapitow z kreska na poczatku */
.artlist{display:grid;gap:.55em;max-width:80ch;margin:0;padding:0;list-style:none}
.artlist li{position:relative;padding-left:1.35em}
.artlist li::before{content:"";position:absolute;left:.15em;top:.62em;width:7px;height:7px;
  border-radius:50%;background:var(--accent-2)}

/* contact */
.contact{display:grid;gap:clamp(22px,3vw,40px)}
@media(min-width:860px){.contact{grid-template-columns:1.2fr .8fr;align-items:start}}
.form{display:grid;gap:16px;padding:clamp(22px,3vw,34px);background:var(--panel);
  border:1px solid var(--line);border-radius:calc(var(--card-r,16px) + 4px)}
.field{display:grid;gap:.4em}
.field label{font-weight:600;font-size:.92rem}
.field input,.field textarea{width:100%;padding:.8em 1em;background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--field-r,var(--btn-r,10px));font:inherit;transition:border-color .2s,box-shadow .2s}
.field textarea{resize:vertical;min-height:120px}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
/* Pole z bledem [user 2026-08-04]: samo obramowanie, bez dokladania
   elementow - komunikat idzie do istniejacej linijki pod przyciskiem,
   ktora ma zarezerwowana wysokosc, wiec nic sie nie przesuwa. */
.field input.is-invalid,.field textarea.is-invalid{border-color:var(--err)}
.field input.is-invalid:focus,.field textarea.is-invalid:focus{border-color:var(--err);box-shadow:0 0 0 4px rgba(220,38,38,.14)}
/* Klauzula informacyjna RODO pod formularzem: ma byc czytelna, ale nie moze
   konkurowac z polami. Drobny druk, ktory da sie przeczytac. */
.form__rodo{font-size:.78rem;line-height:1.5;color:var(--muted);
  margin-top:.4em;max-width:68ch}
.form__rodo a{color:var(--accent);text-decoration:underline}
/* Linijka komunikatu ma ZAREZERWOWANA wysokosc jednego wiersza. Bez tego
   pusty <p> ma 0 px i pierwszy komunikat przesuwa wszystko pod formularzem
   o ~22 px (zasada NO-JUMP). Dluzszy komunikat, ktory zawinie sie na dwa
   wiersze, urosnie o jeden - i to jest akceptowalne, bo doklada w dol. */
.form__note{font-size:.86rem;color:var(--muted);min-height:1.6em}
.form__note.is-sent{color:var(--accent);font-weight:600}
.form__note.is-error{color:var(--err);font-weight:600}
/* Gwiazdka pola wymaganego. aria-hidden, bo czytnik ekranu i tak
   ogloszy pole jako wymagane z atrybutu required - inaczej uslyszalby
   "gwiazdka" jako tresc etykiety. */
.req{color:var(--err);font-weight:700;margin-left:.18em}
/* POTWIERDZENIE WYSYLKI (zasada NO-JUMP, user 2026-06-11 i ponownie 2026-08-02).
   Wczesniej po udanej wysylce pola dostawaly .is-hidden i formularz znikal,
   przez co strona zwijala sie o 590-900 px. Teraz formularz ZOSTAJE z wpisana
   trescia, tylko wygaszony i zablokowany, a NAD polami DOKLADA sie ten panel.
   Kontener jest pusty w markupie (:empty = display:none), a JS wstawia do niego
   tresc z <template>. Dzieki temu zmiana tresci zachodzi w zywym regionie
   role="status" aria-live="polite" i czytnik ekranu na pewno ja przeczyta
   (odslanianie gotowego, ukrytego regionu bywa pomijane).
   UWAGA: kontener musi byc renderowany BEZ bialych znakow w srodku, inaczej
   :empty przestaje dzialac i pusty panel widac na stronie. */
.form__done{padding:clamp(16px,2.2vw,22px);background:var(--accent-soft);
  border:1px solid var(--line);border-radius:var(--card-r,16px);display:grid;gap:.5em}
.form__done:empty{display:none}
.form__done-h{margin:0;font-weight:700;color:var(--ink);font-size:1.05rem;line-height:1.35}
.form__done-p{margin:0;color:var(--muted);line-height:1.6;font-size:.95rem}
.form__done-p a{color:var(--accent);font-weight:700;white-space:nowrap}
/* Wygaszone pola po wysylce: widoczne, nieaktywne, o tej samej wysokosci.
   Nie uzywamy display:none, bo to wlasnie ono powodowalo skakanie strony. */
.form.is-sent .field,.form.is-sent .cf-turnstile,.form.is-sent button[type="submit"],
.qlead.is-sent .qlead__step,.qlead.is-sent .cf-turnstile,.qlead.is-sent button[type="submit"]{opacity:.55}
.form.is-sent button[type="submit"],.qlead.is-sent button[type="submit"]{cursor:not-allowed}
.contact__side{padding:clamp(22px,3vw,34px);background:var(--accent-soft);border:1px solid var(--line);
  border-radius:calc(var(--card-r,16px) + 4px)}
.contact__side h2{font-size:1.3rem;margin-bottom:.4em}
.contact__list{display:grid;gap:.6em;margin:1.1em 0}
.contact__list li{display:flex;align-items:center;gap:.6em;color:var(--ink);font-size:.96rem}
.contact__list .ico{color:var(--accent)}
.contact__confirm{font-size:.84rem;color:var(--muted);border-top:1px solid var(--line);padding-top:1em}

/* hero shared bits */
.hero{position:relative;overflow:hidden}
.hero__copy,.hero__stage,.hero__inner,.hero__grid>*{min-width:0}
.sec__title,.page-head__h1,.article__h1,.proof__title,.band__h{overflow-wrap:break-word}
/* H1 hero: nigdy nie lamiemy slowa w srodku; wiersze balansujemy. Dopasowanie
   rozmiaru do dlugich slow robi .hero__h1--tight (nadawane automatycznie). */
.hero__h1{overflow-wrap:normal;hyphens:none;text-wrap:balance}
.hero__cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:1.6em}
.hero__proof{display:flex;flex-wrap:wrap;gap:.5em 1.4em;margin-top:1.8em}
.hero__proof li{display:inline-flex;align-items:center;gap:.5em;color:var(--muted);font-size:.92rem;font-weight:500}
.hero__proof .ico{color:var(--accent);width:1.05em;height:1.05em}

/* footer */
.foot{background:var(--foot-bg);border-top:1px solid var(--line);color:var(--foot-ink,var(--ink))}
.foot__grid{display:grid;gap:clamp(26px,4vw,48px);padding:clamp(44px,6vw,72px) 0 clamp(28px,3vw,40px)}
@media(min-width:780px){.foot__grid{grid-template-columns:1.4fr .8fr 1fr}}
.foot__tag{color:var(--muted);margin-top:1em;max-width:36ch}
.foot__note{color:var(--muted);opacity:.8;font-size:.84rem;margin-top:1em;max-width:40ch}
.foot__h{font-size:.82rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:1em}
.foot__nav ul{display:grid;gap:.6em}
.foot__nav a{color:var(--foot-ink,var(--ink));opacity:.85}
.foot__nav a:hover{opacity:1;color:var(--accent)}
.foot__cta p{color:var(--muted);margin-bottom:1.2em;max-width:34ch}
.foot__bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;
  padding:18px 0 28px;border-top:1px solid var(--line);font-size:.85rem;color:var(--muted)}
@media(max-width:600px){.foot .wrap{padding-inline:30px}}
.foot__demo{opacity:.8}
.foot__by a{color:var(--accent);font-weight:600}
.foot__by a:hover{text-decoration:underline}
.foot__contact{display:grid;gap:.55em;margin-top:1.1em;list-style:none;padding:0}
.foot__contact li{display:flex;align-items:center;gap:.6em;color:var(--muted);font-size:.92rem}
.foot__contact a{color:var(--foot-ink,var(--ink))}
.foot__contact a:hover{color:var(--accent)}
.foot__contact .ico{color:var(--accent);flex:none;width:1.1em;height:1.1em}
.contact__real{display:grid;gap:.7em;margin:1.1em 0;list-style:none;padding:0}
.contact__real li{display:flex;align-items:center;gap:.6em;font-size:.98rem}
.contact__real a{color:var(--ink);font-weight:500}
.contact__real a:hover{color:var(--accent)}
.contact__real .ico{color:var(--accent);flex:none}
.brand--foot{font-size:1.3rem}
.brand__logo{height:44px;width:auto;display:block}
.brand--head{align-items:center}
.brand__logo--head{height:34px}

/* data wpisu (rok i miesiac) pod leadem artykulu */
.article__date{margin:.6em 0 0;color:var(--muted);font-size:.92rem;letter-spacing:.02em}

/* datowane sprostowanie NAD trescia wpisu - patrz POST_UPDATES.
   PIONOWY PASEK PO LEWEJ ZOSTAL ZDJETY [user 2026-07-30]: "wyglada jak AI,
   wszyscy wiedza, ze tego typu rzeczy robi AI". NIE PRZYWRACAC.
   Wybrany wariant: /pl/lab6/ nr 3 "karta-biala" [user 2026-07-30] - panel na
   BIALYM tle z obwodka i zaokragleniem, etykieta drobnym drukiem u gory.
   Bialy panel odcina sie od tla strony sam, bez pomocy kreski. */
.artupd{margin:2em 0 0;padding:clamp(20px,2.6vw,28px);background:var(--panel);
  border:1px solid var(--line);border-radius:16px}
.artupd__head{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin:0 0 .8em}
.artupd__tag{font-size:12.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--accent)}
.artupd__date{font-size:.9rem;color:var(--muted)}
.artupd__body p{margin:0 0 .7em;color:var(--ink);font-size:1rem;line-height:1.62;max-width:72ch}
.artupd__body p:last-child{margin-bottom:0}

/* terminy z lacznikiem (Wi-Fi) nie moga sie lamac w srodku - patrz nb() */
.nb{white-space:nowrap}

/* Zamkniecie podstrony projektu. Wczesniej byl tu SAM przycisk w zwyklej
   .sec (56-108 px paddingu gora i dol, nic wiecej) - wygladal jak zgubiony
   w pustym pasie (uwaga usera 2026-07-29). Teraz: polowa paddingu, kreska
   spinajaca z trescia powyzej i zdanie, ktore daje przyciskowi powod. */
/* Zamkniecie podstrony projektu: SAME przyciski, do lewej, na szarym pasie.
   User 2026-07-29: zdanie "Prowadzimy to rowniez jako stala usluge" i rzad
   rozstrzelony na boki nie byly "clean" - zostaja same wyjscia. */
.sec--projx{padding:clamp(26px,4vw,44px) 0;background:var(--accent-soft)}
/* Przyciski w szarym pasie sa WYSRODKOWANE [user 2026-08-03]. Wczesniej
   staly do lewej i przy jednym albo dwoch przyciskach wygladalo to jak
   niedokonczony rzad. Dotyczy wszystkich pasow tego typu: powiazane LP,
   pas LP pod usluga i zamkniecie podstrony projektu. */
.projx{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:clamp(12px,2vw,20px)}
.projx .hero__cta{justify-content:center}
.projx .hero__cta{margin-top:0}

/* centered section head */
.sec__head--center{text-align:center;margin-inline:auto}
.sec__head--center .sec__lead{margin-inline:auto}
.sec__head--center .hero__cta{justify-content:center}

/* partners / certs marquee */
.partners{overflow:hidden}
.partners__viewport{position:relative;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.partners__track{display:flex;align-items:center;gap:clamp(30px,5vw,72px);width:max-content;
  animation:c4pl-partners-marquee 70s linear infinite}
.partners:hover .partners__track{animation-play-state:paused}
.partner{flex:0 0 auto;display:flex;align-items:center;justify-content:center}
.partner img{height:40px;width:auto;opacity:.82;filter:grayscale(35%);transition:opacity .25s,filter .25s}
.partner img:hover{opacity:1;filter:none}
@keyframes c4pl-partners-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .partners__track{animation:none;flex-wrap:wrap;justify-content:center;width:auto;row-gap:18px}
}

/* news cards with photos */
.lnews{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:1fr}
@media(min-width:640px){.lnews{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.lnews{grid-template-columns:repeat(3,minmax(0,1fr))}}
.lnews__card{display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--card-r,16px);overflow:hidden;color:var(--ink);
  transition:transform .28s ease,border-color .3s ease,box-shadow .3s ease}
.lnews__card:hover{transform:translateY(-4px);border-color:var(--accent);
  box-shadow:0 24px 50px -38px var(--shadow)}
.lnews__media{display:block;aspect-ratio:16/9;overflow:hidden}
.lnews__media img{width:100%;height:100%;object-fit:cover;transition:transform .4s ease}
.lnews__card:hover .lnews__media img{transform:scale(1.04)}
.lnews__body{display:flex;flex-direction:column;gap:.5em;padding:clamp(16px,2vw,22px);flex:1}
.lnews__body .post__go{margin-top:auto;padding-top:.6em}
.lnews__more{margin-top:clamp(20px,3vw,32px);text-align:center}
.lnews__card--static{cursor:default}
.lnews__card--static:hover{transform:none;border-color:var(--line);box-shadow:none}
.lnews__card--static:hover .lnews__media img{transform:none}

/* project cards ("Projekty i koncepty wdrożeń"): identical media box for photo + SVG art */
.lnews__media--proj{aspect-ratio:16/10;background:var(--accent-soft)}
.lnews__media--art img{object-fit:contain;padding:clamp(10px,2vw,18px)}
.lnews__card:hover .lnews__media--art img{transform:scale(1.02)}

/* linked project card */
.proj--link .post__go{margin-top:.4em}

/* quick-lead form pattern (LP) */
.sec--qlead{background:var(--accent-soft)}
.qlead{max-width:760px;margin-inline:auto;display:grid;gap:clamp(14px,2vw,22px)}
.qlead__hp{position:absolute!important;left:-9999px;width:1px;height:1px;opacity:0}
/* STANDARD f1 "spokojna karta, wszystko od razu" (user 2026-06-11) + ZASADA
   NO-JUMP: wszystkie kroki sa widoczne od poczatku. Wczesniej .qlead__step
   mial display:none i odslanial sie po kliknieciu chipa - to jest DOKLADNIE
   ten wzorzec zwijanych krokow, ktory user odrzucil ("zwijanie krokow =
   skakanie strony"). Nie przywracac. .is-active zostaje jako no-op dla
   zgodnosci ze starym HTML. */
/* JEDNA KARTA, nie trzy [user 2026-07-30: "formularz totalnie do dupy, zle
   wyglada"]. Kazdy krok byl osobnym OBRAMOWANYM <fieldset>, a <legend> siada
   natywnie NA KRAWEDZI ramki - stad numerek wchodzacy w obramowanie i trzy
   rozbite pudelka zamiast formularza. Teraz karta jest jedna (.qlead), a kroki
   sa zwyklymi blokami rozdzielonymi kreska. Markup i selektory JS bez zmian. */
.qlead{border:1px solid var(--line);border-radius:calc(var(--card-r,16px) + 4px);
  background:var(--panel);padding:clamp(22px,3vw,34px);
  display:grid;gap:clamp(16px,2.2vw,24px);max-width:760px;margin-inline:auto}
.qlead__step{display:block;border:0;background:none;padding:0;margin:0;min-inline-size:0}
.qlead__step + .qlead__step{border-top:1px solid var(--line);padding-top:clamp(16px,2.2vw,24px)}
.qlead__step legend{display:flex;align-items:center;gap:.6em;font-weight:700;font-size:1.02rem;
  padding:0;margin:0;float:left;width:100%}
.qlead__step legend + *{clear:both}
/* linijka telefoniczna NAD karta - czesc wybranego standardu f1 */
.qlead__call{max-width:760px;margin:0 auto .9em;text-align:right;color:var(--muted);font-size:.95rem}
.qlead__call a{color:var(--accent);font-weight:700;white-space:nowrap}
.qlead__n{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;flex:none;
  border-radius:50%;background:var(--accent);color:#fff;font-size:.9rem}
.qlead__chips{display:flex;flex-wrap:wrap;gap:10px;margin-top:1em}
.qlead__chip{padding:.7em 1.2em;border:1.5px solid var(--line);border-radius:999px;background:var(--bg);
  font-weight:600;cursor:pointer;transition:border-color .2s,background .2s,color .2s}
.qlead__chip:hover{border-color:var(--accent)}
.qlead__chip.is-on{background:var(--accent);border-color:var(--accent);color:#fff}
.qlead__fields{display:grid;gap:14px;margin:1em 0 1.2em}
@media(min-width:640px){.qlead__fields{grid-template-columns:repeat(2,minmax(0,1fr))}}
.qlead .cf-turnstile{margin-bottom:1em}
.is-hidden{display:none!important}

/* interleaved project story (zigzag text/graphics) */
.pstories{display:grid;gap:clamp(36px,5vw,72px);margin:clamp(32px,5vw,56px) 0}
.pstory{display:grid;gap:clamp(20px,3vw,44px);align-items:center;grid-template-columns:1fr;min-width:0}
@media(min-width:880px){
  .pstory{grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr)}
  .pstory--flip .pstory__art{order:2}
  .pstory--flip .pstory__txt{order:1}
}
.pstory__art{margin:0}
.pstory__art img{width:100%;height:auto;border-radius:var(--card-r,20px);
  box-shadow:0 30px 60px -42px var(--shadow)}
.pstory__txt h2{font-size:clamp(1.4rem,1.1rem + 1.3vw,1.9rem);letter-spacing:-.015em;
  margin-bottom:.6em;font-family:var(--display,var(--font))}
.pstory__txt p{color:var(--muted);margin-bottom:.8em;max-width:62ch}
.pstory__txt p:last-child{margin-bottom:0}
.pfx{max-width:860px;margin-inline:auto;text-align:left}
.pfx .sec__title{margin-bottom:.8em}
.pfx .pstats{margin:0 0 1.4em}
.pfx .article__xref{margin-top:1.6em}

/* project story stats */
.pstats{display:grid;gap:clamp(12px,1.6vw,20px);grid-template-columns:1fr;margin:1.8em 0}
@media(min-width:640px){.pstats{grid-template-columns:repeat(3,minmax(0,1fr))}}
.pstat{display:flex;flex-direction:column;gap:.2em;padding:clamp(16px,2vw,24px);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);text-align:center}
.pstat__n{font-size:clamp(2rem,1.4rem + 2vw,3rem);font-weight:800;letter-spacing:-.02em;
  background:var(--grad-hero);-webkit-background-clip:text;background-clip:text;color:transparent}
.pstat__l{color:var(--muted);font-size:.95rem}
.article__xref{margin-top:1.6em}
.article--project .article__media--svg{border:0;background:transparent}

/* article extras */
.article__media{margin:1.6em 0;border-radius:var(--card-r,16px);overflow:hidden;border:1px solid var(--line)}
.article__media img{width:100%;height:auto}
.article__results{display:grid;gap:.6em;margin:1em 0 0;padding:0;list-style:none}
.article__results li{display:flex;align-items:flex-start;gap:.6em}
.article__results .ico{color:var(--accent);flex:none;margin-top:.2em}

/* expandable service panels (/uslugi) */
.svcx{background:var(--panel);border:1px solid var(--line);border-radius:var(--card-r,16px);
  overflow:hidden;scroll-margin-top:90px;transition:border-color .25s}
.svcx[open]{border-color:var(--accent)}
.svcx summary{display:flex;align-items:center;gap:16px;padding:clamp(16px,2.2vw,24px);
  cursor:pointer;list-style:none}
.svcx summary::-webkit-details-marker{display:none}
.svcx__head{display:flex;flex-direction:column;gap:.15em;min-width:0;flex:1}
.svcx__head strong{font-size:1.15rem;letter-spacing:-.01em}
.svcx__head small{color:var(--muted);font-size:.95rem}
.svcx .faq__plus{flex:none}
.svcx__grid{display:grid;gap:12px;padding:0 clamp(16px,2.2vw,24px) clamp(18px,2.4vw,26px)}
@media(min-width:680px){.svcx__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1020px){.svcx__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.svcx__item{display:flex;flex-direction:column;gap:.25em;padding:.9em 1.05em;
  background:var(--bg);border:1px solid var(--line);border-radius:12px;
  transition:transform .25s,border-color .25s,box-shadow .25s}
/* Kafle zakresu NIE sa linkami, wiec ich reakcja na kursor jest CELOWO
   slabsza niz .card (unosi sie o 2 px zamiast 4 i nie zmienia koloru tekstu).
   Rownoczesnie strona przestaje sprawiac wrazenie martwej - to byla uwaga
   z przegladu 2026-07-30. Pelny lift + strzalka zostaja zarezerwowane dla
   elementow, w ktore naprawde da sie kliknac. */
.svcx__item:hover{transform:translateY(-2px);border-color:var(--accent);
  box-shadow:0 16px 34px -30px var(--shadow)}
.svcx__item strong{font-size:.99rem}
.svcx__item span{color:var(--muted);font-size:.9rem;line-height:1.5}
.svcx__grid--page{display:grid;gap:14px;padding:0}
@media(min-width:680px){.svcx__grid--page{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1020px){.svcx__grid--page{grid-template-columns:repeat(3,minmax(0,1fr))}}
.svcx__grid--page .svcx__item{background:var(--panel);padding:1.1em 1.2em}

/* service detail blocks */
.sec--svc .wrap{display:grid;gap:clamp(18px,2.4vw,28px)}
.svc{display:grid;gap:14px;padding:clamp(20px,2.6vw,30px);background:var(--panel);
  border:1px solid var(--line);border-radius:var(--card-r,16px);scroll-margin-top:90px}
.svc__head{display:flex;gap:14px;align-items:flex-start}
.svc__h{font-size:clamp(1.2rem,1rem + .9vw,1.6rem);letter-spacing:-.01em}
.svc__short{color:var(--accent);font-weight:600;margin-top:.2em}
.svc__body{color:var(--muted);display:grid;gap:.8em}
.svc__body p{max-width:75ch}
/* clickable cloud banner on /uslugi/ - reuses .card for hover/transition,
   overridden to a horizontal icon+copy layout with its own soft background */
a.svc-cloud.card{flex-direction:row;align-items:flex-start;gap:14px;
  padding:clamp(20px,2.6vw,30px);background:var(--accent-soft)}
.svc-cloud__body{display:flex;flex-direction:column;gap:.3em;min-width:0}
.svc-cloud__body .card__p{color:var(--ink);max-width:75ch}
.svc-cloud__body .card__go{padding-top:.5em}
@media(max-width:560px){a.svc-cloud.card{flex-direction:column}}

/* team certifications */
/* `.sec--teamline{padding-top:0}` USUNIETE 2026-09-02 razem z linijka o
   zsumowanym stazu zespolu, ktora byla jedynym powodem zerowego odstepu.
   Sekcja referencji ma dzis zwykly padding sekcji, jak kazda inna na tej
   stronie. NIE przywracac zerowego paddingu bez elementu, ktory go uzasadnia. */
/* Kolumna czytania wysrodkowana - ta sama miara co wpis na blogu (860 px).
   `.wrap` ma `max-width:var(--maxw,1140px)` i `padding-inline` do 40 px,
   wiec 940 px daje rowno 860 px tresci. Tekst zostaje wyrownany do lewej,
   srodkuje sie sama kolumna. Uzywane na stronie "o firmie", ktora jest
   prawie samym tekstem; sekcje z siatka kart i logotypami zostaja szerokie. */
.sec--mid .wrap{--maxw:940px}
/* Styl haslowy `.teamline` (2rem, waga 700, gradient przez caly tekst, 34ch)
   ubyl razem ze zdaniem o zsumowanym stazu zespolu, ktore bylo jego jedynym
   uzyciem w calym serwisie (2026-09-02). Gdyby wrocila jednozdaniowa linia
   haslowa, regule odtwarza sie z historii gita. */
.certs{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:1fr}
@media(min-width:680px){.certs{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.certs{grid-template-columns:repeat(3,minmax(0,1fr))}}
.cert{display:flex;gap:16px;align-items:center;padding:clamp(16px,2vw,22px);background:var(--panel);
  border:1px solid var(--line);border-radius:var(--card-r,16px);color:var(--ink);
  transition:transform .28s ease,border-color .3s ease,box-shadow .3s ease;
  animation:c4pl-cert-float 7s ease-in-out infinite;animation-delay:calc(var(--i,0)*1.3s)}
.cert:hover{transform:translateY(-4px);border-color:var(--accent);box-shadow:0 24px 50px -38px var(--shadow);animation-play-state:paused}
.cert__media{flex:none;width:86px;height:86px;display:flex;align-items:center;justify-content:center}
.cert__media img{width:86px;height:86px;object-fit:contain}
.cert--wide .cert__media{width:132px}
.cert--wide .cert__media img{width:132px;height:74px;padding:4px;object-fit:contain;background:#fff;
  border:1px solid var(--line);border-radius:10px;box-shadow:0 14px 32px -28px var(--shadow)}
.cert__ico{display:inline-flex;align-items:center;justify-content:center;width:64px;height:64px;
  border-radius:50%;background:var(--accent-soft);color:var(--accent)}
.cert__ico .ico{width:30px;height:30px}
.cert__body{display:flex;flex-direction:column;gap:.2em}
.cert__body strong{font-size:1.02rem;letter-spacing:-.01em}
.cert__body span{color:var(--muted);font-size:.92rem}
.cert__body small{color:var(--muted);opacity:.8}
@media(max-width:520px){
  .cert{align-items:flex-start}
  .cert--wide{flex-direction:column}
  .cert--wide .cert__media{width:100%;height:auto;justify-content:flex-start}
  .cert--wide .cert__media img{width:min(100%,250px);height:auto;max-height:132px}
}
@keyframes c4pl-cert-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
@media (prefers-reduced-motion:reduce){.cert{animation:none}}

/* reveal: EFEKT ZDJETY [user 2026-07-30]
   "to, ze te strony laduja sie dopiero po scrollowaniu, jest dziwne, bo dziala
   to wolno (...) mialem kilka razy sytuacje, ze musze naprawde nisko zjechac,
   zeby mi sie zaladowalo".
   Tresc byla ukryta (opacity:0) do momentu, gdy IntersectionObserver dolozyl
   klase .is-in, plus opoznienie do 55 ms na element (--i). Efekt uboczny:
   przy dluzszej stronie czytelnik widzial pustke i mial wrazenie wolnego
   ladowania, a gdy obserwator nie zdazyl, tresc nie pojawiala sie wcale.
   Klasa .reveal zostaje w markupie (jest w kilkunastu generatorach), ale NIC
   NIE UKRYWA. NIE PRZYWRACAC opacity:0 bez decyzji usera. */
.reveal{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .btn:hover,.card:hover,.proj:hover,.post:hover,.svcx__item:hover{transform:none}
  *{animation-duration:.001ms!important;animation-iteration-count:1!important}
}


/* --- rozwijany przelacznik jezyka ------------------------------------- */
.langsel{position:relative;display:flex;align-items:center}
.langsel__btn{display:inline-flex;align-items:center;gap:.34em;height:34px;padding:0 .5em 0 .55em;
  border:1px solid var(--line);border-radius:8px;background:transparent;color:var(--muted);
  font:700 .78rem/1 inherit;letter-spacing:.04em;cursor:pointer;
  transition:color .18s ease,border-color .18s ease,background .18s ease}
.langsel__btn:hover{color:var(--ink);border-color:var(--accent)}
.langsel__btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.langsel__globe{width:15px;height:15px;flex:none;opacity:.85}
.langsel__chev{width:12px;height:12px;flex:none;transition:transform .2s ease}
.langsel__cur{line-height:1}

.langsel__dd{position:absolute;top:100%;right:0;min-width:186px;padding:8px;z-index:70;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 28px 60px -30px var(--shadow);
  opacity:0;visibility:hidden;transform:translateY(0);
  transition:opacity .18s ease,transform .18s ease,visibility .18s}
/* niewidzialny mostek, zeby kursor nie gubil menu w drodze w dol */
.langsel__dd::before{content:"";position:absolute;left:0;right:0;top:-10px;height:10px}

.langsel:hover .langsel__dd,
.langsel:focus-within .langsel__dd,
.langsel.is-open .langsel__dd{opacity:1;visibility:visible;transform:translateY(6px)}
.langsel:hover .langsel__chev,
.langsel:focus-within .langsel__chev,
.langsel.is-open .langsel__chev{transform:rotate(180deg)}

.langsel__link{display:flex;align-items:center;gap:.6em;padding:.55em .7em;border-radius:10px;
  color:var(--ink);font-weight:500;font-size:.92rem;
  transition:background .15s ease,color .15s ease}
.langsel__link:hover{background:var(--accent-soft);color:var(--accent)}
.langsel__code{display:inline-flex;align-items:center;justify-content:center;min-width:30px;
  padding:.16em .3em;border-radius:6px;background:var(--accent-soft);color:var(--accent);
  font:700 .72rem/1 inherit;letter-spacing:.04em;flex:none}
.langsel__link.is-cur{color:var(--muted);cursor:default}
.langsel__link.is-cur .langsel__code{background:var(--line);color:var(--muted)}
.langsel__link.is-cur:hover{background:transparent;color:var(--muted)}

/* Panel nie moze wyjsc poza ekran. UWAGA na pulapke: przycisk jezyka NIE stoi
   przy prawej krawedzi, tylko jest pierwszy w grupie .site__cta (jezyk, telefon,
   przycisk). Ponizej ok. 700 px ta grupa wedruje w lewo, wiec panel kotwiczony
   prawa krawedzia (right:0) wyjezdzal poza ekran o kilkadziesiat pikseli
   (zmierzone: -56 px przy 390 px). Pierwszy pomiar tego nie zlapal, bo przy
   360 px uklad naglowka jest inny i panel akurat sie miescil.
   Dlatego w tym pasmie panel otwiera sie W PRAWO od przycisku. */
@media (max-width:700px){
  .langsel__dd{left:0;right:auto}
}
@media (max-width:520px){
  .langsel__btn .langsel__cur{display:none}
  .langsel__btn{padding:0 .4em}
  .langsel__dd{min-width:170px}
}


:root{
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --maxw:1160px;
  --bg:#f3f7ff;--panel:#ffffff;--ink:#0b1430;--muted:#56638a;--line:#dde7fb;--err:#dc2626;
  --accent:#2563eb;--accent-2:#06b6d4;--accent-soft:#e7efff;--on-accent:#fff;
  --header-bg:rgba(247,250,255,.78);--header-line:#dde7fb;--shadow:rgba(20,40,90,.45);
  --band-bg:linear-gradient(120deg,#0b1430,#15306b 60%,#0e2a66);--band-line:transparent;
  --band-ink:#fff;--band-muted:#bcccf2;
  --foot-bg:#f7faff;--foot-ink:#0b1430;--input-bg:#fbfdff;--btn-r:999px;--field-r:12px;--card-r:20px;
  /* Gradient tokens - kanoniczne wzorce marki, uzywaj ich zamiast literalow */
  --grad-hero:linear-gradient(120deg,#0b1430 12%,#2563eb 58%,#06b6d4);
  --grad-accent:linear-gradient(120deg,var(--accent),var(--accent-2));
}
body{background:
  radial-gradient(1100px 620px at 82% -8%,#dbe7ff 0,transparent 60%),
  radial-gradient(900px 560px at -6% 8%,#e4f7ff 0,transparent 55%),var(--bg)}
.brand__mark{filter:drop-shadow(0 2px 6px rgba(37,99,235,.35))}
.btn--primary{background:var(--grad-accent);color:#fff;
  box-shadow:0 12px 30px -12px rgba(37,99,235,.6)}
.btn--primary:hover{box-shadow:0 18px 40px -14px rgba(37,99,235,.7)}
.btn--ghost{background:#fff;border-color:var(--line);color:var(--ink);box-shadow:0 6px 18px -12px var(--shadow)}
.btn--ghost:hover{border-color:var(--accent);color:var(--accent)}

.hero--aurora{position:relative;display:flex;flex-direction:column;justify-content:center;
  min-height:calc(100vh - 66px);min-height:calc(100svh - 66px);
  padding:clamp(56px,8vh,110px) 0 clamp(76px,9vh,120px)}
.hero--aurora .hero__grid{width:100%}
.hero__scroll{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);display:inline-flex;
  flex-direction:column;align-items:center;gap:9px;color:var(--muted);font-size:.68rem;font-weight:700;
  letter-spacing:.22em;text-transform:uppercase;z-index:2}
.hero__scroll:hover{color:var(--accent)}
.hero__scroll i{width:16px;height:16px;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);
  transform:rotate(45deg);animation:c4pl-bob 1.8s ease-in-out infinite}
@keyframes c4pl-bob{0%,100%{transform:rotate(45deg) translate(-2px,-2px)}50%{transform:rotate(45deg) translate(3px,3px)}}
@media (prefers-reduced-motion:reduce){.hero__scroll i{animation:none}}
@media (max-width:560px){.hero__scroll{display:none}}
.aurora{position:absolute;inset:0;z-index:0;filter:blur(60px);opacity:.85;pointer-events:none}
.blob{position:absolute;width:46vw;max-width:620px;aspect-ratio:1;border-radius:50%;mix-blend-mode:multiply;
  animation:drift 22s ease-in-out infinite}
.b1{top:-8%;left:-4%;background:radial-gradient(circle,#7aa6ff,transparent 66%)}
.b2{top:6%;right:-6%;background:radial-gradient(circle,#67e8f9,transparent 66%);animation-delay:-7s}
.b3{bottom:-22%;left:32%;background:radial-gradient(circle,#2a4fd0,transparent 66%);animation-delay:-13s}
@keyframes drift{0%,100%{transform:translate3d(0,0,0) scale(1)}
  33%{transform:translate3d(3%,4%,0) scale(1.08)}66%{transform:translate3d(-3%,-2%,0) scale(.96)}}
.hero__grid{position:relative;z-index:1;display:grid;gap:clamp(30px,4vw,56px);align-items:center}
@media(min-width:920px){.hero__grid{grid-template-columns:1.05fr .95fr}}
.hero--aurora .hero__h1{font-size:clamp(2.6rem,1.5rem + 5.4vw,4.8rem);line-height:1.02;letter-spacing:-.035em;
  background:var(--grad-hero);-webkit-background-clip:text;
  background-clip:text;color:transparent;padding-bottom:.18em;margin-bottom:-.18em}
/* Dlugie slowo w H1: rozmiar liczony od szerokosci KOLUMNY (cqi), nie viewportu -
   kolumna hero zweza sie skokowo przy gridzie 2-kolumnowym (>=920px). */
.hero--aurora .hero__copy{container-type:inline-size}
.hero--aurora .hero__h1--tight{font-size:clamp(2.15rem,1.2rem + 4.6vw,4.2rem)}
@supports (font-size:1cqi){.hero--aurora .hero__h1--tight{font-size:clamp(2.1rem,11.3cqi,4.2rem)}}
.hero--aurora .hero__lead{font-size:clamp(1.05rem,1rem + .5vw,1.3rem);color:var(--muted);margin-top:.9em;max-width:36ch}
.hero__stage{position:relative;perspective:1200px}
/* TABLET: hero jest jednokolumnowy dopiero ponizej 920 px, wiec "ruchomy
   obiekt" (szklana karta z kafelkami, logotypy na LP, animacje) rozciagal sie
   na cala szerokosc kolumny - przy 768 px to bylo 676 px szerokosci przy
   216 px wysokosci, czyli plaski pas przez caly ekran (uwaga usera
   2026-07-27). Zwezamy o ~30% i centrujemy. Telefony (<560 px) zostaja bez
   zmian - tam pelna szerokosc jest wlasciwa.
   UWAGA SPECYFICZNOSC: selektor MUSI byc mocniejszy niz `.glasscard`
   (ma max-width:100% i stoi nizej w pliku) - przy rownej wadze wygralaby
   pozniejsza regula i nic by sie nie zmienilo. */
@media (min-width:560px) and (max-width:919px){
  .hero .hero__stage>*{max-width:clamp(360px,72%,520px);margin-inline:auto}
}
.glasscard{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:14px;padding:22px;max-width:100%;
  background:linear-gradient(150deg,rgba(255,255,255,.82),rgba(255,255,255,.55));
  border:1px solid rgba(255,255,255,.85);border-radius:26px;
  box-shadow:0 40px 90px -40px rgba(20,40,90,.55),inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);transform-style:preserve-3d;
  transition:transform .3s ease}
.glasscard>*{min-width:0}
/* overflow-wrap: break-word, NIE "anywhere". "anywhere" pozwala lamac slowo
   w dowolnym miejscu i zaniza min-content kolumny, przez co na waskich
   ekranach "Bezpieczeństwo" lamalo sie na "Bezpieczeństw" + "o" (user
   2026-07-27). Przy ciasnocie kafelek zmienia uklad na pionowy - ikona
   nad slowem - zamiast rozjezdzac wyraz. */
.float{display:flex;align-items:center;gap:.5em;min-width:0;padding:.85em .9em;background:rgba(255,255,255,.78);
  border:1px solid var(--line);border-radius:14px;font-weight:600;font-size:.86rem;color:var(--ink);
  overflow-wrap:break-word;hyphens:none;box-shadow:0 14px 30px -22px var(--shadow)}
@media (max-width:400px){
  .float{flex-direction:column;align-items:flex-start;gap:.3em}
}
/* Kafelki hero sa linkami do podstron uslug - musza to po sobie pokazywac
   (kursor, hover, widoczny focus). Wczesniej byly to <div>: wygladaly
   klikalnie, ale nie reagowaly ani na mysz, ani na klawiature. */
a.float{text-decoration:none;cursor:pointer;
  transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease,background .18s ease}
a.float:hover{background:#fff;border-color:var(--accent);color:var(--accent);
  transform:translateY(-2px);box-shadow:0 18px 34px -20px var(--shadow)}
a.float:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){a.float,a.float:hover{transition:none;transform:none}}
.float__ico{display:inline-flex;color:var(--accent)}.float__ico .ico{width:20px;height:20px}
.glasscard--art{display:block;padding:10px}
.glasscard--art img{display:block;width:100%;height:auto}
.card{box-shadow:0 24px 50px -38px var(--shadow)}
.card__ico{box-shadow:inset 0 0 0 1px rgba(37,99,235,.12)}
.sec--band::after{content:"";position:absolute;width:520px;height:520px;right:-140px;top:-220px;border-radius:50%;
  background:radial-gradient(circle,rgba(103,232,249,.38),transparent 65%);pointer-events:none}
