/* =============================================================================
   signature-moves.css — Awwwards Vault: sygnaturowe ruchy „wow", drop-in.
   Każdy ruch = klasa fx-*. Seed (uniqueness-seed.json → signature_moves) mówi,
   które wpiąć. Wszystkie: lekkie, animują tylko transform/opacity/clip (CWV-safe),
   i WYŁĄCZANE przez prefers-reduced-motion. JS dla części w assets/signature-moves.js.
   Podłącz po styles.css:  <link rel="stylesheet" href="signature-moves.css">
   ============================================================================= */

/* --- fx-grain: ziarno/noise overlay (STATYCZNE = zero kosztu animacji) -------- */
.fx-grain { position: relative; isolation: isolate; }
.fx-grain::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .06;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.fx-grain--strong::after { opacity: .12; }

/* --- fx-marquee: przewijający się pasek (tekst/logo) -------------------------- */
.fx-marquee { overflow: hidden; white-space: nowrap; -webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.fx-marquee__track { display: inline-flex; gap: var(--space-6, 32px); will-change: transform; animation: fx-marquee 22s linear infinite; }
.fx-marquee:hover .fx-marquee__track { animation-play-state: paused; }
@keyframes fx-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* --- fx-mask: nagłówek odsłaniany maską przy wejściu (reuse .is-in z reveal) -- */
.reveal-ready .fx-mask { clip-path: inset(0 100% 0 0); transition: clip-path .9s var(--motion-ease, cubic-bezier(.16,1,.3,1)); }
.reveal-ready .fx-mask.is-in { clip-path: inset(0 0 0 0); }

/* --- fx-split: dwie połowy wjeżdżające z przeciwnych stron (reuse .is-in) ----- */
.reveal-ready .fx-split > :nth-child(odd)  { transform: translateX(-40px); opacity: 0; transition: transform .8s var(--motion-ease), opacity .8s var(--motion-ease); }
.reveal-ready .fx-split > :nth-child(even) { transform: translateX(40px);  opacity: 0; transition: transform .8s var(--motion-ease), opacity .8s var(--motion-ease); }
.reveal-ready .fx-split.is-in > * { transform: none; opacity: 1; }

/* --- fx-tilt: karta z lekkim przechyłem 3D na hover (JS ustawia --rx/--ry) ---- */
.fx-tilt { transform: perspective(800px) rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg)); transition: transform .15s ease-out; transform-style: preserve-3d; }

/* --- fx-kinetic: duża typografia z lekkim skew sterowanym scrollem (JS --sk) -- */
.fx-kinetic { display: inline-block; transform: skewY(var(--sk, 0deg)); transition: transform .2s ease-out; will-change: transform; }

/* --- fx-sticky: pozioma galeria przypięta na scrollu (JS przesuwa --x) -------- */
.fx-sticky { position: relative; }
.fx-sticky__viewport { position: sticky; top: 0; height: 100vh; display: flex; align-items: center; overflow: hidden; }
.fx-sticky__row { display: flex; gap: var(--space-6, 32px); padding-inline: var(--space-5, 24px); transform: translateX(var(--x, 0px)); will-change: transform; }
.fx-sticky__row > * { flex: 0 0 auto; }

/* --- fx-cursor: warstwa pod poświatę kursora (JS przesuwa --mx/--my) ---------- */
.fx-cursor { position: relative; isolation: isolate; }
.fx-cursor::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .5;
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--color-accent) 30%, transparent), transparent 70%);
  transition: opacity .3s ease;
}

/* --- fx-count: liczniki (JS wpisuje wartość) --------------------------------- */
.fx-count { font-variant-numeric: tabular-nums; }

/* Cursor/tilt/magnetic to efekty WSKAŹNIKOWE — tylko myszka (nie dotyk) -------- */
@media (hover: none), (pointer: coarse) {
  .fx-tilt { transform: none; }
  .fx-cursor::before { display: none; }
}

/* Szacunek dla preferencji ruchu — wyłącz wszystkie sygnaturowe ruchy ---------- */
@media (prefers-reduced-motion: reduce) {
  .fx-marquee__track { animation: none; }
  .fx-mask, .reveal-ready .fx-mask { clip-path: none !important; }
  .reveal-ready .fx-split > * { transform: none !important; opacity: 1 !important; }
  .fx-tilt, .fx-kinetic { transform: none !important; }
  .fx-cursor::before { display: none; }
}

/* =============================================================================
   ROZSZERZENIE VAULT (sesja Młody Barber) — efekty „bohatera" + wzorzec izolacji.
   ZASADA OSADZANIA: ciężki efekt (WebGL/canvas) ZAWSZE w JEDNEJ sekcji (scoped),
   z pauzą poza ekranem (JS IntersectionObserver), fallbackiem i reduced-motion.
   ============================================================================= */

