/* ═══════════════════════════════════════════════════════════════════════════
   PTS - style wzorców blokowych

   `components.css` obsługuje elementy układu przeniesione z wersji B:
   nawigację, stopkę, nagłówki podstron. Ich HTML pisał generator, więc
   selektory zakładają dokładną strukturę.

   Bloki Gutenberga generuje WordPress i ta struktura wygląda inaczej.
   Zamiast naginać tamte selektory, wzorce dostają własny arkusz. Dzięki
   temu zmiana w bloku nie psuje nawigacji i odwrotnie.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Hero ─────────────────────────────────────────────────────────────────
   Zbudowany na core/cover, bo redakcja ma móc wymienić zdjęcie tła bez
   dotykania kodu. Wersja B miała tu canvas ze smugami i animację liter;
   nie przenoszę ich, bo wiazaly sie z konkretnym HTML generatora, a efekt
   dawaly kosztem tego, ze tresci nie dalo sie edytowac. */

.hero-blok.wp-block-cover {
  min-height: clamp(32rem, 26rem + 26vh, 46rem);
  padding-block: var(--section-y);
  align-items: flex-end;

  /* Podkład na wypadek braku zdjęcia. Tekst hero jest biały, więc bez tego
     świeżo wstawiona sekcja to biały napis na białym tle i wygląda na
     zepsutą, zanim redakcja zdąży wybrać zdjęcie. */
  background-color: var(--navy-ink);
}

.hero-blok .wp-block-cover__inner-container {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
}

/* Hero wychodzi poza kolumnę treści na pełną szerokość okna. Pas przerwany
   białymi marginesami czyta się jak baner wklejony w stronę, a nie jak
   otwarcie serwisu. */
.hero-blok.wp-block-cover.alignfull {
  width: calc(100vw - var(--pasek, 0px));
  max-width: calc(100vw - var(--pasek, 0px));
  margin-left: calc(50% - (100vw - var(--pasek, 0px)) / 2);
  margin-right: calc(50% - (100vw - var(--pasek, 0px)) / 2);
}

/* Filtr „Deep Blue" z księgi (s. 15). Zdjęcia hali bywają jasne i szare,
   a tekst musi się na nich obronić bez przyciemniania całości na czarno.
   Gradient idzie na własnym pseudoelemencie, a nie na warstwie WordPressa:
   przy `dimRatio: 0` rdzeń nadaje jej `opacity: 0` i cokolwiek by tam nie
   wpisać, pozostaje niewidoczne. */
.hero-blok::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(
      to top,
      rgba(20, 17, 59, 0.92) 0%,
      rgba(20, 17, 59, 0.62) 38%,
      rgba(29, 40, 122, 0.30) 70%,
      rgba(29, 40, 122, 0.42) 100%
    ),
    linear-gradient(
      to right,
      rgba(20, 17, 59, 0.55) 0%,
      rgba(20, 17, 59, 0.12) 55%,
      transparent 100%
    );
}

.hero-blok .wp-block-cover__inner-container {
  position: relative;
  z-index: 2;
}

/* Zdjęcie hero zostaje bez `z-index` i bez `will-change`. Dodałem je pod
   parallax, którego tu nie ma, a oba tworzą własny kontekst stackingu
   i wpychają zdjęcie pod gradient, przez co hero pokazywało sam podkład.
   Kolejność warstw wystarczy tu ta domyślna. */
.hero-blok .wp-block-cover__image-background {
  object-fit: cover;
}

/* ── Warstwa ruchu hero ───────────────────────────────────────────────────
   Markup dokłada filtr z `inc/ruch.php`, nie wzorzec, więc redakcja nie ma
   tu czego zepsuć ani czego zgubić przy wstawianiu sekcji od nowa. */

/* Smugi pochylone jak w znaku PTS. Leżą nad gradientem, bo pod nim gasną:
   filtr Deep Blue ma przy dolnej krawędzi 0,92 krycia i zjada wszystko,
   co jest pod nim. Krycie samego canvasu trzyma je w tle, żeby nie
   konkurowały z typografią. */
