/* =============================================
   MONTAGE — Used on: hero
   Working name; section is about "nasz montaż" — why our installation
   is better than the competition. Marquee of alternating text/image cards.
   ============================================= */

.montage {
  /* Tokeny kaskady wejscia — ruch hero (0.7s ease-out, 30px), jak why-us v63,
     services v37 i partners v31. Siedza na `.montage`, a NIE na
     `.montage.section-fade`, bo `.montage__viewport` wciaga je do swojej listy
     `transition` (patrz tam) — niezdefiniowana zmienna uniewaznilaby CALA te
     deklaracje. */
  --montage-reveal-dur: 0.7s;
  --montage-reveal-ease: ease-out;
  --montage-reveal-step: 0.25s;
  --montage-reveal-shift: 30px;

  padding: 100px 24px;
  background: var(--white);
  overflow: hidden;
  position: relative;
  /* Isolate the section into its own compositor layer + containment so
     paint/layout work in the marquee doesn't compete with page scroll. */
  contain: layout paint;
  transform: translateZ(0);
}

.montage__container {
  max-width: var(--max-width-wide);
  margin: 0 auto;
}

/* ---- Header (mirror .testimonials__container 2-col) ---- */
.montage__header {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto;
  column-gap: 40px;
  row-gap: 16px;
  /* `start`, NIE `end` — podtytul jest nizszy od dwuliniowego naglowka, wiec
     wyrownanie do dolu wiersza spychalo jego GORNA krawedz ~40px w dol.
     Patrz montage.css v59. */
  align-items: start;
  margin-bottom: 64px;
}

.montage__label {
  grid-column: 1;
  grid-row: 1;
  display: inline-block;
  width: max-content;
  padding: 0;
  background: transparent;
  color: var(--dark-gray);
  font-size: 15px;
  font-weight: 500;
  text-transform: capitalize;
  letter-spacing: 0;
}

.montage__label::before {
  content: "// ";
}

.montage__heading {
  grid-column: 1;
  grid-row: 2;
  margin: 0;
  font-size: var(--heading-size);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--dark-gray);
  max-width: 720px;
}

.montage__heading span {
  color: var(--dark-gray);
  display: block;
}

.montage__subheading {
  grid-column: 2;
  grid-row: 2;
  margin: 0;
  max-width: 424px;
  justify-self: end;
  align-self: start;
  /* 18px/1.7 — wspolny rozmiar subheadingu sekcji na desktopie (hero, services,
     showroom, realizacje, testimonials, why-us, process). Ta sekcja byla jedyna
     na 16px/1.6 i odstawala od sasiadow. Tablet i telefon zostaja na 16px/1.6
     (override w bloku ≤1024 nizej) — tam reszta sekcji tez schodzi do 15-17px. */
  font-size: 18px;
  line-height: 1.7;
  color: var(--gray-500);
}

/* ---- Marquee viewport + track ---- */
.montage__viewport {
  --montage-card-w: 410.4px;
  /* +48px na zyczenie klienta (2026-08-09; bylo 451.44px). UWAGA: karta NIE ma
     juz proporcji zdjec z `Grafiki Montaż/` (900×990 = 0.9091) — teraz 0.8217,
     wiec `object-fit: cover` przycina zdjecia po ~4.8% szerokosci z KAZDEJ
     strony. Zmieniajac te wartosc, sprawdz kadry kart obrazkowych. */
  --montage-card-h: 499.44px;
  --montage-gap: 26.4px;

  position: relative;
  /* clip-path replaces overflow:hidden so card shadows can bleed top/bottom
     (16px each side) while horizontal edges still clip the marquee track.
     contain: layout (without paint) preserves layout isolation without
     re-establishing a paint clip that would defeat the clip-path bleed. */
  clip-path: inset(-16px 0);
  /* Bleed edges out to viewport so cards extend past container on both sides.
     Left bleed extends 140px past the natural container edge (60px original
     bleed + 80px additional shift), right edge reaches the window edge. */
  margin-left: calc(50% - 50vw - 140px);
  margin-right: calc(50% - 50vw);
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  /* Let browser handle vertical scroll natively — prevents pointer events
     firing during page scroll inside the marquee */
  touch-action: pan-y;
  contain: layout;
}

.montage__viewport.is-dragging {
  cursor: grabbing;
}

