/* ============================================================
   PROJEKTOWANIE GRAFICZNE — PRACOWNIA PO CIEMKU
   Podstrona wraca do ciemnego świata serwisu: czerń pola, siatka heksów,
   jeden zimny błękit na wszystko, co reaguje, Vogjer w nagłówkach,
   Montserrat 500 w treści.

   Pierwsza sekcja stoi na zdjęciu własnej pracowni (`assets/gfl/`),
   przestrojonym na paletę serwisu — oryginał świeci magentą, a zasada
   jednego akcentu na to nie pozwala. Na zdjęciu leży szklany blok
   z obwodem światła biegnącym po krawędzi i bryłą three.js pod listą.

   Zmienne globalne (`--blue`, `--bg`, `--ink`, `--frame`, `--ease`)
   pochodzą ze `styles.css`.

   Klasa `body` NIE może nazywać się `gfx` — pod tą nazwą w `styles.css`
   siedzi karta pracy z `transform` i `preserve-3d`, a transform na `body`
   robi z niego blok zawierający dla przypiętej stopki i stopka odjeżdża
   poza ekran.
   ============================================================ */

body.gfl-strona{
  --tusz:#eaf3ff;
  --tusz-2:rgba(206,226,255,.72);
  --tusz-3:rgba(206,226,255,.5);
  --akcent:#7cb3ff;
  --linia:rgba(124,179,255,.16);
  --linia-mocna:rgba(124,179,255,.38);
  --szybko:cubic-bezier(.2,.8,.2,1);

  background:var(--bg);
  color:var(--tusz);
}
/* Kryjące tło z siatką heksów — bez niego przez treść prześwituje
   przypięta stopka, która leży pod nią jako element `fixed`. */
body.gfl-strona .gfl,
body.gfl-strona .gfl__stopa{
  background-color:var(--bg);
  background-image:
    linear-gradient(rgba(2,4,9,.955),rgba(2,4,9,.955)),
    url('assets/hex.svg');
  background-repeat:no-repeat,repeat;
  background-size:auto,84px 48.497px;
  background-attachment:fixed,fixed;
}

.gfl{position:relative;z-index:1;padding-bottom:clamp(30px,5vh,60px)}
.gfl > :last-child{margin-bottom:0}

/* ============================================================
   1. PIERWSZY KADR — TEKST PO LEWEJ, TABLET PO PRAWEJ
   Proporcje zmierzone z linii pomocniczych na makiecie właściciela
   (obraz 1863×922 px):
     • lewa krawędź tekstu   199 px → 10,7% szerokości
     • linia podziału kolumn 1041 px → 55,9%
     • prawa krawędź tabletu 1669 px → 89,6%  (margines 10,4%)
     • pas treści           141–784 px → 15,3%–85% wysokości
     • tablet               104–856 px → 81,6% wysokości, czyli wyższy
       od pasa tekstu i celowo z niego wystający
   Tło jest zwykłe: ciemne pole z siatką heksów maluje `.gfl` wyżej,
   ta sekcja niczego na nie nie nakłada.
   ============================================================ */
.gfl__hero{
  --mx:0;--my:0;
  position:relative;
  min-height:100svh;
  display:grid;align-items:center;
  /* Równo u góry i u dołu. Górny padding musi zmieścić nawigację, więc
     to on wyznacza obie wartości — inaczej treść siada za nisko i nad nią
     zostaje pusty pas. */
  --oddech:clamp(96px,13svh,132px);
  padding:var(--oddech) clamp(24px,10.4vw,200px) var(--oddech) clamp(24px,10.7vw,205px);
  isolation:isolate;
}

/* ---------------- akcenty przy krawędziach ---------------- */
/* Numer sekcji z kreską biegnącą w górę — po lewej, przy krawędzi. */
.gfl__nr{
  position:absolute;z-index:2;right:clamp(10px,1.9vw,34px);bottom:clamp(104px,14vh,150px);
  margin:0;pointer-events:none;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.2em;color:var(--tusz-3);
}
.gfl__nr::before{
  content:"";position:absolute;left:50%;bottom:calc(100% + 10px);
  width:1px;height:clamp(40px,9vh,90px);translate:-50% 0;
  background:linear-gradient(to top,var(--linia-mocna),transparent);
}

/* Pionowy podpis przy LEWEJ krawędzi — prawy pas należy teraz do
   wskaźnika postępu i stały dwie rzeczy jedna na drugiej. */
.gfl__szyna{
  position:absolute;z-index:2;top:50%;margin:0;
  translate:0 -50%;pointer-events:none;
  font-family:'Vogjer',sans-serif;font-weight:400;line-height:1;
  font-size:clamp(11px,1.15vw,19px);letter-spacing:.14em;
  text-transform:uppercase;white-space:nowrap;
  color:rgba(206,226,255,.26);
}
.gfl__szyna span{display:block;writing-mode:vertical-rl}
.gfl__szyna--p{left:clamp(10px,1.9vw,34px)}
/* Przy lewej krawędzi napis czyta się z dołu do góry — tak stoi
   na makiecie właściciela. */
.gfl__szyna--p span{rotate:180deg}

/* ---------------- lewa kolumna ---------------- */
/* Szerokość kolumny wprost z makiety: 199→1041 px z 1863, czyli 45,2%
   kadru. Tablet leży obok jako warstwa, więc to ta liczba pilnuje, żeby
   tekst pod niego nie wszedł. */
