/* Font Handlee — @import MUSI być pierwszą regułą w pliku,
   inaczej przeglądarka go ignoruje i czcionka się nie ładuje. */
@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300&display=swap');

/* ═══════════════════════════════════════════════════════════════
   ADSY — 2 · KOMPONENTY
   Elementy wielokrotnego użytku. Dopisuj tu nowe klasy.
   ═══════════════════════════════════════════════════════════════ */

/* ── NADTYTUŁ ─────────────────────────────────────────────────

/* ── PODSTAWA ────────────────────────────────────────────────── */
.eyebrow {
  display: inline-flex !important;
  align-items: center;
  gap: 11px;

  /* jedyny element z DODATNIM odstępem liter na całej stronie */
  font-size: clamp(10.5px, 0.85vw, 12px);
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;

  color: #02603d !important;
  margin: 0 0 clamp(18px, 2.2vw, 26px) !important;
}

/* kreska przed tekstem */
.eyebrow::before {
  content: '';
  flex: none;
  width: 26px;
  height: 1.5px;
  background: currentColor;
}

/* ── NA CIEMNYM TLE ──────────────────────────────────────────── */
.hero-gradient .eyebrow,
.sec--forest .eyebrow,
.sec--void .eyebrow,
.has-theme-palette-1-background-color .eyebrow,
.has-theme-palette1-background-color .eyebrow {
  color: #48f093 !important;
}

/* ── ODMIANY  (dopisz jako druga klasa) ──────────────────────── */

/* bez kreski */
.eyebrow--bez::before {
  display: none;
}

/* kreska po tekście */
.eyebrow--po::before {
  display: none;
}
.eyebrow--po::after {
  content: '';
  flex: none;
  width: 26px;
  height: 1.5px;
  background: currentColor;
}

/* kreska z obu stron — do nagłówków wyśrodkowanych */
.eyebrow--srodek {
  justify-content: center;
}
.eyebrow--srodek::after {
  content: '';
  flex: none;
  width: 26px;
  height: 1.5px;
  background: currentColor;
}

/* kreska ciągnąca się do końca kolumny */
.eyebrow--dluga {
  display: flex !important;
  width: 100%;
}
.eyebrow--dluga::after {
  content: '';
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.28;
}

/* wariant przygaszony — gdy nadtytuł ma nie konkurować z nagłówkiem */
.eyebrow--cichy {
  color: #5b625f !important;
  font-weight: 700;
}
.hero-gradient .eyebrow--cichy {
  color: rgba(230, 242, 236, 0.55) !important;
}

/* wariant akcentowy — jasna zieleń również na jasnym tle */
.eyebrow--akcent {
  color: #02603d !important;
}
.eyebrow--akcent::before {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #48f093;
}

/* ── KIEDY NADTYTUŁ JEST NAD OBRAZEM ─────────────────────────── */
.eyebrow--nakadrze {
  color: #fff !important;
  padding: 7px 14px;
  border-radius: 200px;
  background: rgba(4, 10, 22, 0.5);
  backdrop-filter: blur(8px);
}
.eyebrow--nakadrze::before {
  display: none;
}

/* ── TELEFON ─────────────────────────────────────────────────── */
@media (max-width: 600px) {
  .eyebrow {
    font-size: 10.5px;
    letter-spacing: 0.18em;
    gap: 9px;
    margin-bottom: 14px !important;
  }
  .eyebrow::before,
  .eyebrow--po::after,
  .eyebrow--srodek::after {
    width: 18px;
  }
}

/* ── ZAPAS: gdy Kadence dołoży własny margines ───────────────── */
.wp-block-kadence-advancedheading.eyebrow {
  margin-top: 0 !important;
}
/* nagłówek stojący zaraz pod nadtytułem nie potrzebuje własnego
   marginesu górnego — odstęp daje już eyebrow */
.eyebrow + .wp-block-kadence-advancedheading,
.eyebrow + h1,
.eyebrow + h2,
.eyebrow + h3 {
  margin-top: 0 !important;
}

/* ── 1 · FUNDAMENT ───────────────────────────────────────────── */
.hero-gradient {
  position: relative;
  background-color: #063d28;
  color: #e6f2ec;
  /* NIGDY hidden — zamraża animacje sterowane przewijaniem
     w całym drzewie pod spodem. clip odcina tak samo. */
  overflow: clip;
  isolation: isolate;
}

/* ── 2 · TRZY PLAMY ZAMIAST NIEBIESKIEGO GRADIENTU ───────────── */
.hero-gradient .kt-row-layout-overlay {
  background-image:
    radial-gradient(
      46vw 46vw at 90% -12%,
      rgba(72, 240, 147, 0.34),
      transparent 62%
    ),
    radial-gradient(
      34vw 34vw at -6% 112%,
      rgba(191, 230, 242, 0.24),
      transparent 62%
    ),
    radial-gradient(
      30vw 30vw at 38% 122%,
      rgba(2, 96, 61, 0.62),
      transparent 60%
    ) !important;
  opacity: 1 !important;
  mix-blend-mode: normal !important;
}

/* Krycie ustawione w wartościach kolorów, nie suwakiem — dzięki temu
   każda plama ma własną siłę. Suwak Kadence przyciemniałby wszystkie
   naraz, więc zostaje na 100. */

/* ── 3 · TREŚĆ NAD NAKŁADKĄ ──────────────────────────────────── */
.hero-gradient .kt-row-column-wrap {
  position: relative;
  z-index: 2;
}

.hero-gradient h1,
.hero-gradient h2,
.hero-gradient h3 {
  color: #fff;
}

.hero-gradient p,
.hero-gradient li {
  color: rgba(230, 242, 236, 0.78);
}

.hero-gradient a:not(.kb-button):not(.wp-block-button__link) {
  color: #48f093;
}

/* nadtytuł */
.hero-gradient .nadtytul,
.hero-gradient .kt-blocks-info-box-subtitle {
  color: #48f093;
}

/* akcent pisany */
.hero-gradient .hand {
  color: #48f093;
}

/* ── 4 · PRZYCISKI NA CIEMNYM ────────────────────────────────── */
.hero-gradient .kb-button.kb-btn-global-fill,
.hero-gradient .wp-block-button__link {
  background: #48f093;
  color: #063d28;
  border-color: transparent;
}
.hero-gradient .kb-button.kb-btn-global-fill:hover,
.hero-gradient .wp-block-button__link:hover {
  background: #fff;
  color: #063d28;
}
.hero-gradient .kb-button.kb-btn-global-outline,
.hero-gradient .is-style-outline .wp-block-button__link {
  background: transparent;
  color: #fff;
  border: 1.5px solid rgba(255, 255, 255, 0.32);
}
.hero-gradient .kb-button.kb-btn-global-outline:hover,
.hero-gradient .is-style-outline .wp-block-button__link:hover {
  background: #fff;
  color: #063d28;
  border-color: #fff;
}

/* ── 5 · ODMIANY ─────────────────────────────────────────────── */

/* Prawie czarne tło — pod treści, które mają być cięższe */
.hero-gradient.hero-gradient--void {
  background-color: #040a16;
}
.hero-gradient.hero-gradient--void .kt-row-layout-overlay {
  background-image:
    radial-gradient(
      44vw 44vw at 88% -10%,
      rgba(72, 240, 147, 0.26),
      transparent 60%
    ),
    radial-gradient(
      36vw 36vw at -8% 108%,
      rgba(2, 96, 61, 0.5),
      transparent 62%
    ) !important;
}

/* Spokojniejsza — jedna plama, mniej ruchu w tle */
.hero-gradient.hero-gradient--cicha .kt-row-layout-overlay {
  background-image: radial-gradient(
    52vw 52vw at 84% -14%,
    rgba(72, 240, 147, 0.22),
    transparent 64%
  ) !important;
}

/* ── 6 · WERSJA Z RUCHEM  (opcjonalna) ───────────────────────────
   Gradient jest nieruchomy. Jeśli plamy mają oddychać, dodaj
   wierszowi DRUGĄ klasę: hero-gradient--zywa

   Wtedy nakładka Kadence gaśnie, a jej miejsce zajmują dwa
   pseudoelementy z własną animacją. */

/* Zabezpieczenie: gdyby na wierszu została sama klasa
   .hero-gradient--zywa (bez bazowej .hero-gradient), plamy nie
   miałyby do czego się przyczepić ani czym się przyciąć i
   wychodziłyby poza sekcję. Powtarzamy tu trzy własności bazy. */
.hero-gradient--zywa {
  position: relative;
  overflow: clip;
  isolation: isolate;
}

.hero-gradient--zywa .kt-row-layout-overlay {
  opacity: 0 !important;
}

.hero-gradient--zywa::before,
.hero-gradient--zywa::after {
  content: '';
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  will-change: transform, border-radius;
}
.hero-gradient--zywa::before {
  width: 46vw;
  height: 46vw;
  max-width: 640px;
  max-height: 640px;
  background: #48f093;
  opacity: 0.16;
  top: -16%;
  right: -10%;
  animation: hero-bl1 26s ease-in-out infinite;
}
.hero-gradient--zywa::after {
  width: 34vw;
  height: 34vw;
  max-width: 480px;
  max-height: 480px;
  background: #02603d;
  opacity: 0.42;
  bottom: -22%;
  left: -6%;
  animation: hero-bl2 32s ease-in-out infinite;
}

@keyframes hero-bl1 {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    border-radius: 52% 48% 40% 60% / 56% 44% 56% 44%;
  }
  50% {
    transform: translate(6%, 8%) scale(1.14);
    border-radius: 38% 62% 58% 42% / 42% 58% 42% 58%;
  }
}
@keyframes hero-bl2 {
  0%,
  100% {
    transform: translate(0, 0) scale(1.05);
    border-radius: 44% 56% 62% 38% / 48% 52% 48% 52%;
  }
  50% {
    transform: translate(-8%, 6%) scale(0.9);
    border-radius: 60% 40% 36% 64% / 60% 40% 60% 40%;
  }
}

