/* =============================================
   TESTIMONIALS SECTION
   Used on: hero.html, oferta-okna.html
   ============================================= */
.testimonials {
  background-color: var(--white);
  padding: 175px 0 100px;
  position: relative;
  overflow: hidden;
}

.testimonials__container {
  position: relative;
  z-index: 1;
  max-width: var(--max-width-wide);
  margin: 0 auto;
  padding: 0 24px;
  margin-bottom: 56px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 80px;
}

.testimonials__label {
  display: inline-block;
  padding: 0;
  background: transparent;
  color: var(--dark-gray);
  border: none;
  font-size: 15px;
  font-weight: 500;
  border-radius: 0;
  letter-spacing: 0.02em;
  margin-bottom: 20px;
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
}

.testimonials__heading {
  font-size: var(--heading-size);
  font-weight: var(--heading-weight);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: 0;
  color: var(--dark-gray);
  grid-column: 1;
  grid-row: 2;
}

.testimonials__heading span {
  color: inherit;
}

.testimonials__subheading {
  font-size: 18px;
  font-weight: 400;
  line-height: 1.7;
  color: var(--gray-500);
  max-width: none;
  margin: 0;
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  justify-self: end;
  max-width: 380px;
}

/* Marquee wrapper */
.testimonials__marquee {
  position: relative;
  z-index: 1;
  overflow: hidden;
  width: 100%;
  padding: 20px 0;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  mask-image: linear-gradient(to right, transparent 0%, black 5%, black 95%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 5%, black 95%, transparent 100%);
}

/* Track */
.testimonials__track {
  display: flex;
  width: max-content;
  gap: 24px;
  will-change: transform;
}

.testimonials__marquee--right {
  margin-bottom: -16px;
}

.testimonials__track--right {
  animation: marquee-right 84s linear infinite;
  animation-play-state: paused;
}

.testimonials__track--left {
  animation: marquee-left 84s linear infinite;
  animation-play-state: paused;
}

/* Hero merged single-row marquee — twice as many cards, twice the duration */
.testimonials__marquee--single .testimonials__track--left {
  animation-duration: 168s;
}

/* Hero merged variant — narrower + taller cards, larger stars (Google logo removed) */
.testimonials__marquee--single .testimonials__card,
.testimonials__marquee--single .testimonials__photo {
  width: 415px;
  height: 499px;
}

.testimonials__marquee--single .testimonials__title {
  font-size: 24px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--dark-gray);
  margin: 0 0 10px;
  letter-spacing: -0.01em;
}

.testimonials__marquee--single .testimonials__stars {
  font-size: 22.77px;
  gap: 0;
}

.testimonials__marquee--single .testimonials__text {
  font-size: 17px;
  font-weight: 400;
}

.testimonials.in-view .testimonials__track--right,
.testimonials.in-view .testimonials__track--left {
  animation-play-state: running;
}

/* Pause marquee on mousedown (desktop only) */
@media (min-width: 769px) {
  .testimonials__marquee:active .testimonials__track,
  .testimonials__marquee:has(:active) .testimonials__track {
    animation-play-state: paused;
  }

  .testimonials__marquee {
    cursor: grab;
  }

  .testimonials__marquee:active {
    cursor: grabbing;
  }
}

/* Card */
.testimonials__card {
  flex-shrink: 0;
  width: 480px;
  height: 300px;
  background: #ffffff;
  border-radius: 9px;
  padding: 32px 28px 28px;
  display: flex;
  flex-direction: column;
  gap: 0;
  border: none;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
  position: relative;
  overflow: hidden;
}

/* Photo slide (same dimensions as card) */
.testimonials__photo {
  flex-shrink: 0;
  width: 480px;
  height: 300px;
  border-radius: 9px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}

/* `video` jest tu obok `img`, bo od 2026-08-05 jeden ze slajdow pasa opinii
   jest wideo (montaz manipulatorem). Selektor MUSI wymieniac oba elementy —
   sam `img` zostawilby `<video>` bez `object-fit`, czyli z czarnymi pasami
   w kadrze 415×499. */