.gfl__tresc{position:relative;z-index:2;min-width:0;max-width:45.2vw}

/* Nadtytuł: kropka, tekst, kreska w prawo. */
.gfl__oko{
  display:flex;align-items:center;gap:12px;margin:0 0 clamp(14px,2vh,24px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:var(--akcent);
}
.gfl__oko i{
  flex:none;width:6px;height:6px;border-radius:50%;
  background:var(--akcent);box-shadow:0 0 0 4px rgba(124,179,255,.16);
}
.gfl__oko s{
  flex:1;max-width:120px;height:1px;text-decoration:none;
  background:linear-gradient(to right,var(--linia-mocna),transparent);
}

.gfl__h1{
  margin:0;
  font-family:'Vogjer',sans-serif;font-weight:400;
  /* Górny limit dobrany tak, żeby najdłuższy wiersz („PROJEKTOWANIE")
     mieścił się w lewej kolumnie — przy większym stopniu wchodził pod
     tablet. */
  font-size:clamp(30px,3.9vw,56px);line-height:1;letter-spacing:.01em;
  text-transform:uppercase;color:var(--tusz);
}
/* Środkowy wiersz niesie jedyny akcent nagłówka. */
.gfl__h1 em{font-style:normal;color:var(--akcent)}

/* Opis w miejscu zaznaczonym na makiecie ramką — między nagłówkiem
   a rzędem atutów. */
.gfl__opis{margin:clamp(16px,2.4vh,26px) 0 0;max-width:54ch}
.gfl__opis p{
  margin:0 0 clamp(8px,1.1vh,13px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11.5px,.8vw,13.5px);line-height:1.78;color:var(--tusz-2);
}
.gfl__opis p:last-child{margin-bottom:0;color:var(--tusz-3)}

/* Trzy rzeczy, które klient dostaje — ikona w heksie, nazwa, dopisek. */
.gfl__atuty{
  /* Trzy w rzędzie, nie zawijane: przy zawijaniu ostatni zostawał sam
     w drugim wierszu i rząd przestawał czytać się jako jedna rzecz. */
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(10px,1.2vw,20px);
  margin:clamp(18px,2.6vh,30px) 0 0;padding:0;list-style:none;
}
.gfl__atuty li{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  align-items:center;column-gap:10px;
}
.gfl__atuty b{
  grid-column:2;align-self:end;
  font-family:'Montserrat',sans-serif;font-weight:600;
  font-size:13px;line-height:1.2;color:var(--tusz);
}
.gfl__atuty i{
  grid-column:2;align-self:start;font-style:normal;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--tusz-3);
}
.gfl__ikona{
  grid-row:1 / 3;
  display:grid;place-items:center;width:38px;height:43px;
  /* Heks, nie kółko — ta sama geometria, co wszędzie w serwisie. */
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  background:linear-gradient(160deg,rgba(124,179,255,.22),rgba(124,179,255,.07));
  color:var(--akcent);
}
.gfl__ikona svg{width:17px;height:17px}

.gfl__akcje{
  display:flex;flex-wrap:wrap;align-items:center;gap:clamp(14px,2vw,28px);
  margin:clamp(22px,3vh,36px) 0 0;
}
/* Przycisk mniejszy niż domyślny wariant serwisu — kształt i zachowanie
   bez zmian, schodzi tylko skala. */
.gfl__cta{
  padding:12px 22px;
  font-size:10px;letter-spacing:.16em;
}
.gfl__cta .pbtn__ar{width:15px;height:15px}

/* Drugie wyjście — sam tekst i strzałka w kole, żeby nie konkurowało
   z przyciskiem głównym. */
.gfl__drugi{
  display:inline-flex;align-items:center;gap:12px;
  text-decoration:none;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--tusz-2);
  transition:color .35s var(--szybko);
}
.gfl__drugi i{
  display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--linia-mocna);color:var(--akcent);
  transition:background .35s var(--szybko),transform .35s var(--szybko);
}
.gfl__drugi i svg{width:15px;height:15px}
.gfl__drugi:hover{color:var(--tusz)}
.gfl__drugi:hover i{background:rgba(124,179,255,.14);transform:translateX(3px)}

/* Licznik przy dolnej krawędzi kolumny, rozdzielony kreskami. */
.gfl__licz{
  display:flex;flex-wrap:wrap;gap:clamp(18px,2.6vw,40px);
  margin:clamp(22px,3vh,40px) 0 0;padding-top:clamp(16px,2.2vh,26px);
  border-top:1px solid var(--linia);
}
.gfl__licz > div{position:relative;padding-right:clamp(18px,2.6vw,40px)}
.gfl__licz > div:not(:last-child)::after{
  content:"";position:absolute;right:0;top:50%;translate:0 -50%;
  width:1px;height:26px;background:var(--linia);
}
.gfl__licz dt{
  /* Montserrat, nie Vogjer: stylizowane cyfry Vogjera w tym stopniu
     czytają się jak przekreślone. Tak samo numerowane są kroki procesu. */
  font-family:'Montserrat',sans-serif;font-weight:600;
  font-size:clamp(20px,2.1vw,30px);line-height:1;letter-spacing:.02em;
  color:var(--tusz);
}
.gfl__licz dd{
  margin:7px 0 0;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--tusz-3);
}