.hero-blok__smugi {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  opacity: 0.5;
  pointer-events: none;
}

/* Zapas skali musi pokryć przesunięcie parallaxu, inaczej spod zdjęcia
   wyjrzy granatowy podkład bloku. Przy współczynniku 0,07 z filtru
   przesunięcie nie przekracza kilkudziesięciu pikseli, a 18% wysokości
   hero to zapas ponad dwukrotny. */
.hero-blok .wp-block-cover__image-background[data-parallax] {
  z-index: 0;
  transform: scale(1.18);
  will-change: transform;
}

/* Kaskada słów w nagłówku. Wersja B animowała całe wiersze, ale wiersze
   trzeba było wpisać w markup jako `<span class="ln">`. Tu tekst pisze
   redakcja i żaden podział na wiersze nie przetrwa zmiany treści ani
   szerokości okna, więc maska idzie na słowo: `app.js` owija słowa sam,
   a efekt jest ten sam, tylko odporny na dowolny tekst. */
.hero-blok h1 .wd {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;

  /* Nagłówek hero ma interlinię 1.03, czyli pole wiersza jest NIŻSZE niż
     litery, które się w nim mieszczą. Maska bez zapasu obcina wtedy nie
     ogonki, ale połowę wysokości liter - „doświadczenie" traciło dolną
     część każdego znaku. Zapas idzie z obu stron, a ujemne marginesy
     zdejmują go z układu, więc odstępy między wierszami zostają takie,
     jakie zaprojektował arkusz. */
  padding-block: 0.2em;
  margin-block: -0.2em;
}

.hero-blok h1 .wd > span {
  display: inline-block;
  will-change: transform;
}

.js-motion .hero-blok h1 .wd > span {
  transform: translateY(108%);
}

/* Kursywa w nagłówku hero wychodzi pomarańczem, nie pochyleniem. Redakcja
   ma w edytorze zwykły przycisk kursywy i tym samym dostęp do akcentu
   z księgi, bez wpisywania klas. */
.hero-blok h1 em {
  font-style: normal;
  color: var(--orange);
}

/* Wskaźnik przewijania. Przy wąskim ekranie schodzi: hero jest tam niskie,
   a pionowy napis przy krawędzi wchodzi w treść. */
.hero-blok__scroll {
  position: absolute;
  right: calc(var(--gutter) - 0.5rem);
  bottom: clamp(2.5rem, 6vw, 5rem);
  z-index: 2;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  font-size: 0.64rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--on-navy-3);
  writing-mode: vertical-rl;
}

.hero-blok__scroll i {
  display: block;
  width: 1px;
  height: 54px;
  background: linear-gradient(to bottom, var(--orange), transparent);
  transform-origin: top;
  animation: pts-scroll-hint 2.4s var(--ease-out) infinite;
}

@keyframes pts-scroll-hint {
  0%        { transform: scaleY(0.2); opacity: 0; }
  30%       { opacity: 1; }
  60%, 100% { transform: scaleY(1); opacity: 0; }
}

@media (max-width: 900px) {
  .hero-blok__scroll { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-blok__scroll i { animation: none; }
  .hero-blok .wp-block-cover__image-background[data-parallax] { transform: none; }
}

.hero-blok .eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  font-weight: 700;
}

.hero-blok .eyebrow::before {
  content: "";
  width: 2.4rem;
  height: 2px;
  background: var(--orange);
  flex: none;
}

.hero-blok h1 {
  max-width: 16ch;
  margin-block: var(--s-5) var(--s-4);
}

.hero-blok .hero-blok__sub {
  max-width: 52ch;
}

