/* Fonty hostowane lokalnie: Sora i JetBrains Mono (jak w css/style.css i
   css/one.css - te same pliki, zeby przegladarka nie sciagala ich dwa razy
   przy nawigacji miedzy stronami). */
@font-face{font-family:'Sora';font-style:normal;font-weight:100 800;font-display:swap;src:url(/assets/fonts/sora-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Sora';font-style:normal;font-weight:100 800;font-display:swap;src:url(/assets/fonts/sora-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:100 800;font-display:swap;src:url(/assets/fonts/jetbrains-mono-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:100 800;font-display:swap;src:url(/assets/fonts/jetbrains-mono-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

/* ═══════════════ ZORNA — strona glowna, koncepcja "edytor ruchu" ═══════════════
   Ten arkusz jest SAMODZIELNY (nie laduje css/style.css). Bez JS albo z
   prefers-reduced-motion strona jest zwyklym, czytelnym dokumentem w normalnym
   przeplywie - caly uklad "warstwy absolutne + przypiecia" wlacza sie
   WYLACZNIE pod klasa html.is-motion, ktora js/home.js dokleja tylko, gdy GSAP
   i ScrollTrigger sa zaladowane i nie ma reduced-motion (patrz sekcja na
   koncu pliku). */

:root{
  --bg:#050607;
  --ink:#eef0f2;
  --mut:#9aa0a6;
  --dim:#7c8288;
  --faint:#565f66;
  --line:rgba(255,255,255,.08);
  --line2:rgba(255,255,255,.16);
  --rec:#e5484d;
  --ease:cubic-bezier(.2,.8,.2,1);
  --font:'Sora',sans-serif;
  --mono:'JetBrains Mono',monospace;
  /* Strefa HUD na dole ekranu (status + os czasu, position:fixed) - kazda
     przypieta sekcja dostaje tyle bezpiecznego marginesu na dole, zeby jej
     wlasna ostatnia linia tekstu nigdy nie wchodzila pod HUD. */
  --hud-safe:64px;
}

@media (max-width:768px){:root{--hud-safe:48px}}
@media (max-height:720px){:root{--hud-safe:36px}}

*,*::before,*::after{box-sizing:border-box}
html{scrollbar-width:thin;scrollbar-color:#2a2e32 var(--bg)}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
.lenis.lenis-stopped{overflow:hidden}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:var(--font);font-weight:300;overflow-x:clip;min-height:100dvh;
}
main{overflow-x:clip;display:block}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4,p{margin:0}
button{font-family:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
::selection{background:var(--ink);color:var(--bg)}
img,video{max-width:100%;display:block}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
html.on-light :focus-visible{outline-color:#050607}

.sec-label{font:400 11px var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--dim)}
/* visually-hidden klasyczny: tresc dla czytnikow ekranu, usunieta z ukladu wizualnego */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
h2.split{font:300 clamp(32px,4.4vw,54px)/1.08 var(--font);letter-spacing:-.01em}
.split .word{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.1em;margin-bottom:-.1em}
.split .word>span{display:inline-block;will-change:transform}
.ch-mask{display:inline-block;overflow:hidden;padding-bottom:.08em;margin-bottom:-.08em;vertical-align:top}
.ch{display:inline-block;will-change:transform}

.pill{
  display:inline-flex;align-items:center;gap:6px;
  font:400 12px var(--mono);letter-spacing:.14em;text-transform:uppercase;
  padding:14px 28px;border-radius:999px;transition:translate .3s var(--ease),box-shadow .3s,background .3s;
}
.pill-light{color:#050607;background:var(--ink)}
.pill-light:hover{translate:0 -3px;box-shadow:0 14px 40px -14px rgba(255,255,255,.3)}
.pill-outline{box-shadow:inset 0 0 0 1px rgba(255,255,255,.32);color:var(--ink)}
.pill-outline:hover{box-shadow:inset 0 0 0 1px #fff;background:rgba(255,255,255,.06)}
.pill-dark{color:var(--ink);background:#050607}
.pill-dark:hover{translate:0 -3px;box-shadow:0 14px 40px -14px rgba(0,0,0,.4)}
html.on-light .pill-outline{box-shadow:inset 0 0 0 1px rgba(5,6,7,.32);color:#050607}
html.on-light .pill-outline:hover{box-shadow:inset 0 0 0 1px #050607;background:rgba(5,6,7,.06)}

.teaser-cta{
  font:400 13.5px var(--font);letter-spacing:.03em;color:var(--ink);
  border-bottom:1px solid var(--line2);padding-bottom:3px;width:fit-content;
  transition:color .25s var(--ease),border-color .25s var(--ease);
}
.teaser-cta:hover{color:var(--ink);border-color:var(--ink)}

.roll{display:inline-flex;flex-direction:column;overflow:hidden;height:1.25em;line-height:1.25}
.roll span{display:block;transition:transform .45s var(--ease)}
.site-link:hover .roll span,.site-cta:hover .roll span,.nav-link:hover .roll span{transform:translateY(-100%)}
.site-link .roll span:nth-child(2),.nav-link .roll span:nth-child(2){color:var(--ink)}

/* ═══════════════ MEDIA (wideo + zastepczy gradient) ═══════════════ */
.media{position:relative;overflow:hidden;background:#0a0c0e}
.media video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 1.2s ease;filter:grayscale(1) contrast(1.05);
}
.media.media-live video{opacity:1}
.media-fallback{position:absolute;inset:-20%;filter:grayscale(1)}
.media-fallback::before{
  content:'';position:absolute;inset:0;
  background:
    radial-gradient(50% 60% at 28% 34%,rgba(255,255,255,.13),transparent 68%),
    radial-gradient(44% 52% at 72% 66%,rgba(255,255,255,.09),transparent 62%),
    radial-gradient(60% 70% at 55% 22%,rgba(255,255,255,.05),transparent 70%),
    linear-gradient(160deg,#0b0d0f,#050607 62%);
  animation:blob 16s ease-in-out infinite alternate;
}
.media.media-live .media-fallback{opacity:0;transition:opacity 1.2s ease}
@keyframes blob{0%{transform:translate(-4%,-3%) scale(1)}50%{transform:translate(4%,3%) scale(1.12)}100%{transform:translate(-3%,4%) scale(1.04)}}

/* ═══════════════ PRELOADER "RENDER" ═══════════════
   Wydajnosc ladowania: tlo NIE jest juz jednolitym #preloader{background},
   tylko dwoma panelami (.pre-panel-top/.pre-panel-bottom) - wyjscie animuje
   ich transform (translateY), a nie clip-path na pelnym ekranie (ten
   wymuszal repaint calej powierzchni w kazdej klatce). */
#preloader{
  position:fixed;inset:0;z-index:1000;background:transparent;
  opacity:1;visibility:visible;
  animation:preFallback 0s 3s forwards;
}
.pre-panel{position:absolute;left:0;right:0;height:50%;background:#050607;will-change:transform}
.pre-panel-top{top:0}
.pre-panel-bottom{bottom:0}
/* visibility+opacity (nie display) w fallbacku (poprawka rundy 3, punkt 23):
   niektore starsze silniki nie animuja "display" w ogole (keyframe do
   display:none nigdy sie nie stosuje), wiec gdyby js/home.js z jakiegos
   powodu sie nie wykonal, preloader zasłanialby strone NA ZAWSZE zamiast
   zniknac po 3 s. visibility/opacity sa animowalne wszedzie i dodatkowo
   wylaczaja klikalnosc/fokus, jak display:none. Jesli setup trwal dluzej niz
   te 3 s i fallback zdazyl zadzialac, initPreloader to wykrywa
   (visibility:hidden) i przejmuje stan koncowy bez animacji, zamiast dac
   fallbackowi zgasic preloader w polowie animacji JS (poprawka punkt 5). */
@keyframes preFallback{to{opacity:0;visibility:hidden;pointer-events:none}}
/* 4 rogi geometrycznie jak .hud-corner, ale WLASNA klasa: initHeroIntro
   animuje selektor ".hud-corner" globalnie (patrz nizej), preloader i HUD
   nie moga wiec dzielic klasy, inaczej rogi preloadera dostalyby ta sama
   animacje drugi raz. */
.pre-corner{position:absolute;width:26px;height:26px;opacity:.6}
.pre-corner i{position:absolute;background:var(--ink)}
.pre-corner.tl{left:16px;top:16px}
.pre-corner.tl i:first-child{top:0;left:0;width:100%;height:1.2px}
.pre-corner.tl i:last-child{top:0;left:0;width:1.2px;height:100%}
.pre-corner.tr{right:16px;top:16px}
.pre-corner.tr i:first-child{top:0;right:0;width:100%;height:1.2px}
.pre-corner.tr i:last-child{top:0;right:0;width:1.2px;height:100%}
.pre-corner.bl{left:16px;bottom:16px}
.pre-corner.bl i:first-child{bottom:0;left:0;width:100%;height:1.2px}
.pre-corner.bl i:last-child{bottom:0;left:0;width:1.2px;height:100%}
.pre-corner.br{right:16px;bottom:16px}
.pre-corner.br i:first-child{bottom:0;right:0;width:100%;height:1.2px}
.pre-corner.br i:last-child{bottom:0;right:0;width:1.2px;height:100%}
.pre-content{
  position:relative;z-index:1;height:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;
}
/* Wykres i podpisy powiekszone wzgledem pierwszej wersji (poprawka punkt 2 -
   bylo 160px/12px/10px na sztywno, na desktopie ledwo widoczne). */
.pre-graph{position:relative;width:clamp(150px,15vw,210px);height:clamp(150px,15vw,210px);flex:none}
.pre-editor{width:100%;height:100%;overflow:visible}
.pre-grid line{stroke:var(--line)}
/* pathLength="1" na <path> (patrz index.html) normalizuje dlugosc sciezki do
   1 jednostki - dasharray/dashoffset:1 chowaja krzywa juz w CZYSTYM CSS, od
   pierwszego malowania, bez potrzeby wywolywania w JS curve.getTotalLength()
   (wymuszony layout) i bez okna czasu, w ktorym w pelni narysowana krzywa
   stoi nieruchomo, zanim JS zdazy ja schowac (poprawka wydajnosci ladowania,
   punkt 1 - "zamrozony" preloader zglaszany po wdrozeniu). */
.pre-curve{fill:none;stroke:var(--ink);stroke-width:1.4;stroke-linecap:round;stroke-dasharray:1;stroke-dashoffset:1}
.pre-dot{fill:var(--ink);transform-box:fill-box;transform-origin:center;animation:prePulse 1.6s ease-in-out infinite}
/* Raczki beziera edytora krzywych - schowane w CSS, JS je odslania po
   starcie osi czasu. */
.pre-handles{opacity:0}
.pre-handles line{stroke:var(--line2);stroke-width:1}
.pre-handles rect{fill:var(--bg);stroke:var(--mut)}
/* Logo NIE jest juz czescia SVG i nie ma clip-path (poprawka punkt 1: krzywa
   przecinala znak przy wycieraniu) - osobny <img>, wysrodkowany absolutnie
   nad calym wykresem (inset:0;margin:auto - bez transform), krotko
   przenika sie z gasnacym edytorem krzywej (JS), nigdy nie naklada sie z
   linia. width/height="256" w znaczniku (poprawka rundy review) daja
   przegladarce naturalny rozmiar przed doladowaniem pliku, zeby nie liczyc
   layoutu z 0x0. transform w calosci nalezy do GSAP (scale/rotate) - bez
   wlasnego transform w CSS, GSAP nie musi parsowac istniejacej macierzy. */
.pre-logo{position:absolute;inset:0;margin:auto;width:62%;height:auto;aspect-ratio:1;opacity:0}

.pre-timeline{position:relative;width:clamp(220px,22vw,300px);margin-top:16px}
.pre-timeline::before,.pre-timeline::after{
  content:'';position:absolute;top:50%;width:5px;height:5px;z-index:1;
  transform:translate(-50%,-50%) rotate(45deg);
  border:1px solid var(--mut);background:var(--bg);
}
.pre-timeline::before{left:0}
.pre-timeline::after{left:auto;right:0;transform:translate(50%,-50%) rotate(45deg)}
.pre-timeline.is-done::after{background:var(--ink)}
.pre-track{position:relative;height:11px;overflow:hidden}
.pre-track::before{content:'';position:absolute;left:0;right:0;top:50%;height:1px;background:var(--line2);transform:translateY(-50%)}
.pre-track-fill{position:relative;width:100%;height:100%;transform:translateX(-100%)}
.pre-track-fill::before{content:'';position:absolute;left:0;right:0;top:50%;height:1px;background:var(--ink);transform:translateY(-50%)}
.pre-track-fill::after{content:'';position:absolute;right:0;top:0;width:1.2px;height:100%;background:var(--ink)}
/* Stan oczekiwania WIDOCZNY zanim JS przejmie preloader (setup moze trwac
   dluzej niz jedna klatke) - tylko transform, kompozytor, dziala nawet gdy
   glowny watek jest zajety. #preloader.pre-run go chowa, gdy JS bierze
   animacje na siebie (poprawka punkt 5). */
.pre-track-wait{
  position:absolute;top:50%;left:0;width:30%;height:1px;
  background:linear-gradient(90deg,transparent,var(--mut),transparent);
  transform:translate(-100%,-50%);
  animation:preWait 1.3s ease-in-out infinite;
}
@keyframes preWait{0%{transform:translate(-100%,-50%)}100%{transform:translate(333%,-50%)}}
#preloader.pre-run .pre-track-wait{display:none}

.pre-meta{display:flex;justify-content:space-between;width:clamp(220px,22vw,300px)}
.pre-counter{font:400 13px var(--mono);letter-spacing:.18em;color:var(--mut);font-variant-numeric:tabular-nums}
.pre-counter span{color:var(--ink)}
.pre-caption{font:400 10px var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--dim);animation:preBreathe 2.2s ease-in-out infinite}
@media (min-width:1200px){
  .pre-counter{font-size:14px}
  .pre-caption{font-size:11px}
}
/* Oddychanie/puls TYLKO na opacity+transform (kompozytor) - dziala nawet gdy
   glowny watek jest zajety dlugim zadaniem setupu, wiec statyczny ekran
   preloadera (krzywa i licznik jeszcze nieruchome, czekaja na JS) nie
   wyglada na zawieszony (poprawka wydajnosci ladowania, punkt 1). */
@keyframes preBreathe{0%,100%{opacity:.55}50%{opacity:1}}
@keyframes prePulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.35);opacity:.6}}
/* opacity:0 domyslnie (poprawka rundy review) - przed startem JS klik/klawisz
   jeszcze nic nie pomija (tl nie istnieje), wiec podpowiedz nie ma sensu
   obiecywac zanim #preloader dostanie .pre-run. */
.pre-skip-hint{position:absolute;bottom:26px;left:0;right:0;z-index:1;font:400 10px var(--mono);letter-spacing:.1em;color:var(--dim);padding:0 20px;text-align:center;opacity:0;transition:opacity .4s ease}
#preloader.pre-run .pre-skip-hint{opacity:1}
/* Na telefonie ta podpowiedz lamala sie w dwie linie (poprawka punkt 4) -
   .hint-touch jest krotsza i pokazuje sie tylko na dotykowych ekranach.
   Drugi warunek (poprawka rundy review) lapie hybrydy typu laptop z
   ekranem dotykowym, gdzie hover:none moze nie byc prawdziwe, ale ekran
   jest waski i wskazywanie zgrubne. */
.pre-skip-hint .hint-touch{display:none}
@media (hover:none) and (pointer:coarse), (max-width:480px) and (any-pointer:coarse){
  .pre-skip-hint .hint-mouse{display:none}
  .pre-skip-hint .hint-touch{display:inline}
}
html.pre-skip #preloader{display:none}

/* ═══════════════ HUD "EDYTOR" ═══════════════
   Bez GSAP/z reduced-motion (html.reduced) HUD nie ma sensu bez sterujacej
   go osi scrolla - zostalby jako martwy, nigdy-nie-aktualizowany element. */
html.reduced #hud,html.reduced #grain{display:none}
/* Bez GSAP-owej sceny "Plotno" tez nie ma czego "puszczac" scrollem - podpowiedz
   ponizej hero CTA odnosi sie wprost do pinowanej animacji kamery, ktorej w
   reduced-motion w ogole nie ma (initScena() nigdy sie nie uruchamia). */
html.reduced .scroll-hint{display:none}
#hud{position:fixed;inset:0;z-index:820;pointer-events:none;opacity:0}
html.is-motion #hud{opacity:1}
.hud-corner{position:absolute;width:26px;height:26px;opacity:.6}
.hud-corner i{position:absolute;background:var(--ink)}
.hud-corner.tl{left:16px;top:16px}
.hud-corner.tl i:first-child{top:0;left:0;width:100%;height:1.2px}
.hud-corner.tl i:last-child{top:0;left:0;width:1.2px;height:100%}
.hud-corner.tr{right:16px;top:16px}
.hud-corner.tr i:first-child{top:0;right:0;width:100%;height:1.2px}
.hud-corner.tr i:last-child{top:0;right:0;width:1.2px;height:100%}
.hud-corner.bl{left:16px;bottom:16px}
.hud-corner.bl i:first-child{bottom:0;left:0;width:100%;height:1.2px}
.hud-corner.bl i:last-child{bottom:0;left:0;width:1.2px;height:100%}
.hud-corner.br{right:16px;bottom:16px}
.hud-corner.br i:first-child{bottom:0;right:0;width:100%;height:1.2px}
.hud-corner.br i:last-child{bottom:0;right:0;width:1.2px;height:100%}
html.on-light .hud-corner i{background:#050607}

.hud-status{
  position:absolute;left:16px;bottom:34px;display:flex;align-items:center;gap:8px;
  font:400 11px var(--mono);letter-spacing:.12em;color:var(--mut);
}
html.on-light .hud-status{color:#5a6168}
.status-dot{width:7px;height:7px;border-radius:50%;box-shadow:inset 0 0 0 1.3px var(--mut);flex:none}
.hud-status.is-play .status-dot{background:var(--ink);box-shadow:none;animation:hudPulse 1.1s ease-in-out infinite}
.hud-status.is-pause .status-dot{opacity:.4}
.hud-status.is-rec .status-dot{background:var(--rec);box-shadow:none;animation:hudPulse 1.1s ease-in-out infinite}
.hud-status.is-live .status-dot{background:var(--ink);box-shadow:none;animation:hudPulse .8s ease-in-out infinite}
@keyframes hudPulse{0%,100%{opacity:1}50%{opacity:.3}}
.status-frames{font-variant-numeric:tabular-nums}
@media (max-width:768px){.status-label,.status-fps{display:none}}

.hud-chapter{
  position:absolute;left:50%;bottom:34px;transform:translateX(-50%);
  font:400 11px var(--mono);letter-spacing:.14em;color:var(--dim);white-space:nowrap;
}
html.on-light .hud-chapter{color:#5a6168}
@media (max-width:768px){.hud-chapter{display:none}}

/* Wysokosc kontenera 24px, ale sama linia siedzi na bottom:10px (poprawka
   rundy 1): przy bottom:0 romby (9px, wyosiowane na linii przez ujemny
   bottom) wychodzily czescia pod krawedz ekranu i byly przyciete. */
.hud-timeline{position:absolute;left:0;right:0;bottom:0;height:24px}
.hud-fill,.hud-timeline::before{content:'';position:absolute;left:0;right:0;bottom:10px;height:1px;background:var(--line2)}
/* width:100% + transform:scaleX() zamiast animowanego width (poprawka rundy
   3, punkt 19): scaleX to wlasnosc kompozytora (brak layoutu w kazdej
   klatce scrolla), transform-origin trzyma wzrost od lewej krawedzi. */
.hud-fill{background:var(--ink);width:100%;transform-origin:0 50%;transform:scaleX(0);z-index:1;will-change:transform}
html.on-light .hud-timeline::before{background:rgba(5,6,7,.16)}
/* left:0 jako baza, dokladna pozycja doklejana w JS przez transform:translateX
   w pikselach (bufor szerokosci toru) zamiast style.left w procentach. */
.hud-playhead{position:absolute;bottom:3.5px;width:2px;height:13px;background:var(--ink);left:0;transform:translateX(-1px);z-index:2;will-change:transform}
/* .hud-chapters-nav zajmuje dokladnie to samo miejsce co dawne .hud-ticks
   (poprawka rundy 3, punkt 5) - teraz jako wlasny <nav> POZA #hud (patrz
   index.html), zeby prawdziwa nawigacja miala wlasna etykiete dla czytnikow
   ekranu i nie siedziala w kolejce Tab przed tresc strony. */
.hud-chapters-nav{position:fixed;left:0;right:0;bottom:0;height:24px;z-index:820;pointer-events:none}
html.reduced .hud-chapters-nav{display:none}
/* Romb rysowany na ::before, NIE na samym <button> (poprawka rundy 3, punkt
   20): gdy rotate(45deg) siedzial na elemencie z .hud-tick-label w srodku,
   podpis dziedziczyl ten sam obrocony uklad wspolrzednych i wychodzil
   ukosnie. Przycisk zostaje "kwadratowym", nieobroconym obszarem kliku;
   tylko dekoracyjny ::before jest wizualnie diamentem. */
.hud-tick{
  position:absolute;bottom:1px;width:16px;height:16px;transform:translate(-50%,0);
  background:none;border:0;pointer-events:none;
}
.hud-tick::before{
  content:'';position:absolute;left:50%;top:4.5px;width:9px;height:9px;
  transform:translate(-50%,0) rotate(45deg);
  background:var(--bg);box-shadow:inset 0 0 0 1.2px var(--line2);
}
.hud-tick.is-done::before{background:var(--ink);box-shadow:none}
button.hud-tick{cursor:pointer;pointer-events:auto}
.hud-tick-label{
  position:absolute;bottom:16px;left:50%;transform:translateX(-50%);white-space:nowrap;
  font:400 10px var(--mono);letter-spacing:.1em;color:var(--ink);background:#050607;
  padding:4px 8px;border-radius:4px;opacity:0;transition:opacity .2s;pointer-events:none;
}
button.hud-tick:hover .hud-tick-label,button.hud-tick:focus-visible .hud-tick-label{opacity:1}
@media (max-width:768px){
  .hud-corner{width:16px;height:16px}
  .hud-corner.tl,.hud-corner.tr{top:8px}
  .hud-corner.bl,.hud-corner.br{bottom:8px}
  .hud-corner.tl,.hud-corner.bl{left:8px}
  .hud-corner.tr,.hud-corner.br{right:8px}
  .pre-corner{width:16px;height:16px}
  .pre-corner.tl,.pre-corner.tr{top:8px}
  .pre-corner.bl,.pre-corner.br{bottom:8px}
  .pre-corner.tl,.pre-corner.bl{left:8px}
  .pre-corner.tr,.pre-corner.br{right:8px}
  .hud-status{left:8px;bottom:16px}
  .hud-timeline{height:18px}
  .hud-timeline::before,.hud-fill{bottom:6px}
  .hud-chapters-nav{height:18px}
  .hud-tick::before{top:1.5px}
  .hud-playhead{bottom:-.5px}
  /* Telefon: romby zostaja (widoczne), ale bez klikalnosci - "oś czasu bez
     klikalnych rombów" (SPEC). tabindex=-1 dodany w JS (patrz placeChapterTicks). */
  button.hud-tick{pointer-events:none}
  .hud-tick-label{display:none}
}

/* ═══════════════ ZIARNO ═══════════════ */
#grain{position:fixed;inset:0;z-index:810;pointer-events:none;opacity:0;mix-blend-mode:overlay;background-repeat:repeat;background-size:128px 128px}
html.is-motion #grain{opacity:.05}
html.on-light #grain{opacity:.04}
.blysk{position:fixed;inset:0;background:#fff;opacity:0;pointer-events:none;z-index:900}

/* ═══════════════ ODSLONIECIA (JS overrides przez GSAP fromTo) ═══════════════
   Domyslny stan ukryty tylko pod is-motion - bez tej klasy (dokument bez JS
   albo z reduced-motion) wszystko ma byc widoczne od razu (regula 2 specyfikacji). */
html.is-motion [data-anim],
html.is-motion [data-intro]{opacity:0}
/* Dymki czatu asystenta chowane juz w CZYSTYM CSS, nie tylko przez gsap.set w
   initAsystentChat() (poprawka regresji ladowania, punkt 3): initAsystentChat
   jest teraz w kolejce requestIdleCallback, wiec jesli ktos zdazy szybko
   przewinac do #chatTeaser (ktory sam w sobie odslania sie synchronicznie -
   ma data-anim, obsluguje go initGenericRevealsAnim) ZANIM idle sie wykona,
   wszystkie dymki (uzytkownik/pisze/bot/formularz/podziekowanie) pokazalyby
   sie naraz w swoim surowym stanie HTML, a potem doslownie zamigaly do
   niewidocznosci w momencie, gdy JS w koncu ustawia gsap.set(...,{opacity:0}).
   Bazowa regula CSS eliminuje to okno calkowicie - JS i tak ustawia identyczny
   stan poczatkowy (i bardziej szczegolowy: y/scale/clip-path), wiec podmiana
   jest niezauwazalna. */
html.is-motion #chatTeaser [data-step]{opacity:0}
/* .hero-word CELOWO nie jest tu wymieniony (poprawka rundy 1): ukrywa sie
   przez maske+transform liter (.ch-mask/.ch, jak .split .word), NIE przez
   opacity rodzica - inaczej samo intro (ktore animuje wylacznie yPercent/
   rotate liter .ch, nigdy opacity .hero-word) nigdy nie odslania calego
   bloku i litery zostaja niewidoczne na zawsze, mimo poprawnego transformu. */

/* Powrot bez preloadera (html.pre-skip, poprawka wydajnosci ladowania,
   punkt 7): reguly powyzej chowaja header/[data-intro] na czas preloadera i
   normalnie odslania je initHeroIntro() PO calym synchronicznym setupie JS -
   na wolnym telefonie to nawet sekunda samego wideo bez tekstu. Przy pre-skip
   preloadera w ogole nie ma, wiec wejscie hero jest tu czystym CSS-em,
   startujacym od pierwszego malowania (bez czekania na JS). js/home.js dla
   pre-skip NIE odtwarza tego samego wejscia drugi raz - initHeroIntro() nie
   jest tam w ogole wolane (patrz initPreloader w js/home.js), litery "zorna"
   nie sa nawet dzielone na spany (heroChars=[] dla pre-skip) - cale slowo
   wjezdza jako jeden blok. html.is-motion.pre-skip (obie klasy naraz) bije
   specificznoscia pojedyncze html.is-motion powyzej, wiec kolejnosc w pliku
   nie ma znaczenia. */
html.is-motion.pre-skip [data-intro]{opacity:1;animation:preSkipUp .7s cubic-bezier(.16,1,.3,1) both}
html.is-motion.pre-skip #site-header{opacity:1;animation:preSkipDown .6s cubic-bezier(.16,1,.3,1) both}
html.is-motion.pre-skip .hero-word{animation:preSkipWord .8s cubic-bezier(.16,1,.3,1) both}
html.is-motion.pre-skip .hero-one-pill{animation-delay:0s}
html.is-motion.pre-skip .hero-badge{animation-delay:.05s}
html.is-motion.pre-skip .hero-word{animation-delay:.08s}
html.is-motion.pre-skip .hero-sub{animation-delay:.14s}
html.is-motion.pre-skip .hero-cta{animation-delay:.2s}
html.is-motion.pre-skip .scroll-hint{animation-delay:.26s}
@keyframes preSkipUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
@keyframes preSkipDown{from{opacity:0;transform:translateY(-24px)}to{opacity:1;transform:translateY(0)}}
@keyframes preSkipWord{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}

/* ═══════════════ KURSOR "ZAZNACZENIE" ═══════════════ */
/* a/button/.layer-row wymienione OSOBNO (poprawka rundy 3, punkt 21): same
   te elementy maja wlasne cursor:pointer (przegladarkowy default albo nasze
   .pill/.layer-row), ktory wygrywa specyficznoscia z odziedziczonym
   cursor:none z przodka - bez tego pod prawdziwym kursorem widac byloby
   OBA: systemowa "reke" i nasz wlasny krzyzyk. */
html.has-cursor main,html.has-cursor #site-header,html.has-cursor footer,
html.has-cursor main a,html.has-cursor main button,html.has-cursor main .layer-row,
html.has-cursor #site-header a,html.has-cursor #site-header button,
html.has-cursor footer a,html.has-cursor footer button{cursor:none!important}
#ed-cursor{
  position:fixed;top:0;left:0;z-index:950;pointer-events:none;width:18px;height:18px;
  mix-blend-mode:difference;opacity:0;transition:opacity .25s,width .3s var(--ease),height .3s var(--ease),border-radius .3s;
  will-change:transform;
}
html.has-cursor #ed-cursor{opacity:1}
.ed-cross i{position:absolute;background:var(--ink)}
.ed-cross i:first-child{left:50%;top:0;width:1.4px;height:100%;margin-left:-.7px}
.ed-cross i:last-child{top:50%;left:0;height:1.4px;width:100%;margin-top:-.7px}
#ed-cursor .ed-corner{position:absolute;width:7px;height:7px;border:1.4px solid var(--ink);opacity:0;transition:opacity .2s}
#ed-cursor .ed-corner.c-tl{top:-4px;left:-4px;border-right:0;border-bottom:0}
#ed-cursor .ed-corner.c-tr{top:-4px;right:-4px;border-left:0;border-bottom:0}
#ed-cursor .ed-corner.c-bl{bottom:-4px;left:-4px;border-right:0;border-top:0}
#ed-cursor .ed-corner.c-br{bottom:-4px;right:-4px;border-left:0;border-top:0}
#ed-cursor.is-target .ed-cross{opacity:0}
#ed-cursor.is-target .ed-corner{opacity:1}
.ed-tag{
  position:absolute;left:100%;top:100%;margin:6px 0 0 6px;white-space:nowrap;
  font:400 9.5px var(--mono);letter-spacing:.1em;color:var(--ink);
}

/* ═══════════════ NAGLOWEK ═══════════════ */
#site-header{
  position:fixed;top:0;left:0;right:0;z-index:800;
  display:flex;align-items:center;justify-content:space-between;
  padding:20px 44px;background:linear-gradient(rgba(5,6,7,.88),rgba(5,6,7,0));
  will-change:transform;transition:background .3s,backdrop-filter .3s;
}
/* Tlo rozmyte PO zjechaniu z hero (SPEC, brak wzgledem specu): .is-scrolled
   dokleja initHeader (js/home.js) na tym samym progu, na ktorym naglowek
   zaczyna sie chowac/wracac przy scrollu. */
#site-header.is-scrolled{
  background:linear-gradient(rgba(5,6,7,.82),rgba(5,6,7,.55));
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
html.on-light #site-header{background:linear-gradient(rgba(250,250,247,.9),rgba(250,250,247,0));color:#050607}
html.on-light #site-header.is-scrolled{background:linear-gradient(rgba(250,250,247,.85),rgba(250,250,247,.6))}
.site-logo{display:flex;align-items:center;gap:11px}
.logo-badge{position:relative;width:32px;height:32px;flex:none;display:grid;place-items:center;border-radius:50%}
.logo-badge.is-sm{width:26px;height:26px}
.logo-img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 0 8px rgba(255,255,255,.16));transition:transform .7s var(--ease)}
.site-logo:hover .logo-img{transform:rotate(120deg)}
.logo-name{font:300 17px var(--font);letter-spacing:.05em}
.site-links{display:flex;align-items:center;gap:30px}
.site-link{font:300 13px var(--font);letter-spacing:.06em;text-transform:uppercase;color:var(--mut)}
html.on-light .site-link{color:#5a6168}
.site-cta{
  font:400 12.5px var(--mono);letter-spacing:.14em;text-transform:uppercase;
  padding:10px 22px;border-radius:999px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.28);
  transition:box-shadow .3s,background .3s;
}
html.on-light .site-cta{box-shadow:inset 0 0 0 1px rgba(5,6,7,.28)}
.site-cta:hover{box-shadow:inset 0 0 0 1px #fff;background:rgba(255,255,255,.06)}
html.on-light .site-cta:hover{box-shadow:inset 0 0 0 1px #050607;background:rgba(5,6,7,.06)}
.nav-burger{display:none;flex:none;width:40px;height:40px;flex-direction:column;align-items:center;justify-content:center;gap:5px}
.nav-burger span{display:block;width:21px;height:1.5px;background:var(--ink);transition:transform .35s var(--ease),opacity .35s var(--ease)}
html.on-light .nav-burger span{background:#050607}
.nav-burger.is-open span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
.nav-burger.is-open span:nth-child(2){opacity:0}
.nav-burger.is-open span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}
@media (max-width:900px){
  #site-header{padding:16px 20px}
  .site-links{display:none}
  .nav-burger{display:flex}
  .logo-name{font-size:15px}
}

/* ── menu mobilne ── */
.menu-overlay{
  position:fixed;inset:0;z-index:790;display:flex;flex-direction:column;justify-content:center;
  padding:88px 30px 30px;background:rgba(5,6,7,.97);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .4s var(--ease),visibility .4s;
  overflow-y:auto;-webkit-overflow-scrolling:touch;
}
.menu-overlay.is-open{opacity:1;visibility:visible;pointer-events:auto}
.menu-close{position:absolute;top:16px;right:18px;z-index:1;width:44px;height:44px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background .25s var(--ease)}
.menu-close:hover{background:rgba(255,255,255,.06)}
.menu-close span{position:absolute;width:22px;height:1.5px;background:var(--ink)}
.menu-close span:nth-child(1){transform:rotate(45deg)}
.menu-close span:nth-child(2){transform:rotate(-45deg)}
.menu-list{display:flex;flex-direction:column}
.menu-item{display:flex;align-items:baseline;gap:16px;padding:14px 0;border-bottom:1px solid rgba(255,255,255,.07)}
.menu-num{font:400 10px var(--mono);color:var(--faint)}
.menu-label{font:300 28px var(--font);color:var(--ink)}
.menu-cta{align-self:flex-start;margin-top:26px;font:400 15px var(--font);letter-spacing:.04em;color:#050607;background:var(--ink);padding:15px 32px;border-radius:999px}
.menu-tel{align-self:flex-start;margin-top:12px;font:300 14px var(--font);color:var(--dim);border-bottom:1px solid var(--line2);padding-bottom:2px}

/* ═══════════════════════════════════════════════════════════════════
   01 · START + 02 · REALIZACJE — SCENA "PLOTNO"
   Baza (bez motion): dokument normalny, hero jako sekcja z wideo w tle,
   pod nim naglowek rozdzialu i siatka realizacji.
   ═══════════════════════════════════════════════════════════════════ */
/* overflow:clip (nie hidden) na #scena/.plotno-hero (poprawka rundy 3,
   krytyczny punkt 1): "hidden" tworzy nowy kontener przewijalny, wiec Tab
   na niewidocznych (opacity:0) artboardach rzedu przewijal #scena w poziomie
   scrollLeft-em przegladarki (poza kontrola Lenisa/GSAP) i caly hero znikal
   z ekranu. "clip" nadal przycina tresc, ale nie tworzy wlasnego scrollportu. */
#scena{position:relative;background:#050607;overflow:clip}
/* justify-content:safe center (poprawka rundy 3, punkt 7): na niskich
   laptopach (np. 1366x657) tresc hero bywa wyzsza niz dostepna wysokosc -
   zwykle "center" wtedy centruje tresc W GLAB gornej krawedzi (pastylka ONE
   chowa sie pod stalym naglowkiem); "safe center" przelacza sie na start,
   gdy centrowanie wypychaloby cokolwiek poza ekran. */
.plotno-hero{position:relative;min-height:100svh;display:flex;flex-direction:column;justify-content:center;justify-content:safe center;overflow:clip;padding-top:78px}
.plotno-canvas-bg{position:absolute;inset:0;opacity:0;pointer-events:none;background-image:radial-gradient(rgba(255,255,255,.14) 1px,transparent 1.4px);background-size:26px 26px}

.hero-artboard{position:absolute;inset:0;border-radius:0;overflow:hidden}
.hero-video-frame{position:absolute;inset:0}
/* .hero-chrome: patrz komentarz w index.html - siostra .hero-artboard z tymi
   samymi wspolrzednymi (JS), ale WLASNA szerokosc/wysokosc w px zamiast
   scale, i bez overflow:hidden (uchwyty/etykieta nie sa juz przycinane). */
.hero-chrome{position:absolute;inset:0;pointer-events:none}
html.is-motion .hero-chrome{inset:auto;left:50%;top:50%}
.hero-vignette{
  position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 30%,transparent 30%,rgba(5,6,7,.9) 92%),
    linear-gradient(to top,rgba(5,6,7,.75) 0%,rgba(5,6,7,.32) 34%,transparent 62%);
}
.sel-handles{position:absolute;inset:0;opacity:0;pointer-events:none}
.sel-handles .sh{position:absolute;width:9px;height:9px;border:1.2px solid var(--ink)}
.sh-tl{top:-1px;left:-1px;border-right:0;border-bottom:0}
.sh-tr{top:-1px;right:-1px;border-left:0;border-bottom:0}
.sh-bl{bottom:-1px;left:-1px;border-right:0;border-top:0}
.sh-br{bottom:-1px;right:-1px;border-left:0;border-top:0}
.sh-t{top:-5px;left:50%;margin-left:-4.5px;border-width:0 0 1.2px 0}
.sh-b{bottom:-5px;left:50%;margin-left:-4.5px;border-width:1.2px 0 0 0}
.sh-l{left:-5px;top:50%;margin-top:-4.5px;border-width:0 1.2px 0 0}
.sh-r{right:-5px;top:50%;margin-top:-4.5px;border-width:0 0 0 1.2px}
.ab-label{position:absolute;left:0;bottom:100%;margin-bottom:14px;opacity:0;font:400 11px var(--mono);letter-spacing:.1em;color:var(--mut);white-space:nowrap}
.ab-dim{position:absolute;left:0;top:100%;margin-top:14px;opacity:0;display:flex;align-items:center;gap:8px;font:400 10px var(--mono);letter-spacing:.08em;color:var(--dim)}
.ab-dim i{width:40px;height:1px;background:var(--line2)}

.hero-content{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:26px;text-align:center;padding:64px 24px;margin:0 auto}
.hero-one-pill{
  display:inline-flex;align-items:center;gap:8px;padding:8px 16px 8px 10px;border-radius:999px;
  background:rgba(255,255,255,.06);box-shadow:inset 0 0 0 1px var(--line2);
  font:400 11px var(--mono);letter-spacing:.05em;color:var(--ink);transition:background .25s,box-shadow .25s;
}
.hero-one-pill:hover{background:rgba(255,255,255,.1);box-shadow:inset 0 0 0 1px rgba(255,255,255,.4)}
.hero-one-pill .one-glyph{width:9px;height:auto;flex:none}
.hero-badge{display:inline-flex;align-items:center;gap:9px;font:400 11px var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.pulse-dot{width:7px;height:7px;flex:none;border-radius:50%;background:var(--ink);animation:pulse 1.8s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.78)}}
/* min(21vw,28svh) (poprawka rundy 3, punkt 7): na szerokich, ale NISKICH
   ekranach (1366x657) samo 21vw dawalo litery wyzsze niz sensowny kawalek
   dostepnej wysokosci - ograniczamy tez wzgledem wysokosci ekranu. */
.hero-word{font:200 clamp(72px,min(21vw,28svh),300px)/.86 var(--font);letter-spacing:-.01em;color:var(--ink)}
/* Scrim WYLACZNIE za H1+lead (poprawka rundy 1): na jasnych fragmentach
   wideo lead byl nieczytelny mimo winiety na calym kadrze - ta plama jest
   przyklejona dokladnie do bloku tekstu, wiec dziala niezaleznie od tego,
   co akurat gra w tle. z-index:-1 dziala tu bez sztuczek, bo .hero-sub ma
   position:relative wiec tworzy wlasny kontekst warstwowania. */
.hero-sub{position:relative;display:flex;flex-direction:column;gap:14px;max-width:56ch}
.hero-sub::before{
  content:'';position:absolute;inset:-22px -32px;z-index:-1;border-radius:28px;
  background:radial-gradient(60% 85% at 50% 45%,rgba(5,6,7,.78) 0%,rgba(5,6,7,.55) 55%,transparent 100%);
}
.hero-h1{font:300 20px/1.4 var(--font);color:var(--ink)}
.hero-sub p{font:300 15px/1.6 var(--font);color:var(--mut);text-shadow:0 2px 16px rgba(0,0,0,.7)}
.hero-cta{display:flex;flex-wrap:wrap;justify-content:center;gap:14px}
.scroll-hint{display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--dim);margin-top:8px}
.scroll-hint span:first-child{font:400 10px var(--mono);letter-spacing:.18em;text-transform:uppercase}
.hint-line{width:1px;height:30px;background:rgba(255,255,255,.18);overflow:hidden;position:relative}
.hint-line span{position:absolute;left:0;top:0;width:1px;height:12px;background:var(--ink);animation:hint 2s ease-in-out infinite}
@keyframes hint{0%{transform:translateY(-14px)}70%,100%{transform:translateY(34px)}}

/* opacity:0 tutaj byloby BLEDEM (poprawka rundy 3, punkt krytyczny 2): ta
   klasa bazowa dziala tez bez JS/z reduced-motion, gdzie nic nigdy nie
   przywracaloby opacity - stan ukryty jest WYLACZNIE pod html.is-motion,
   nizej w pliku. */
.plotno-chaptertext{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:14px;max-width:520px;padding:60px 6vw 0}

/* -- rzad/siatka realizacji -- */
.plotno-row{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:20px;padding:0 6vw 90px;max-width:1400px;margin:0 auto}
.artboard{
  position:relative;display:flex;flex-direction:column;gap:0;border-radius:14px;overflow:hidden;
  background:#0b0d0f;box-shadow:inset 0 0 0 1px var(--line2);
}
.artboard.is-wide{grid-column:1/-1}
.ab-top{display:flex;justify-content:space-between;align-items:center;padding:14px 16px;gap:10px}
.ab-index{font:400 11px var(--mono);letter-spacing:.1em;color:var(--dim)}
.ab-name{font:400 15px var(--font);color:var(--ink)}
.ab-media{position:relative;display:block;aspect-ratio:16/10;overflow:hidden;background:#14171a}
.ab-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:left top}
.ab-soon{
  position:absolute;top:12px;right:12px;font:400 10px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ink);
  background:rgba(5,6,7,.55);border:1px solid rgba(255,255,255,.24);border-radius:999px;padding:6px 12px;backdrop-filter:blur(6px);
}
.ab-bottom{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px 16px}
.ab-desc{font:300 13px var(--font);color:var(--mut)}
.ab-domain{font:400 11px var(--mono);letter-spacing:.08em;color:var(--dim);white-space:nowrap}
/* Slot 0 (hero jako pierwszy artboard rzedu, FLIP - patrz initScena w
   js/home.js): nieobecny wizualnie poza desktopowym is-motion - w bazowym
   dokumencie i na telefonie hero zostaje osobnym, pelnoekranowym blokiem nad
   ta lista (regula 2 specyfikacji), wiec duplikat pustego slotu tylko by
   przeszkadzal. */
.artboard-hero-slot{display:none}
a.artboard{transition:box-shadow .3s}
a.artboard:hover{box-shadow:inset 0 0 0 1px rgba(255,255,255,.4)}
/* BEZ transition na opacity/transform (poprawka rundy 3, punkt 22): oba te
   wlasciwosci sa sterowane przez GSAP co klatke scrubu (rowTick) - rownolegla
   CSS-owa transition "goni" kazda nowa wartosc z 0.35 s opoznieniem, wiec
   slot 0 (wideo) dojezdzal do pozycji zauwazalnie po czasie, a nie razem ze
   scrollem. */
.artboard.is-dim{opacity:.45}
/* Uchwyty zaznaczenia na aktywnym artboardzie w jezdzie kamery (SPEC): 4 rogi
   rysowane WYLACZNIE przez tlo (gradient-corners), zero dodatkowych
   elementow DOM na kazda z 9 kart. */
.artboard.is-active{
  box-shadow:inset 0 0 0 1.5px var(--ink);
}
.artboard.is-active::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    linear-gradient(var(--ink),var(--ink)) top left/9px 1.2px no-repeat,
    linear-gradient(var(--ink),var(--ink)) top left/1.2px 9px no-repeat,
    linear-gradient(var(--ink),var(--ink)) top right/9px 1.2px no-repeat,
    linear-gradient(var(--ink),var(--ink)) top right/1.2px 9px no-repeat,
    linear-gradient(var(--ink),var(--ink)) bottom left/9px 1.2px no-repeat,
    linear-gradient(var(--ink),var(--ink)) bottom left/1.2px 9px no-repeat,
    linear-gradient(var(--ink),var(--ink)) bottom right/9px 1.2px no-repeat,
    linear-gradient(var(--ink),var(--ink)) bottom right/1.2px 9px no-repeat;
}
.artboard-final{
  grid-column:1/-1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  min-height:180px;border:1.5px dashed var(--line2);background:transparent;box-shadow:none;
}
.artboard-final:hover{border-color:rgba(255,255,255,.4)}
.ab-plus{font:200 46px/1 var(--font);color:var(--dim)}
.ab-final-text{font:400 13px var(--mono);letter-spacing:.08em;color:var(--mut)}

@media (max-width:900px){
  .plotno-row{grid-template-columns:1fr;padding:0 5vw 70px}
  .artboard.is-wide{grid-column:auto}
}
@media (max-width:768px){
  .hero-word{font-size:30vw}
  /* pastylka "Nowosc": na waskim ekranie caly tekst sie nie miesci i lamal
     sie na dwie linie w srodku pastylki (brzydko) - chowamy mniej wazny
     kawalek ("Production Agency") i wymuszamy jeden wiersz. */
  .hero-one-pill{white-space:nowrap;font-size:10px;max-width:calc(100vw - 40px)}
  .hero-one-pill .hp-full{display:none}
  /* padding-top skromny (NIE dublujemy .plotno-hero, ktory juz ma wlasne
     padding-top:78px na odstep od naglowka) - runda telefon, poprawka #1:
     stare 110px + 78px z rodzica dawaly razem prawie 190px, .hero-content
     na 320x568 wychodzil wyzszy niz caly ekran (rozjezdzal sie pin na
     is-motion, patrz tez html.is-motion .plotno-hero nizej). */
  .hero-content{padding:8px 20px 20px;gap:14px}
  .hero-h1{font-size:17px}
  .hero-sub{gap:8px}
  .scroll-hint{margin-top:0}
  .plotno-chaptertext{padding:40px 5vw 0}
}
@media (max-width:768px) and (max-height:640px){
  /* Ekrany niskie (iPhone SE 568 i podobne): dociskamy dalej, a podpowiedz
     scrolla (najmniej istotny element, czysto dekoracyjny) znika - inaczej
     tresc hero nie miesci sie w jednym ekranie is-motion (patrz komentarz
     wyzej). */
  .hero-content{gap:10px;padding-top:4px}
  .scroll-hint{display:none}
}
@media (max-width:400px){
  .hero-cta{gap:10px}
  .pill{padding:12px 20px;font-size:11px}
}
/* Niskie ekrany DESKTOP tez (poprawka rundy 3, punkt 7: 1366x657 i podobne
   laptopy) - podpowiedz scrolla i etykieta HUD nachodzily na siebie w dole
   ekranu. Ten sam warunek co telefon (max-height:640px), bez ograniczenia
   szerokosci. */
@media (min-width:769px) and (max-height:660px){
  .scroll-hint{display:none}
  .hero-content{gap:16px}
}

/* ═══════════════ 03 · USLUGI: PANEL WARSTW ═══════════════ */
#services{padding:120px 44px;max-width:1400px;margin:0 auto}
.svc-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(360px,560px);gap:60px;align-items:start}
/* position:sticky (nie tylko flex): .layers-panel jest przypiety osobno przez
   ScrollTrigger (pin:'.layers-panel') na czas dluzszy niz naturalna wysokosc
   .svc-copy - bez sticky lewa kolumna przewijalaby sie i znikala, zostawiajac
   puste miejsce obok wciaz przypietego panelu. */
.svc-copy{display:flex;flex-direction:column;align-items:flex-start;gap:16px;position:sticky;top:120px;align-self:start}
@media (max-width:900px){ .svc-copy{position:static} }
.svc-copy p{font:300 15px/1.65 var(--font);color:var(--mut);max-width:42ch}
.layers-panel{background:#0d1012;border:1px solid var(--line2);border-radius:16px;overflow:hidden}
.layers-head{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid var(--line);font:400 11px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mut)}
.layers-head-icons{color:var(--dim)}
.layers-head-icons svg{width:14px;height:14px}
.layers-list{display:flex;flex-direction:column}
.layer-row{
  position:relative;display:grid;grid-template-columns:22px 34px 1fr auto;gap:16px;align-items:center;
  padding:22px 18px;border-top:1px solid var(--line);transition:background .3s;
}
/* cursor:pointer tylko na WARIANCIE-LINKU (poprawka rundy 3, punkt 21): 3 z 4
   wierszy to zwykle <div>, nieklikalne - pointer sugerowalby cos przeciwnego. */
a.layer-row{cursor:pointer}
.layer-row:hover,.layer-row.is-active{background:rgba(255,255,255,.04)}
.layer-eye{color:var(--faint);transition:color .3s}
.layer-eye svg{width:16px;height:16px;display:block}
.layer-row.is-active .layer-eye,.layer-row:hover .layer-eye{color:var(--ink)}
.layer-num{font:400 11px var(--mono);color:var(--dim)}
.layer-body{display:flex;flex-direction:column;gap:4px;min-width:0}
.layer-name{font:400 16px var(--font);color:var(--ink)}
.layer-desc{font:300 12.5px/1.55 var(--font);color:var(--mut)}
.layer-arrow{color:var(--faint);transition:transform .3s var(--ease),color .3s}
.layer-row:hover .layer-arrow,.layer-row.is-active .layer-arrow{color:var(--ink);transform:translateX(6px)}
.svc-branze{margin-top:30px;padding-top:26px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;align-items:center;gap:10px 20px}
.svc-branze span{font:400 11px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.svc-branze a{font:300 14px var(--font);color:var(--mut);text-decoration:underline;text-decoration-color:var(--line2);text-underline-offset:4px;transition:color .3s}
.svc-branze a:hover{color:var(--ink);text-decoration-color:var(--ink)}
@media (max-width:900px){
  #services{padding:90px 22px}
  .svc-grid{grid-template-columns:1fr;gap:34px}
  .layer-row{grid-template-columns:20px 28px 1fr;padding:18px 14px}
  .layer-arrow{display:none}
}

/* ═══════════════ 04 · PROCES: CZTERY KLATKI KLUCZOWE ═══════════════ */
#process{padding:120px 44px;max-width:1400px;margin:0 auto;background:#08090b}
.sec-head{display:flex;flex-direction:column;gap:14px;margin-bottom:56px}
.proc-wrap{display:flex;flex-direction:column;gap:40px}
.proc-graph-wrap{position:relative}
/* max-height w svh (poprawka rundy 3, punkt 6): #process jest przypiety na
   caly ekran - bez gornej granicy wysokosci wykres (viewBox 1000x260, proporcja
   ~3.85:1) przy width:100% na szerokich, ale niskich oknach (1366x657,
   1440x789) wychodzil czescia pod HUD albo poza gorna krawedz. Wysokosc
   liczona od ekranu, szerokosc dopasowuje sie sama (SVG zachowuje proporcje). */
.proc-graph{width:auto;max-width:100%;height:auto;max-height:32svh;display:block;overflow:visible;margin:0 auto}
.pg-grid line{stroke:var(--line)}
.pg-curve{fill:none;stroke:var(--ink);stroke-width:2}
.pg-dot{fill:var(--ink)}
.pg-key{fill:#08090b;stroke:var(--line2);stroke-width:1.4;transition:fill .3s}
.pg-key.is-done{fill:var(--ink);stroke:var(--ink)}
.pg-playhead{stroke:var(--ink);stroke-width:1.4}
.proc-readout{position:absolute;top:0;right:0;font:400 11px var(--mono);letter-spacing:.06em;color:var(--dim);font-variant-numeric:tabular-nums}
.proc-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.proc-card{padding:24px 22px;border-radius:14px;border:1px solid var(--line);display:flex;flex-direction:column;gap:10px}
/* opacity:.4 tylko pod is-motion (poprawka rundy 3, punkt 14): w bazowym
   regule (bez tej klasy) karty przygasaly na zawsze, bo nic bez JS nigdy nie
   dokleja .is-active - w dokumencie bez motion/reduced wszystkie 4 maja byc
   od razu w pelni czytelne. */
html.is-motion .proc-card{opacity:.4;transition:opacity .4s,border-color .4s,background .4s}
.proc-card.is-active{opacity:1;border-color:var(--line2);background:rgba(255,255,255,.03)}
.proc-num{font:400 11px var(--mono);letter-spacing:.14em;color:var(--dim)}
.proc-name{font:400 17px var(--font)}
.proc-desc{font:300 13px/1.6 var(--font);color:var(--mut)}
@media (max-width:900px){
  #process{padding:90px 22px}
  .proc-cards{grid-template-columns:1fr 1fr;gap:12px}
}
@media (max-width:600px){
  .proc-cards{grid-template-columns:1fr}
}
@media (max-width:768px){
  /* Wykres na telefonie byl faktycznie ograniczany SZEROKOSCIA, nie
     max-height:32svh (poprawka zgloszenia Jasa, punkt 3): .proc-graph ma
     preserveAspectRatio="none" w znaczniku (krzywa ma sie swobodnie
     rozciagac do dowolnego pudelka), ale reguła bazowa (width:auto;
     max-width:100%;height:auto;max-height:32svh) liczy rozmiar tak, jakby
     trzeba bylo zachowac proporcje viewBoksa (1000x260, ~3.85:1) - na waskim
     ekranie to WLASNIE szerokosc (nie wysokosc) byla ciasniejszym
     ograniczeniem (np. 320px szer. -> ok. 72px wys., duzo mniej niz
     dostepne 32svh), stad ok. 35% pustego ekranu pod karta. Jawne width/
     height (zamiast auto+max) pozwala krzywej faktycznie wykorzystac
     preserveAspectRatio="none" i wypelnic zadana wysokosc. 24svh/200px (nie
     32svh/280px) - na iPhone SE (320x568) 32svh razem z nagłówkiem, odstepami
     i karta wychodzilo ok. 118px pod dolna krawedz strefy bezpiecznej HUD;
     ten rozmiar, razem z przycietymi odstepami nizej, mieści się z zapasem. */
  .proc-graph{width:100%;max-width:none;height:min(24svh,200px);max-height:none}
  /* Odczyt "t · y" nachodzil na koniec krzywej / romb w prawym gornym rogu
     (poprawka zgloszenia Jasa, punkt 2): krzywa konczy sie plateau u gory, a
     pod nim (prawy DOL obszaru wykresu) zostaje puste miejsce - tam realnie
     nie koliduje z niczym. */
  .proc-readout{top:auto;bottom:0}
  /* Odstepy scisniete na telefonie (uzupelnienie punktu 3 - zmieszczenie na
     iPhone SE po powiekszeniu wykresu): #process .sec-head scopowane tylko
     do tej sekcji, zeby nie ruszac uslug/wyceny, ktore tez uzywaja .sec-head. */
  #process .sec-head{margin-bottom:20px}
  .proc-wrap{gap:18px}
  .proc-card{padding:16px 18px}
}
/* Tryb "jedna karta": KAZDA szerokosc <=768px (bez warunku wysokosci -
   poprawka rundy 3, punkt 6: telefony wyzsze niz 720px w ogole nie
   dostawaly tego trybu i siatka 2x2 nie miescila sie razem z wykresem) ORAZ
   kazdy niski ekran niezaleznie od szerokosci (laptopy 1366x657 i podobne -
   te same "OR"-owane warunki w jednej regule przez przecinek). */
@media (max-width:768px), (max-height:720px){
  /* Stos przez CSS grid zamiast position:absolute;inset:0 na sztywnym
     min-height:110px (poprawka zgloszenia Jasa): karta miala 108px wysokosci,
     a tresc (dwuwierszowy opis) potrzebowala 121+px scrollHeight - druga
     linia wystawala poza dolna ramke. grid-area:1/1 klepie wszystkie karty w
     TA SAMA komorke siatki - niejawny wiersz siatki rosnie sam do
     najwyzszej z nich, bez zadnej sztywnej wysokosci do zgadywania.
     Przelaczanie nadal przez opacity/.is-active, bez zmian w JS. */
  /* grid-template-columns:1fr wymuszone tutaj (nie tylko dziedziczone z
     reguly @768/600px wyzej): tryb "jedna karta" moze byc aktywny przy
     szerokosciach miedzy 600 a 768px (albo przy niskim, ale szerokim oknie -
     druga galaz OR), gdzie bazowa siatka wciaz ma 2 kolumny - bez tego
     nadpisania widoczna karta zajmowalaby tylko lewa polowe, z pusta prawa. */
  html.is-motion .proc-cards{display:grid;grid-template-columns:1fr}
  /* Przejscie sekwencyjne, bez nakladania (poprawka zgloszenia Jasa, punkt 1):
     karty stoja w jednej komorce gridu, wiec dawne rownoczesne opacity .4s
     (stara gasnie / nowa zapala sie w tym samym momencie) dawaly ok. 0.4 s, w
     ktorych oba teksty lezaly na sobie. Teraz: karta NIEAKTYWNA znika szybko
     (.18s, bez opoznienia - dziala natychmiast, jak tylko traci .is-active) i
     przesuwa sie o 8px w strone, z ktorej "przyszla" (patrz .is-past nizej);
     karta AKTYWNA wchodzi dopiero PO uplywie tego czasu (transition-delay
     .18s), przez .25s, z przeciwnej strony do 0. W kazdej chwili widoczny co
     najwyzej jeden tekst. is-past/is-active ustawiane w JS (initProcess) z
     tego samego postepu (cp), co romby - kierunek dziala tak samo w obie
     strony scrolla. */
  html.is-motion .proc-cards .proc-card{
    grid-area:1/1;opacity:0;transform:translateY(8px);
    transition:opacity .18s,transform .18s;
  }
  html.is-motion .proc-cards .proc-card.is-past{transform:translateY(-8px)}
  html.is-motion .proc-cards .proc-card.is-active{
    opacity:1;transform:translateY(0);
    transition:opacity .25s .18s,transform .25s .18s;
  }
}

/* ═══════════════ 05 · WYDAJNOSC: RAPORT LIGHTHOUSE ═══════════════ */
#wydajnosc{position:relative;isolation:isolate;padding:120px 44px;max-width:1400px;margin:0 auto}
/* siatka kropek "plotna" (jak .plotno-canvas-bg) wygaszona maska radialna, pod raportem */
#wydajnosc::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(rgba(255,255,255,.12) 1px,transparent 1.4px);background-size:26px 26px;
  -webkit-mask-image:radial-gradient(62% 55% at 50% 66%,#000 18%,transparent 78%);
  mask-image:radial-gradient(62% 55% at 50% 66%,#000 18%,transparent 78%)}
.lh-intro{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:60px;align-items:end;margin-bottom:56px}
.lh-intro-l{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.lh-big{display:flex;align-items:flex-start;font:200 clamp(120px,15vw,232px)/1 var(--font);letter-spacing:-.04em;color:var(--ink);margin:2px 0 -4px}
.lh-big-plus{display:inline-block;font-size:.46em;line-height:1;margin:.12em 0 0 .06em;color:var(--mut)}
.lh-big-cap{font:400 11px var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.lh-intro-r{display:flex;flex-direction:column;align-items:flex-start;gap:18px;padding-bottom:12px}
.lh-intro-r p{font:300 15px/1.7 var(--font);color:var(--mut);max-width:46ch}

.lh-report{position:relative}
/* 4 narozniki zaznaczenia WOKOL okna (jak .artboard.is-active::after, tylko inset ujemny, 12px x 1.2px, kolor var(--mut)) */
.lh-report::after{content:'';position:absolute;inset:-8px;pointer-events:none;
  background:
    linear-gradient(var(--mut),var(--mut)) top left/12px 1.2px no-repeat,
    linear-gradient(var(--mut),var(--mut)) top left/1.2px 12px no-repeat,
    linear-gradient(var(--mut),var(--mut)) top right/12px 1.2px no-repeat,
    linear-gradient(var(--mut),var(--mut)) top right/1.2px 12px no-repeat,
    linear-gradient(var(--mut),var(--mut)) bottom left/12px 1.2px no-repeat,
    linear-gradient(var(--mut),var(--mut)) bottom left/1.2px 12px no-repeat,
    linear-gradient(var(--mut),var(--mut)) bottom right/12px 1.2px no-repeat,
    linear-gradient(var(--mut),var(--mut)) bottom right/1.2px 12px no-repeat}
.lh-window{position:relative;background:#0b0d0f;border:1px solid var(--line2);border-radius:16px;overflow:hidden;box-shadow:0 40px 120px -60px rgba(0,0,0,.9)}
.lh-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 14px;padding:14px 20px;border-bottom:1px solid var(--line);font:400 11px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mut)}
.lh-bar-l{display:flex;align-items:center;gap:14px}
.lh-status{display:inline-flex;align-items:center;gap:8px;color:var(--ink)}
.lh-status-dot{width:7px;height:7px;border-radius:50%;background:var(--ink);flex:none;transition:background .3s,box-shadow .3s}
.lh-status.is-run .lh-status-dot{animation:hudPulse 1.1s ease-in-out infinite}
.lh-status.is-done .lh-status-dot{background:#8fd19e;box-shadow:0 0 0 3px rgba(143,209,158,.16)}
.lh-bar-r{color:var(--dim);letter-spacing:.1em}

.lh-dials{list-style:none;margin:0;padding:48px 28px 40px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px;border-bottom:1px solid var(--line)}
.lh-item{display:flex;flex-direction:column;align-items:center;gap:16px}
.lh-dial{position:relative;width:min(100%,208px);aspect-ratio:1}
.lh-svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.lh-tk{fill:none;stroke:rgba(255,255,255,.13);stroke-width:8;stroke-dasharray:.2 .8}
.lh-tk-major{fill:none;stroke:rgba(255,255,255,.26);stroke-width:14;stroke-dasharray:.3 9.7}
.lh-ring.is-lit .lh-tk,.lh-ring.is-lit .lh-tk-major{stroke:var(--ink)}
.lh-mask-arc{fill:none;stroke:#fff;stroke-width:22;stroke-dasharray:100 100}
.lh-rail{fill:none;stroke:var(--line2);stroke-width:1}
.lh-arc{fill:none;stroke:var(--ink);stroke-width:1.6;stroke-dasharray:100 100}
.lh-mark line{stroke:var(--dim);stroke-width:1;stroke-dasharray:2 2;transition:stroke .3s}
.lh-mark text{font:400 11px var(--mono);fill:var(--dim);text-anchor:middle;dominant-baseline:central;transition:fill .3s}
.lh-item.is-pass .lh-mark line{stroke:var(--ink);stroke-dasharray:none}
.lh-item.is-pass .lh-mark text{fill:var(--ink)}
.lh-knob{fill:var(--bg);stroke:var(--ink);stroke-width:1.4;transition:fill .3s}
.lh-item.is-done .lh-knob{fill:var(--ink)}
.lh-num{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;pointer-events:none}
.lh-num-val{font:200 clamp(44px,4vw,62px)/1 var(--font);letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:var(--ink)}
.lh-num-max{font:400 10px var(--mono);letter-spacing:.16em;color:var(--dim)}
.lh-name{display:flex;flex-direction:column;align-items:center;gap:5px;text-align:center}
.lh-name-pl{font:400 15px var(--font);color:var(--ink)}
.lh-name-en{font:400 10px var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
@media (hover:hover) and (pointer:fine){
  .lh-ring:not(.is-lit) .lh-tk{transition:stroke .3s}
  .lh-item:hover .lh-ring:not(.is-lit) .lh-tk{stroke:rgba(255,255,255,.26)}
}

.lh-load{padding:30px 28px 26px;border-bottom:1px solid var(--line)}
.lh-load-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:14px;font:400 11px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--mut)}
.lh-load-t{font-variant-numeric:tabular-nums;color:var(--dim);text-transform:none;letter-spacing:.06em;white-space:nowrap;flex:none}
.lh-load-tv{color:var(--ink)}
.lh-track{position:relative;height:62px}
.lh-tr-base{position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--line2)}
.lh-tr-fill{position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--ink);transform-origin:0 50%;transform:scaleX(.32);will-change:transform}
/* wrapper na cala szerokosc toru: translateX(%) liczy sie od WLASNEJ szerokosci = szerokosci toru -> zero pomiarow w JS */
.lh-tr-headwrap{position:absolute;left:0;right:0;bottom:0;height:0;transform:translateX(32%);will-change:transform;z-index:1}
.lh-tr-head{position:absolute;left:-1px;bottom:-6px;width:2px;height:13px;background:var(--ink)}
.lh-key{position:absolute;left:var(--x);top:0;bottom:0;width:0;z-index:2}
.lh-key i{position:absolute;left:0;bottom:0;width:9px;height:9px;transform:translate(-50%,50%) rotate(45deg);background:#0b0d0f;box-shadow:inset 0 0 0 1.2px var(--line2);transition:background .3s,box-shadow .3s}
.lh-key.is-done i{background:var(--ink);box-shadow:none}
.lh-key.is-goal i{box-shadow:inset 0 0 0 1.2px var(--mut)}
.lh-key::before{content:'';position:absolute;left:-.5px;width:1px;bottom:8px;background:var(--line2);transition:background .3s}
.lh-key.k1::before{top:16px}
.lh-key.k2::before{top:36px}
.lh-key-lbl{position:absolute;left:8px;white-space:nowrap;font:400 10.5px var(--mono);letter-spacing:.08em;color:var(--dim);transition:color .3s}
.lh-key.k1 .lh-key-lbl{top:0}
.lh-key.k2 .lh-key-lbl{top:20px}
.lh-key.is-done::before{background:var(--mut)}
.lh-key.is-done .lh-key-lbl{color:var(--ink)}
.lh-key.is-goal .lh-key-lbl{left:auto;right:8px;color:var(--mut)}
.lh-ruler{position:relative;height:16px;margin-top:12px}
.lh-ruler span{position:absolute;left:var(--x);top:0;transform:translateX(-50%);font:400 10px var(--mono);letter-spacing:.06em;color:var(--dim);font-variant-numeric:tabular-nums;white-space:nowrap}
.lh-ruler span:first-child{transform:none}
.lh-ruler span:last-child{transform:translateX(-100%)}

.lh-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:0}
.lh-stat{padding:24px 28px 26px;display:flex;flex-direction:column;gap:10px;border-left:1px solid var(--line)}
.lh-stat:first-child{border-left:0}
.lh-stat dt{font:400 10px var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.lh-stat dd{margin:0;display:flex;flex-direction:column;gap:6px}
.lh-stat-v{font:200 clamp(28px,2.6vw,38px)/1 var(--font);color:var(--ink);font-variant-numeric:tabular-nums}
.lh-stat-d{font:300 12.5px/1.5 var(--font);color:var(--mut)}
.lh-note{margin-top:18px;font:400 11px var(--mono);letter-spacing:.04em;color:var(--dim)}
/* Stany startowe tylko pod html.is-motion (bazowy dokument bez JS ma byc w pelni widoczny) */
html.is-motion .lh-window{opacity:0}
html.is-motion .lh-report::after{opacity:0;transition:opacity .6s .25s}
html.is-motion .lh-report.is-in::after{opacity:1}
@media (max-width:900px){
  #wydajnosc{padding:90px 22px}
  .lh-intro{grid-template-columns:1fr;gap:26px;margin-bottom:40px}
  .lh-dials{grid-template-columns:repeat(2,minmax(0,1fr));gap:34px 14px;padding:34px 18px 30px}
  .lh-stats{grid-template-columns:repeat(2,minmax(0,1fr))}
  .lh-stat{padding:20px 18px;border-left:0;border-top:1px solid var(--line)}
  .lh-stat:nth-child(-n+2){border-top:0}
  .lh-stat:nth-child(2n){border-left:1px solid var(--line)}
}
@media (max-width:768px){
  .lh-big{font-size:clamp(104px,34vw,150px)}
  .lh-dial{width:min(100%,168px)}
  .lh-num-val{font-size:clamp(34px,10vw,46px)}
  .lh-bar{padding:12px 16px;font-size:10px}
  .lh-load{padding:24px 16px 22px}
  .lh-report::after{inset:-6px}
  /* znacznik "90" na tarczy: .lh-mark text nie mial wlasnego rozmiaru w px
     (font-size dziedziczony z domyslnego rozmiaru SVG), po przeskalowaniu
     tarczy do ok. 168px szerokosci (.lh-dial wyzej) wychodzil ledwo czytelny,
     ok. 6px. */
  .lh-mark text{font-size:15px}
}
/* .lh-big ma line-height:1 - .ch-mask dostaje odstep u gory, zeby gorne
   krawedzie cyfr "90" nie byly przycinane przez overflow:hidden maski. */
.lh-big .ch-mask{padding-top:.06em;margin-top:-.06em}
/* Bardzo waskie ekrany (poprawka rundy 4, punkt 6 - zgloszenie z testu na
   320px): etykieta "FCP · 0,4 s" nachodzila na "prog Google · 2,5 s", tytul
   osi i odczyt "t 0,80 s" lamaly sie na dwie linie, a na linijce podzialki
   "2,0" dotykalo "2,5 s". .lh-sm-hide chowa mniej wazny fragment etykiet
   (patrz index.html), a linijka podzialki zostaje tylko z "0 s"/"1,0"/"2,5 s". */
@media (max-width:480px){
  .lh-sm-hide{display:none}
  .lh-ruler span:nth-child(2),.lh-ruler span:nth-child(4),.lh-ruler span:nth-child(5){display:none}
}

/* ═══════════════ 06 · WYCENA ═══════════════ */
#wycena{padding:120px 44px;max-width:1400px;margin:0 auto}
.wyc-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(360px,560px);gap:60px;align-items:start}
.wyc-copy{display:flex;flex-direction:column;align-items:flex-start;gap:18px}
.wyc-copy p{font:300 15px/1.65 var(--font);color:var(--mut);max-width:42ch}
.wyc-demo{display:flex;flex-direction:column;gap:18px}
.browser-frame{border-radius:14px;overflow:hidden;box-shadow:0 30px 80px -40px rgba(0,0,0,.6)}
.browser-top{height:38px;background:#eef0f2;display:flex;align-items:center;gap:10px;padding:0 14px}
.bf-dot{width:8px;height:8px;border-radius:50%;background:#c3c8cd;flex:none}
.bf-addr{margin-left:8px;font:400 11px var(--mono);color:#5a6168;background:#dfe2e5;padding:5px 12px;border-radius:6px}
/* Siatka na CALA wysokosc ramki (poprawka rundy 1): 2 kolumny, Hero i trzy
   szerokie moduly na dole (Wideo/Koszyk/Platnosci) rozpiete na cala
   szerokosc - dawny uklad 4-kolumnowy zostawial pol ramki puste, bo wiekszosc
   slotow siedziala w gornej polowie. */
.browser-view{
  position:relative;background:#0b0d0f;padding:16px;
  display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:34px;gap:8px;
}
.slot{border:1.5px dashed var(--line2);border-radius:8px;position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden}
.slot::after{
  content:attr(data-modul);font:400 9.5px var(--mono);letter-spacing:.06em;color:var(--faint);
  opacity:.65;transition:opacity .2s,color .2s,font-size .2s;
}
/* Wypelniony slot ma wygladac jak realny, widoczny kafel (nie tylko
   podpisana ramka) - poprawka rundy 1, punkt "kafle maja byc widoczne". */
.slot.is-filled{
  border-style:solid;border-color:rgba(255,255,255,.22);
  background:linear-gradient(155deg,#1d2226,#15181b);
  box-shadow:0 10px 26px -14px rgba(0,0,0,.7),inset 0 0 0 1px rgba(255,255,255,.04);
}
.slot.is-filled::after{opacity:1;color:var(--ink);font-size:11px;font-weight:400}
.slot-hero{grid-column:1/-1;grid-row:span 3}
.slot-sekcje{grid-column:1/2;grid-row:span 2}
.slot-galeria{grid-column:2/3;grid-row:span 2}
.slot-formularz{grid-column:1/2;grid-row:span 2}
.slot-animacje{grid-column:2/3;grid-row:span 2}
.slot-wideo{grid-column:1/-1;grid-row:span 2}
.slot-podstrony{grid-column:1/2;grid-row:span 2}
.slot-cms{grid-column:2/3;grid-row:span 2}
.slot-koszyk{grid-column:1/-1;grid-row:span 2}
.slot-platnosci{grid-column:1/-1;grid-row:span 2}
.fly-tile{position:absolute;font:400 10px var(--mono);letter-spacing:.06em;color:var(--ink);background:#1d2226;border-radius:6px;padding:6px 10px;box-shadow:0 10px 24px -10px rgba(0,0,0,.6);opacity:0;pointer-events:none}
.wyc-counter{display:flex;flex-direction:column;gap:6px}
.wyc-counter-name{font:400 15px var(--font);color:var(--ink)}
/* Format "okolo 5 350 zl": "okolo" mono i male, liczba duza z NBSP jako
   separatorem tysiecy (wstawiany w JS), "zl" ok. 45% rozmiaru liczby,
   wszystko na jednej linii wyrownane do linii bazowej (poprawka rundy 1). */
.wyc-counter-value{display:flex;align-items:baseline;gap:10px;font-variant-numeric:tabular-nums}
.wyc-about{font:400 12px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}
.wyc-number{font:200 clamp(32px,3.4vw,46px)/1 var(--font);color:var(--ink);white-space:nowrap}
.wyc-suffix{font:300 clamp(15px,1.6vw,20px) var(--font);color:var(--mut)}
/* --dim, nie --faint (poprawka rundy 3, punkt 14): #565f66 na #050607 dawal
   3.11:1, ponizej progu 4.5:1 dla tresci informacyjnej (nie dekoracyjnej). */
.wyc-note{font:400 11px var(--mono);letter-spacing:.04em;color:var(--dim)}
@media (max-width:900px){
  #wycena{padding:90px 22px}
  .wyc-grid{grid-template-columns:1fr;gap:36px}
}

/* ═══════════════ 07 · ASYSTENT AI ═══════════════ */
#asystent{padding:120px 44px;max-width:1400px;margin:0 auto}
.teaser-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(340px,440px);gap:60px;align-items:start}
.teaser-copy{display:flex;flex-direction:column;align-items:flex-start;gap:18px}
.teaser-copy p{font:300 15px/1.7 var(--font);color:var(--mut);max-width:44ch}
.chat-demo{width:100%;max-width:440px;margin:0 auto}
/* Wysokosc ograniczona (poprawka rundy 1): bez max-height okno bylo bardzo
   wysokie i przez wiekszosc petli w duzej czesci puste. flex-column + body
   jako flex:1 z justify-content:flex-end sprawia, ze wiadomosci "rosna od
   dolu" jak w prawdziwym komunikatorze, zamiast stac przyklejone do gory
   nad morzem pustego miejsca. */
.chat-window{
  display:flex;flex-direction:column;max-height:520px;
  border:1px solid var(--line2);border-radius:20px;overflow:hidden;
  background:rgba(255,255,255,.03);box-shadow:0 30px 80px -40px rgba(0,0,0,.6);transform-style:preserve-3d;
}
.chat-head{flex:none;display:flex;align-items:center;gap:12px;padding:16px 18px;border-bottom:1px solid var(--line)}
.chat-avatar{width:34px;height:34px;border-radius:50%;background:var(--ink);color:#050607;display:grid;place-items:center;font:400 12px var(--font);flex:none}
.chat-head-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.chat-firm{font:400 13px var(--font);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chat-tag{font:400 10px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.chat-disclosure{flex:none;padding:8px 18px;font:400 10px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--dim);background:rgba(255,255,255,.03);border-bottom:1px solid var(--line);text-align:center}
.chat-body{flex:1;min-height:0;overflow:hidden;padding:20px 18px;display:flex;flex-direction:column;justify-content:flex-end;gap:12px;position:relative}
.chat-bubble{max-width:82%;padding:11px 15px;border-radius:16px;font:300 13.5px/1.5 var(--font)}
.chat-bubble.is-user{align-self:flex-end;background:var(--ink);color:#050607;border-bottom-right-radius:4px}
.chat-bubble.is-bot{align-self:flex-start;background:rgba(255,255,255,.06);color:var(--ink);border:1px solid var(--line2);border-bottom-left-radius:4px}
.chat-typing{align-self:flex-start;display:flex;gap:5px;padding:14px 16px;border-radius:16px;border:1px solid var(--line2);background:rgba(255,255,255,.06);border-bottom-left-radius:4px}
.chat-typing span{width:6px;height:6px;border-radius:50%;background:var(--dim);animation:chatDot 1.1s ease-in-out infinite}
.chat-typing span:nth-child(2){animation-delay:.15s}
.chat-typing span:nth-child(3){animation-delay:.3s}
@keyframes chatDot{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.chat-form{align-self:stretch;display:flex;flex-direction:column;gap:8px;padding:14px 16px;border-radius:14px;border:1px solid var(--line2);background:rgba(255,255,255,.03)}
.chat-form-label{font:400 10px var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.chat-form input{font:300 13px var(--font);padding:9px 12px;border-radius:8px;border:1px solid var(--line2);background:rgba(255,255,255,.02);color:var(--ink)}
.chat-form input::placeholder{color:var(--faint)}
.chat-form-btn{align-self:flex-start;font:400 12.5px var(--font);color:#050607;background:var(--ink);padding:8px 18px;border-radius:999px}
@media (max-width:900px){
  #asystent{padding:90px 22px}
  .teaser-grid{grid-template-columns:1fr;gap:40px}
}

/* ═══════════════ 08 · ZORNA × ONE (JASNE TLO) ═══════════════ */
#zorna-x-one{background:#fafaf7;color:#050607;padding:100px 0;position:relative;overflow:hidden}
/* Taśma CIEMNA (#0b0d0f) na jasnym tle sekcji, z perforacjami jak prawdziwy
   film (SPEC, brak wzgledem specu): poprzednio taśma byla przezroczysta,
   wiec kadry "plywaly" bezposrednio na jasnym tle bez wyczucia filmu. */
.one-tasma{position:relative;margin-bottom:70px;background:#0b0d0f;padding:0}
.one-tasma-perf{height:8px;background:repeating-linear-gradient(90deg,rgba(255,255,255,.75) 0 6px,transparent 6px 20px)}
.one-tasma-row{display:flex;gap:14px;overflow-x:auto;padding:14px 24px;scrollbar-width:none}
.one-tasma-row::-webkit-scrollbar{display:none}
.one-kadr{flex:none;width:min(280px,72vw);margin:0;display:flex;flex-direction:column;gap:6px}
.one-kadr img,.one-kadr video{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:4px;background:#111}
.one-kadr figcaption{font:400 9.5px var(--mono);letter-spacing:.06em;color:rgba(255,255,255,.55);text-align:center}
.one-inner{max-width:760px;margin:0 auto;padding:0 6vw;display:flex;flex-direction:column;align-items:flex-start;gap:20px}
/* #54584d, nie #7a7f74 (poprawka rundy 3, punkt 14): stary odcien na #fafaf7
   dawal 3.93:1, ponizej 4.5:1. */
#zorna-x-one .sec-label{color:#54584d}
#zorna-x-one p{font:300 16px/1.65 var(--font);color:#3a3d38;max-width:60ch}
.one-lockup{display:flex;align-items:center;gap:12px;margin-top:6px}
.one-lockup-logo{width:30px;height:30px;object-fit:contain}
.one-lockup-x{font:400 15px var(--mono);color:#54584d}
.one-lockup-glyph{width:13px;height:auto;color:#050607}
.one-lockup-name{font:600 18px var(--font);letter-spacing:.04em}
.one-cta-row{display:flex;flex-wrap:wrap;align-items:center;gap:20px;margin-top:8px}
.one-ext-link{font:400 13px var(--mono);letter-spacing:.06em;color:#050607;border-bottom:1px solid rgba(5,6,7,.3);padding-bottom:2px;transition:border-color .25s}
.one-ext-link:hover{border-color:#050607}
@media (max-width:768px){
  #zorna-x-one{padding:70px 0}
  .one-tasma{margin-bottom:44px}
}

/* ═══════════════ 09 · PYTANIA ═══════════════ */
#faq{padding:120px 44px;max-width:1100px;margin:0 auto}
.faq-list{display:flex;flex-direction:column;border-bottom:1px solid var(--line2)}
.faq-item{border-top:1px solid var(--line2)}
.faq-q{width:100%;display:grid;grid-template-columns:56px 1fr auto;gap:22px;align-items:center;padding:26px 8px;text-align:left;transition:background .3s}
.faq-q:hover{background:rgba(255,255,255,.03)}
.faq-num{font:200 20px var(--font);color:var(--faint)}
.faq-title{font:300 clamp(16px,1.6vw,20px) var(--font)}
.faq-icon{font:200 26px/1 var(--font);color:var(--faint);transition:transform .4s var(--ease),color .3s}
.faq-item.is-open .faq-icon{transform:rotate(45deg);color:var(--ink)}
.faq-a{overflow:hidden;height:0}
.faq-a p{margin:0;padding:0 8px 28px 78px;font:300 14px/1.7 var(--font);color:var(--mut);max-width:64ch}
.faq-a a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
@media (max-width:768px){
  #faq{padding:90px 20px}
  .faq-q{grid-template-columns:auto 1fr auto;gap:14px;padding:20px 2px}
  .faq-a p{padding:0 2px 22px 30px;font-size:13.5px}
}

/* ═══════════════ 10 · KONTAKT ═══════════════ */
#contact{position:relative;padding:170px 44px;overflow:hidden}
.contact-bg{position:absolute;inset:0;opacity:.3}
.contact-vignette{position:absolute;inset:0;pointer-events:none;background:radial-gradient(120% 100% at 50% 50%,transparent 20%,rgba(5,6,7,.9) 85%)}
.contact-inner{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:28px;text-align:center;max-width:720px;margin:0 auto}
/* Dwie linie na sztywno ("Wprawmy to" / "w ruch.") - poprawka rundy 1: model
   z jednym splitCharsem lamal sie losowo w zaleznosci od szerokosci ekranu
   (kropka potrafila wyladowac na osobnej linii). .cw-line2 ma white-space:
   nowrap, wiec "w ruch" i kropka juz nigdy sie nie rozdzielaja - telefon
   dostaje wiecej linii tylko przez zawiniecie .cw-line1, nigdy .cw-line2. */
.contact-word{font:300 clamp(42px,7vw,92px)/1.08 var(--font);letter-spacing:-.02em;display:flex;flex-direction:column;align-items:center;text-align:center}
.cw-line2{white-space:nowrap;display:flex;align-items:baseline;justify-content:center}
.contact-dot{width:.13em;height:.13em;border-radius:50%;background:var(--ink);margin-left:.05em;align-self:baseline;animation:pulse 1.6s ease-in-out infinite}
.contact-inner>p{font:300 16px/1.6 var(--font);color:var(--mut);max-width:46ch}
.contact-btn{font:400 15px var(--font);letter-spacing:.04em;color:#050607;background:var(--ink);padding:18px 44px;border-radius:999px;transition:translate .3s var(--ease),box-shadow .3s}
.contact-btn:hover{translate:0 -3px;box-shadow:0 14px 40px -12px rgba(255,255,255,.25)}
.contact-form{width:min(560px,100%);display:flex;flex-direction:column;gap:14px;text-align:left;padding:26px;border-radius:18px;border:1px solid var(--line2);background:rgba(6,8,10,.78);backdrop-filter:blur(8px)}
.cf-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.cf-grid .cf-field:first-child{grid-column:1/-1}
.cf-field{display:flex;flex-direction:column;gap:7px}
.cf-label{font:400 10px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.cf-input{font:300 15px var(--font);color:var(--ink);background:rgba(255,255,255,.04);border:1px solid var(--line2);border-radius:10px;padding:12px 14px;width:100%;transition:border-color .25s var(--ease),background .25s var(--ease)}
.cf-input::placeholder{color:var(--faint)}
.cf-input:hover{border-color:rgba(255,255,255,.28)}
.cf-input:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.cf-area{resize:vertical;min-height:104px;line-height:1.6}
.cf-submit{align-self:flex-start;margin-top:4px}
.cf-submit[disabled]{opacity:.55;cursor:progress}
.cf-status{font:300 13.5px/1.5 var(--font);color:var(--mut);min-height:1.2em}
.cf-status.is-error{color:#c9915a}
.cf-status.is-ok{color:#8fd19e}
.cf-alt-group{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 26px}
.cf-alt{font:300 14px var(--font);color:var(--mut);border-bottom:1px solid var(--line2);padding-bottom:3px;transition:color .25s var(--ease),border-color .25s var(--ease)}
.cf-alt:hover{color:var(--ink);border-color:var(--ink)}
@media (max-width:768px){
  #contact{padding:100px 22px}
  .contact-form{padding:20px;gap:12px}
  .cf-grid{grid-template-columns:1fr}
  .cf-input{font-size:16px}
  .cf-submit{align-self:stretch;text-align:center}
}

/* ═══════════════ STOPKA ═══════════════ */
/* padding-bottom spory celowo: HUD (fixed) zajmuje dolny pas ekranu (status +
   os czasu), wiec przy scrollu do samego konca strony musi zostac zapas,
   zeby "KL 02400 / 02400" z .foot-end-bar nie chowalo sie pod HUD-em. */
footer{display:flex;flex-direction:column;gap:22px;padding:30px 44px 96px;border-top:1px solid var(--line)}
.foot-left{display:flex;align-items:center;gap:10px;font:300 13px var(--font);color:var(--dim)}
.foot-left-text{display:flex;flex-direction:column;align-items:flex-start;gap:2px}
.foot-legal{font:300 11px var(--font);color:var(--dim)}
.foot-tel{transition:color .25s var(--ease)}
.foot-tel:hover{color:var(--ink)}
.foot-time{display:flex;align-items:center;gap:9px;font:400 11px var(--mono);letter-spacing:.12em;color:var(--dim);font-variant-numeric:tabular-nums}
.foot-links{display:flex;flex-wrap:wrap;gap:20px}
.foot-links .nav-link{font:400 11px var(--mono);letter-spacing:.04em;color:var(--dim);transition:color .25s}
.foot-links .nav-link:hover{color:var(--ink)}
.foot-break{display:none}
.foot-end-bar{display:flex;justify-content:space-between;align-items:center;gap:14px;padding-top:18px;border-top:1px solid var(--line);flex-wrap:wrap}
.foot-end-text{font:400 10px var(--mono);letter-spacing:.1em;color:var(--faint)}
.foot-end-top{font:400 10px var(--mono);letter-spacing:.1em;color:var(--dim);transition:color .25s}
.foot-end-top:hover{color:var(--ink)}
@media (min-width:769px){
  footer{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between}
  .foot-end-bar{width:100%;order:3}
}
@media (max-width:768px){
  footer{padding:26px 20px 88px}
}

/* ═══════════════════════════════════════════════════════════════════
   html.is-motion — warstwy absolutne i przypiecia (tylko >=769px dla
   sceny "Plotno"; telefon dostaje wlasny, krotszy pin - patrz nizej).
   Wlacza sie tylko gdy js/home.js potwierdzil GSAP + ScrollTrigger i
   brak prefers-reduced-motion. ═══════════════════════════════════════ */
html.is-motion #site-header{opacity:0}
html.is-motion .plotno-chaptertext{opacity:0}

@media (min-width:769px){
  html.is-motion #scena{height:100vh;height:100svh;overflow:clip;position:relative}
  html.is-motion .plotno-hero,
  html.is-motion .plotno-row,
  html.is-motion .plotno-chaptertext{position:absolute;inset:0;padding-top:0}
  /* Kolejnosc warstw (poprawka rundy 1, FLIP): .plotno-hero (wiec i prawdziwy
     .hero-artboard z wideo w srodku) musi renderowac sie NAD .plotno-row, bo
     po wyladowaniu wideo ma zakrywac pusty placeholder slotu 0 pod spodem -
     bez tego karta rzedu (pozniejsza w DOM) rysowalaby sie na wierzchu wideo. */
  html.is-motion .plotno-hero{z-index:2}
  html.is-motion .plotno-row{z-index:1}
  /* Blok tekstu w GORNEJ lewej cwiartce (poprawka rundy 2, punkt 2): dawniej
     wyscentrowany w pionie (top:50%) siedzial na wysokosci rzedu artboardow i
     "proximity" gasila go niemal natychmiast. Teraz ma wlasna, gorna strefe
     (top:14vh), a rzad jedzie nizej (top:59vh na .plotno-row ponizej) - obie
     strefy normalnie sie nie stykaja. */
  html.is-motion .plotno-chaptertext{
    inset:auto;left:6vw;top:14vh;transform:none;
    padding:0;max-width:min(40vw,480px);z-index:3;
  }
  /* Bez specjalnego padding-left (poprawka rundy 1, FLIP): pozycjonowanie
     kazdego slotu (w tym slotu 0) liczy JS z rzeczywistych offsetow +
     translateX rzedu (patrz measureRow/rowTick w initScena), wiec dowolny
     padding tutaj tylko przesuwalby punkt odniesienia bez potrzeby. Rzad
     wyscentrowany na wysokosci ~59vh (nie 50%, poprawka rundy 2): yPercent:-50
     ustawiony raz w JS (initScena), top:59vh tutaj w CSS - z zapasem nad
     strefa HUD na kazdej sprawdzonej wysokosci (720/900/1080). */
  html.is-motion .plotno-row{
    inset:auto;left:0;right:0;top:59vh;
    display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:34px;
    padding:0;width:max-content;max-width:none;will-change:transform;opacity:0;
  }
  html.is-motion .plotno-row .artboard{width:30vw;flex:none}
  html.is-motion .plotno-row .artboard.is-wide{width:30vw}
  html.is-motion .plotno-row .artboard-final{width:24vw;min-height:0;aspect-ratio:16/10}
  html.is-motion .plotno-row .artboard-hero-slot{display:flex}
  html.is-motion .plotno-canvas-bg{opacity:0}
  /* Kazda warstwa sceny domyslnie przezroczysta na kliki (nachodza na siebie
     przez position:absolute;inset:0) - bez tego niewidoczny, przygaszony
     element z gornej warstwy DOM (np. pusty obszar .plotno-row) przechwytywal
     kliki nalezne linkom pod spodem. Wlaczamy pointer-events z powrotem
     tylko na faktycznie klikalnych elementach. */
  html.is-motion .plotno-hero,
  html.is-motion .plotno-row,
  html.is-motion .plotno-chaptertext{pointer-events:none}
  html.is-motion .plotno-hero .hero-cta a,
  html.is-motion .plotno-hero .hero-one-pill,
  html.is-motion .plotno-chaptertext .teaser-cta,
  html.is-motion .plotno-row .artboard{pointer-events:auto}
  /* aspect-ratio 16/10 (nie 16/9): zgodne z etykieta "1440 x 900" NAD
     artboardem i z proporcja .ab-media kart w rzedzie (poprawka rundy 1,
     FLIP) - dzieki temu skalowanie do rozmiaru slotu 0 jest dokladne, bez
     rozjazdu ksztaltu. */
  html.is-motion .hero-artboard{
    inset:auto;left:50%;top:50%;width:60vw;aspect-ratio:16/10;
    border-radius:4px;will-change:transform;overflow:hidden;
  }
  html.is-motion .sel-handles{will-change:opacity}
}
@media (max-width:768px){
  /* height (nie min-height) + overflow:hidden: siatka zabezpieczajaca. JS
     przypina ".plotno-hero" na dokladnie zadana odleglosc scrolla
     (+=120%, patrz initScena w js/home.js) - gdyby na jakims urzadzeniu
     tresc hero i tak nie zmiescila sie w jednym ekranie (mimo zciasnien
     wyzej), element ma twarda wysokosc 100svh zamiast rosnac ponad
     przypiety obszar i rozjezdzac sie z dlugoscia pinu/spacera. */
  html.is-motion .plotno-hero{height:100svh;min-height:0;overflow:clip}
  html.is-motion .hero-artboard{
    inset:auto;left:50%;top:50%;width:86vw;aspect-ratio:16/9;
    border-radius:4px;overflow:hidden;will-change:transform;
  }
}

html.is-motion #zorna-x-one .one-tasma-row{will-change:transform}
html.is-motion .one-tasma{overflow:hidden}
html.is-motion .one-tasma-row{overflow:visible}

/* Strefa bezpieczna HUD (poprawka rundy 1): tylko w is-motion, tylko dolny
   margines - w bazowym dokumencie (bez JS/reduced) nie ma stalego HUD-a na
   dole, wiec dodatkowy odstep byłby tam niepotrzebny. Dotyczy sekcji, ktore
   bywaja przypiete (caly ekran) i moga miec wlasna tresc blisko dolnej
   krawedzi w momencie pinu. */
html.is-motion #services,
html.is-motion #process,
html.is-motion #wycena{padding-bottom:calc(120px + var(--hud-safe))}
@media (max-width:768px){
  html.is-motion #services,
  html.is-motion #process,
  html.is-motion #wycena{padding-bottom:calc(90px + var(--hud-safe))}
}
@media (max-height:720px){
  /* Niskie ekrany (poprawka rundy 3, punkt 6/7): 120px gornego/dolnego
     odstepu to duzo na ekranie wysokim na 657-720px - #process jest
     przypiety na caly ekran, wiec kazdy zaoszczedzony piksel pomaga tresci
     zmiescic sie w jednym kadrze. */
  html.is-motion #services,
  html.is-motion #process,
  html.is-motion #wycena{padding-top:64px;padding-bottom:calc(64px + var(--hud-safe))}
}

/* prefers-reduced-motion dziala NIEZALEZNIE od is-motion (js/home.js i tak
   nigdy nie dokleja is-motion, gdy jest wlaczone reduced-motion - ale czysto
   CSS-owe animacje dekoracyjne, np. puls kropek, maja zgasnac zawsze). */
@media (prefers-reduced-motion: reduce){
  *{animation:none!important}
}