/* ---------------- prawa kolumna: tablet ----------------
   Tablet jest wyższy od pasa treści i celowo z niego wystaje — tak stoi
   na makiecie. Wysokość prowadzi, szerokość wynika z proporcji pliku
   ramy; `max-width` przejmuje ster, gdy kolumna jest węższa niż ta
   wysokość by wymagała. */
.gfl__tablet{
  /* Warstwa, nie kolumna siatki: na makiecie tablet wystaje ponad pas
     treści i pod niego, więc nie może współdecydować o wysokości
     sekcji — inaczej kadr rośnie ponad ekran. */
  position:absolute;z-index:2;margin:0;
  /* Odsunięcie w procentach, nie w `vw`: `vw` liczy się z szerokości
     okna razem z paskiem przewijania, więc tablet uciekałby o jego
     grubość w lewo względem kolumny tekstu. Środek na 52%, bo na
     makiecie tablet stoi odrobinę niżej niż połowa kadru. */
  right:clamp(24px,10.4%,200px);top:52%;translate:0 -52%;
  aspect-ratio:1086 / 1519;
  height:81.6svh;max-width:33.7vw;
  /* Perspektywa na samym elemencie, żeby obrót był realną bryłą w głąb,
     a nie płaskim skosem. `translateZ` wysuwa tablet ku widzowi tym
     mocniej, im bliżej środka kadru stoi kursor. */
  perspective:1100px;transform-style:preserve-3d;
  opacity:1;
  filter:drop-shadow(0 30px 60px rgba(2,4,9,.6));
  transform:
    rotateY(calc(var(--mx) * -11deg))
    rotateX(calc(var(--my) * 8deg))
    translate3d(calc(var(--mx) * 14px),calc(var(--my) * 10px),0);
  transition:transform .45s cubic-bezier(.16,1,.3,1);
}
/* Ekran leży głębiej niż rama — przy obrocie rama zaczyna go przysłaniać
   krawędzią, dokładnie tak jak prawdziwa obudowa. */
.gfl__tablet .gfl__ekran{transform:translateZ(-14px)}
.gfl__tablet .gfl__rama{transform:translateZ(6px)}
/* Refleks światła przesuwający się po szkle za kursorem. */
.gfl__tablet::after{
  content:"";position:absolute;z-index:2;
  left:7.09%;top:11.39%;width:86.46%;height:76.76%;
  border-radius:.6%;pointer-events:none;
  background:linear-gradient(
      calc(108deg + var(--mx) * 26deg),
      transparent 38%,rgba(214,234,255,.14) 50%,transparent 62%);
  transform:translateZ(8px);
}
/* Wycięcie ekranu w pliku ramy: 77–1015 px w poziomie i 173–1338 px
   w pionie z 1086×1519 — stąd te procenty. Wideo leży pod ramą. */
.gfl__ekran{
  position:absolute;z-index:0;
  backface-visibility:hidden;
  /* Wycięcie ekranu w ramie to 7,09% / 11,39% / 86,46% / 76,76%.
     Materiał ma po brzegach własną czarną obwódkę, więc kładziemy go
     o 2% szerzej z każdej strony — nadmiar wchodzi pod nieprzezroczystą
     obudowę i obwódki nie widać. */
  left:5.09%;top:9.39%;width:90.46%;height:80.76%;
  object-fit:cover;display:block;
  border-radius:.6%;
  background:#0b1524;
}
.gfl__rama{
  position:relative;z-index:1;
  display:block;width:100%;height:100%;
  pointer-events:none;
}

/* ---------------- wejścia i wyjścia pierwszego kadru ----------------
   Każdy element wchodzi osobno, w kolejności czytania. Wspólna zasada
   jest jedna: rzecz wypływa spod własnej krawędzi i tam wraca. Opóźnienia
   idą z `--k`, więc kolejność ustala znacznik, nie arkusz. */

/* Nadtytuł rozsuwa się od lewej jak odsłonięta taśma. */
.js-gfl .gfl__oko{
  clip-path:inset(0 100% 0 0);opacity:0;
  transition:clip-path .8s var(--szybko),opacity .5s var(--szybko);
}
.js-gfl .gfl__oko.w-kadrze{clip-path:inset(0 0 0 0);opacity:1}
.js-gfl .gfl__oko.poza-kadrem{clip-path:inset(0 0 0 100%);opacity:0;transition-duration:.5s}

/* Nagłówek: każdy wiersz siedzi we własnym oknie i wypływa spod jego
   dolnej krawędzi, z lekkim obrotem w głąb. Wyjście składa wiersze
   w drugą stronę, ku górze. */
.gfl__wiersz{display:block;overflow:hidden;padding-bottom:.06em}
.gfl__wiersz i{display:block;font-style:normal;transform-origin:50% 100%}
.js-gfl .gfl__h1 .gfl__wiersz i{
  transform:translate3d(0,110%,0) rotateX(-55deg);opacity:0;
  transition:transform .95s cubic-bezier(.16,1,.3,1),opacity .6s linear;
}
.js-gfl .gfl__h1.w-kadrze .gfl__wiersz i{transform:none;opacity:1}
.js-gfl .gfl__h1 .gfl__wiersz:nth-child(2) i{transition-delay:.09s}
.js-gfl .gfl__h1 .gfl__wiersz:nth-child(3) i{transition-delay:.18s}
.js-gfl .gfl__h1.poza-kadrem .gfl__wiersz i{
  transform:translate3d(0,-110%,0) rotateX(55deg);opacity:0;
  transition-duration:.5s,.3s;
}
.js-gfl .gfl__h1.poza-kadrem .gfl__wiersz:nth-child(2) i{transition-delay:.05s}
.js-gfl .gfl__h1.poza-kadrem .gfl__wiersz:nth-child(1) i{transition-delay:.1s}