/* ── Pas z faktami ────────────────────────────────────────────────────────
   UWAGA na nazwy klas. `components.css` z wersji B definiuje wlasne `.facts`
   jako siatke czterokolumnowa i celuje w `.facts > div`. Uzyta na bloku
   przechwytywala kontener kolumn i sciskala je do jednej czwartej szerokosci,
   az tekst lamal sie litera po literze. Wzorce blokowe uzywaja wiec wlasnych
   nazw wszedzie tam, gdzie stary arkusz steruje ukladem, a nie samym wygladem.
   Klasy `.card` i `.ph` zostaja swiadomie: tam kolizja daje dokladnie ten
   efekt, ktorego chcemy, lacznie z filtrem Deep Blue z ksiegi. */

/* Pas idzie przez cala szerokosc okna, tak jak hero nad nim. Sekcja
   urwana weziej niz ta powyzej lamie rytm strony w miejscu, w ktorym
   oko akurat go szuka. */
/* Zasada ukladu: tlo sekcji idzie przez cala szerokosc okna, tresc zostaje
   w kolumnie o szerokosci `--shell`. Kolorowy prostokat urwany na 1280 px
   czyta sie jak wklejony w strone banner, a nie jak jej czesc.

   Wyrownanie robi padding kontenera, a nie `max-width` na dzieciach.
   Przy dzieciach kazde z nich centruje sie osobno i elementy o wlasnych
   marginesach, jak nadtytul z kreska, wychodza z linii reszty sekcji. */
.pas-faktow.alignfull,
.cta.alignfull,
.wp-block-group.alignfull.section--mist {
  width: calc(100vw - var(--pasek, 0px));
  max-width: calc(100vw - var(--pasek, 0px));
  margin-left: calc(50% - (100vw - var(--pasek, 0px)) / 2);
  margin-right: calc(50% - (100vw - var(--pasek, 0px)) / 2);
  padding-inline: max(var(--gutter), calc((100vw - var(--pasek, 0px) - var(--shell)) / 2));
}

/* Kolumny wewnatrz takiej sekcji maja juz wyrownanie z paddingu rodzica,
   wiec `alignwide` nie moze dokladac wlasnych marginesow ujemnych. */
.pas-faktow.alignfull .wp-block-columns.alignwide,
.wp-block-group.alignfull.section--mist .wp-block-columns.alignwide {
  max-width: 100%;
  margin-inline: 0;
}

/* Kreska przy kolumnie jest pseudoelementem, a nie obramowaniem, bo ma się
   rysować od góry przy wejściu sekcji, w rytmie kaskady kolumn. Obramowania
   nie da się animować skalą, a animowanie samej szerokości szarpie układ.
   Bez `js-motion` - czyli przy prośbie o ograniczenie ruchu - kreska stoi
   od razu pełnej wysokości, więc niczego nie brakuje. */
.pas-faktow .wp-block-column {
  position: relative;
  padding-left: var(--s-4);
}

.pas-faktow .wp-block-column::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--orange);
  transform-origin: top;
  transition: transform 0.8s var(--ease-out) var(--anim-delay, 0s);
}

.js-motion .pas-faktow .wp-block-column::before { transform: scaleY(0); }
.pas-faktow .wp-block-column.is-in::before { transform: scaleY(1); }

.pas-faktow__liczba {
  line-height: var(--lh-tight);
  margin-bottom: var(--s-1);
}

/* ── Pas z siecią w tle ───────────────────────────────────────────────────
   Wariant pasa faktów dla sekcji o nadzorze nad siecią pojazdu. Rysunek jest
   ozdobą generowaną losowo, nie schematem: powód i zakaz dopisywania podpisów
   siedzą w nagłówku wzorca `patterns/siec-w-tle.php`. */

.pas-sieci {
  position: relative;
  overflow: hidden;
}