.testimonials__photo img,
.testimonials__photo video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Stars */
.testimonials__stars {
  display: flex;
  align-items: center;
  gap: 22px;
  font-size: 20.7px;
  color: var(--orange);
  letter-spacing: 2px;
  margin-bottom: 29.04px;
  line-height: 1;
}


/* Text */
.testimonials__text {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--dark-gray);
}

/* Author */
.testimonials__author {
  display: flex;
  align-items: center;
  gap: 12px;
  position: absolute;
  bottom: 28px;
  left: 28px;
}

.testimonials__avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  border: none;
}

.testimonials__name {
  font-size: 15px;
  font-weight: 600;
  color: var(--dark-gray);
  letter-spacing: -0.01em;
}

/* =============================================
   REVEAL — kaskada wejscia sekcji
   Kolejnosc (zyczenie klienta): label → heading + subheading RAZEM (na
   desktopie stoja obok siebie w gridzie `1fr 1fr`, wiec osobne wejscie
   czytaloby sie jak blad) → pas kart.

   Ruch hero: 0.7s ease-out, 30px — te same tokeny co why-us v63, services v37,
   showroom v63, montage v52, realizacje v28, process v82. NIE wracaj tu do
   `--reveal-duration`/`--reveal-ease`: to expo-out, ktory upycha ~90% drogi
   w ~20% czasu i czyta sie jak szarpniecie (przed ta zmiana sekcja jechala
   wlasnie na nich, i to jednym fadem calego naglowka).
   Wszystko z dolu — zasada klienta „nic z gory".
   ============================================= */
.testimonials {
  --ts-reveal-dur: 0.7s;
  --ts-ease: ease-out;
  --ts-step: 0.25s;
  --ts-shift: 30px;
}

/* Kontener przestal sie animowac jako blok — `.reveal-testimonials` sluzy juz
   WYLACZNIE jako haczyk dla obserwatora (main.js na hero, inline JS na 8
   stronach oferty), ktory dodaje `.visible`. Nie usuwaj tej klasy z HTML „bo
   kontener sie nie fade'uje" — to jedyny trigger kaskady. */
.testimonials__container.reveal-testimonials {
  opacity: 1;
  transform: none;
  transition: none;
}

.testimonials__container.reveal-testimonials .testimonials__label,
.testimonials__container.reveal-testimonials .testimonials__heading,
.testimonials__container.reveal-testimonials .testimonials__subheading {
  opacity: 0;
  transform: translateY(var(--ts-shift));
  transition: opacity var(--ts-reveal-dur) var(--ts-ease),
              transform var(--ts-reveal-dur) var(--ts-ease);
}

.testimonials__container.reveal-testimonials.visible .testimonials__label,
.testimonials__container.reveal-testimonials.visible .testimonials__heading,
.testimonials__container.reveal-testimonials.visible .testimonials__subheading {
  opacity: 1;
  transform: translateY(0);
}

.testimonials__container.reveal-testimonials.visible .testimonials__label { transition-delay: 0s; }
.testimonials__container.reveal-testimonials.visible .testimonials__heading,
.testimonials__container.reveal-testimonials.visible .testimonials__subheading { transition-delay: var(--ts-step); }

/* ---- Pas kart — wlasny trigger, na koncu ----
   Nie potrzebuje osobnego modulu JS: ten sam obserwator obserwuje takze sam
   pas, wiec `.visible` dostaje on dopiero, gdy SAM wjedzie w widok (zmierzone
   @1440×900: ~330px scrolla po naglowku). Opoznienie 2 krokow trzyma kolejnosc
   w przypadku brzegowym, gdy naglowek i pas wpadna w widok w tej samej klatce
   (wysokie okno, odswiezenie w srodku sekcji).
   Ruch idzie na WRAPPERZE `.testimonials__marquee`, a nie na `.testimonials__track`:
   track ma nieskonczona animacje CSS na `transform` (marquee-left/right) i ta
   sama wlasciwosc na tym samym elemencie nie moze prowadzic dwoch ruchow —
   animacja zawsze wygrywa z przejsciem. Nie przenos tego na track. */