/* Akapity opisu wchodzą jeden po drugim spod własnej linii. */
.js-gfl .gfl__opis p{
  opacity:0;transform:translate3d(0,16px,0);
  transition:opacity .7s var(--szybko),transform .7s var(--szybko);
}
.js-gfl .gfl__opis.w-kadrze p{opacity:1;transform:none}
.js-gfl .gfl__opis p:nth-child(2){transition-delay:.12s}
.js-gfl .gfl__opis.poza-kadrem p{opacity:0;transform:translate3d(0,-14px,0);transition-duration:.4s}

/* Heksy z atutami: każdy wskakuje osobno, z obrotem — heks obraca się
   wokół własnego środka, więc ruch czyta się jako wskoczenie w gniazdo. */
.js-gfl .gfl__atuty li{
  opacity:0;transform:translate3d(0,22px,0) scale(.86) rotate(-6deg);
  transition:opacity .6s var(--szybko),transform .75s cubic-bezier(.34,1.4,.5,1);
}
.js-gfl .gfl__atuty.w-kadrze li{opacity:1;transform:none}
.js-gfl .gfl__atuty.w-kadrze li:nth-child(2){transition-delay:.1s}
.js-gfl .gfl__atuty.w-kadrze li:nth-child(3){transition-delay:.2s}
.js-gfl .gfl__atuty.poza-kadrem li{
  opacity:0;transform:translate3d(0,-18px,0) scale(.9) rotate(5deg);
  transition-duration:.4s;transition-delay:0s;
}

/* Przyciski: główny wysuwa się z lewej, drugi dochodzi po nim. */
.js-gfl .gfl__akcje > *{
  opacity:0;transform:translate3d(-26px,0,0);
  transition:opacity .6s var(--szybko),transform .8s var(--szybko);
}
.js-gfl .gfl__akcje.w-kadrze > *{opacity:1;transform:none}
.js-gfl .gfl__akcje.w-kadrze > *:nth-child(2){transition-delay:.12s}
.js-gfl .gfl__akcje.poza-kadrem > *{opacity:0;transform:translate3d(-20px,0,0);transition-duration:.4s}

/* Licznik: kreska rozciąga się w bok, kolumny wstają po kolei. */
.js-gfl .gfl__licz{
  border-top-color:transparent;
  transition:border-top-color .6s var(--szybko) .1s;
}
.js-gfl .gfl__licz.w-kadrze{border-top-color:var(--linia)}
.js-gfl .gfl__licz > div{
  opacity:0;transform:translate3d(0,18px,0);
  transition:opacity .6s var(--szybko),transform .7s var(--szybko);
}
.js-gfl .gfl__licz.w-kadrze > div{opacity:1;transform:none}
.js-gfl .gfl__licz.w-kadrze > div:nth-child(2){transition-delay:.09s}
.js-gfl .gfl__licz.w-kadrze > div:nth-child(3){transition-delay:.18s}
.js-gfl .gfl__licz.poza-kadrem > div{opacity:0;transform:translate3d(0,-14px,0);transition-duration:.4s}

/* Tablet wjeżdża jako ostatni: z głębi, obrócony, i prostuje się
   w miejscu. Przy wyjściu odchyla się w drugą stronę i odpływa w tył. */
.js-gfl .gfl__tablet{opacity:0}
.js-gfl .gfl__hero.w-kadrze .gfl__tablet{
  opacity:1;
  /* `backwards`, nie `forwards`: po wybrzmieniu klatek kluczowych
     transform wraca pod regułę wychylenia za kursorem. Przy `forwards`
     zostałby zamrożony na wartości końcowej i parallaks by stał. */
  animation:gflTabletWjazd 1.15s cubic-bezier(.16,1,.3,1) .2s backwards;
}
@keyframes gflTabletWjazd{
  from{opacity:0;transform:translate3d(60px,40px,-260px) rotateY(-24deg) rotateX(10deg)}
  to  {opacity:1;transform:none}
}
/* Po wjeździe ster nad `transform` przejmuje reguła wychylenia
   za kursorem — stąd osobna klasa zamiast `w-kadrze`. */
.js-gfl .gfl__hero.w-kadrze .gfl__tablet{
  transform:
    rotateY(calc(var(--mx) * -11deg))
    rotateX(calc(var(--my) * 8deg))
    translate3d(calc(var(--mx) * 14px),calc(var(--my) * 10px),0);
}
/* Wyjscie: odchyla sie w druga strone i odplywa w tyl. Regula musi stac
   PO tej wyzej — zakres zachowuje `w-kadrze`, kiedy dostaje
   `poza-kadrem`, wiec rozstrzyga kolejnosc w arkuszu, nie waga. */
.js-gfl .gfl__hero.poza-kadrem .gfl__tablet{
  opacity:0;animation:none;
  transform:translate3d(-30px,-70px,-220px) rotateY(20deg) rotateX(-9deg);
  transition:opacity .5s var(--szybko),transform .6s var(--szybko);
}