/* ==== RUCH: CALOSC W JS (v58) ====
   Ten arkusz NIE animuje juz zadnego elementu ruchu marquee. Pozycje tasmy,
   krok autoplaya, snap po dragu i efekt przytrzymania (kurczenie kart do
   0.92 + kompensacja odstepow) prowadzi JEDNA petla rAF w inline JS
   hero.html — dokladnie architektura marquee z /o-nas: transformy pisane
   wprost na elementach, po klatkach. Wczesniejsze wersje (v54–v57) mieszaly
   przejscia CSS (`translate` tasmy, animowany `--hold`, animowane
   `margin-left`) z JS-em i kazda granica miedzy tymi swiatami (start/stop
   przejscia, podmiana klas, inwalidacje stylow) potrafila dac widoczne
   zaciecie przy zlapaniu albo puszczeniu pasa. NIE dodawaj tu z powrotem
   `transition` na `translate`/`transform` tasmy ani kart — kazdy taki
   transition bedzie walczyl z per-klatkowymi zapisami z JS (efekt gumki). */

.montage__viewport {
  /* Reveal (opacity/translate) to jedyne przejscia, jakie zostaly — ruch
     marquee ich nie dotyka (JS pisze translate TASMY, nie viewportu). */
  transition: opacity var(--montage-reveal-dur) var(--montage-reveal-ease),
              translate var(--montage-reveal-dur) var(--montage-reveal-ease);
}

.montage__track {
  display: flex;
  column-gap: 0;
  /* Pozycja tasmy: inline `translate` pisane z JS (render()). Wartosc
     poczatkowa 0 — do czasu init() tasma stoi na karcie 0. */
  translate: 0 0;
  /* STALA warstwa kompozytora dla tasmy (jak elementy marquee na /o-nas,
     promowane translate3d od pierwszej klatki) — zadnego will-change
     doklejanego klasami: promocja/demontaz warstwy wypadalyby dokladnie
     w momencie zlapania i puszczenia pasa. */
  transform: translateZ(0);
}

/* ---- Cards (shared) ---- */
.montage__card {
  flex: 0 0 var(--montage-card-w);
  height: var(--montage-card-h);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
  -webkit-user-drag: none;
  contain: layout paint;
  /* Wszystkie karty stoją na JEDNEJ linii — bez naprzemiennego przesunięcia
     w pionie (patrz montage.css v51).

     Efekt przytrzymania (kurczenie do 0.92 + dosuniecie utrzymujace staly
     widoczny odstep) pisze JS wprost jako inline
     `translate3d(...) scale(...)` w kazdej klatce (render() w hero.html).
     Tutaj zostaje tylko bazowy `translateZ(0)` — STALA warstwa kompozytora
     per karta od pierwszej klatki (jak elementy marquee na /o-nas), zeby
     per-klatkowe zmiany transformu byly przesunieciem warstwy, a nie
     przemalowaniem duzych bitmap ze zdjeciami. */
  transform: translateZ(0);
}

/* Staly layoutowy odstep kart — NIE jest animowany (margines = layout
   calego flexboxa co klatke; kompensacja kurczenia przy przytrzymaniu
   siedzi w transformach pisanych z JS). */
.montage__card + .montage__card {
  margin-left: var(--montage-gap);
}

/* ---- Text card ---- */
.montage__card--text {
  background: #ffffff;
  padding: 36px 32px;
  display: flex;
  flex-direction: column;
}

.montage__card-icon {
  width: 48px;
  height: 48px;
  border-radius: 5px;
  background: var(--dark-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: auto;
  color: var(--white);
}

.montage__card-icon svg {
  width: 24px;
  height: 24px;
}

.montage__card-title {
  font-size: 24px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--dark-gray);
  margin: 0 0 12px;
}

.montage__card-desc {
  font-size: 15px;
  line-height: 1.55;
  color: var(--gray-500);
  margin: 0;
}

/* ---- Image card ---- */
.montage__card--image {
  background: var(--border-color);
  padding: 0;
}

.montage__card--image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* ---- Marquee navigation (copied from o-nas.css) ---- */
.montage__nav-wrapper {
  display: flex;
  justify-content: flex-start;
  margin-top: 48px;
}

.montage .marquee-nav {
  position: relative;
  inset: auto;
  opacity: 1;
  animation: none;
  display: flex;
  align-items: center;
  gap: 8px;
}

.montage .marquee-nav__btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: #151515;
  color: var(--white);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.2s;
}

.montage .marquee-nav__btn:hover {
  background: #2a2a2a;
}

.montage .marquee-nav__btn:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}

.montage .marquee-nav__toggle {
  width: 44px;
  height: 44px;
  background: transparent;
  color: var(--dark-gray);
  position: relative;
}

.montage .marquee-nav__toggle:hover {
  background: rgba(0, 0, 0, 0.04);
}

.montage .marquee-nav__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  pointer-events: none;
}

.montage .marquee-nav__icon {
  position: relative;
  z-index: 1;
}