/* --- fx-paint: żywa farba WebGL jako TŁO sekcji (scoped, izolowane) ----------- */
.fx-paint { position: relative; isolation: isolate; }
.fx-paint__canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1;
  display: block; pointer-events: none; }
/* fallback gdy JS/WebGL off — pod canvasem zostaje tło/gradient sekcji */

/* --- fx-spray-reveal: nagłówek „natryskany" sprayem przy wejściu -------------- */
.fx-spray-reveal { position: relative; display: inline-block; }
.fx-spray-reveal .ink { display: inline-block; opacity: 0; filter: blur(9px);
  transform: translateY(7px) scale(.98);
  transition: opacity .55s var(--motion-ease, cubic-bezier(.16,1,.3,1)),
              filter .55s var(--motion-ease), transform .55s var(--motion-ease); }
.fx-spray-reveal.is-sprayed .ink { opacity: 1; filter: none; transform: none; }
.fx-spray-reveal.is-sprayed .ink:nth-child(n+3) { transition-delay: .16s; }
.fx-spray-reveal::before { content: ""; position: absolute; inset: -30% -12%; z-index: -1;
  border-radius: 50%; pointer-events: none; opacity: 0; transform: scale(.55);
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--color-accent) 30%, transparent), transparent 70%); }
.fx-spray-reveal.is-sprayed::before { animation: fx-spray-puff .8s ease forwards; }
@keyframes fx-spray-puff { 0%{opacity:0;transform:scale(.55)} 40%{opacity:.85} 100%{opacity:0;transform:scale(1.2)} }

/* --- fx-splatter: rozprysk farby za elementem na hover (themeable) ------------ */
.fx-splatter { position: relative; overflow: visible; }
.fx-splatter::after { content: ""; position: absolute; inset: -45% -28%; z-index: -1;
  pointer-events: none; opacity: 0; transform: scale(.5) rotate(-10deg);
  transition: opacity .3s var(--motion-ease), transform .3s var(--motion-ease);
  --sc: color-mix(in srgb, var(--color-accent) 85%, transparent);
  background:
    radial-gradient(circle at 20% 55%, var(--sc) 0 9%, transparent 10%),
    radial-gradient(circle at 44% 30%, var(--sc) 0 6%, transparent 7%),
    radial-gradient(circle at 66% 60%, var(--sc) 0 7%, transparent 8%),
    radial-gradient(circle at 82% 35%, var(--sc) 0 4%, transparent 5%),
    radial-gradient(circle at 54% 78%, var(--sc) 0 5%, transparent 6%); }
.fx-splatter:hover::after { opacity: .55; transform: scale(1) rotate(-2deg); }

/* --- fx-stencil: nagłówek wycierany szablonem na scroll (alias do .is-in) ----- */
.reveal-ready .fx-stencil { clip-path: inset(0 100% 0 0); transition: clip-path .6s var(--motion-ease); }
.reveal-ready .fx-stencil.is-in { clip-path: inset(0 0 0 0); }