/* ============================================================
   2. ŚCIANA REALIZACJI
   Płaszczyzna kafli odchylona w perspektywie, powoli dryfująca, z
   nagłówkiem na wierzchu.

   Brzegi gasną MASKĄ, nie rozmyciem. `filter:blur()` na kilkudziesięciu
   kaflach przelicza się na każdej klatce i kładzie płynność; maska nie
   kosztuje nic, a wrażenie głębi jest to samo. Ruch robi jedna animacja
   całej płaszczyzny — nie czterdzieści osobnych.
   ============================================================ */
.gfl__scianka{
  --mx:0;--my:0;
  position:relative;
  height:clamp(440px,74vh,820px);
  /* Zero u góry: pasek to ::before ściany, więc każdy margines odsuwałby
     go od krawędzi wideo i zostawiał pas gołego tła. */
  margin:0 0 clamp(48px,8vh,100px);
  overflow:hidden;
  display:grid;place-items:center;
  isolation:isolate;
}
/* Pasy w stali na górze i na dole ściany — ten sam znak rozdzielający,
   co na stykach sekcji strony głównej. Tu nie rozdzielają jasnego od
   ciemnego, tylko odcinają ścianę realizacji od tekstu nad i pod nią. */
/* Paski cieńsze niż wspólny `--pasek` i nie płaskie: stal ściemnia się
   ku krawędziom, a po wierzchu przesuwa się smuga światła. Ruch jest
   powolny i wąski, żeby pas nadal czytał się jako krawędź sekcji,
   a nie jako animacja. */