/* =============================================
   SCROLL REVEAL — kaskada wejscia sekcji
   Kolejnosc: label → heading + subheading (razem) → pas kart → sterowanie.

   Label, heading i subheading leza przy GORZE sekcji, wiec ida na kaskadzie
   CZASOWEJ. Pas kart i sterowanie dostaja `.is-revealed` z modulu "Montage
   Reveal" w main.js, bo w chwili startu kaskady sa jeszcze pod krawedzia okna
   (ta sama diagnoza co why-us v64 / services v35 / partners v31).

   Heading i subheading wchodza RAZEM (jeden krok) — stoja obok siebie w tym
   samym rzedzie gridu naglowka, wiec osobne wejscie czytaloby sie jak blad.
   Tak samo jak w services v34.

   Reveal idzie na `translate` VIEWPORTU, nie `transform`: `.montage` ma
   `translateZ(0)` (warstwa kompozytora), a JS pisze inline `translate` na
   `.montage__track` i `transform` na kartach (silnik ruchu) — reveal celuje
   w viewport, wiec te dwa swiaty sie nie mieszaja.
   ============================================= */

/* Sekcja nie gasnie juz jako blok. `.section-fade` zostaje WYLACZNIE po to,
   zeby wspoldzielony obserwator w common.js dodal `.visible` (to ono odpala
   kaskade). NIE ustawiamy tu `transform: none` — skasowaloby to
   `translateZ(0)` z `.montage`, czyli podpowiedz o osobnej warstwie
   kompozytora dla marquee. */
.montage.section-fade {
  opacity: 1;
  transition: none;
}

/* WSZYSTKIE stany ukryte sa zagniezdzone pod `.montage--js-reveal`, ktora
   dodaje modul "Montage Reveal" w main.js. To NIE jest ozdobnik: bez tej
   bramki wystarczy, ze przegladarka poda nowy CSS ze starym (zbuforowanym)
   JS-em, a pas kart zostaje na `opacity: 0` NA ZAWSZE i sekcja renderuje sie
   jako pusta przestrzen. Zdarzylo sie to realnie przy kolizji numerow wersji.
   Brak modulu = brak klasy = tresc widoczna, tylko bez animacji. */
.montage--js-reveal .montage__label,
.montage--js-reveal .montage__heading,
.montage--js-reveal .montage__subheading,
.montage--js-reveal .marquee-nav {
  opacity: 0;
  translate: 0 var(--montage-reveal-shift);
  transition: opacity var(--montage-reveal-dur) var(--montage-reveal-ease),
              translate var(--montage-reveal-dur) var(--montage-reveal-ease);
}

/* Viewport ma stan ukryty bez wlasnego `transition` — ta lista jest wyzej
   (regula `.montage__viewport`). */
.montage--js-reveal .montage__viewport {
  opacity: 0;
  translate: 0 var(--montage-reveal-shift);
}

/* --- Kaskada czasowa: tylko gora sekcji --- */
.montage--js-reveal.visible .montage__label,
.montage--js-reveal.visible .montage__heading,
.montage--js-reveal.visible .montage__subheading {
  opacity: 1;
  translate: 0 0;
}

.montage--js-reveal.visible .montage__label { transition-delay: 0s; }
.montage--js-reveal.visible .montage__heading,
.montage--js-reveal.visible .montage__subheading {
  transition-delay: var(--montage-reveal-step);
}

/* --- Pas kart + sterowanie: trigger pozycyjny (main.js) --- */
.montage--js-reveal .montage__viewport.is-revealed,
.montage--js-reveal .marquee-nav.is-revealed {
  opacity: 1;
  translate: 0 0;
}

@media (prefers-reduced-motion: reduce) {
  .montage--js-reveal .montage__label,
  .montage--js-reveal .montage__heading,
  .montage--js-reveal .montage__subheading,
  .montage--js-reveal .montage__viewport,
  .montage--js-reveal .marquee-nav {
    translate: none;
  }

  /* (0,3,0) — tyle samo co reguly kaskady wyzej, wiec zeruje ich opoznienia
     kolejnoscia w zrodle. Nizsza specyficznosc by przegrala. */
  .montage--js-reveal.visible .montage__label,
  .montage--js-reveal.visible .montage__heading,
  .montage--js-reveal.visible .montage__subheading {
    transition-delay: 0s;
  }
}