.pas-sieci__plotno {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Treść musi zostać nad płótnem, inaczej impulsy przechodzą po literach. */
.pas-sieci > .wp-block-columns {
  position: relative;
  z-index: 1;
}

/* ── Karty ────────────────────────────────────────────────────────────────
   Wyrównanie wysokości idzie z siatki, nie z ustawionej ręcznie wysokości.
   Redakcja wpisuje różnej długości opisy i karty muszą to znieść. */

.wp-block-column > .card {
  height: 100%;
  border-radius: var(--r-lg);
  border: var(--hair);
  transition: box-shadow var(--t) var(--ease), transform var(--t) var(--ease);
}

.wp-block-column > .card:hover {
  box-shadow: var(--lift-1);
  transform: translateY(-2px);
}

.wp-block-column > .card h3 {
  margin-bottom: var(--s-3);
}

/* ── Sekcje ───────────────────────────────────────────────────────────── */

.section .eyebrow,
.section--mist .eyebrow {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  font-weight: 700;
  margin-bottom: var(--s-3);
}

.cta {
  border-radius: 0;
  text-align: center;
}

.cta .wp-block-buttons {
  justify-content: center;
}

/* ── Przyciski blokowe ────────────────────────────────────────────────────
   Rdzeń WordPressa daje im kolor i zaokrąglenie z `theme.json`, ale nie daje
   żadnej reakcji na kursor. Przycisk, który nie odpowiada na najechanie,
   czyta się jak makieta, a nie jak działający serwis - i to jest pierwsza
   rzecz, którą widać na stronie firmy remontującej tabor. */

.wp-block-button__link {
  position: relative;
  transition:
    background-color var(--t) var(--ease),
    border-color var(--t) var(--ease),
    color var(--t) var(--ease),
    box-shadow var(--t) var(--ease),
    transform var(--t) var(--ease);
}

.wp-block-button:not(.is-style-outline) > .wp-block-button__link:hover {
  background-color: var(--orange-deep);
  box-shadow: var(--lift-1);
  transform: translateY(-2px);
}

.wp-block-button > .wp-block-button__link:active {
  transform: translateY(0);
}

/* Strzałka jest w pseudoelemencie, więc redakcja nie musi jej wpisywać
   w tekst przycisku ani pamiętać o niej przy zmianie etykiety. */
.wp-block-button:not(.is-style-outline) > .wp-block-button__link::after {
  content: "\2192";
  display: inline-block;
  margin-left: 0.6em;
  transition: transform var(--t) var(--ease);
}

.wp-block-button:not(.is-style-outline) > .wp-block-button__link:hover::after {
  transform: translateX(0.25em);
}

/* Obrys widoczny przy nawigacji klawiaturą. Bez tego przycisk blokowy
   gubi ognisko na ciemnym tle i strona przestaje być obsługiwalna
   bez myszy. */
.wp-block-button__link:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

/* Przycisk obrysowany na ciemnym tle: wariant WordPressa dziedziczy kolor
   tekstu, który na granacie i na zdjęciu hero znika. */
.cta .is-style-outline .wp-block-button__link,
.hero-blok .is-style-outline .wp-block-button__link {
  color: var(--on-navy);
  border-color: rgba(255, 255, 255, 0.4);
}

.cta .is-style-outline .wp-block-button__link:hover,
.hero-blok .is-style-outline .wp-block-button__link:hover {
  border-color: var(--orange);
  color: var(--orange);
}

/* ── Zdjęcia w blokach ────────────────────────────────────────────────── */

.wp-block-image.ph img,
.wp-block-gallery.ph-siatka img {
  border-radius: var(--r-lg);
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.wp-block-video.film video {
  border-radius: var(--r-lg);
  width: 100%;
}

/* ── Zawężenie treści wpisywanej swobodnie ────────────────────────────────
   Akapit rozciągnięty na 1280 px jest nieczytelny. Bloki treści trzymają
   szerokość tekstową, a pełną szerokość dostają tylko te, które o nią proszą. */

.wp-block-post-content > p,
.wp-block-post-content > h2,
.wp-block-post-content > h3,
.wp-block-post-content > ul,
.wp-block-post-content > ol {
  max-width: var(--shell-narrow);
  margin-inline: auto;
}

/* ── Lista realizacji ─────────────────────────────────────────────────────
   Siatka dopasowuje liczbę kolumn do szerokości, bez progów wpisanych
   ręcznie. Realizacji przybywa i nikt nie będzie poprawiał breakpointów
   przy trzynastej. */

.lista-realizacji {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: var(--s-5);
  margin-top: var(--s-6);
}

.karta-realizacji .ph {
  display: block;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 3 / 2;
}

.karta-realizacji img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out);
}