.gfl__scianka::before,
.gfl__scianka::after{
  content:'';position:absolute;left:0;right:0;z-index:3;
  height:clamp(3px,.34vw,6px);pointer-events:none;
  background:
    linear-gradient(90deg,
      transparent 0%,rgba(226,240,255,.85) 8%,transparent 16%) 0 0 / 260% 100% no-repeat,
    linear-gradient(180deg,#7ea0c8 0%,#5b7fae 46%,#3d5c85 100%);
  animation:gflSmuga 9s linear infinite;
}
.gfl__scianka::before{top:0;box-shadow:0 5px 14px rgba(2,4,9,.5)}
.gfl__scianka::after{bottom:0;box-shadow:0 -5px 14px rgba(2,4,9,.5);animation-delay:-4.5s}
@keyframes gflSmuga{
  from{background-position:-160% 0,0 0}
  to  {background-position: 260% 0,0 0}
}

.gfl__persp{
  position:absolute;inset:0;z-index:0;
  perspective:1200px;perspective-origin:50% 42%;
  pointer-events:none;
  -webkit-mask-image:radial-gradient(ellipse 78% 70% at 50% 48%,#000 28%,rgba(0,0,0,.5) 60%,transparent 86%);
  mask-image:radial-gradient(ellipse 78% 70% at 50% 48%,#000 28%,rgba(0,0,0,.5) 60%,transparent 86%);
}
/* Płaszczyzna jest szersza i wyższa od kadru, bo odchylenie i dryf muszą
   mieć czym zachodzić na brzegi. */
.gfl__plan{
  position:absolute;left:50%;top:50%;
  width:150%;height:190%;
  display:grid;
  grid-template-columns:repeat(5,1fr);
  gap:clamp(12px,1.4vw,26px);
  transform-style:preserve-3d;
  transform:
    translate3d(-50%,-50%,0)
    rotateX(52deg)
    rotateZ(calc(-16deg + var(--mx) * 2deg))
    translate3d(0,calc(var(--my) * 1.5%),0)
    scale(1.06);
  /* Dryf jedzie właściwością `translate`, nie `transform` — ten niesie
     odchylenie i wychylenie za kursorem, więc animacja nie ma prawa go
     nadpisać. Jedna animacja na całą płaszczyznę, nie czterdzieści. */
  animation:gflDryf 52s linear infinite;
  will-change:transform,translate;
}
@keyframes gflDryf{
  from{translate:0 6%}
  to  {translate:0 -16%}
}
.gfl__kafel{
  position:relative;display:block;
  aspect-ratio:4 / 3;
  background:#0b1320;
  padding:clamp(6px,.6vw,11px);
  box-shadow:
    inset 0 0 0 1px rgba(124,179,255,.12),
    0 14px 34px rgba(0,0,0,.5);
}
.gfl__kafel img{display:block;width:100%;height:100%;object-fit:contain}

.gfl__napis{
  position:relative;z-index:1;text-align:center;
  padding:clamp(20px,4vw,48px) clamp(18px,5vw,70px);
}
.gfl__napis::before{
  content:'';position:absolute;inset:-20% -16%;z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse 62% 66% at 50% 50%,
      rgba(2,4,9,.92) 20%,rgba(2,4,9,.7) 52%,transparent 80%);
}
.gfl__kicker{
  margin:0 0 clamp(8px,1.4vh,16px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.42em;text-indent:.42em;
  text-transform:uppercase;color:var(--akcent);
}
.gfl__mega{
  margin:0;
  font-family:'Vogjer',sans-serif;font-weight:400;
  font-size:clamp(32px,5.6vw,88px);line-height:.94;letter-spacing:.02em;
  text-transform:uppercase;color:var(--tusz);
}
/* Zdanie pod nagłówkiem — mówi, co jest w katalogu, zanim ktoś w niego
   wejdzie. Wąskie, bo leży na ruchomej ścianie kafli. */
.gfl__podnapis{
  margin:clamp(12px,1.8vh,20px) auto 0;max-width:46ch;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11px,.78vw,13px);line-height:1.8;color:var(--tusz-2);
}
.gfl__napis .pbtn{margin-top:clamp(16px,2.6vh,30px)}

/* Wejście ściany: płaszczyzna kafli nadjeżdża z głębi i z większego
   odchylenia, prostując się do swojego kąta roboczego. Napis idzie
   w przeciwną stronę — zjeżdża ze skali w dół, na swoje miejsce.
   Wyjście odwraca oba ruchy, więc sekcja „zamyka się" tak, jak się
   otworzyła. */
.js-gfl .gfl__persp[data-ark]{
  opacity:0;transform:translate3d(0,90px,0) scale(1.18);
  transition:opacity 1s var(--szybko),transform 1.3s cubic-bezier(.16,1,.3,1);
}
.js-gfl .gfl__persp[data-ark].w-kadrze{opacity:1;transform:none}
.js-gfl .gfl__persp[data-ark].poza-kadrem{
  opacity:0;transform:translate3d(0,-70px,0) scale(1.1);transition-duration:.6s,.7s;
}
.js-gfl .gfl__napis .gfl__mega[data-ark]{
  opacity:0;transform:scale(1.32);
  transition:opacity .8s var(--szybko),transform 1.1s cubic-bezier(.16,1,.3,1);
}
.js-gfl .gfl__napis .gfl__mega[data-ark].w-kadrze{opacity:1;transform:none}
.js-gfl .gfl__napis .gfl__mega[data-ark].poza-kadrem{
  opacity:0;transform:scale(.82);transition-duration:.5s,.6s;
}
.js-gfl .gfl__kicker[data-ark]{
  opacity:0;transform:translate3d(0,14px,0);letter-spacing:.9em;
  transition:opacity .7s var(--szybko),transform .7s var(--szybko),
             letter-spacing 1s cubic-bezier(.16,1,.3,1);
}
.js-gfl .gfl__kicker[data-ark].w-kadrze{opacity:1;transform:none;letter-spacing:.42em}
.js-gfl .gfl__kicker[data-ark].poza-kadrem{opacity:0;letter-spacing:.9em;transition-duration:.45s}

/* ============================================================
   2b. KADR OBOK TEKSTU
   Dwa razy ten sam układ, raz odbity. Kadr dryfuje w głąb za kursorem
   i przy wjeździe, tekst wchodzi z boku — strony idą ku sobie.
   ============================================================ */
.gfl__para{
  --mx:0;--my:0;
  position:relative;
  width:min(1260px,88vw);margin:0 auto clamp(56px,10vh,120px);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  align-items:center;gap:clamp(26px,4vw,72px);
}
/* Odbicie robi kolejność kolumn, nie duplikat znaczników. */
.gfl__para--odwrot .gfl__kadr{order:2}

.gfl__kadr{
  position:relative;margin:0;
  /* Kant prosty, bez zaokrąglenia — obrys ma być widoczny jako kreska,
     nie jako miękka ramka. `inset` rysuje ją po wewnętrznej krawędzi,
     więc nie walczy z `overflow:hidden`. */
  overflow:hidden;
  box-shadow:
    inset 0 0 0 1px rgba(124,179,255,.5),
    0 26px 60px rgba(2,4,9,.55);
  perspective:900px;
}
.gfl__kadr img{
  display:block;width:100%;height:auto;
  /* Zapas skali, żeby dryf nie odsłonił krawędzi kadru. */
  transform:
    scale(1.07)
    translate3d(calc(var(--mx) * -14px),calc(var(--my) * -10px),0);
  transition:transform .7s cubic-bezier(.16,1,.3,1);
}
/* Przyciemnienie od dołu — pod nim kadr styka się z ciemnym polem
   zamiast urywać się jasną krawędzią. */
.gfl__kadr::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(0deg,rgba(2,4,9,.5) 0%,transparent 42%);
}

.gfl__obok{min-width:0}
.gfl__oko--m{margin-bottom:clamp(10px,1.6vh,18px)}
.gfl__para .gfl__h2{margin-bottom:clamp(12px,2vh,22px)}
.gfl__para .gfl__tekst{margin:0}

/* Wejście kadru: zasłona odjeżdża w bok i odsłania zdjęcie, a samo
   zdjęcie w tym czasie schodzi ze zbliżenia na swoją skalę roboczą —
   dwa ruchy w przeciwnych kierunkach, więc kadr „otwiera się", zamiast
   wjeżdżać. Wersja odbita odsłania z drugiej strony. */
.js-gfl .gfl__para .gfl__kadr[data-ark]{
  transform:none;opacity:1;
  clip-path:inset(0 100% 0 0);
  transition:clip-path 1.05s cubic-bezier(.76,0,.24,1);
}
.js-gfl .gfl__para--odwrot .gfl__kadr[data-ark]{clip-path:inset(0 0 0 100%)}
.js-gfl .gfl__para .gfl__kadr[data-ark].w-kadrze{clip-path:inset(0 0 0 0)}
.js-gfl .gfl__para .gfl__kadr[data-ark].poza-kadrem{
  clip-path:inset(0 0 0 100%);transition-duration:.6s;
}
.js-gfl .gfl__para--odwrot .gfl__kadr[data-ark].poza-kadrem{clip-path:inset(0 100% 0 0)}

/* Zdjęcie pod zasłoną: startuje mocniej przybliżone i dojeżdża do skali
   roboczej dokładnie wtedy, gdy zasłona kończy bieg. */
.js-gfl .gfl__para .gfl__kadr[data-ark] img{
  transform:scale(1.24);
  transition:transform 1.25s cubic-bezier(.16,1,.3,1);
}
.js-gfl .gfl__para .gfl__kadr[data-ark].w-kadrze img{
  transform:scale(1.07) translate3d(calc(var(--mx) * -14px),calc(var(--my) * -10px),0);
}
.js-gfl .gfl__para .gfl__kadr[data-ark].poza-kadrem img{
  transform:scale(1.16);transition-duration:.6s;
}

/* Tekst obok wstaje wierszami spod własnej linii, z przechyłem — idzie
   w rytmie zasłony, nie równolegle do niej. */
.js-gfl .gfl__para .gfl__obok [data-ark]{
  opacity:0;transform:translate3d(0,26px,0) rotate(.7deg);
  transform-origin:0% 50%;
  transition:opacity .7s var(--szybko),transform .85s cubic-bezier(.16,1,.3,1);
}
.js-gfl .gfl__para .gfl__obok [data-ark].w-kadrze{opacity:1;transform:none}
.js-gfl .gfl__para .gfl__obok [data-ark].poza-kadrem{
  opacity:0;transform:translate3d(0,-20px,0) rotate(-.6deg);transition-duration:.45s;
}

/* ============================================================
   3. SPECYFIKACJA, PROCES, TEKST
   ============================================================ */
.gfl__sekcja{width:min(1120px,84vw);margin:0 auto clamp(48px,8vh,100px)}
.gfl__h2{
  margin:0;
  font-family:'Vogjer',sans-serif;font-weight:400;
  /* 1,22 zamiast 1,1: Vogjer wypuszcza ogonki „ą" i „ę" nisko pod linię
     pisma i przy ciaśniejszej interlinii obcina je górna krawędź
     następnego wiersza. */
  font-size:clamp(18px,2.1vw,32px);line-height:1.22;letter-spacing:.01em;
  text-transform:uppercase;color:var(--tusz);
}

.gfl__spec{margin:clamp(20px,3vh,34px) 0 0;padding:0;list-style:none}
.gfl__spec li{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.5fr) auto;
  gap:6px clamp(16px,2.4vw,40px);align-items:baseline;
  padding:clamp(13px,1.7vh,20px) 0;
  border-bottom:1px solid var(--linia);
}
.gfl__spec li:first-child{border-top:1px solid var(--linia-mocna)}
.gfl__spec h3{
  margin:0;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11.5px,.84vw,14px);letter-spacing:.1em;
  text-transform:uppercase;color:var(--tusz);
}
.gfl__spec p{
  margin:0;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11px,.74vw,12.5px);line-height:1.7;color:var(--tusz-2);
}
.gfl__spec b{
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--akcent);white-space:nowrap;
}
.gfl__spec-ile{
  grid-column:1;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--tusz-3);
}