.testimonials__marquee {
  opacity: 0;
  transform: translateY(var(--ts-shift));
  transition: opacity var(--ts-reveal-dur) var(--ts-ease),
              transform var(--ts-reveal-dur) var(--ts-ease);
}

.testimonials__marquee--right.visible,
.testimonials__marquee--left.visible,
.testimonials__marquee--single.visible {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--ts-step) * 2);
}

/* Dwurzedowy wariant (zaden ze stron juz go nie renderuje — patrz v60) mial
   rzedy rozjezdzone o 0.2s; zostaje ten sam odstep jednego kroku. */
.testimonials__marquee--left.visible {
  transition-delay: calc(var(--ts-step) * 3);
}

/* ---- TELEFON: pas kart BEZ opoznienia ----
   Opoznienie 2 krokow wyzej istnieje wylacznie dla przypadku brzegowego (pas i
   naglowek w jednej klatce IO). Na telefonie pas ma ZAWSZE wlasny wyzwalacz —
   sekcja ma ~870px, a sam pas ~410px — wiec te 0.5s to czysty zegar, i to
   najdrozszy w calym serwisie: zmierzone @390x844 przy przewijaniu 900 px/s pas
   osiagal polowe widocznosci dopiero **14px od GORY ekranu**, czyli praktycznie
   przejezdzal caly ekran jako biale tlo (najgorszy wynik ze wszystkich sekcji;
   nastepna w kolejnosci miala 205px). To bylo zrodlo zgloszenia „doscrolluje do
   konca sekcji, a nastepnej nie widac". Po zmianie: 534px, czyli pas jest
   czytelny juz w dolnej polowie ekranu.
   Selektory maja ta sama specyficznosc co reguly opoznien wyzej (0,2,0), wiec
   wygrywaja WYLACZNIE kolejnoscia w zrodle — nie przenos tego bloku wyzej.
   Blok reduced-motion nizej i tak zeruje delay, wiec go to nie dotyczy. */
@media (max-width: 768px) {
  .testimonials__marquee--right.visible,
  .testimonials__marquee--left.visible,
  .testimonials__marquee--single.visible {
    transition-delay: 0s;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Selektory z `.visible` sa tu konieczne: reguly opoznien wyzej maja (0,4,0),
     wiec wpis bez tej klasy (0,3,0) przegralby i kaskada zostalaby mimo
     reduced motion. Media query nie dodaje specyficznosci. */
  .testimonials__container.reveal-testimonials .testimonials__label,
  .testimonials__container.reveal-testimonials .testimonials__heading,
  .testimonials__container.reveal-testimonials .testimonials__subheading,
  .testimonials__container.reveal-testimonials.visible .testimonials__label,
  .testimonials__container.reveal-testimonials.visible .testimonials__heading,
  .testimonials__container.reveal-testimonials.visible .testimonials__subheading,
  .testimonials__marquee,
  .testimonials__marquee--right.visible,
  .testimonials__marquee--left.visible,
  .testimonials__marquee--single.visible {
    transform: none;
    transition-delay: 0s;
  }
}

/* Marquee keyframes */
@keyframes marquee-right {
  0% {
    transform: translateX(-50%);
  }
  100% {
    transform: translateX(0%);
  }
}

@keyframes marquee-left {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(-50%);
  }
}

/* =============================================
   RESPONSIVE — TESTIMONIALS
   ============================================= */