/* ---- Tablet ---- */
@media (max-width: 1024px) {
  .montage {
    padding: 80px 24px;
  }

  .montage__header {
    grid-template-columns: 1fr;
    margin-bottom: 48px;
    row-gap: 20px;
  }

  .montage__label,
  .montage__heading,
  .montage__subheading {
    grid-column: 1;
  }

  .montage__label { grid-row: 1; }
  .montage__heading { grid-row: 2; font-size: 40px; max-width: none; }
  .montage__subheading {
    grid-row: 3;
    justify-self: start;
    align-self: start;
    max-width: 560px;
    /* Trzyma tablet i telefon na dotychczasowych 16px/1.6 — blok ≤768 tez
       lapie sie w ten media query, wiec jeden override wystarcza na oba. */
    font-size: 16px;
    line-height: 1.6;
  }

  .montage__viewport {
    --montage-card-w: 345.6px;
    --montage-card-h: 428.16px; /* +48px, patrz uwaga przy wartosci bazowej */
  }
}

/* ---- Mobile ---- */
@media (max-width: 768px) {
  .montage {
    padding: 64px 24px;
  }

  .montage__heading { font-size: 32px; }

  .montage__viewport {
    --montage-card-w: 302.4px;
    --montage-card-h: 380.64px; /* +48px, patrz uwaga przy wartosci bazowej */
    --montage-gap: 17.6px;
    /* Full-width bleed (edge to edge), NO extra 140px left shift — the
       desktop left bleed pushes the whole track off-screen on mobile so
       the active card is never centred / always cut off. */
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }

  /* Centre the active card in the viewport: pad the track by half the
     leftover space so card 0 sits centred, and every JS step (-idx*stepW)
     lands the next card dead-centre too. */
  .montage__track {
    padding-left: calc((100vw - var(--montage-card-w)) / 2);
    padding-right: calc((100vw - var(--montage-card-w)) / 2);
  }

  .montage__card--text {
    padding: 28px 24px;
  }

  .montage__card-title { font-size: 20px; }
  .montage__card-desc { font-size: 14px; }

  /* v60 — MOBILE ONLY: sterowanie na srodku, BEZ pauzy.
     Karty ze zdjeciami sa na tej szerokosci usuwane z DOM przez inline JS
     w hero.html (silnik ruchu liczy pozycje z indeksow flexboxa, wiec samo
     `display: none` rozjechaloby kompensacje przytrzymania — patrz komentarz
     przy `buildTrack()`). Zostaje 5 kart tekstowych. */
  .montage__nav-wrapper {
    margin-top: 32px;
    justify-content: center;
  }

  .montage .marquee-nav { gap: 16px; }

  /* Pauza/odtwarzanie znika razem z pierscieniem postepu — autoplay dalej
     dziala, a pierwsza interakcja (strzalka / przytrzymanie / drag) i tak go
     zatrzymuje na stale (`stopAuto()` w inline JS). */
  .montage .marquee-nav__toggle { display: none; }
}

/* (reduced motion: silnik ruchu w JS sam skraca animacje do zera —
   patrz REDUCE w inline JS hero.html; tasma nie ma juz przejsc CSS) */

/* ---- TELEFON: etykieta + naglowek wjezdzaja Z LEWEJ ----
   Wspolna regula calego serwisu (2026-08-03, base.css v142): na telefonie
   NAGLOWEK sekcji wchodzi Z BOKU, a TRESC (karty, zdjecia, listy) Z DOLU.
   Mieszanka jest zamierzona — klient poprosil, zeby ruch byl „i lewo/prawo,
   i z dolu", zamiast dotychczasowego przypadkowego rozklad kierunkow.
   Selektor jest KOPIA stanu ukrytego wyzej, wiec ma te sama specyficznosc i
   wygrywa kolejnoscia w zrodle; reguly odslaniajace maja o klase wiecej
   (`.visible` / `.is-revealed`), wiec dalej przebijaja obie.
   Warunek `no-preference` jest KONIECZNY: blok `prefers-reduced-motion` w tym
   pliku lezy WYZEJ, wiec bez niego ta regula by go przebila.
   Dystans idzie z tokenu sekcji (na telefonie 44px — base.css v142), a sekcja
   przycina poziomo, wiec wjazd nie robi przewijania w bok. */
@media (max-width: 768px) and (prefers-reduced-motion: no-preference) {
  /* **`translate`, a NIE `transform`** — i to nie jest wybor stylu: ta sekcja
     trzyma wejscia na osobnej wlasciwosci `translate` (bo `.montage` i karty
     maja stale `transform: translateZ(0)` — warstwa kompozytora, patrz
     montage.css v58), a stan odsloniety zeruje wlasnie `translate: 0 0`.
     Regula napisana na `transform` NIE zostalaby wiec nigdy skasowana i
     naglowek zostawalby przesuniety o 44px NA STALE — zmierzone, tak wlasnie
     bylo w pierwszej wersji tej zmiany. */
  .montage--js-reveal .montage__label,
  .montage--js-reveal .montage__heading {
    translate: calc(-1 * var(--montage-reveal-shift)) 0;
  }
}