.gfl__proces{
  list-style:none;margin:clamp(20px,3vh,34px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:clamp(20px,2.6vw,44px);
}
.gfl__proces b{
  display:block;margin-bottom:clamp(9px,1.2vh,14px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(19px,1.9vw,28px);line-height:1;letter-spacing:.04em;
  color:var(--akcent);
}
.gfl__proces h3{
  margin:0 0 7px;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11.5px,.8vw,13px);letter-spacing:.16em;
  text-transform:uppercase;color:var(--tusz);
}
.gfl__proces p{
  margin:0;
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11px,.74vw,12.5px);line-height:1.8;color:var(--tusz-2);
}

/* Tekst biegnie na pelna szerokosc sekcji, czyli do tej samej prawej
   krawedzi co ostatnia kolumna procesu nizej. Zeby wiersz nie zrobil sie
   nieczytelnie dlugi, laman jest na dwie szpalty — szerokosc ta sama,
   dlugosc wiersza ta sama co wczesniej. Sekcje z kadrem obok maja wlasna,
   waska kolumne, wiec je z tego wylaczamy. */
.gfl__tekst{
  column-count:2;column-gap:clamp(24px,3.4vw,60px);
}
.gfl__tekst p{break-inside:avoid}
.gfl__para .gfl__tekst{column-count:1}
.gfl__tekst p{
  margin:0 0 clamp(11px,1.6vh,18px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11.5px,.78vw,13.5px);line-height:1.85;color:var(--tusz-2);
}
.gfl__tekst a{
  color:var(--akcent);text-decoration:none;
  border-bottom:1px solid rgba(124,179,255,.32);
  transition:border-color .3s var(--ease);
}
.gfl__tekst a:hover{border-color:var(--akcent)}

.gfl__stopa{
  position:relative;z-index:1;
  padding:clamp(44px,7vh,90px) var(--frame) clamp(52px,9vh,110px);
  text-align:center;
  border-top:1px solid var(--linia);
}
.gfl__stopa .gfl__h2{margin-bottom:clamp(10px,1.6vh,18px)}
.gfl__stopa p{
  max-width:56ch;margin:0 auto clamp(18px,2.6vh,30px);
  font-family:'Montserrat',sans-serif;font-weight:500;
  font-size:clamp(11.5px,.78vw,13.5px);line-height:1.8;color:var(--tusz-2);
}