/* === Tablet (≤1024px) === */
@media (max-width: 1024px) {
  .testimonials__container {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .testimonials__label {
    grid-column: 1;
    grid-row: 1;
  }

  .testimonials__heading {
    font-size: 36px;
    grid-column: 1;
    grid-row: 2;
    margin-bottom: 12px;
  }

  .testimonials__subheading {
    grid-column: 1;
    grid-row: 3;
    margin-left: 0;
    margin-right: 0;
  }

  .testimonials__card {
    width: 420px;
    height: 300px;
    padding: 28px 24px 24px;
  }

  .testimonials__photo {
    width: 420px;
    height: 300px;
  }

  .testimonials__marquee--single .testimonials__card,
  .testimonials__marquee--single .testimonials__photo {
    width: 363px;
    height: 499px;
  }

  .testimonials__text {
    line-height: 1.52;
  }

  .testimonials__author {
    bottom: 24px;
  }
}

/* === Mobile (≤768px) === */
@media (max-width: 768px) {
  .testimonials {
    padding: 72px 0;
  }

  .testimonials__container {
    padding: 0 20px;
    margin-bottom: 40px;
  }

  .testimonials__heading {
    font-size: 32px;
  }

  .testimonials__subheading {
    font-size: 16px;
  }

  .testimonials__card {
    width: 340px;
    height: 288px;
    padding: 24px 20px 22px;
  }

  .testimonials__photo {
    width: 340px;
    height: 288px;
  }

  /* Karta jest SZERSZA i przez to NIZSZA — patrz testimonials.css v65.
     Te dwie liczby sa sprzezone: 320px mieszcza najdluzsza opinie w 9 liniach
     zamiast 11, wiec tresc konczy sie na 319px i 410px wystarcza z zapasem.
     Zwezenie karty bez podniesienia wysokosci utnie tekst pod autorem. */
  .testimonials__marquee--single .testimonials__card,
  .testimonials__marquee--single .testimonials__photo {
    width: 320px;
    height: 410px;
  }

  .testimonials__marquee--single .testimonials__text {
    font-size: 16px;
  }

  .testimonials__text {
    font-size: 14px;
    line-height: 1.4;
  }

  .testimonials__author {
    bottom: 20px;
  }

  .testimonials__track--right,
  .testimonials__track--left {
    animation-duration: 61s;
  }

  .testimonials__marquee--single .testimonials__track--left {
    animation-duration: 122s;
  }

  .testimonials__marquee--right {
    margin-bottom: -16px;
  }

  .testimonials__track {
    gap: 16px;
  }
}

/* Najwezsze telefony (iPhone SE 1. gen i pochodne).
   Karta 320px zajmowalaby TAM cala szerokosc ekranu — dotykalaby obu krawedzi,
   wiec znikalby podglad sasiedniej karty i pas przestawalby czytac sie jak
   karuzela. Wezsza karta sama z siebie PODNOSI wysokosc (tekst lamie sie na
   wiecej linii: przy 296px i foncie 16px tresc siega 394px, czyli wiecej niz
   przed cala zmiana), dlatego razem z nia schodzi font tekstu na 15px — dopiero
   ta para trzyma tresc w 316px i pozwala zostac przy TEJ SAMEJ wysokosci 410px
   co na szerszych ekranach. Zmiana jednej z tych liczb bez drugiej albo utnie
   tekst pod autorem, albo cofnie efekt obnizenia karty.
   Blok MUSI stac PO bloku `max-width: 768px` — selektory maja identyczna
   specyficznosc (0,2,0) i decyduje kolejnosc w zrodle. */
@media (max-width: 359px) {
  .testimonials__marquee--single .testimonials__card,
  .testimonials__marquee--single .testimonials__photo {
    width: 296px;
  }

  .testimonials__marquee--single .testimonials__text {
    font-size: 15px;
  }
}

/* Section badge prefix "// " */
.testimonials__label::before { content: "// "; }
.testimonials__label { text-transform: capitalize; }

/* ---- 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) {
  .testimonials__container.reveal-testimonials .testimonials__label,
  .testimonials__container.reveal-testimonials .testimonials__heading {
    transform: translateX(calc(-1 * var(--ts-shift)));
  }
}