.karta-realizacji .ph:hover img {
  transform: scale(1.04);
}

/* Podpis leży na zdjęciu, więc potrzebuje własnego podkładu. Zdjęcia hali
   bywają jasne u dołu i sam biały tekst na nich ginie. */
.karta-realizacji__tytul {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--s-6) var(--s-4) var(--s-4);
  color: var(--on-navy);
  font-weight: 700;
  background: linear-gradient(to top, rgba(20, 17, 59, 0.88), transparent);
}

.prev-next {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding-block: var(--s-7);
  border-top: var(--hair);
}

/* ── Formularz kontaktowy ─────────────────────────────────────────────── */

.form-kontakt .field {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}

.form-kontakt label {
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--ink-2);
}

.form-kontakt input[type="text"],
.form-kontakt input[type="email"],
.form-kontakt input[type="tel"],
.form-kontakt textarea {
  font: inherit;
  color: var(--ink);
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--white);
  transition: border-color var(--t-fast) var(--ease);
}

.form-kontakt input:focus-visible,
.form-kontakt textarea:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 1px;
  border-color: var(--orange);
}

.form-kontakt textarea {
  resize: vertical;
  min-height: 8rem;
}

.field--zgoda label {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink-2);
  cursor: pointer;
}

.field--zgoda input {
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.2rem;
  flex: none;
  accent-color: var(--orange);
}

.form-note {
  font-size: var(--fs-micro);
  color: var(--ink-3);
  max-width: 60ch;
  margin-bottom: var(--s-5);
}

/* Pole pułapka na roboty. `display: none` bywa przez nie wykrywane, więc
   pole zostaje w układzie, tylko poza widocznym obszarem. */
.pole-pulapka {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-komunikat {
  padding: var(--s-4);
  border-radius: var(--r);
  border-left: 3px solid;
  margin-bottom: var(--s-5);
}

.form-komunikat--ok {
  background: var(--navy-wash);
  border-color: var(--navy);
}

.form-komunikat--blad {
  background: var(--orange-wash);
  border-color: var(--orange-ink);
  color: var(--orange-ink);
}

/* ── Numeracja w nawigacji ────────────────────────────────────────────────
   Numer i nazwa pozycji sa osobnymi elementami, wiec bez odstepu skleja sie
   w "01Start". W wersji B odstep dawal uklad generatora, ktorego tu nie ma. */

.nav__links a > span,
.drawer__links a > span {
  margin-right: 0.5em;
  font-size: 0.72em;
  font-weight: 700;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
}

.nav:not(.is-solid) .nav__links a > span { color: rgba(255, 255, 255, 0.55); }


/* ── Czytelność nawigacji na zdjęciu ──────────────────────────────────────
   Nagłówek jest przezroczysty nad hero, żeby zdjęcie szło pod nim na całą
   wysokość. Zdjęcia hali bywają jednak jasne u góry i biały tekst menu na
   nich znika. Delikatny gradient pod nagłówkiem rozwiązuje to bez malowania
   paska na kolor, który przykryłby zdjęcie. */

.nav:not(.is-solid)::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 220%;
  pointer-events: none;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    rgba(20, 17, 59, 0.72) 0%,
    rgba(20, 17, 59, 0.38) 45%,
    transparent 100%
  );
}

/* Cień pod tekstem nawigacji dokłada czytelności tam, gdzie pod spodem
   trafi się jasny fragment zdjęcia mimo gradientu. */
.nav:not(.is-solid) .nav__links a,
.nav:not(.is-solid) .nav__lang a {
  text-shadow: 0 1px 3px rgba(20, 17, 59, 0.55);
}