/* ── 7 · TELEFON ─────────────────────────────────────────────── */
@media (max-width: 767px) {
  /* Plamy liczone w jednostkach szerokości ekranu robią się na
     telefonie za małe. Powiększamy i przesuwamy bliżej rogów. */
  .hero-gradient .kt-row-layout-overlay {
    background-image:
      radial-gradient(
        90vw 90vw at 96% -14%,
        rgba(72, 240, 147, 0.3),
        transparent 62%
      ),
      radial-gradient(
        80vw 80vw at -12% 108%,
        rgba(2, 96, 61, 0.58),
        transparent 62%
      ) !important;
  }
  .hero-gradient--zywa::before {
    width: 90vw;
    height: 90vw;
    top: -12%;
    right: -22%;
  }
  .hero-gradient--zywa::after {
    width: 76vw;
    height: 76vw;
    bottom: -14%;
    left: -20%;
  }
}

/* ── 8 · OGRANICZONY RUCH ────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .hero-gradient--zywa::before,
  .hero-gradient--zywa::after {
    animation: none;
  }
}
/* ===== PRZYCISKI ===== */
.wp-block-kadence-singlebtn.kb-button {
  transition:
    transform 0.25s ease,
    box-shadow 0.25s ease;
  display: inline-flex;
  align-items: center;
}
.wp-block-kadence-singlebtn.kb-button:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.12);
}
.wp-block-kadence-singlebtn.kb-button .kb-svg-icon-wrap {
  transition: transform 0.25s ease;
}
.wp-block-kadence-singlebtn.kb-button:hover .kb-svg-icon-wrap {
  transform: translateX(4px);
}

/* ===== KARTY Z LINKIEM (podnoszenie + ikona + strzałka) =====
   WAŻNE: kombinator ">" (dziecko bezpośrednie), nie spacja.
   Ze spacją reguła łapała KAŻDY .kt-inside-inner-col w środku
   karty — także zagnieżdżonych sekcji — i podnosiło się wszystko.
   .kt-inside-inner-col to zawsze bezpośrednie dziecko kolumny,
   więc ">" celuje wyłącznie we wrap tej jednej karty. */
.wp-block-kadence-column.kb-section-has-link > .kt-inside-inner-col {
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  height: 100%;
}
.wp-block-kadence-column.kb-section-has-link:hover > .kt-inside-inner-col {
  transform: translateY(-14px);
  box-shadow: 0 22px 45px rgba(0, 0, 0, 0.14);
}
.wp-block-kadence-column.kb-section-has-link .wp-block-kadence-icon {
  transition: transform 0.3s ease;
  transform-origin: left center;
}
.wp-block-kadence-column.kb-section-has-link:hover .wp-block-kadence-icon {
  transform: scale(1.08);
}
.wp-block-kadence-column.kb-section-has-link
  .kb-svg-icon-wrap.kb-svg-icon-fe_arrowRight {
  transition: transform 0.3s ease;
}
.wp-block-kadence-column.kb-section-has-link:hover
  .kb-svg-icon-wrap.kb-svg-icon-fe_arrowRight {
  transform: translateX(4px);
}

/* ===== IKONY – UNIWERSALNIE (dowolna liczba kolumn, tylko karta pod kursorem) ===== */
.wp-block-kadence-column:not(.kb-section-has-link)
  > .kt-inside-inner-col
  > .wp-block-kadence-icon
  .wp-block-kadence-single-icon {
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.wp-block-kadence-column:not(.kb-section-has-link)
  > .kt-inside-inner-col:hover
  > .wp-block-kadence-icon
  .wp-block-kadence-single-icon {
  transform: translateY(-6px) scale(1.1);
}

/* ===== GALERIA – zoom w kadrze ===== */
.wp-block-kadence-advancedgallery .kadence-blocks-gallery-item-inner,
.wp-block-kadence-advancedgallery .kb-gallery-figure {
  overflow: hidden;
}
.wp-block-kadence-advancedgallery .kb-gallery-figure img {
  display: block;
  transition: transform 0.6s ease;
}
.wp-block-kadence-advancedgallery
  .kadence-blocks-gallery-item:hover
  .kb-gallery-figure
  img {
  transform: scale(1.06);
}

/* ===== FORMULARZ FLUENT FORMS – animowany focus ===== */
.frm-fluent-form .ff-el-group {
  position: relative;
}
.frm-fluent-form .ff-el-form-control {
  transition:
    border-color 0.25s ease,
    box-shadow 0.25s ease;
}
.frm-fluent-form .ff-el-form-control:focus {
  border-color: var(--global-palette1);
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1);
  outline: none;
}
.frm-fluent-form .ff-el-input--label label {
  display: inline-block;
  transition:
    transform 0.25s ease,
    color 0.25s ease;
  transform-origin: left center;
}
.frm-fluent-form .ff-el-group:focus-within .ff-el-input--label label {
  transform: translateY(-3px);
  color: var(--global-palette1);
}

/* ===== STABILIZACJA TŁA-ZDJĘCIA (koniec migania) ===== */
/* Dodaj klasę "stabilo" kolumnie/sekcji ze zdjęciem w tle:
   blok w Kadence → zakładka Advanced → Additional CSS classes → stabilo */