/* ============================================================
   WEJŚCIA I WYJŚCIA
   Element wypływa spod krawędzi i wraca pod nią, gdy jego zakres
   odjeżdża w górę. Bez rozmyć.
   ============================================================ */
.js-gfl [data-ark]{
  opacity:0;transform:translate3d(0,20px,0);
  transition:opacity .85s var(--szybko),transform 1s var(--szybko);
  transition-delay:calc(var(--k,0) * .07s);
}
.js-gfl [data-ark].w-kadrze{opacity:1;transform:none}
.js-gfl [data-ark].poza-kadrem{
  opacity:0;transform:translate3d(0,-16px,0);
  transition-duration:.45s,.55s;
  transition-delay:calc(var(--k,0) * .03s);
}

/* ============================================================
   WĘŻSZE EKRANY
   ============================================================ */
@media (max-width:1180px){
  .gfl__sekcja{width:min(1120px,92vw)}
  .gfl__hero{gap:clamp(18px,3vw,40px)}
}
@media (max-width:900px){
  /* Kolejność na telefonie: nadtytuł i nagłówek, potem tablet, potem
     reszta treści. `display:contents` rozpuszcza kolumnę tekstu, żeby jej
     dzieci stały się elementami tej samej siatki co tablet — bez tego
     tablet mógłby być tylko przed całą kolumną albo za nią. */
  .gfl__hero{
    grid-template-columns:minmax(0,1fr);gap:clamp(18px,3vh,30px);
    padding:clamp(92px,12vh,132px) var(--frame) clamp(48px,7vh,86px);
  }
  .gfl__tresc{display:contents}
  .gfl__oko{order:1}
  .gfl__h1{order:2}
  .gfl__tablet{
    order:3;
    position:static;translate:none;justify-self:center;
    height:auto;width:min(340px,68vw);max-width:none;
    margin-block:clamp(6px,1.4vh,14px);
  }
  .gfl__opis{order:4}
  .gfl__atuty{order:5}
  .gfl__akcje{order:6}
  .gfl__licz{order:7}
  /* Odstępy liczone wcześniej względem sąsiada w kolumnie — po
     rozpuszczeniu kolumny robi je `gap` siatki. */
  .gfl__opis,.gfl__atuty,.gfl__akcje{margin-top:0}
  .gfl__licz{margin-top:clamp(6px,1.2vh,12px)}
  /* Treść idzie tu od krawędzi do krawędzi, więc podpis przy boku nie ma
     już gdzie stać — wchodziłby pod tekst. */
  .gfl__szyna,.gfl__nr{display:none}
}
@media (max-width:900px){
  /* Kadr zawsze nad tekstem, także w wersji odbitej — na telefonie
     kolejność czyta się z góry na dół, nie z boku na bok. */
  .gfl__para{grid-template-columns:minmax(0,1fr);gap:clamp(18px,3vh,28px)}
  .gfl__para--odwrot .gfl__kadr{order:0}
  /* Na wąskim ekranie zasłona idzie z góry na dół — ruch w bok na
     szerokości telefonu czyta się jak przypadkowe przesunięcie. */
  .js-gfl .gfl__para .gfl__kadr[data-ark],
  .js-gfl .gfl__para--odwrot .gfl__kadr[data-ark]{clip-path:inset(0 0 100% 0)}
  .js-gfl .gfl__para .gfl__kadr[data-ark].poza-kadrem,
  .js-gfl .gfl__para--odwrot .gfl__kadr[data-ark].poza-kadrem{clip-path:inset(100% 0 0 0)}
}
@media (max-width:640px){
  /* Trzy w rzędzie przestają się mieścić — idą jeden pod drugim. */
  .gfl__atuty{grid-template-columns:minmax(0,1fr);gap:12px}
  .gfl__akcje{gap:16px}
}
@media (max-width:860px){
  .gfl__spec li{grid-template-columns:minmax(0,1fr);gap:4px}
  .gfl__spec b{grid-column:1}
  .gfl__spec-ile{grid-row:1;justify-self:end;grid-column:1}
  .gfl__sekcja{width:auto;margin-inline:var(--frame)}
  .gfl__licz{gap:clamp(12px,4vw,24px)}
  .gfl__licz > div{padding-right:clamp(12px,4vw,24px)}
}

@media (prefers-reduced-motion:reduce){
  .js-gfl [data-ark],
  .js-gfl [data-ark].w-kadrze,
  .js-gfl [data-ark].poza-kadrem{opacity:1;transform:none;transition:none}
  .gfl__plan{animation:none}
  .gfl__tablet,.gfl__kadr img{transition:none;transform:none}
  .js-gfl .gfl__h1 .gfl__wiersz i,
  .js-gfl .gfl__opis p,
  .js-gfl .gfl__atuty li,
  .js-gfl .gfl__akcje > *,
  .js-gfl .gfl__licz > div,
  .js-gfl .gfl__persp[data-ark],
  .js-gfl .gfl__napis .gfl__mega[data-ark],
  .js-gfl .gfl__kicker[data-ark]{opacity:1;transform:none;transition:none}
  .js-gfl .gfl__oko{clip-path:none;opacity:1}
  .js-gfl .gfl__tablet{opacity:1;animation:none}
  .js-gfl .gfl__para .gfl__kadr[data-ark]{clip-path:none;transition:none}
  .js-gfl .gfl__para .gfl__kadr[data-ark] img{transform:none;transition:none}
  .gfl__scianka::before,.gfl__scianka::after{animation:none}
}