@media (hover: none), (pointer: coarse) { .fx-splatter::after { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .fx-paint__canvas { display: none; }
  .fx-spray-reveal .ink { opacity: 1 !important; filter: none !important; transform: none !important; }
  .fx-spray-reveal::before { display: none; }
  .fx-splatter::after { display: none; }
  .reveal-ready .fx-stencil { clip-path: none !important; }
}

/* =============================================================================
   ROZSZERZENIE VAULT (korpus stolarz/meble 2026-07) — 11 ruchów wydestylowanych
   z korpusu 13 stron niszy meble na wymiar (references/branza-korpus.md → meble).
   Filozofia niszy: żywe POWOLNE hero (zoom długi liniowy + fade krótki), rytm
   sekcji drewno/paper, mikro-niespodzianki. Zasady jak wyżej: animujemy tylko
   transform/opacity/clip-path (CWV-safe), guard prefers-reduced-motion na końcu
   bloku, zero bibliotek. JS (kenburns/kategorie/manifest/rotator/flip-tap/
   przed-po/faq/podpis) w signature-moves.js — blok „korpus stolarz".
   ============================================================================= */

/* --- fx-kenburns: hero-slideshow z powolnym zbliżeniem (źr. lidersmeble) ------
   KLUCZ: zoom DŁUGI liniowy (12s, scale 1→1.14) + fade KRÓTKI (.8s) — inaczej
   robi się nerwowo. Markup: <section class="hero fx-kenburns">
   <div class="fx-kenburns__slide" style="background-image:url(…)"></div>…
   Bez JS / przy reduced-motion: statyczny pierwszy slajd (fallback niżej). */
.fx-kenburns { position: relative; overflow: hidden; isolation: isolate; }
.fx-kenburns__slide {
  position: absolute; inset: 0; z-index: -1; background-size: cover; background-position: center;
  opacity: 0; transform: scale(1); will-change: transform, opacity;
  transition: opacity .8s ease, transform 12s linear;
}
.fx-kenburns__slide.is-active { opacity: 1; transform: scale(1.14); }
.fx-kenburns:not(.fx-kenburns--js) .fx-kenburns__slide:first-of-type { opacity: 1; }

/* --- fx-hero-kategorie: slajd hero = LINIA OFERTY (źr. imian-kuchnie) ---------
   Synchroniczna podmiana: zdjęcie + wielki nagłówek + tagline + licznik „1/3";
   strzałki .fx-hk__prev/.fx-hk__next; autoplay 10s (JS). Slajdy tekstowe w
   .fx-hk__slides (stos grid → zero CLS), obrazy w .fx-hk__media. */
.fx-hero-kategorie { position: relative; }
.fx-hero-kategorie .fx-hk__media { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.fx-hk__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .5s ease; }
.fx-hk__img.is-active { opacity: 1; }
.fx-hk__slides { display: grid; }
.fx-hk__slide { grid-area: 1 / 1; opacity: 0; transform: translateY(14px); pointer-events: none;
  transition: opacity .5s var(--motion-ease, ease), transform .5s var(--motion-ease, ease); }
.fx-hk__slide.is-active { opacity: 1; transform: none; pointer-events: auto; }
.fx-hk__title { font-size: clamp(2.75rem, 7vw, 5rem); line-height: 1.05; text-transform: uppercase; margin: 0; }
.fx-hk__licznik { font-variant-numeric: tabular-nums; letter-spacing: .12em; }
.fx-hero-kategorie:not(.fx-hk--js) .fx-hk__img:first-of-type,
.fx-hero-kategorie:not(.fx-hk--js) .fx-hk__slide:first-of-type { opacity: 1; transform: none; pointer-events: auto; }

/* --- fx-hero-manifest: crossfade haseł-manifestów Z KROPKĄ (źr. milman) -------
   Każdy slajd = inne hasło (uppercase, KROPKA na końcu = „pewność siebie" marki)
   + zdjęcie; opacity 1s, autoplay 10s (JS). */
.fx-hero-manifest { position: relative; display: grid; overflow: hidden; }
.fx-manifest__slide { grid-area: 1 / 1; opacity: 0; pointer-events: none; transition: opacity 1s ease; }
.fx-manifest__slide.is-active { opacity: 1; pointer-events: auto; }
.fx-manifest__haslo { font-size: clamp(3rem, 9vw, 6.5rem); line-height: .98; text-transform: uppercase; margin: 0; }
.fx-hero-manifest:not(.fx-manifest--js) .fx-manifest__slide:first-of-type { opacity: 1; pointer-events: auto; }

/* --- fx-flip: kafel oferty 3D zdjęcie→opis (źr. fabryczkamebli) ---------------
   Front sprzedaje obrazem, tył domyka tekstem — na tyle OBOWIĄZKOWO CTA-link,
   tyły wszystkich kart w JEDNYM kolorze. Desktop: hover/focus; dotyk: tap
   (JS toggluje .is-flipped). Markup: .fx-flip > .fx-flip__inner > (front|back). */
.fx-flip { perspective: 1000px; }
.fx-flip__inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(.4, .2, .2, 1); }
.fx-flip:hover .fx-flip__inner { transform: rotateY(180deg); }
.fx-flip:focus-within .fx-flip__inner { transform: rotateY(180deg); }
.fx-flip.is-flipped .fx-flip__inner { transform: rotateY(180deg); }
.fx-flip__front, .fx-flip__back { -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.fx-flip__back { position: absolute; inset: 0; transform: rotateY(180deg); }

/* --- fx-przed-po: suwak porównania w kaflu realizacji (źr. drzwidrawex) -------
   Dwie warstwy img (spód = przed, wierzch .fx-przed-po__po = po), wierzch
   przycinany clip-path wg --cut (JS: pointerdown/pointermove). Uchwyt w kolorze
   akcentu + pigułki „Przed"/„Po". Interakcja BEZPOŚREDNIA (nie dekoracja) —
   działa także przy reduced-motion. touch-action: pan-y nie blokuje scrolla. */
.fx-przed-po { position: relative; overflow: hidden; touch-action: pan-y; user-select: none; --cut: 50%; }
.fx-przed-po img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.fx-przed-po__po { position: absolute; inset: 0; clip-path: inset(0 calc(100% - var(--cut)) 0 0); }
.fx-przed-po__uchwyt { position: absolute; top: 0; bottom: 0; left: var(--cut); width: 2px; margin-left: -1px;
  background: var(--color-accent, #B0793C); pointer-events: none; }
.fx-przed-po__uchwyt::after { content: "↔"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
  background: var(--color-accent, #B0793C); color: #fff; font-size: 16px; }
.fx-przed-po__label { position: absolute; top: 12px; padding: 4px 12px; border-radius: 999px; z-index: 1;
  background: rgba(15, 14, 12, .6); color: #fff; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }
.fx-przed-po__label--przed { left: 12px; }
.fx-przed-po__label--po { right: 12px; }

/* --- fx-kolaz: galeria-kolaż edge-to-edge (źr. projekt5r) ---------------------
   Grid dense, fuga 10–15px, RYTM robi robotę: 1 kafel-bohater (--hero) na 8–10
   zdjęć + przeplot pion/poziom wg orientacji zdjęcia. aspect-ratio przeciw CLS.
   Pełny kolaż na podstronie /realizacje (20–30 zdjęć); na home zajawka 6–8 kafli.
   Lightbox = ~20 linii JS strony (nie Vault). Czysty CSS, zero JS. */
.fx-kolaz { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); grid-auto-flow: dense; }
.fx-kolaz__item { position: relative; overflow: hidden; aspect-ratio: 4 / 3; margin: 0; /* reset dla <figure> */ }
.fx-kolaz__item > img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s var(--motion-ease, ease); }
.fx-kolaz__item:hover > img { transform: scale(1.04); }
.fx-kolaz__item--pion { grid-row: span 2; aspect-ratio: auto; }
.fx-kolaz__item--poziom { grid-column: span 2; aspect-ratio: auto; }
.fx-kolaz__item--hero { grid-column: span 2; grid-row: span 2; aspect-ratio: auto; }
@media (max-width: 599px) { .fx-kolaz__item--poziom, .fx-kolaz__item--hero { grid-column: auto; } }

/* --- fx-drewno + fx-paper: rytm sekcji ciemna-tekstura / jasny „paper" --------
   (źr. asgardmd + milman). fx-drewno: zdjęcie przekroju/słojów drewna + overlay
   rgba(20,16,12,.8) + jasna typografia — koszt = 1 zoptymalizowany WebP, zero JS
   (strona ustawia --fx-drewno-img: url(…)). fx-paper: jasny „oddech" #f3f1ec
   między ciemnymi sekcjami (#1f1f1f). Czysty CSS, zero ruchu. */
.fx-drewno {
  background-color: var(--fx-drewno-bg, #1f1f1f);
  background-image: linear-gradient(rgba(20, 16, 12, .8), rgba(20, 16, 12, .8)), var(--fx-drewno-img, none);
  background-size: cover; background-position: center;
  color: var(--fx-drewno-ink, #f6f4f0);
}
.fx-paper { background-color: var(--fx-paper-bg, #f3f1ec); color: var(--fx-paper-ink, #1d1b19); }

/* --- fx-rotator-slow: rotator słów w H1 (źr. drzwidrawex) ---------------------
   <span class="fx-rotator-slow" data-words="kuchnie|szafy|garderoby">kuchnie</span>
   Fade+translateY 400ms co ~2.5s; JS rezerwuje szerokość najdłuższym słowem
   (inline-block + min-width w ch) → zero CLS. Reduced-motion: statyczne 1. słowo. */
.fx-rotator-slow { display: inline-block; transition: opacity .4s ease, transform .4s ease; }
.fx-rotator-slow.is-out { opacity: 0; transform: translateY(8px); }

/* --- fx-index-uslug: typograficzny index usług (źr. imian-kuchnie) ------------
   Wielkie uppercase wiersze-linki oddzielone linią + strzałka → po prawej —
   elegancka alternatywa dla oklepanych kart z ikonami. Czysty CSS.
   Markup: <nav class="fx-index-uslug"><a href="…">Meble kuchenne
   <span class="fx-index-uslug__strzalka" aria-hidden="true">→</span></a>…</nav> */
.fx-index-uslug a {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 22px 8px; text-decoration: none; color: inherit; text-transform: uppercase;
  font-size: clamp(1.4rem, 4vw, 2.4rem); line-height: 1.1;
  border-bottom: 1px solid color-mix(in srgb, currentColor 25%, transparent);
  transition: background-color .25s ease;
}
.fx-index-uslug a:first-child { border-top: 1px solid color-mix(in srgb, currentColor 25%, transparent); }
.fx-index-uslug__strzalka { flex: 0 0 auto; transition: transform .25s var(--motion-ease, ease); }
.fx-index-uslug a:hover { background-color: color-mix(in srgb, currentColor 6%, transparent); }
.fx-index-uslug a:hover .fx-index-uslug__strzalka { transform: translateX(8px); }

/* --- fx-podpis: odręczny podpis właściciela kreślony na scroll (źr. silvan) ---
   SVG path (fill:none, stroke) rysowany stroke-dashoffset przy wejściu w viewport
   (reuse .is-in z bazowego reveala, jak fx-mask; JS domierza getTotalLength()).
   Bez JS/reveala oraz przy reduced-motion podpis po prostu jest widoczny. */
.reveal-ready .fx-podpis path {
  stroke-dasharray: var(--fx-podpis-len, 1200); stroke-dashoffset: var(--fx-podpis-len, 1200);
  transition: stroke-dashoffset 1.6s ease .2s;
}
.reveal-ready .fx-podpis.is-in path { stroke-dashoffset: 0; }

/* --- fx-akordeon-faq: FAQ jako details/summary z animowanym otwarciem ---------
   (naprawa antywzorca piaw: FAQ-ściana rozwinięta na stałe). Pytania widoczne,
   odpowiedź na klik; wysokość animowana grid-template-rows 0fr→1fr (bez layout-
   thrashingu), ikona +/× , radius umiarkowany 12–16px (nie organiczne pigułki).
   Markup: <div class="fx-akordeon-faq"><details><summary>Pytanie?</summary>
   <div class="fx-faq__tresc"><div><p>Odpowiedź…</p></div></div></details>…</div>
   Bez JS działa natywnie (bez animacji); JS dodaje klasę .fx-faq--js. */
.fx-akordeon-faq details { border: 1px solid color-mix(in srgb, currentColor 18%, transparent); border-radius: 14px; margin-bottom: 12px; }
.fx-akordeon-faq summary { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 20px; font-weight: 600; }
.fx-akordeon-faq summary::-webkit-details-marker { display: none; }
.fx-akordeon-faq summary::after { content: "+"; font-size: 1.4em; line-height: 1; flex: 0 0 auto;
  color: var(--color-accent, currentColor); transition: transform .3s var(--motion-ease, ease); }
.fx-akordeon-faq details[open] summary::after { transform: rotate(45deg); }
.fx-akordeon-faq .fx-faq__tresc { padding: 0 20px; }
.fx-akordeon-faq .fx-faq__tresc > * { min-height: 0; overflow: hidden; }
.fx-akordeon-faq .fx-faq__tresc p:last-child { padding-bottom: 16px; margin-bottom: 0; }
.fx-akordeon-faq.fx-faq--js .fx-faq__tresc { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s var(--motion-ease, ease); }
.fx-akordeon-faq.fx-faq--js details.is-open .fx-faq__tresc { grid-template-rows: 1fr; }

/* Dotyk: flip nie reaguje na "hover" (ghost-hover) — flip wyłącznie tapnięciem - */
@media (hover: none), (pointer: coarse) {
  .fx-flip:hover .fx-flip__inner { transform: none; }
  .fx-flip.is-flipped .fx-flip__inner { transform: rotateY(180deg); }
}

/* Szacunek dla preferencji ruchu (blok „korpus stolarz"): statyka / stany
   natychmiastowe. Slidery pauzują (JS nie startuje timerów), interakcje
   bezpośrednie (flip/przed-po/akordeon/strzałki) zostają — bez animacji. ------ */
@media (prefers-reduced-motion: reduce) {
  .fx-kenburns__slide { transition: none; transform: none !important; }
  .fx-hk__img, .fx-hk__slide, .fx-manifest__slide { transition: none; transform: none !important; }
  .fx-flip__inner { transition: none; }
  .fx-kolaz__item > img { transition: none; }
  .fx-kolaz__item:hover > img { transform: none; }
  .fx-rotator-slow { transition: none; }
  .fx-rotator-slow.is-out { opacity: 1; transform: none; }
  .fx-index-uslug a, .fx-index-uslug__strzalka { transition: none; }
  .fx-index-uslug a:hover .fx-index-uslug__strzalka { transform: none; }
  .reveal-ready .fx-podpis path { stroke-dasharray: none; stroke-dashoffset: 0 !important; transition: none; }
  .fx-akordeon-faq summary::after { transition: none; }
  .fx-akordeon-faq.fx-faq--js .fx-faq__tresc { transition: none; }
}