.stabilo,
.stabilo > .kt-inside-inner-col,
.stabilo .kt-inside-inner-col {
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Highlight w Kadence Advanced Heading */
.wp-block-kadence-advancedheading .kt-highlight {
  font-family: 'Kalam', cursive;
  font-weight: 400;
  background: transparent;
}

.sec--forest .wp-block-kadence-advancedheading .kt-highlight,
.sec--void .wp-block-kadence-advancedheading .kt-highlight {
  color: #48f093;
  -webkit-text-fill-color: #48f093;
}

/* Ograniczenie szerokości paragrafów */
.entry-content p,
.wp-block-post-content p {
  max-width: 890px;
}
/* ═══════════════════════════════════════════════════════════════
   ADSY FX — PAKIET 2
   Tła gradientowe, efekty przewijania, mikrointerakcje
   ───────────────────────────────────────────────────────────────
   Wklej do: Wygląd → Dostosuj → Dodatkowy CSS  (pod pakietem 1)
   Klasy dodajesz w bloku: Zaawansowane → Dodatkowa klasa CSS

   ZASADA: JavaScript (osobny plik) tylko ustawia zmienne CSS.
   Nigdy nie przebudowuje DOM, nie czeka na obrazy, nie walczy
   z cache. Wszystko poniżej działa też bez niego — po prostu
   bez reakcji na kursor.
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   A. TŁA GRADIENTOWE
   Klasę dodajesz na blok Wiersz (Row Layout).
   Wymaga, żeby wiersz miał ustawione jakieś tło (choćby białe),
   inaczej plamy będą widoczne przez sekcję pod spodem.
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-bg-blobs ── rozmyte plamy, powoli dryfują.
   To jest ten efekt z Salient. Dwie plamy jako pseudoelementy,
   trzecia jako gradient na samym wierszu. */
.fx-bg-blobs {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.fx-bg-blobs::before,
.fx-bg-blobs::after {
  content: '';
  position: absolute;
  z-index: -1;
  width: 46vw;
  height: 46vw;
  max-width: 620px;
  max-height: 620px;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  will-change: transform, border-radius;
}
.fx-bg-blobs::before {
  background: var(--global-palette2, #02603d);
  opacity: 0.38;
  top: -18%;
  left: -10%;
  animation: fx-blob-a 26s ease-in-out infinite;
}
.fx-bg-blobs::after {
  background: var(--global-palette3, #48f093);
  opacity: 0.3;
  bottom: -24%;
  right: -12%;
  animation: fx-blob-b 32s ease-in-out infinite;
}
@keyframes fx-blob-a {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    border-radius: 52% 48% 40% 60% / 56% 44% 56% 44%;
  }
  50% {
    transform: translate(8%, 10%) scale(1.14);
    border-radius: 38% 62% 58% 42% / 42% 58% 42% 58%;
  }
}
@keyframes fx-blob-b {
  0%,
  100% {
    transform: translate(0, 0) scale(1.06);
    border-radius: 44% 56% 62% 38% / 48% 52% 48% 52%;
  }
  50% {
    transform: translate(-10%, -8%) scale(0.9);
    border-radius: 60% 40% 36% 64% / 60% 40% 60% 40%;
  }
}

/* ── fx-bg-blobs-warm ── ta sama mechanika, cieplejsza paleta */
.fx-bg-blobs-warm::before {
  background: #e8dcc2;
  opacity: 0.6;
}
.fx-bg-blobs-warm::after {
  background: var(--global-palette2, #02603d);
  opacity: 0.26;
}

/* ── fx-bg-mesh ── gradient siatkowy, bez ostrych krawędzi.
   Spokojniejszy od plam — dobry pod długie sekcje tekstowe. */
.fx-bg-mesh {
  position: relative;
  isolation: isolate;
  background-color: var(--global-palette9, #fff);
}
.fx-bg-mesh::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background:
    radial-gradient(
      46% 42% at 18% 22%,
      var(--global-palette3, #48f093) 0%,
      transparent 62%
    ),
    radial-gradient(
      40% 46% at 82% 14%,
      var(--global-palette2, #02603d) 0%,
      transparent 58%
    ),
    radial-gradient(52% 48% at 68% 88%, #e8dcc2 0%, transparent 60%);
  background-size: 180% 180%;
  animation: fx-mesh 34s ease-in-out infinite;
}
@keyframes fx-mesh {
  0%,
  100% {
    background-position:
      0% 0%,
      100% 0%,
      60% 100%;
  }
  50% {
    background-position:
      24% 18%,
      72% 22%,
      30% 74%;
  }
}

/* ── fx-bg-grain ── delikatne ziarno na wierzchu.
   Zdejmuje „plastikowość" płaskich gradientów. Dodaj RAZEM
   z blobs albo mesh, np. class="fx-bg-blobs fx-bg-grain" */
.fx-bg-grain {
  position: relative;
}
.fx-bg-grain > * {
  position: relative;
  z-index: 1;
}
.fx-bg-grain::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── fx-bg-lines ── siatka cienkich linii, bardzo dyskretna */
.fx-bg-lines {
  position: relative;
  isolation: isolate;
}
.fx-bg-lines::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background-image:
    linear-gradient(var(--global-palette7, #e2e5e2) 1px, transparent 1px),
    linear-gradient(90deg, var(--global-palette7, #e2e5e2) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(72% 62% at 50% 40%, #000 0%, transparent 78%);
}

/* ── fx-bg-dots ── delikatna kropkowana faktura (jak w kartach demo) */
.fx-bg-dots {
  position: relative;
  isolation: isolate;
}
.fx-bg-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(
    circle,
    currentColor 1.3px,
    transparent 1.3px
  );
  background-size: 26px 26px;
  opacity: 0.07;
}

/* ═══════════════════════════════════════════════════════════════
   B. EFEKTY PRZEWIJANIA — czysty CSS
   animation-timeline steruje animacją pozycją na ekranie.
   Zero JS, zero obserwatorów. W starszych przeglądarkach
   @supports nie zadziała i element zostaje normalny.
   ═══════════════════════════════════════════════════════════════ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* ── fx-parallax ── element płynie wolniej niż strona.
       Warianty: -slow / -fast. Daj na obrazek albo kolumnę. */
    .fx-parallax,
    .fx-parallax-slow,
    .fx-parallax-fast {
      animation: fx-kf-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      will-change: transform;
    }
    .fx-parallax-slow {
      animation-name: fx-kf-parallax-slow;
    }
    .fx-parallax-fast {
      animation-name: fx-kf-parallax-fast;
    }

    /* ── fx-zoom-out ── zdjęcie startuje przybliżone i się cofa */
    .fx-zoom-out img,
    img.fx-zoom-out {
      animation: fx-kf-zoomout linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
    }

    /* ── fx-blur-in ── tekst wyostrza się przy wjeździe */
    .fx-blur-in {
      animation: fx-kf-blur linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 34%;
    }

    /* ── fx-progress ── pasek postępu czytania.
       Daj na pusty blok Dzielnik/Spacer na górze strony. */
    .fx-progress {
      position: sticky;
      top: 0;
      z-index: 90;
      height: 3px;
      background: var(--global-palette1, #063d28);
      transform-origin: left center;
      animation: fx-kf-progress linear both;
      animation-timeline: scroll(root);
    }

    /* ── fx-rotate-in ── delikatne prostowanie się elementu */
    .fx-rotate-in {
      animation: fx-kf-rotate linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 38%;
    }
  }
}

@keyframes fx-kf-parallax {
  from {
    transform: translateY(38px);
  }
  to {
    transform: translateY(-38px);
  }
}
@keyframes fx-kf-parallax-slow {
  from {
    transform: translateY(20px);
  }
  to {
    transform: translateY(-20px);
  }
}
@keyframes fx-kf-parallax-fast {
  from {
    transform: translateY(70px);
  }
  to {
    transform: translateY(-70px);
  }
}
@keyframes fx-kf-reveal {
  from {
    clip-path: inset(100% 0 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
@keyframes fx-kf-zoomout {
  from {
    transform: scale(1.18);
  }
  to {
    transform: scale(1);
  }
}
@keyframes fx-kf-blur {
  from {
    opacity: 0;
    filter: blur(9px);
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: none;
  }
}
@keyframes fx-kf-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
@keyframes fx-kf-rotate {
  from {
    opacity: 0;
    transform: rotate(-2.5deg) translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── fx-stack ── karty nakładają się przy przewijaniu.
   Klasyk z Framera, a to zwykły position:sticky — działa wszędzie.
   Daj fx-stack-wrap na Wiersz, fx-stack na każdą Kolumnę w środku. */
.fx-stack-wrap {
  position: relative;
}
.fx-stack {
  position: sticky;
  top: 90px;
}
.fx-stack:nth-child(1) {
  top: 90px;
}
.fx-stack:nth-child(2) {
  top: 110px;
}
.fx-stack:nth-child(3) {
  top: 130px;
}
.fx-stack:nth-child(4) {
  top: 150px;
}
.fx-stack:nth-child(5) {
  top: 170px;
}

/* ── fx-marquee ── nieskończony przewijany pasek.
   Struktura: blok z klasą fx-marquee, w środku DWA identyczne
   zestawy tekstu obok siebie (skopiuj i wklej ten sam wiersz). */
.fx-marquee {
  overflow: hidden;
  display: flex;
  gap: 0;
  white-space: nowrap;
}
.fx-marquee > * {
  display: flex;
  flex: 0 0 auto;
  gap: 44px;
  padding-right: 44px;
  animation: fx-kf-marquee var(--fx-marquee-time, 30s) linear infinite;
  will-change: transform;
}
.fx-marquee:hover > * {
  animation-play-state: paused;
}
@keyframes fx-kf-marquee {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-100%, 0, 0);
  }
}
/* prędkości */
.fx-marquee-slow {
  --fx-marquee-time: 48s;
}
.fx-marquee-fast {
  --fx-marquee-time: 18s;
}

/* ═══════════════════════════════════════════════════════════════
   C. TEKST
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-text-gradient ── gradient przelewa się przez litery */
.fx-text-gradient,
.fx-text-gradient .kb-adv-text-inner {
  background: linear-gradient(
    100deg,
    var(--global-palette1, #063d28) 0%,
    var(--global-palette2, #02603d) 34%,
    var(--global-palette3, #48f093) 58%,
    var(--global-palette1, #063d28) 100%
  );
  background-size: 260% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: fx-kf-textgrad 9s linear infinite;
}
@keyframes fx-kf-textgrad {
  to {
    background-position: 260% center;
  }
}

/* ── fx-outline ── tekst konturem zamiast wypełnienia.
   Świetny jako co drugi element w marquee. */
.fx-outline {
  -webkit-text-stroke: 1.5px currentColor;
  color: transparent;
}

/* ═══════════════════════════════════════════════════════════════
   D. MIKROINTERAKCJE — wymagają pliku JS
   Bez JS wyglądają normalnie, po prostu nie reagują na kursor.
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-magnetic ── przycisk lekko podąża za kursorem */
.fx-magnetic {
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  transform: translate(var(--fx-mx, 0px), var(--fx-my, 0px));
}
.fx-magnetic.is-pulling {
  transition: transform 0.1s linear;
}

/* ── fx-tilt ── karta przechyla się w stronę kursora */
.fx-tilt {
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg))
    rotateY(var(--fx-ry, 0deg));
}
.fx-tilt.is-pulling {
  transition: transform 0.12s linear;
}

/* ── fx-spot ── poświata podąża za kursorem po karcie */
.fx-spot {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.fx-spot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  transition: opacity 0.45s ease;
  background: radial-gradient(
    220px circle at var(--fx-px, 50%) var(--fx-py, 50%),
    rgba(255, 255, 255, 0.18),
    transparent 62%
  );
  pointer-events: none;
}
.fx-spot:hover::before {
  opacity: 1;
}
.fx-spot > * {
  position: relative;
  z-index: 1;
}

/* ═══════════════════════════════════════════════════════════════
   E. OGRANICZONY RUCH
   ═══════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .fx-bg-blobs::before,
  .fx-bg-blobs::after,
  .fx-bg-mesh::before,
  .fx-text-gradient,
  .fx-text-gradient .kb-adv-text-inner,
  .fx-marquee > * {
    animation: none !important;
  }
  .fx-magnetic,
  .fx-tilt {
    transform: none !important;
  }
  .fx-stack {
    position: static;
  }
}

/* Hero – odsłanianie zdjęcia kółkiem od środka */
.fx-reveal-img img {
  animation: fxCircleReveal 1.1s cubic-bezier(0.22, 1, 0.36, 1) 0.2s both;
}

@keyframes fxCircleReveal {
  from {
    clip-path: circle(0% at 50% 50%);
  }
  to {
    clip-path: circle(72% at 50% 50%);
  }
}

/* szacunek dla ustawień ograniczenia animacji */
@media (prefers-reduced-motion: reduce) {
  .fx-reveal-img img {
    animation: none;
  }
}
/* ── fx-lines · odsłanianie nagłówka linia po linii ──────────────
   Splitter (zewnętrzny JS) dzieli nagłówek na .line > .word i dodaje
   klasy: fx-ready (podział gotowy) oraz is-visible (w widoku).

   ZERO przeskoku układu wymaga, by nagłówek PRZED i PO podziale
   zajmował identyczną wysokość. Gwarantują to dwie rzeczy:
   • .line jako blok o dziedziczonym line-height — te same odstępy
     między wierszami co w nierozbitym tekście,
   • słowa z vertical-align:top — inline-block nie podbija line-boxa.

   Zapas na ogonki: TYLKO padding-bottom + margin-bottom (ujemny),
   nigdy po obu stronach. Dwustronny padding był sprawcą skoku —
   ujemne marginesy SĄSIEDNICH wierszy zwijają się (margin
   collapsing) do wartości mniejszej niż ich suma, więc padding nie
   był w pełni odejmowany i blok robił się o ~0.3–0.5em wyższy.
   Przy samym dole górny margines następnego wiersza to 0, nic się
   nie zwija „podwójnie", a ujemny margines ostatniego wiersza
   przechodzi przez nagłówek i zdejmuje padding z układu — wysokość
   nagłówka zostaje = liczba wierszy × line-height. */
.fx-lines {
  visibility: hidden; /* rezerwuje miejsce, nie zeruje wysokości */
}
.fx-lines.fx-ready {
  visibility: visible;
}
.fx-lines .line {
  display: block;
  overflow: hidden;
  line-height: inherit;
  padding-bottom: 0.18em; /* miejsce na ogonki: g y ą ę */
  margin-bottom: -0.18em; /* zdjęte z układu, nie zmienia wysokości */
}
.fx-lines .word {
  display: inline-block;
  vertical-align: top; /* nie rozpycha wysokości wiersza */
  transform: translateY(130%);
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.fx-lines.is-visible .word {
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .fx-lines,
  .fx-lines.fx-ready {
    visibility: visible;
  }
  .fx-lines .word {
    transform: none;
    transition: none;
  }
}

.sub-button-txt {
  margin-top: -20px !important;
  font-size: 12px;
  margin-left: 15px;
  max-width: 350px !important;
}

@keyframes bgDrift {
  0% {
    background-position: 16% 20%;
  }
  50% {
    background-position: 22% 28%;
  }
  100% {
    background-position: 16% 20%;
  }
}
.img-hero-bg-j .kt-inside-inner-col {
  animation: bgDrift 15s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .img-hero-bg-j {
    animation: none;
  }
}
/* ═══════════════════════════════════════════════════════════════
   ADSY FX — PAKIET 2
   Tła gradientowe, efekty przewijania, mikrointerakcje
   ───────────────────────────────────────────────────────────────
   Wklej do: Wygląd → Dostosuj → Dodatkowy CSS  (pod pakietem 1)
   Klasy dodajesz w bloku: Zaawansowane → Dodatkowa klasa CSS

   ZASADA: JavaScript (osobny plik) tylko ustawia zmienne CSS.
   Nigdy nie przebudowuje DOM, nie czeka na obrazy, nie walczy
   z cache. Wszystko poniżej działa też bez niego — po prostu
   bez reakcji na kursor.
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   A. TŁA GRADIENTOWE
   Klasę dodajesz na blok Wiersz (Row Layout).
   Wymaga, żeby wiersz miał ustawione jakieś tło (choćby białe),
   inaczej plamy będą widoczne przez sekcję pod spodem.
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-bg-blobs ── rozmyte plamy, powoli dryfują.
   To jest ten efekt z Salient. Dwie plamy jako pseudoelementy,
   trzecia jako gradient na samym wierszu. */
.fx-bg-blobs {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.fx-bg-blobs::before,
.fx-bg-blobs::after {
  content: '';
  position: absolute;
  z-index: -1;
  width: 46vw;
  height: 46vw;
  max-width: 620px;
  max-height: 620px;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  will-change: transform, border-radius;
}
.fx-bg-blobs::before {
  background: var(--global-palette2, #02603d);
  opacity: 0.38;
  top: -18%;
  left: -10%;
  animation: fx-blob-a 26s ease-in-out infinite;
}
.fx-bg-blobs::after {
  background: var(--global-palette3, #48f093);
  opacity: 0.3;
  bottom: -24%;
  right: -12%;
  animation: fx-blob-b 32s ease-in-out infinite;
}
@keyframes fx-blob-a {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    border-radius: 52% 48% 40% 60% / 56% 44% 56% 44%;
  }
  50% {
    transform: translate(8%, 10%) scale(1.14);
    border-radius: 38% 62% 58% 42% / 42% 58% 42% 58%;
  }
}
@keyframes fx-blob-b {
  0%,
  100% {
    transform: translate(0, 0) scale(1.06);
    border-radius: 44% 56% 62% 38% / 48% 52% 48% 52%;
  }
  50% {
    transform: translate(-10%, -8%) scale(0.9);
    border-radius: 60% 40% 36% 64% / 60% 40% 60% 40%;
  }
}

/* ── fx-bg-blobs-warm ── ta sama mechanika, cieplejsza paleta */
.fx-bg-blobs-warm::before {
  background: #e8dcc2;
  opacity: 0.6;
}
.fx-bg-blobs-warm::after {
  background: var(--global-palette2, #02603d);
  opacity: 0.26;
}

/* ── fx-bg-mesh ── gradient siatkowy, bez ostrych krawędzi.
   Spokojniejszy od plam — dobry pod długie sekcje tekstowe. */
.fx-bg-mesh {
  position: relative;
  isolation: isolate;
  background-color: var(--global-palette9, #fff);
}
.fx-bg-mesh::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background:
    radial-gradient(
      46% 42% at 18% 22%,
      var(--global-palette3, #48f093) 0%,
      transparent 62%
    ),
    radial-gradient(
      40% 46% at 82% 14%,
      var(--global-palette2, #02603d) 0%,
      transparent 58%
    ),
    radial-gradient(52% 48% at 68% 88%, #e8dcc2 0%, transparent 60%);
  background-size: 180% 180%;
  animation: fx-mesh 34s ease-in-out infinite;
}
@keyframes fx-mesh {
  0%,
  100% {
    background-position:
      0% 0%,
      100% 0%,
      60% 100%;
  }
  50% {
    background-position:
      24% 18%,
      72% 22%,
      30% 74%;
  }
}

/* ── fx-bg-grain ── delikatne ziarno na wierzchu.
   Zdejmuje „plastikowość" płaskich gradientów. Dodaj RAZEM
   z blobs albo mesh, np. class="fx-bg-blobs fx-bg-grain" */
.fx-bg-grain {
  position: relative;
}
.fx-bg-grain > * {
  position: relative;
  z-index: 1;
}
.fx-bg-grain::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── fx-bg-lines ── siatka cienkich linii, bardzo dyskretna */
.fx-bg-lines {
  position: relative;
  isolation: isolate;
}
.fx-bg-lines::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background-image:
    linear-gradient(var(--global-palette7, #e2e5e2) 1px, transparent 1px),
    linear-gradient(90deg, var(--global-palette7, #e2e5e2) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(72% 62% at 50% 40%, #000 0%, transparent 78%);
}

/* ── fx-bg-dots ── delikatna kropkowana faktura (jak w kartach demo) */
.fx-bg-dots {
  position: relative;
  isolation: isolate;
}
.fx-bg-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(
    circle,
    currentColor 1.3px,
    transparent 1.3px
  );
  background-size: 26px 26px;
  opacity: 0.07;
}

/* ═══════════════════════════════════════════════════════════════
   B. EFEKTY PRZEWIJANIA — czysty CSS
   animation-timeline steruje animacją pozycją na ekranie.
   Zero JS, zero obserwatorów. W starszych przeglądarkach
   @supports nie zadziała i element zostaje normalny.
   ═══════════════════════════════════════════════════════════════ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* ── fx-parallax ── element płynie wolniej niż strona.
       Warianty: -slow / -fast. Daj na obrazek albo kolumnę. */
    .fx-parallax,
    .fx-parallax-slow,
    .fx-parallax-fast {
      animation: fx-kf-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      will-change: transform;
    }
    .fx-parallax-slow {
      animation-name: fx-kf-parallax-slow;
    }
    .fx-parallax-fast {
      animation-name: fx-kf-parallax-fast;
    }

    /* ── fx-reveal-img ── kadr odsłania się od dołu przy wjeździe.
       To jest maska, ale robiona bez JS — nie ma czego zepsuć. */
    .fx-reveal-img {
      animation: fx-kf-reveal linear both;
      animation-timeline: view();
      animation-range: entry 6% cover 40%;
    }

    /* ── fx-zoom-out ── zdjęcie startuje przybliżone i się cofa */
    .fx-zoom-out img,
    img.fx-zoom-out {
      animation: fx-kf-zoomout linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
    }

    /* ── fx-blur-in ── tekst wyostrza się przy wjeździe */
    .fx-blur-in {
      animation: fx-kf-blur linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 34%;
    }

    /* ── fx-progress ── pasek postępu czytania.
       Daj na pusty blok Dzielnik/Spacer na górze strony. */
    .fx-progress {
      position: sticky;
      top: 0;
      z-index: 90;
      height: 3px;
      background: var(--global-palette1, #063d28);
      transform-origin: left center;
      animation: fx-kf-progress linear both;
      animation-timeline: scroll(root);
    }

    /* ── fx-rotate-in ── delikatne prostowanie się elementu */
    .fx-rotate-in {
      animation: fx-kf-rotate linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 38%;
    }
  }
}

@keyframes fx-kf-parallax {
  from {
    transform: translateY(38px);
  }
  to {
    transform: translateY(-38px);
  }
}
@keyframes fx-kf-parallax-slow {
  from {
    transform: translateY(20px);
  }
  to {
    transform: translateY(-20px);
  }
}
@keyframes fx-kf-parallax-fast {
  from {
    transform: translateY(70px);
  }
  to {
    transform: translateY(-70px);
  }
}
@keyframes fx-kf-reveal {
  from {
    clip-path: inset(100% 0 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
@keyframes fx-kf-zoomout {
  from {
    transform: scale(1.18);
  }
  to {
    transform: scale(1);
  }
}
@keyframes fx-kf-blur {
  from {
    opacity: 0;
    filter: blur(9px);
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: none;
  }
}
@keyframes fx-kf-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
@keyframes fx-kf-rotate {
  from {
    opacity: 0;
    transform: rotate(-2.5deg) translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── fx-stack ── karty nakładają się przy przewijaniu.
   Klasyk z Framera, a to zwykły position:sticky — działa wszędzie.
   Daj fx-stack-wrap na Wiersz, fx-stack na każdą Kolumnę w środku. */
.fx-stack-wrap {
  position: relative;
}
.fx-stack {
  position: sticky;
  top: 90px;
}
.fx-stack:nth-child(1) {
  top: 90px;
}
.fx-stack:nth-child(2) {
  top: 110px;
}
.fx-stack:nth-child(3) {
  top: 130px;
}
.fx-stack:nth-child(4) {
  top: 150px;
}
.fx-stack:nth-child(5) {
  top: 170px;
}

/* ── fx-marquee ── nieskończony przewijany pasek.
   Struktura: blok z klasą fx-marquee, w środku DWA identyczne
   zestawy tekstu obok siebie (skopiuj i wklej ten sam wiersz). */
.fx-marquee {
  overflow: hidden;
  display: flex;
  gap: 0;
  white-space: nowrap;
}
.fx-marquee > * {
  display: flex;
  flex: 0 0 auto;
  gap: 44px;
  padding-right: 44px;
  animation: fx-kf-marquee var(--fx-marquee-time, 30s) linear infinite;
  will-change: transform;
}
.fx-marquee:hover > * {
  animation-play-state: paused;
}
@keyframes fx-kf-marquee {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-100%, 0, 0);
  }
}
/* prędkości */
.fx-marquee-slow {
  --fx-marquee-time: 48s;
}
.fx-marquee-fast {
  --fx-marquee-time: 18s;
}

/* ═══════════════════════════════════════════════════════════════
   C. TEKST
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-text-gradient ── gradient przelewa się przez litery */
.fx-text-gradient,
.fx-text-gradient .kb-adv-text-inner {
  background: linear-gradient(
    100deg,
    var(--global-palette1, #063d28) 0%,
    var(--global-palette2, #02603d) 34%,
    var(--global-palette3, #48f093) 58%,
    var(--global-palette1, #063d28) 100%
  );
  background-size: 260% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: fx-kf-textgrad 9s linear infinite;
}
@keyframes fx-kf-textgrad {
  to {
    background-position: 260% center;
  }
}

/* ── fx-outline ── tekst konturem zamiast wypełnienia.
   Świetny jako co drugi element w marquee. */
.fx-outline {
  -webkit-text-stroke: 1.5px currentColor;
  color: transparent;
}

/* ═══════════════════════════════════════════════════════════════
   D. MIKROINTERAKCJE — wymagają pliku JS
   Bez JS wyglądają normalnie, po prostu nie reagują na kursor.
   ═══════════════════════════════════════════════════════════════ */

/* ── fx-magnetic ── przycisk lekko podąża za kursorem */
.fx-magnetic {
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  transform: translate(var(--fx-mx, 0px), var(--fx-my, 0px));
}
.fx-magnetic.is-pulling {
  transition: transform 0.1s linear;
}

/* ── fx-tilt ── karta przechyla się w stronę kursora */
.fx-tilt {
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg))
    rotateY(var(--fx-ry, 0deg));
}
.fx-tilt.is-pulling {
  transition: transform 0.12s linear;
}

/* ── fx-spot ── poświata podąża za kursorem po karcie */
.fx-spot {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.fx-spot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  transition: opacity 0.45s ease;
  background: radial-gradient(
    220px circle at var(--fx-px, 50%) var(--fx-py, 50%),
    rgba(255, 255, 255, 0.18),
    transparent 62%
  );
  pointer-events: none;
}
.fx-spot:hover::before {
  opacity: 1;
}
.fx-spot > * {
  position: relative;
  z-index: 1;
}

/* ═══════════════════════════════════════════════════════════════
   E. OGRANICZONY RUCH
   ═══════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .fx-bg-blobs::before,
  .fx-bg-blobs::after,
  .fx-bg-mesh::before,
  .fx-text-gradient,
  .fx-text-gradient .kb-adv-text-inner,
  .fx-marquee > * {
    animation: none !important;
  }
  .fx-magnetic,
  .fx-tilt {
    transform: none !important;
  }
  .fx-stack {
    position: static;
  }
}

/* =========================================================
   ADSY FX — biblioteka animacji (ekstrakt z demo)
   Wklej w Kadence → Customize → Custom CSS
   lub w plikach shared CSS pluginu ADSY Motion
   Wymaga: --global-palette1..9 (Kadence Customizer definiuje sam)
   ========================================================= */

:root {
  --fx-base: 0.45s;
  --fx-fast: 0.28s;
  --fx-slow: 0.7s;
  --fx-out: cubic-bezier(0.22, 1, 0.36, 1);
  --fx-soft: cubic-bezier(0.05, 0.2, 0.1, 1);
  --fx-lift: -6px;
  --fx-lift-b: -4px;
  --fx-shadow: 0 22px 48px rgba(0, 0, 0, 0.13);
  --fx-marquee-time: 48s;
}

.kb-button:not(.fx-off),
.wp-block-button__link:not(.fx-off) {
  transition:
    transform var(--fx-base) var(--fx-out),
    box-shadow var(--fx-base) var(--fx-out),
    background-color var(--fx-base) var(--fx-out),
    color var(--fx-base) var(--fx-out);
}

.kb-button:not(.fx-off):active,
.wp-block-button__link:not(.fx-off):active {
  transform: scale(0.97);
  transition-duration: 0.1s;
}

.kb-button:not(.fx-off) .kb-svg-icon-wrap {
  transition: transform var(--fx-base) var(--fx-out);
}

.wp-block-kadence-infobox:not(.fx-off) .kt-blocks-info-box-link-wrap,
.kadence-column:not(.fx-off) > .kt-inside-inner-col {
  transition:
    transform var(--fx-slow) var(--fx-soft),
    box-shadow var(--fx-slow) var(--fx-soft);
}

.wp-block-kadence-infobox:not(.fx-off) .kadence-info-box-icon-container,
.wp-block-kadence-infobox:not(.fx-off) .kb-svg-icon-wrap {
  transition: transform var(--fx-base) var(--fx-out);
}

.kt-svg-icon-list:not(.fx-off) .kt-svg-icon-list-item {
  transition: transform var(--fx-fast) var(--fx-out);
}

.entry-content p a:not(.kb-button):not(.fx-off) {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--fx-base) var(--fx-out);
}

.wp-block-kadence-infobox.fx-live-on .kt-blocks-info-box-link-wrap,
.kadence-column.fx-live-on > .kt-inside-inner-col,
.fx-live.fx-live-on {
  transform: translateY(var(--fx-lift));
  box-shadow: var(--fx-shadow);
}

.wp-block-kadence-infobox.fx-live-on .kadence-info-box-icon-container,
.wp-block-kadence-infobox.fx-live-on .kb-svg-icon-wrap {
  transform: translateY(-5px) scale(1.07);
}

.fx-live {
  transition:
    transform var(--fx-slow) var(--fx-soft),
    box-shadow var(--fx-slow) var(--fx-soft);
}

@keyframes fx-kf-live {
  0%,
  100% {
    transform: translateY(0) scale(1);
    box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  }
  50% {
    transform: translateY(var(--fx-lift)) scale(1.012);
    box-shadow: var(--fx-shadow);
  }
}

@keyframes fx-kf-focus {
  0%,
  100% {
    opacity: 0.55;
  }
  50% {
    opacity: 1;
  }
}

@keyframes fx-kf-up {
  from {
    opacity: 0;
    transform: translateY(28px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-kf-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fx-kf-scale {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-kf-right {
  from {
    opacity: 0;
    transform: translateX(-26px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-kf-left {
  from {
    opacity: 0;
    transform: translateX(26px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-kf-blur {
  from {
    opacity: 0;
    filter: blur(9px);
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: none;
  }
}

@keyframes fx-kf-rotate {
  from {
    opacity: 0;
    transform: rotate(-2.5deg) translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fx-kf-parallax {
  from {
    transform: translateY(38px);
  }
  to {
    transform: translateY(-38px);
  }
}

@keyframes fx-kf-parallax-slow {
  from {
    transform: translateY(20px);
  }
  to {
    transform: translateY(-20px);
  }
}

@keyframes fx-kf-parallax-fast {
  from {
    transform: translateY(70px);
  }
  to {
    transform: translateY(-70px);
  }
}

@keyframes fx-kf-reveal {
  from {
    clip-path: inset(100% 0 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

@keyframes fx-kf-zoomout {
  from {
    transform: scale(1.18);
  }
  to {
    transform: scale(1);
  }
}

@keyframes fx-kf-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

.fx-btn-slide.kb-button,
.fx-btn-slide .kb-button {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.fx-btn-slide.kb-button::before,
.fx-btn-slide .kb-button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--global-palette2, #02603d);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--fx-base) var(--fx-out);
}

.fx-btn-slide.kb-button:hover::before,
.fx-btn-slide .kb-button:hover::before {
  transform: scaleX(1);
}

.fx-btn-ring.kb-button,
.fx-btn-ring .kb-button {
  position: relative;
}

.fx-btn-ring.kb-button::after,
.fx-btn-ring .kb-button::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid currentColor;
  opacity: 0;
  pointer-events: none;
}

.fx-btn-ring.kb-button:hover::after,
.fx-btn-ring .kb-button:hover::after {
  animation: fx-ring var(--fx-slow) var(--fx-out);
}

@keyframes fx-ring {
  from {
    transform: scale(1);
    opacity: 0.55;
  }
  to {
    transform: scale(1.18);
    opacity: 0;
  }
}

.fx-ic-pulse .kb-svg-icon-wrap {
  position: relative;
}

.fx-ic-pulse .kb-svg-icon-wrap::before {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0;
  animation: fx-pulse 2.4s ease-out infinite;
}

@keyframes fx-pulse {
  0% {
    transform: scale(0.6);
    opacity: 0.5;
  }
  70% {
    transform: scale(2.2);
    opacity: 0;
  }
  100% {
    transform: scale(2.2);
    opacity: 0;
  }
}

.fx-ic-tilt .kb-svg-icon-wrap {
  transition: transform var(--fx-slow) var(--fx-out);
}

.fx-ic-tilt:hover .kb-svg-icon-wrap {
  transform: rotate(-9deg) scale(1.06);
}

.fx-card-line {
  position: relative;
  overflow: hidden;
  overflow: clip;
}

/* KRESKA KART WYŁĄCZONA GLOBALNIE — nie pasowała na kartach.
   Nie rysuje się nigdzie, niezależnie od klas. Żeby przywrócić,
   odkomentuj poniższe (wtedy fx-off wyłącza ją per-karta). */
/*
.fx-card-line:not(.fx-off)::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 3px;
  height: 100%;
  z-index: 2;
  background: var(--global-palette1, #063d28);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform var(--fx-slow) var(--fx-out);
}

.fx-card-line:not(.fx-off):hover::before {
  transform: scaleY(1);
}
*/

@keyframes fx-kf-lineY {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

.fx-card-tint {
  position: relative;
  isolation: isolate;
}

.fx-card-tint::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(
    120% 100% at 20% 0%,
    rgba(255, 255, 255, 0.2),
    transparent 62%
  );
  transition: opacity var(--fx-slow) var(--fx-soft);
}

.fx-card-tint:hover::after {
  opacity: 1;
}

.fx-stack-wrap {
  position: relative;
}

.fx-stack {
  position: sticky;
  top: 90px;
}

.fx-stack:nth-child(2) {
  top: 110px;
}

.fx-stack:nth-child(3) {
  top: 130px;
}

.fx-stack:nth-child(4) {
  top: 150px;
}

.fx-stack:nth-child(5) {
  top: 170px;
}

.fx-mark {
  background-image: linear-gradient(
    var(--global-palette3, #48f093),
    var(--global-palette3, #48f093)
  );
  background-size: 100% 0.32em;
  background-position: 0 88%;
  background-repeat: no-repeat;
  padding: 0 0.06em;
}

.fx-text-gradient,
.fx-text-gradient .kb-adv-text-inner {
  background: linear-gradient(
    100deg,
    var(--global-palette1, #063d28) 0%,
    var(--global-palette2, #02603d) 34%,
    var(--global-palette3, #48f093) 58%,
    var(--global-palette1, #063d28) 100%
  );
  background-size: 260% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: fx-kf-textgrad 9s linear infinite;
}

@keyframes fx-kf-textgrad {
  to {
    background-position: 260% center;
  }
}

.fx-outline {
  -webkit-text-stroke: 1.5px currentColor;
  color: transparent;
}

.fx-bg-blobs {
  position: relative;
  overflow: hidden;
  overflow: clip;
  isolation: isolate;
}

.fx-bg-blobs::before,
.fx-bg-blobs::after {
  content: '';
  position: absolute;
  z-index: -1;
  width: 46vw;
  height: 46vw;
  max-width: 620px;
  max-height: 620px;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  will-change: transform, border-radius;
}

.fx-bg-blobs::before {
  background: var(--global-palette2, #02603d);
  opacity: 0.38;
  top: -18%;
  left: -10%;
  animation: fx-blob-a 26s ease-in-out infinite;
}

.fx-bg-blobs::after {
  background: var(--global-palette3, #48f093);
  opacity: 0.3;
  bottom: -24%;
  right: -12%;
  animation: fx-blob-b 32s ease-in-out infinite;
}

@keyframes fx-blob-a {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    border-radius: 52% 48% 40% 60% / 56% 44% 56% 44%;
  }
  50% {
    transform: translate(8%, 10%) scale(1.14);
    border-radius: 38% 62% 58% 42% / 42% 58% 42% 58%;
  }
}

@keyframes fx-blob-b {
  0%,
  100% {
    transform: translate(0, 0) scale(1.06);
    border-radius: 44% 56% 62% 38% / 48% 52% 48% 52%;
  }
  50% {
    transform: translate(-10%, -8%) scale(0.9);
    border-radius: 60% 40% 36% 64% / 60% 40% 60% 40%;
  }
}

.fx-bg-blobs-warm::before {
  background: #e8dcc2;
  opacity: 0.6;
}

.fx-bg-blobs-warm::after {
  background: var(--global-palette2, #02603d);
  opacity: 0.26;
}

.fx-bg-mesh {
  position: relative;
  isolation: isolate;
}

.fx-bg-mesh::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background:
    radial-gradient(
      46% 42% at 18% 22%,
      var(--global-palette3, #48f093) 0%,
      transparent 62%
    ),
    radial-gradient(
      40% 46% at 82% 14%,
      var(--global-palette2, #02603d) 0%,
      transparent 58%
    ),
    radial-gradient(52% 48% at 68% 88%, #e8dcc2 0%, transparent 60%);
  background-size: 180% 180%;
  animation: fx-mesh 34s ease-in-out infinite;
}

@keyframes fx-mesh {
  0%,
  100% {
    background-position:
      0% 0%,
      100% 0%,
      60% 100%;
  }
  50% {
    background-position:
      24% 18%,
      72% 22%,
      30% 74%;
  }
}

.fx-bg-grain {
  position: relative;
}

.fx-bg-grain > * {
  position: relative;
  z-index: 1;
}

.fx-bg-grain::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

.fx-bg-lines {
  position: relative;
  isolation: isolate;
}

.fx-bg-lines::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.5;
  background-image:
    linear-gradient(var(--global-palette7, #e2e5e2) 1px, transparent 1px),
    linear-gradient(90deg, var(--global-palette7, #e2e5e2) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(72% 62% at 50% 40%, #000 0%, transparent 78%);
}

.fx-bg-dots {
  position: relative;
  isolation: isolate;
}

.fx-bg-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.07;
  background-image: radial-gradient(
    circle,
    currentColor 1.3px,
    transparent 1.3px
  );
  background-size: 26px 26px;
}

.fx-marquee {
  overflow: hidden;
  display: flex;
  white-space: nowrap;
}

.fx-marquee > * {
  display: flex;
  flex: 0 0 auto;
  gap: 44px;
  padding-right: 44px;
  animation: fx-kf-marquee var(--fx-marquee-time, 30s) linear infinite;
  will-change: transform;
}

.fx-marquee:hover > * {
  animation-play-state: paused;
}

@keyframes fx-kf-marquee {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-100%, 0, 0);
  }
}

.fx-marquee-slow {
  --fx-marquee-time: 48s;
}

.fx-marquee-fast {
  --fx-marquee-time: 18s;
}

.fx-magnetic {
  transition: transform var(--fx-base) var(--fx-out);
  transform: translate(var(--fx-mx, 0px), var(--fx-my, 0px));
}

.fx-magnetic.is-pulling {
  transition: transform 0.1s linear;
}

.fx-tilt {
  transform-style: preserve-3d;
  transition: transform 0.5s var(--fx-out);
  transform: perspective(900px) rotateX(var(--fx-rx, 0deg))
    rotateY(var(--fx-ry, 0deg));
}

.fx-tilt.is-pulling {
  transition: transform 0.12s linear;
}

.fx-spot {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  overflow: clip;
}

.fx-spot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(
    220px circle at var(--fx-px, 50%) var(--fx-py, 50%),
    rgba(255, 255, 255, 0.18),
    transparent 62%
  );
  transition: opacity var(--fx-base) ease;
}

.fx-spot:hover::before {
  opacity: 1;
}

.fx-spot > * {
  position: relative;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .fx-up,
  .fx-fade,
  .fx-scale,
  .fx-right,
  .fx-left,
  .fx-blur-in,
  .fx-rotate-in,
  .fx-reveal-img {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }
  .fx-magnetic,
  .fx-tilt {
    transform: none !important;
  }
  .fx-stack {
    position: static;
  }
}

/* Kadence Gallery – zoom w kadrze */
.wp-block-kadence-advancedgallery .kadence-blocks-gallery-item-inner,
.wp-block-kadence-advancedgallery .kb-gallery-figure {
  overflow: hidden;
}

.wp-block-kadence-advancedgallery .kb-gallery-figure img {
  display: block;
  transition: transform 0.6s ease;
  will-change: transform;
}

.wp-block-kadence-advancedgallery
  .kadence-blocks-gallery-item:hover
  .kb-gallery-figure
  img {
  transform: scale(1.06);
}

/* Fluent Forms – animowany focus */
.fluent_form_3 .ff-el-group {
  position: relative;
}

/* Input / textarea – płynne przejście */
.fluent_form_3 .ff-el-form-control {
  transition:
    border-color 0.25s ease,
    box-shadow 0.25s ease;
}

/* Podświetlenie ramki na focus */
.fluent_form_3 .ff-el-form-control:focus {
  border-color: var(--global-palette1, #ff5c01);
  box-shadow: 0 0 0 3px rgba(255, 92, 1, 0.18);
  outline: none;
}

/* Label unosi się i podświetla, gdy pole jest aktywne */
.fluent_form_3 .ff-el-input--label label {
  display: inline-block;
  transition:
    transform 0.25s ease,
    color 0.25s ease;
  transform-origin: left center;
}

.fluent_form_3 .ff-el-group:focus-within .ff-el-input--label label {
  transform: translateY(-3px);
  color: var(--global-palette1, #ff5c01);
}

/* Ikony w siatkach kart bez linku – animacja tylko dla karty pod kursorem */
.wp-block-kadence-column:not(.kb-section-has-link)
  > .kt-inside-inner-col
  > .wp-block-kadence-icon
  .wp-block-kadence-single-icon {
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.wp-block-kadence-column:not(.kb-section-has-link)
  > .kt-inside-inner-col:hover
  > .wp-block-kadence-icon
  .wp-block-kadence-single-icon {
  transform: translateY(-6px) scale(1.1);
}

/* Karta z linkiem – podnoszenie + cień
   ">" (dziecko bezpośrednie), NIE spacja — inaczej podnosi też
   .kt-inside-inner-col zagnieżdżonych sekcji i rusza się wszystko. */
.wp-block-kadence-column.kb-section-has-link > .kt-inside-inner-col {
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  will-change: transform;
  height: 100%;
}

.wp-block-kadence-column.kb-section-has-link:hover > .kt-inside-inner-col {
  transform: translateY(-14px);
  box-shadow: 0 22px 45px rgba(0, 0, 0, 0.14);
}

/* Ikona rośnie w prawo (kotwica po lewej) */
.wp-block-kadence-column.kb-section-has-link .wp-block-kadence-icon {
  transition: transform 0.3s ease;
  transform-origin: left center;
}

.wp-block-kadence-column.kb-section-has-link:hover .wp-block-kadence-icon {
  transform: scale(1.08);
}

/* Strzałka w przycisku karty przesuwa się w prawo */
.wp-block-kadence-column.kb-section-has-link
  .kb-svg-icon-wrap.kb-svg-icon-fe_arrowRight {
  transition: transform 0.3s ease;
}

.wp-block-kadence-column.kb-section-has-link:hover
  .kb-svg-icon-wrap.kb-svg-icon-fe_arrowRight {
  transform: translateX(4px);
}

.wp-block-kadence-singlebtn.kb-button {
  transition:
    transform 0.25s ease,
    box-shadow 0.25s ease;
  will-change: transform;
  display: inline-flex;
  align-items: center;
}

.wp-block-kadence-singlebtn.kb-button:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.12);
}

/* Strzałka przesuwa się w prawo */
.wp-block-kadence-singlebtn.kb-button .kb-svg-icon-wrap {
  transition: transform 0.25s ease;
}

.wp-block-kadence-singlebtn.kb-button:hover .kb-svg-icon-wrap {
  transform: translateX(4px);
}

/* ═══════════════════════════════════════════════════════════════
   ZDJĘCIE-KADR Z PARALAKSĄ (obraz w kolumnie, obok treści)
   Kolumna ze zdjęciem staje się RAMKĄ: przycina i pozycjonuje.
   Zdjęcie wypełnia ją z zapasem, a fx-parallax-slow rusza nim
   w środku ramki (nie rusza całej sekcji).
     • Row:        fx-has-bg              (tylko punkt zaczepienia)
     • blok Obraz: fx-bg fx-parallax-slow (albo fx-parallax / -fast)

   NIE łącz z fx-reveal-img — to osobny efekt, który przycina obraz
   od góry (clip-path) i nadpisuje parallaksę. Wybierz jedno. */

/* ramka = kolumna, w której bezpośrednio leży zdjęcie */
.fx-has-bg .kt-inside-inner-col:has(> .fx-bg) {
  position: relative;
  overflow: clip;
  height: 100%;
  border-radius: 20px; /* zaokrąglenie kadru — dopasuj do bloku */
}

.fx-has-bg .fx-bg {
  position: absolute;
  inset: -34px 0; /* zapas dla -slow (±20px) */
  margin: 0 !important; /* kasuje domyślny margines bloku Obraz */
  pointer-events: none;
}
/* zapas = amplituda ruchu + mały margines; im mniejszy, tym mniej
   zdjęcia ucina object-fit:cover */
.fx-has-bg .fx-bg.fx-parallax {
  inset: -52px 0;
} /* ±38px */
.fx-has-bg .fx-bg.fx-parallax-fast {
  inset: -84px 0;
} /* ±70px */

.fx-has-bg .fx-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* wypełnia kadr bez zniekształceń */
  object-position: center; /* daj 'top', jeśli ważna jest góra zdjęcia */
  display: block;
}

/* ── KÓŁKO: odsłonięcie obrazka od środka — RAZ, przy wejściu ────
   Zdjęcie jest ukryte W CSS OD PIERWSZEJ KLATKI (clip-path 0%), więc
   nie ma błysku „widać → znika → wraca" (to była wina JS ukrywającego
   PO narysowaniu strony). JS (adsy.js) dokłada is-inview, gdy zdjęcie
   wejdzie w widok → kółko rozwija się RAZ i zostaje (bez cofania przy
   scrollu). Bezpieczniki w JS pilnują, by nic nie zostało ukryte,
   gdyby obserwator nie zadziałał.
   Na bloku Obraz:  fx-bg fx-parallax-slow fx-circle */
.fx-circle img {
  clip-path: circle(0% at 50% 50%);
}
.fx-circle.is-inview img {
  animation: fxCircleReveal 1.1s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  .fx-circle img {
    clip-path: none;
    animation: none;
  }
}

/* ── OBRAZ W KARCIE: zoom-in + delikatne uniesienie na hover ────
   Klasa fx-hover-zoom na bloku Obraz WEWNĄTRZ karty z linkiem
   (.kb-section-has-link).

   Zaokrąglenie trzyma FIGURA (ona przycina powiększenie), a z <img>
   je zdejmujemy — inaczej skalowany obraz wychodzi poza ramkę i
   pokazuje ostre rogi. Dopasuj border-radius do swojego ustawienia
   z Kadence (tu 20px — tyle miał obraz w hero). */
.kb-section-has-link .fx-hover-zoom {
  overflow: hidden;
  border-radius: 20px; /* ← Twój promień z Kadence */
  transition: transform 0.5s cubic-bezier(0.24, 1, 0.3, 1);
  will-change: transform;
}
.kb-section-has-link .fx-hover-zoom img {
  display: block;
  border-radius: 0; /* zaokrąglenie trzyma teraz ramka */
  transition: transform 0.5s cubic-bezier(0.24, 1, 0.3, 1);
  will-change: transform;
}
/* hover karty: obraz przybliża się w ramce i lekko wyżej niż reszta */
.kb-section-has-link:hover .fx-hover-zoom {
  transform: translateY(-6px);
}
.kb-section-has-link:hover .fx-hover-zoom img {
  transform: scale(1.08);
}
@media (prefers-reduced-motion: reduce) {
  .kb-section-has-link .fx-hover-zoom,
  .kb-section-has-link .fx-hover-zoom img {
    transform: none;
    transition: none;
  }
}

/* ── LISTA IKON: pozycje wjeżdżają jedna po drugiej ────────────
   Klasa fx-stagger na bloku „Lista ikon" (Kadence Icon List).
   JS (adsy.js) dokłada fx-armed (ukrywa pozycje) i is-inview
   (odpala) gdy lista wjeżdża w widok. Bez JS lista jest normalnie
   widoczna. */
.fx-stagger.fx-armed .kt-svg-icon-list-item-wrap {
  opacity: 0;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap {
  animation: fxStaggerIn 0.5s cubic-bezier(0.24, 1, 0.3, 1) both;
}
@keyframes fxStaggerIn {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* opóźnienia kolejnych pozycji — krok 60ms */
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(1) {
  animation-delay: 0s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(2) {
  animation-delay: 0.06s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(3) {
  animation-delay: 0.12s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(4) {
  animation-delay: 0.18s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(5) {
  animation-delay: 0.24s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(6) {
  animation-delay: 0.3s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(7) {
  animation-delay: 0.36s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(8) {
  animation-delay: 0.42s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(9) {
  animation-delay: 0.48s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(10) {
  animation-delay: 0.54s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(11) {
  animation-delay: 0.6s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(12) {
  animation-delay: 0.66s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(13) {
  animation-delay: 0.72s;
}
.fx-stagger.is-inview .kt-svg-icon-list-item-wrap:nth-child(14) {
  animation-delay: 0.78s;
}
@media (prefers-reduced-motion: reduce) {
  .fx-stagger.fx-armed .kt-svg-icon-list-item-wrap {
    opacity: 1;
  }
  .fx-stagger.is-inview .kt-svg-icon-list-item-wrap {
    animation: none;
  }
}

/* ── fx-up: wjazd od dołu + pojawienie, sterowany scrollem ──────
   Dodaj klasę fx-up dowolnemu blokowi (także całemu Row):
   Advanced → Additional CSS classes. Element pojawia się i wjeżdża
   z dołu, gdy wchodzi w widok. Bez obsługi view() (stare
   przeglądarki) jest po prostu widoczny — nic się nie psuje. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .fx-up {
      animation: fx-kf-up linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 32%;
    }
  }
}
@keyframes fx-kf-up {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.jsz-fbox {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  touch-action: pan-y;
  min-height: 500px;
  transition:
    transform 0.65s cubic-bezier(0.05, 0.2, 0.1, 1),
    box-shadow 0.65s cubic-bezier(0.05, 0.2, 0.1, 1);
}

/* Wewnętrzny wrapper Kadence jako flex — content przyklejony do dołu */
.jsz-fbox > .kt-inside-inner-col {
  display: flex;
  flex-direction: column;
  min-height: inherit;
  height: 100%;
  position: relative;
  overflow: hidden; /* respektuje border-radius z Kadence */
}

/* Kadence image → tło z zoomem */
.jsz-fbox > .kt-inside-inner-col > .wp-block-kadence-image {
  position: absolute !important;
  inset: 0;
  margin: 0;
  z-index: 1;
  transform: scale(1);
  transition: transform 0.8s cubic-bezier(0.24, 1, 0.3, 1);
}
.jsz-fbox > .kt-inside-inner-col > .wp-block-kadence-image .kb-is-ratio-image,
.jsz-fbox > .kt-inside-inner-col > .wp-block-kadence-image img {
  width: 100% !important;
  height: 100% !important;
  padding: 0 !important;
  border-radius: 0 !important;
  object-fit: cover;
}

/* Dwa gradienty — dolne 85% */
.jsz-fbox > .kt-inside-inner-col::before,
.jsz-fbox > .kt-inside-inner-col::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 85%;
  z-index: 5;
  pointer-events: none;
  transition: opacity 0.65s cubic-bezier(0.05, 0.2, 0.1, 1);
}
.jsz-fbox > .kt-inside-inner-col::before {
  background: linear-gradient(
    to bottom,
    rgba(15, 15, 15, 0),
    rgba(15, 15, 15, 0.75)
  );
  opacity: 1;
}
.jsz-fbox > .kt-inside-inner-col::after {
  background: linear-gradient(
    to bottom,
    rgba(255, 107, 61, 0),
    rgba(255, 107, 61, 0.92)
  );
  opacity: 0;
}

/* Content wrapper — nad gradientami, przyklejony do dołu */
.jsz-fbox .jsz-fbox__content {
  position: relative;
  z-index: 10;
  margin-top: auto;
  color: #fff;
}
.jsz-fbox .jsz-fbox__content h1,
.jsz-fbox .jsz-fbox__content h2,
.jsz-fbox .jsz-fbox__content h3,
.jsz-fbox .jsz-fbox__content h4,
.jsz-fbox .jsz-fbox__content p {
  color: #fff;
}

/* Opis — schowany bazowo */
.jsz-fbox .jsz-fbox__desc {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  margin-top: 0;
  transform: translateY(20px);
  transition:
    opacity 0.18s cubic-bezier(0.05, 0.2, 0.1, 1),
    transform 0.18s cubic-bezier(0.05, 0.2, 0.1, 1),
    max-height 0.18s cubic-bezier(0.05, 0.2, 0.1, 1),
    margin-top 0.18s cubic-bezier(0.05, 0.2, 0.1, 1);
}

/* Section link overlay nad wszystkim */
.jsz-fbox .kb-section-link-overlay {
  z-index: 20;
}

/* === Stan aktywny === */
@media (hover: hover) {
  .jsz-fbox:hover {
    transform: translateY(-10px);
    box-shadow: 0 25px 55px rgba(0, 0, 0, 0.22);
  }
  .jsz-fbox:hover > .kt-inside-inner-col > .wp-block-kadence-image {
    transform: scale(1.13);
  }
  .jsz-fbox:hover > .kt-inside-inner-col::before {
    opacity: 0;
  }
  .jsz-fbox:hover > .kt-inside-inner-col::after {
    opacity: 1;
  }
  .jsz-fbox:hover .jsz-fbox__desc {
    opacity: 1;
    max-height: 300px;
    margin-top: 15px;
    transform: translateY(0);
    transition:
      opacity 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
      transform 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
      max-height 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
      margin-top 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s;
  }
}

.jsz-fbox.is-touched {
  transform: translateY(-10px);
  box-shadow: 0 25px 55px rgba(0, 0, 0, 0.22);
}
.jsz-fbox.is-touched > .kt-inside-inner-col > .wp-block-kadence-image {
  transform: scale(1.13);
}
.jsz-fbox.is-touched > .kt-inside-inner-col::before {
  opacity: 0;
}
.jsz-fbox.is-touched > .kt-inside-inner-col::after {
  opacity: 1;
}
.jsz-fbox.is-touched .jsz-fbox__desc {
  opacity: 1;
  max-height: 300px;
  margin-top: 15px;
  transform: translateY(0);
  transition:
    opacity 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
    transform 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
    max-height 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s,
    margin-top 0.65s cubic-bezier(0.05, 0.2, 0.1, 1) 0.15s;
}

/* === FIX: wyższa specyficzność niż .jpsa-reveal.jpsa-visible (scroll-reveal) ===
   jpsa-reveal.jpsa-visible ustawia transform: translateY(0) z tą samą specyficznością
   co .jsz-fbox:hover — kolejność kaskady blokuje nasz -10px unos.
   Prefix `body` daje +1 punkt specyficzności bez potrzeby !important. */
body .jsz-fbox:hover {
  transform: translateY(-10px);
  box-shadow: 0 25px 55px rgba(0, 0, 0, 0.22);
}
body .jsz-fbox.is-touched {
  transform: translateY(-10px);
  box-shadow: 0 25px 55px rgba(0, 0, 0, 0.22);
}

/* ── fx-bg-scroll: paralaksa NATYWNEGO tła Row ──────────────────
   Dla Row z ustawionym w Kadence tłem-obrazem. Przesuwa
   background-position przy scrollu (czysty CSS, sterowane pozycją).
   Na Row: klasa fx-bg-scroll.
   WYMAGA tła ze skalowaniem COVER (Kadence: Background → Image →
   Scale = Cover) — inaczej przy przesuwie wyjdą puste brzegi. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .fx-bg-scroll {
      animation: fx-kf-bg-scroll linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
  }
}
@keyframes fx-kf-bg-scroll {
  from {
    background-position: center 15%;
  }
  to {
    background-position: center 85%;
  }
}

/* ── fx-bg-zoom: luksusowy, wolny zoom tła-obrazka na hover ─────
   Dla kolumn-kafli z tłem ustawionym w Kadence (backgroundImg).
   Klasę fx-bg-zoom dajesz na RODZICA (Row lub kolumnę, która
   zawiera kafle) — efekt dostają wszystkie kolumny z tłem w środku.
   Kolumny bez tła są nietknięte (::before dziedziczy „none").
   Skalujemy kopię tła na ::before, nie kolumnę — zoom nie wychodzi
   poza zaokrąglony kadr i jest gładki (transform). */
.fx-bg-zoom .kt-inside-inner-col {
  position: relative;
  overflow: hidden; /* przycina zoom do zaokrąglenia karty */
}
.fx-bg-zoom .kt-inside-inner-col::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: inherit; /* to samo tło, co .kt-inside-inner-col */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transform: scale(1);
  transition: transform 1.8s cubic-bezier(0.16, 0.84, 0.3, 1); /* wolno, gładko */
  will-change: transform;
  pointer-events: none;
}
.fx-bg-zoom .kt-inside-inner-col:hover::before {
  transform: scale(1.09);
}
/* gdyby w kaflu była treść — trzymamy ją nad tłem */
.fx-bg-zoom .kt-inside-inner-col > * {
  position: relative;
  z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
  .fx-bg-zoom .kt-inside-inner-col::before {
    transition: none;
  }
  .fx-bg-zoom .kt-inside-inner-col:hover::before {
    transform: none;
  }
}
/* Karta = grid: rating / cytat / (avatar + meta) */
.op-ts-google .kt-testimonial-item-wrap {
  height: 100%;
  display: grid;
  grid-template-columns: 40px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    'rating  rating'
    'content content'
    'avatar  meta';
  column-gap: 12px;
  row-gap: 14px;
  padding: 24px;
  background: rgb(102 5 5 / 10%) !important;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 16px;
}

/* text-wrap przezroczysty dla grida */
.op-ts-google .kt-testimonial-text-wrap {
  display: contents;
}

/* Rozmieszczenie w gridzie */
.op-ts-google .kt-testimonial-rating-wrap {
  grid-area: rating;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.op-ts-google .kt-testimonial-content-wrap {
  grid-area: content;
  margin: 0;
  padding: 0;
}
.op-ts-google .kt-testimonial-media-wrap {
  grid-area: avatar;
  margin: 0;
  padding: 0;
  align-self: center;
}
.op-ts-google .kt-testimonial-meta-wrap {
  grid-area: meta;
  margin: 0;
  padding: 0;
  align-self: center;
}

/* Ikona Google obok gwiazdek */
.op-ts-google .kt-testimonial-rating-wrap::before {
  content: '';
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path fill='%234285F4' d='M24 9.5c3.5 0 6.6 1.2 9 3.5l6.7-6.7C35.6 2.6 30.2 0 24 0 14.6 0 6.4 5.4 2.5 13.3l7.8 6C12.2 13.6 17.6 9.5 24 9.5z'/><path fill='%2334A853' d='M46.5 24.5c0-1.6-.1-3.2-.4-4.7H24v9h12.7c-.5 3-2.2 5.5-4.7 7.2l7.5 5.8c4.4-4 7-10 7-17.3z'/><path fill='%23FBBC05' d='M10.3 28.7c-.5-1.5-.8-3-.8-4.7s.3-3.2.8-4.7l-7.8-6C.9 16.9 0 20.3 0 24s.9 7.1 2.5 10.7l7.8-6z'/><path fill='%23EA4335' d='M24 48c6.2 0 11.4-2 15.2-5.5l-7.5-5.8c-2 1.4-4.7 2.3-7.7 2.3-6.4 0-11.8-4.1-13.7-9.8l-7.8 6C6.4 42.6 14.6 48 24 48z'/></svg>")
    center/13px no-repeat;
}

/* Avatar */
.op-ts-google .kt-testimonial-media-inner-wrap,
.op-ts-google .kadence-testimonial-image-intrisic {
  margin: 0;
  padding: 0;
  line-height: 0;
  width: 40px;
  height: 40px;
}
.op-ts-google .kt-testimonial-media-wrap img {
  width: 40px !important;
  height: 40px !important;
  border-radius: 50% !important;
  object-fit: cover !important;
  display: block;
}

/* Cytat */
.op-ts-google .kt-testimonial-content {
  margin: 0;
  padding: 0;
  border: 0;
  font-style: normal;
  color: #ffffff;
  font-size: 15px;
  line-height: 1.5;
}

/* Meta */
.op-ts-google .kt-testimonial-meta-name-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.op-ts-google .kt-testimonial-name {
  color: #ffffff;
  font-weight: 600;
  font-size: 14px;
}
.op-ts-google .kt-testimonial-occupation,
.op-ts-google .kt-testimonial-occupation a {
  color: #9aa4b2;
  font-size: 12px;
  text-decoration: none;
}

/* Równa wysokość kart w karuzeli Splide */
.op-ts-google .splide__list {
  align-items: stretch;
}
.op-ts-google .kt-blocks-testimonial-carousel-item {
  height: auto !important;
  display: flex;
}
.op-ts-google .kt-blocks-testimonial-carousel-item > * {
  width: 100%;
}

.op-ts-google .kt-testimonial-rating-wrap::after {
  content: '5.0';
  color: #ffffff;
  font:
    600 13px/1 'Plus Jakarta Sans',
    sans-serif;
  margin-left: 2px;
}
/* Kontener wideo — wymuszamy proporcję 16:9 */
.realizacje .kb-blocks-bg-video-container {
  position: relative; /* nadpisujemy domyślne absolute z Kadence */
  width: 100%;
  aspect-ratio: 16 / 9; /* 1920x1080 = 16:9 */
  overflow: hidden;
}

/* Samo wideo wypełnia kontener w tej samej proporcji */
.realizacje .kb-blocks-bg-video {
  position: absolute;
  inset: 0; /* top/right/bottom/left: 0 */
  width: 100%;
  height: 100%;
  object-fit: cover; /* wypełnia całość, bez czarnych pasków */
  transform: none !important;
}

@media (max-width: 768px) {
  .realizacje .kb-blocks-bg-video-container {
    aspect-ratio: 16 / 9; /* przykład — wyższy kadr na telefonie */
  }

  h2 {
    padding-bottom: 10px !important;
  }
}

/* ── fx-border: animowana ramka „przepływające światło" ─────────
   Na kartę/kolumnę (z zaokrągleniem): klasa fx-border. Świetlny łuk
   gradientu okrąża krawędź, idąc po rogach (gradient + maska).
   Efekt siedzi na .kt-inside-inner-col (tam Kadence trzyma tło,
   radius i padding karty). Najlepiej wygląda, gdy statyczną ramkę
   karty w Kadence zostawisz cienką jako podkład albo zdejmiesz. */
@property --fx-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}
.fx-border > .kt-inside-inner-col {
  position: relative;
  isolation: isolate;
}
.fx-border > .kt-inside-inner-col::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit; /* zaokrąglenie karty */
  padding: 4px; /* grubość świecącej ramki */
  /* ciągła zielona obwódka (baza) + płynnie przepływający jaśniejszy
     łuk. Bez białego punktu i bez przerw (0deg = 360deg). */
  background: conic-gradient(
    from var(--fx-angle),
    rgba(72, 240, 147, 0.14) 0deg,
    rgba(72, 240, 147, 0.14) 120deg,
    rgba(72, 240, 147, 0.95) 200deg,
    rgba(72, 240, 147, 0.14) 280deg,
    rgba(72, 240, 147, 0.14) 360deg
  );
  /* maska: pokaż tylko obwódkę (pierścień paddingu), środek wytnij */
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: fx-border-spin 5s linear infinite;
  pointer-events: none;
}
@keyframes fx-border-spin {
  to {
    --fx-angle: 360deg;
  }
}
/* treść nad ramką */
.fx-border > .kt-inside-inner-col > * {
  position: relative;
  z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
  .fx-border > .kt-inside-inner-col::before {
    animation: none;
  }
}

/* === Strzaka midzy sekcjami (.add_arrow) === */
.add_arrow {
  position: relative;
}
.add_arrow::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 24px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 5;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 24'%3E%3Cg fill='none' stroke='%231f5c3d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='2' y1='12' x2='46' y2='12'/%3E%3Cpolyline points='38,5 46,12 38,19'/%3E%3C/g%3E%3C/svg%3E");
  animation: add_arrow_x 1.8s ease-in-out infinite;
}
@keyframes add_arrow_x {
  0%,
  100% {
    transform: translate(-50%, -50%);
  }
  50% {
    transform: translate(calc(-50% + 6px), -50%);
  }
}
@media (max-width: 767px) {
  .add_arrow::after {
    transform: translate(-50%, -50%) rotate(90deg);
    animation: add_arrow_y 1.8s ease-in-out infinite;
  }
  @keyframes add_arrow_y {
    0%,
    100% {
      transform: translate(-50%, -50%) rotate(90deg);
    }
    50% {
      transform: translate(-50%, calc(-50% + 6px)) rotate(90deg);
    }
  }
}

/* Paralaksa tła (fx-has-bg + fx-bg): na telefonie BEZ zapasu i BEZ
   ruchu. Duży inset (-52/-84px) przy niskim kadrze robił puste
   przestrzenie; na mobile zdjęcie ma po prostu wypełniać kadr. */
@media (max-width: 767px) {
  .fx-has-bg .fx-bg,
  .fx-has-bg .fx-bg.fx-parallax,
  .fx-has-bg .fx-bg.fx-parallax-fast {
    inset: 0;
    animation: none;
  }
}
