/*
 Theme Name: WykopSam
 Theme URI: https://wykopsam.pl
 Description: Samodzielny motyw dla WykopSam.pl — wypożyczalnia sprzętu budowlanego w Puławach. Cała treść edytowalna w panelu (Kokpit → WykopSam). Kolorystyka i kształty wyprowadzone z logotypu, fonty hostowane lokalnie, zero zależności od wtyczek.
 Author: Sadurski.pl
 Author URI: https://sadurski.pl
 Version: 1.0.0
 Requires at least: 6.0
 Requires PHP: 7.4
 License: GNU General Public License v2 or later
 License URI: https://www.gnu.org/licenses/gpl-2.0.html
 Text Domain: wykopsam
 Tags: business, custom-colors, custom-logo, full-width-template, accessibility-ready
*/

/* ══════════════════════════════════════════════════════
   FONT — Archivo, zmienny, hostowany lokalnie

   Jeden plik na podzbiór obsługuje całą zadeklarowaną wagę (400–800)
   i całą oś szerokości (62–125%). Podzbiór latin-ext jest konieczny:
   ą, ć, ę, ł, ń, ś, ź, ż leżą poza podstawowym latin.

   Zero żądań do Google — IP użytkownika nie opuszcza serwisu, nie ma
   zasobu blokującego renderowanie na obcym hoście.
   ══════════════════════════════════════════════════════ */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 400 800;
    font-stretch: 62% 125%;
    font-display: swap;
    src: url('fonts/archivo-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 400 800;
    font-stretch: 62% 125%;
    font-display: swap;
    src: url('fonts/archivo-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ══════════════════════════════════════════════════════
   TOKENY

   Czerwień, biel i czerń to jedyne barwy w logotypie
   (zmierzone na logotyp-wykopsam.webp: badge „Sam" ma #DC2326
   z gradientem #E22525 → #C02026). Kwasowa zieleń z poprzedniej
   wersji serwisu nie występowała w znaku i została wycofana.

   Promienie też pochodzą ze znaku: badge ma 28 px zaokrąglenia
   przy 90 px wysokości, czyli 0,30 wysokości. Stąd 14 px na
   kontrolce 48 px i 22 px na dużym kaflu.
   ══════════════════════════════════════════════════════ */
:root {
    --ws-red:        #DC2326;
    --ws-red-deep:   #A81A20;
    --ws-red-text:   #DC2326;   /* czerwień jako tekst; w trybie ciemnym jaśniejsza */
    --ws-red-wash:   #FCEFEF;

    --ws-ink:        #141414;   /* nagłówki i tekst główny */
    --ws-ink-2:      #4A4A48;   /* tekst uzupełniający */
    --ws-ink-3:      #6B6966;   /* etykiety; 4,9:1 na papierze, przechodzi AA */

    --ws-paper:      #F4F4F1;
    --ws-card:       #FFFFFF;
    --ws-line:       #E2E1DC;
    --ws-line-2:     #CFCEC8;

    --ws-dark:       #161616;   /* jedyny ciemny pas na jasnej stronie */
    --ws-dark-ink:   #F5F4F1;
    --ws-dark-ink-2: #A8A6A1;
    --ws-dark-line:  #2E2E2C;

    --ws-r-sm: 10px;
    --ws-r:    14px;
    --ws-r-lg: 22px;

    /* Wysokosc paska nawigacji. Hero podsuwa sie pod niego o dokladnie
       te wartosc, zeby czerwien zaczynala sie od gory okna. */
    --ws-pasek: 4.5rem;
    /* Pelna wysokosc paska: wiersz plus kreska pod nim. Hero kompensuje
       wlasnie te wartosc, nie sama wysokosc wiersza. Wczesniej odejmowalo
       tylko --ws-pasek i tytul wchodzil pod pasek o grubosc kreski.

       Nie licz tego skryptem z wysokosci paska: .ws-header__row bierze
       swoja wysokosc z --ws-pasek, wiec podstawienie zmierzonej wartosci
       tworzy petle i pasek rosnie o piksel przy kazdym pomiarze. */
    --ws-pasek-calk: calc(var(--ws-pasek) + 1px);

    --ws-max:  1280px;
    --ws-gut:  clamp(1.25rem, 4vw, 3rem);

    --ws-sekcja: clamp(4.5rem, 9vw, 8rem);

    --ws-font: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

    --ws-ease: cubic-bezier(0.16, 1, 0.3, 1);

    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        /* Czerwień wypełnień zostaje bez zmian — biały tekst na #DC2326
           daje 4,9:1 niezależnie od tła strony. Zmienia się tylko czerwień
           używana jako tekst, bo marka na grafitowym tle daje 3,8:1. */
        --ws-red-text:   #FF5A5C;
        --ws-red-wash:   #2A1315;

        --ws-ink:        #F2F1ED;
        --ws-ink-2:      #C9C7C1;
        --ws-ink-3:      #A5A29B;

        --ws-paper:      #131312;
        --ws-card:       #1C1C1A;
        --ws-line:       #302F2D;
        --ws-line-2:     #3E3D3A;

        --ws-dark:       #0B0B0A;
        --ws-dark-line:  #262624;
    }
}

/* ══════════════════════════════════════════════════════
   RESET I PODSTAWY
   ══════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

body {
    margin: 0;
    background: var(--ws-paper);
    color: var(--ws-ink);
    font-family: var(--ws-font);
    font-size: 1.0625rem;
    line-height: 1.65;
    font-stretch: 100%;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: inherit; }

h1, h2, h3, h4 {
    margin: 0;
    font-weight: 800;
    font-stretch: 108%;
    line-height: 1.06;
    letter-spacing: -0.022em;
    text-wrap: balance;
}

p { margin: 0; }

ul, ol { margin: 0; padding: 0; list-style: none; }

:focus-visible {
    outline: 3px solid var(--ws-red);
    outline-offset: 3px;
    border-radius: 4px;
}

::selection { background: var(--ws-red); color: #fff; }

.ws-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--ws-red);
    color: #fff;
    padding: .75rem 1.25rem;
    border-radius: 0 0 var(--ws-r) 0;
    font-weight: 700;
}
.ws-skip:focus { left: 0; }

.ws-sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ══════════════════════════════════════════════════════
   SIATKA
   ══════════════════════════════════════════════════════ */
.ws-wrap {
    width: 100%;
    max-width: var(--ws-max);
    margin-inline: auto;
    padding-inline: var(--ws-gut);
}

.ws-sekcja { padding-block: var(--ws-sekcja); }

.ws-naglowek-sekcji {
    font-size: clamp(2rem, 4.4vw, 3.25rem);
    max-width: 20ch;
}

.ws-lead {
    color: var(--ws-ink-2);
    font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
    max-width: 58ch;
}

.ws-etykieta {
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ws-red-text);
    font-stretch: 100%;
}

/* ══════════════════════════════════════════════════════
   PRZYCISKI — kształt badge'a z logotypu
   ══════════════════════════════════════════════════════ */
.ws-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    min-height: 3rem;
    padding: .8rem 1.6rem;
    border: 2px solid transparent;
    border-radius: var(--ws-r);
    font: inherit;
    font-weight: 700;
    font-stretch: 104%;
    letter-spacing: -.005em;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .18s var(--ws-ease),
                border-color .18s var(--ws-ease),
                color .18s var(--ws-ease),
                transform .12s var(--ws-ease);
}

/* Biały tekst na #DC2326 daje 4,9:1 — przechodzi AA także dla tekstu zwykłego. */
.ws-btn--pelny {
    background: var(--ws-red);
    border-color: var(--ws-red);
    color: #fff;
}
.ws-btn--pelny:hover { background: var(--ws-red-deep); border-color: var(--ws-red-deep); }

.ws-btn--obrys {
    background: transparent;
    border-color: var(--ws-line-2);
    color: var(--ws-ink);
}
.ws-btn--obrys:hover { border-color: var(--ws-ink); }

/* Wariant na ciemnym pasie — obrys musi mieć własny kontrast. */
.ws-btn--jasny {
    background: transparent;
    border-color: rgba(255,255,255,.35);
    color: #fff;
}
.ws-btn--jasny:hover { border-color: #fff; background: rgba(255,255,255,.08); }

/* Wariant na czerwonym bloku hero. Czerwony przycisk zniknalby w tle,
   wiec role sie odwracaja: bialy pelny, a obok bialy obrys.
   Czerwony tekst na bieli daje 4,9:1, czyli AA takze dla tekstu zwyklego. */
.ws-btn--bialy {
    background: #fff;
    border-color: #fff;
    color: var(--ws-red);
}
.ws-btn--bialy:hover { background: rgba(255,255,255,.88); border-color: rgba(255,255,255,.88); }

.ws-btn:active { transform: scale(.985); }

.ws-btn__ikona { width: 1.15em; height: 1.15em; flex: none; }

/* ══════════════════════════════════════════════════════
   NAGŁÓWEK
   ══════════════════════════════════════════════════════ */
.ws-header {
    position: sticky;
    top: 0;
    z-index: 40;
    background: color-mix(in srgb, var(--ws-paper) 88%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--ws-line);
}

@supports not (backdrop-filter: blur(1px)) {
    .ws-header { background: var(--ws-paper); }
}

/* Na stronie glownej pasek lezy na czerwonym bloku hero i jest wtedy
   przezroczysty, a jego tresc biala. Po minieciu hero wraca zwykly,
   papierowy pasek. Klase zdejmuje obserwator punktu kontrolnego
   z motyw.js, nie nasluch na zdarzenie scroll.

   Reguly sa zagniezdzone w .js celowo: bez JavaScriptu klasa zostaje
   w markupie na zawsze, a bialy tekst na papierze bylby nieczytelny.
   Brak skryptu daje wiec po prostu zwykly, jasny pasek. */
.js .ws-header--na-hero {
    background: transparent;
    backdrop-filter: none;
    border-bottom-color: transparent;
}
.js .ws-header--na-hero .ws-logo__tekst { color: #fff; }
.js .ws-header--na-hero .ws-logo__badge { background: #fff; color: var(--ws-red); }
.js .ws-header--na-hero .ws-logo__tld   { color: rgba(255,255,255,.72); }
.js .ws-header--na-hero .ws-nav__lista a { color: rgba(255,255,255,.88); }
.js .ws-header--na-hero .ws-nav__lista a:hover,
.js .ws-header--na-hero .ws-nav__lista .current-menu-item > a {
    color: #fff;
    border-bottom-color: #fff;
}
.js .ws-header--na-hero .ws-header__tel { background: #fff; color: var(--ws-red); }
.js .ws-header--na-hero .ws-header__tel:hover { background: rgba(255,255,255,.88); }
/* Na czerwieni wypelnienie jest biale polprzezroczyste, a nie pelne:
   pelna biel konkurowalaby z przyciskiem telefonu, ktory na otwarciu
   wlasnie taka sie staje. */
.js .ws-header--na-hero .ws-burger {
    background: rgba(255,255,255,.18);
    border-color: transparent;
    color: #fff;
}

/* Scrim pod paskiem, wlaczony przez cala sekcje hero.

   Bez niego tresc przewijajaca sie pod przezroczystym paskiem wchodzila mu
   w tresc: bialy wysiegnik koparki znikal pod bialym menu. Plaskie tlo
   rozwiazywaloby to samo, ale konczyloby sie ostro na dolnej granicy paska
   i rysowalo krawedz przez cala szerokosc okna. Gradient wygasajacy do zera
   nie ma gdzie takiej krawedzi utworzyc.

   Kolor to marka przyciemniona ponizej dolu gradientu hero (#C02026),
   wiec pasek czyta sie jako cien wlasnej sekcji, a nie obcy kolor. Na
   wysokosci tekstu nawigacji krycie wynosi okolo 0,75, co daje bieli
   7,7:1 na czerwieni i 5,7:1 w najgorszym przypadku, czyli gdy pod paskiem
   przejezdza bialy wysiegnik.

   Warstwa siedzi na samym .ws-header z kryciem zero, a nie dopiero na
   wariancie --na-hero. Dzieki temu wyjscie z hero tez sie przenika, zamiast
   gasnac skokowo w chwili, gdy regula przestaje pasowac. */
.js .ws-header::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 190%;
    z-index: -1;
    opacity: 0;
    pointer-events: none;
    background: linear-gradient(
        to bottom,
        rgba(138, 20, 24, .88) 0%,
        rgba(138, 20, 24, .66) 44%,
        rgba(138, 20, 24, .22) 76%,
        rgba(138, 20, 24, 0) 100%
    );
}

.js .ws-header--na-hero::after { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
    .js .ws-header::after { transition: opacity .3s var(--ws-ease); }
}

@media (prefers-reduced-motion: no-preference) {
    .js .ws-header { transition: background-color .25s var(--ws-ease), border-color .25s var(--ws-ease); }
}

.ws-header__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    height: var(--ws-pasek);
}

.ws-logo { display: flex; align-items: center; flex: none; }
.ws-logo img { height: 2.25rem; width: auto; }

/* Logotyp tekstowy — używany, gdy w Kokpicie nie wgrano pliku.
   Odwzorowuje znak: „Wykop" + biały „Sam" na czerwonym badge'u + „.pl". */
.ws-logo__tekst {
    font-weight: 800;
    font-stretch: 112%;
    font-size: 1.375rem;
    letter-spacing: -.03em;
    text-decoration: none;
    display: flex;
    align-items: baseline;
    gap: .12em;
}
.ws-logo__badge {
    background: var(--ws-red);
    color: #fff;
    padding: .04em .28em .1em;
    border-radius: .3em;
}
.ws-logo__tld { color: var(--ws-ink-3); }

.ws-nav { display: flex; align-items: center; gap: 1.75rem; }

.ws-nav__lista { display: flex; align-items: center; gap: 1.5rem; }

.ws-nav__lista a {
    text-decoration: none;
    font-size: .9375rem;
    font-weight: 600;
    color: var(--ws-ink-2);
    padding-block: .35rem;
    border-bottom: 2px solid transparent;
    transition: color .16s var(--ws-ease), border-color .16s var(--ws-ease);
}
.ws-nav__lista a:hover,
.ws-nav__lista .current-menu-item > a {
    color: var(--ws-ink);
    border-bottom-color: var(--ws-red);
}

.ws-header__tel {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    background: var(--ws-red);
    color: #fff;
    text-decoration: none;
    font-weight: 700;
    font-size: .9375rem;
    padding: .6rem 1.05rem;
    border-radius: var(--ws-r-sm);
    transition: background-color .18s var(--ws-ease);
}
.ws-header__tel:hover { background: var(--ws-red-deep); }

/* 2,75rem to 44 px, czyli dolna granica wygodnego celu dotyku i ta sama
   wartosc co przycisk telefonu obok. Nie rozjezdzaj ich: dwa przyciski
   tej samej rangi, stojace obok siebie, w dwoch rozmiarach czytaja sie
   jak blad, a nie jak hierarchia. */
.ws-burger {
    display: none;
    width: 2.75rem; height: 2.75rem;
    align-items: center;
    justify-content: center;
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-sm);
    color: var(--ws-ink);
    cursor: pointer;
    padding: 0;
}
.ws-burger svg { width: 1.25rem; height: 1.25rem; }

@media (max-width: 979px) {
    .ws-nav__lista { display: none; }
    .ws-burger { display: inline-flex; }
    .ws-header__tel span { display: none; }

    /* Kwadrat o tym samym boku co hamburger. Wczesniej padding dawal
       41 na 36 px, czyli prostokat mniejszy od sasiada i ponizej progu
       wygodnego dotyku w obu wymiarach. */
    .ws-header__tel {
        width: 2.75rem;
        height: 2.75rem;
        padding: 0;
        justify-content: center;
        gap: 0;
    }
    .ws-header__tel .ws-btn__ikona { width: 1.25rem; height: 1.25rem; }
}

/* Menu mobilne — panel rozwijany pod paskiem, bez position: fixed,
   żeby nie walczyć z paskiem adresu na iOS. */
.ws-menu-mobilne {
    display: none;
    border-top: 1px solid var(--ws-line);
    background: var(--ws-card);
}
.ws-menu-mobilne[data-otwarte="1"] { display: block; }
.ws-menu-mobilne ul { padding: .5rem 0 1rem; }
.ws-menu-mobilne a {
    display: block;
    padding: .85rem var(--ws-gut);
    text-decoration: none;
    font-weight: 600;
    border-bottom: 1px solid var(--ws-line);
}

/* ═════════════════════════════════════════════════════
   HERO — czerwony blok

   Badge „Sam" z logotypu rozciagniety na cala szerokosc strony: ten sam
   pionowy gradient (#E22525 do #C02026), ta sama biel na wierzchu.
   Maszyna wychodzi poza dolna krawedz bloku.

   To najglosniejszy element serwisu, wiec wszystko pod nim wraca na
   papier. Jesli kiedys pojawi sie druga tak mocna sekcja, ta przestanie
   dzialac — sila tego bloku bierze sie z tego, ze jest jeden.
   ═════════════════════════════════════════════════════ */
.ws-hero {
    position: relative;
    background: linear-gradient(180deg, #E22525 0%, #C02026 100%);
    color: #fff;
    overflow: hidden;

    /* Pasek nawigacji stoi w normalnym przeplywie, wiec hero podsuwamy
       pod niego i oddajemy te wysokosc jako gorny padding. Dzieki temu
       czerwien zaczyna sie od samej gory okna, a pasek dalej sie klei. */
    margin-top: calc(var(--ws-pasek-calk) * -1);
    padding-top: var(--ws-pasek-calk);

    /* Wlasne widelki wysokosci. Bez nich o wielkosci bloku decydowalaby
       sama wycinka, wiec na niskim laptopie hero bylo o jedna trzecia
       nizsze niz na duzym monitorze. Podloga 38rem trzyma obecnosc na
       malych ekranach, sufit 54rem nie pozwala blokowi urosnac ponad
       to, co czlowiek obejmie wzrokiem. */
    min-height: clamp(42rem, 92vh, 60rem);
    display: flex;
    flex-direction: column;
}

.ws-hero__grid {
    flex: 1;
    display: grid;

    /* Siatka hero jest szersza niz --ws-max, ktore obowiazuje w sekcjach
       tekstowych. Tam o szerokosci decyduje dlugosc wiersza; tutaj mamy
       naglowek na dwa wiersze i zdjecie, wiec ciasna ramka tylko dusi
       maszyne. Szersza ramka daje kolumnie obrazka okolo 140 px wiecej,
       a kolumnie tekstowej nic nie zabiera. */
    max-width: 1480px;

    /* Kolumna maszyny jest szersza od tekstowej. Przy wyzszym bloku
       wycinka musi urosnac razem z nim, inaczej tonie w czerwieni. */
    grid-template-columns: 1.02fr 1.18fr;
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: stretch;
    /* Mniej u gory, bo tekst i tak jest wysrodkowany w pionie. Odzyskany
       zapas idzie pod maszyne, zeby lyzka nie wisiala na krawedzi bloku. */
    padding-top: clamp(1.5rem, 3vw, 2.5rem);
}

/* Tekst siedzi w pionie na srodku wolnej przestrzeni, maszyna zostaje
   przy dolnej krawedzi. Przy jednym wspolnym align-items to niemozliwe,
   stad osobny pojemnik na kolumne tekstowa. */
.ws-hero__tresc {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
    min-width: 0;
}

.ws-hero__tytul {
    /* 52 px to gorna granica, przy ktorej "Wynajmij maszyne." wchodzi
       w jeden wiersz w kolumnie tekstowej. Wieksza skala lamie naglowek
       na trzy wiersze i rozpycha hero w pionie. */
    font-size: clamp(2rem, 3.7vw, 3.25rem);
    max-width: 18ch;
    color: #fff;
}

.ws-hero__tekst {
    margin-top: 1.15rem;
    color: rgba(255,255,255,.9);
    font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
    max-width: 40ch;
}

.ws-hero__cta {
    margin-top: 1.85rem;
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
}

.ws-hero__liczby {
    margin-top: 2.25rem;
    padding-top: 1.35rem;
    border-top: 1px solid rgba(255,255,255,.32);
    display: flex;
    flex-wrap: wrap;
    gap: 2.25rem;
}
.ws-hero__liczba b {
    display: block;
    font-size: 1.625rem;
    font-weight: 800;
    font-stretch: 106%;
    letter-spacing: -.02em;
    color: #fff;
}
.ws-hero__liczba span {
    display: block;
    margin-top: .1rem;
    font-size: .875rem;
    color: rgba(255,255,255,.78);
}

/* Wycinka stoi nad dolna krawedzia bloku, nie na niej.

   Pierwotnie maszyna wychodzila poza krawedz, ale w tym kadrze najnizszym
   punktem jest lyzka, a nie podwozie: gasienice zostawaly wysoko, lyzka
   wisiala na samej krawedzi i calosc wygladala, jakby maszyna spadala
   z bloku. Odstep u dolu ustawia caly pojazd nad linia ciecia.

   Cien rysuje CSS, bo w pliku zrodlowym go juz nie ma. */
.ws-hero__maszyna {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: clamp(2.5rem, 5vw, 4.5rem);
    min-width: 0;
}
.ws-hero__maszyna img {
    width: 100%;
    /* Sufit zwiazany wylacznie z wysokoscia okna. Bez niego o wysokosci
       hero decydowal obrazek i na laptopie 1366 x 720 blok wychodzil
       na 109% okna.

       Celowo bez min(100%, ...): procent odnosi sie tu do wiersza siatki
       o nieokreslonej wysokosci, wiec obrazek najpierw rozpychal wiersz
       do swojej naturalnej wysokosci, a dopiero potem sam sie kurczyl.
       Wiersz zostawal wysoki i cala sztuczka nie dzialala. */
    /* 78vh to punkt, w ktorym przy proporcji obecnej wycinki (0,99)
       o wielkosci decyduje juz szerokosc kolumny, a nie wysokosc okna.
       Wyzej nic nie zyskamy, bo obrazek i tak oprze sie o szerokosc. */
    max-height: 78vh;
    object-fit: contain;
    object-position: bottom center;
    filter: drop-shadow(0 26px 44px rgba(0,0,0,.3));
}

/* Punkt kontrolny dla paska nawigacji: zero wysokosci, zero wplywu na
   uklad. Stoi na koncu sekcji i mowi, kiedy czerwien sie skonczyla. */
.ws-hero__wartownik {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

@media (max-width: 899px) {
    /* Stos jest wysoki sam z siebie, wiec widelki tylko by przeszkadzaly. */
    .ws-hero { min-height: 0; }
    .ws-hero__grid { grid-template-columns: 1fr; }
    .ws-hero__tresc { padding-bottom: 1.5rem; }
    .ws-hero__liczby { gap: 1.5rem; }
    .ws-hero__maszyna {
        width: 100%;
        max-width: 30rem;
        margin-inline: auto;
    }
}

/* Laptopy o niskim ekranie. Na szerokosc to pelnoprawny desktop, ale
   przy 720 px wysokosci blok wychodzil na 103% okna i nie bylo widac,
   ze strona ma ciag dalszy. Ograniczenie idzie po wysokosci okna,
   bo to ona jest tu waskim gardlem, nie szerokosc. */
/* Zapas nad tytulem na telefonie. Kompensacje paska ustawia skrypt,
   ale bez JavaScriptu zostaje wartosc domyslna, wiec tytul potrzebuje
   wlasnego marginesu, ktory nie zalezy od niczego innego. */
@media (max-width: 767px) {
    .ws-hero__grid { padding-top: 2rem; }
}

@media (min-width: 900px) and (max-height: 800px) {
    .ws-hero__grid { padding-top: 1.25rem; }
    .ws-hero__maszyna img { max-height: 75vh; }
}

/* Na telefonie hero jest stosem: naglowek, akapit, przyciski, liczby,
   maszyna. Przyciski musza zmiescic sie w 812 px pomniejszonym o pasek
   gorny i o dolny pasek akcji, dlatego maszyna idzie na sam dol. */
@media (max-width: 479px) {
    .ws-hero__grid { padding-top: 1.75rem; }
    .ws-hero__tytul { font-size: 2rem; }
    .ws-hero__tekst { margin-top: 1rem; font-size: 1rem; }
    .ws-hero__cta { margin-top: 1.5rem; }
    .ws-hero__cta .ws-btn { flex: 1; }
    .ws-hero__liczby { margin-top: 1.75rem; padding-top: 1.15rem; gap: 1.25rem 2rem; }
    .ws-hero__maszyna { max-width: 20rem; }
}

/* ═════════════════════════════════════════════════════
   PARK MASZYN — kafle z wycinkami na czerwieni

   Jeden komponent na maszyne, uzywany i w sekcji na stronie glownej,
   i w "Reszcie parku" na podstronach. Wczesniej byly dwa warianty karty
   o innej budowie i ta sama maszyna wygladala inaczej w dwoch miejscach.

   Czerwone pole pod wycinka to ten sam gradient co w hero i w logotypie,
   wiec sekcja czyta sie jako ciag dalszy pierwszego ekranu.
   ═════════════════════════════════════════════════════ */
.ws-maszyny__naglowek {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 2rem;
    flex-wrap: wrap;
    margin-bottom: 2.5rem;
}

.ws-kafle {
    display: grid;
    /* minmax(0,1fr), a nie 1fr: domyslne min-width:auto pozwoliloby
       dlugiej nazwie maszyny rozepchnac kolumne ponad rowny podzial. */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
}

/* Na podstronach maszyn pokazujemy trzy pozostale, nie cztery. */
.ws-kafle--trzy { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.ws-kafel {
    display: flex;
    flex-direction: column;
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-lg);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: border-color .2s var(--ws-ease), transform .2s var(--ws-ease);
}
.ws-kafel:hover { border-color: var(--ws-line-2); transform: translateY(-3px); }

.ws-kafel__pole {
    position: relative;
    aspect-ratio: 1 / 1;
    background: linear-gradient(180deg, #E22525 0%, #C02026 100%);
    padding: clamp(.7rem, 2vw, 1rem);
    overflow: hidden;
}
.ws-kafel__pole img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: bottom center;
    filter: drop-shadow(0 10px 18px rgba(0,0,0,.24));
    transition: transform .4s var(--ws-ease);
}
.ws-kafel:hover .ws-kafel__pole img { transform: translateY(-4px); }

/* Plakietka jest biala, nie czerwona: na czerwonym polu czerwona
   plakietka bylaby niewidoczna. Czerwien na bieli daje 4,9:1. */
.ws-kafel__plakietka {
    position: absolute;
    top: .7rem;
    left: .7rem;
    background: #fff;
    color: var(--ws-red);
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .01em;
    padding: .25rem .55rem;
    border-radius: 7px;
}

.ws-kafel__tresc {
    padding: 1rem 1.1rem 1.15rem;
    display: flex;
    flex-direction: column;
    gap: .2rem;
    flex: 1;
}
.ws-kafel__nazwa {
    font-size: 1.0625rem;
    letter-spacing: -.015em;
}
.ws-kafel__opis {
    font-size: .8438rem;
    color: var(--ws-ink-3);
}

.ws-kafel__stopka {
    margin-top: auto;
    padding-top: .9rem;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
}
.ws-kafel__cena {
    font-size: 1.375rem;
    font-weight: 800;
    font-stretch: 104%;
    letter-spacing: -.02em;
    white-space: nowrap;
}
.ws-kafel__cena span {
    font-weight: 400;
    font-size: .75rem;
    color: var(--ws-ink-3);
}
.ws-kafel__wiecej {
    font-weight: 700;
    font-size: .875rem;
    color: var(--ws-red-text);
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}

@media (max-width: 1023px) {
    .ws-kafle,
    .ws-kafle--trzy { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 559px) {
    .ws-kafle,
    .ws-kafle--trzy { grid-template-columns: 1fr; }
    /* W jednej kolumnie kwadratowe pole zjadaloby caly ekran. */
    .ws-kafel__pole { aspect-ratio: 16 / 10; }
}

/* ══════════════════════════════════════════════════════
   PRZEBIEG NAJMU — jedyny ciemny pas na stronie.
   Świadomy blok koloru, nie przypadkowa inwersja sekcji.
   ══════════════════════════════════════════════════════ */
.ws-przebieg {
    background: var(--ws-dark);
    color: var(--ws-dark-ink);
}
.ws-przebieg h2 { color: #fff; }

/* Os czasu, w ktorej wezlami sa cyfry.

   Linia biegnie przez srodek wysokosci numeru, a kazda cyfra ma wlasne
   ciemne tlo i odstep z prawej, wiec wycina w linii przerwe dokladnie tam,
   gdzie stoi. Dzieki temu nie trzeba osobnych kropek ani liczenia pozycji:
   numer JEST wezlem. Zmiana stopnia pisma cyfry wymaga korekty --wezel. */
.ws-przebieg__siatka {
    --wezel: 1.5rem;

    margin-top: 3rem;
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 2rem 1.75rem;
}
/* Os jest osobnym elementem, nie pseudoelementem: przegladarka nie
   uruchamia przejscia transform na ::before w tym miejscu, sprawdzone
   przez document.getAnimations(). Bez animacji pseudoelement wystarczal. */
.ws-przebieg__linia {
    position: absolute;
    left: 0;
    right: 0;
    top: var(--wezel);
    height: 2px;
    background: var(--ws-dark-line);
    transform-origin: left center;
}

.ws-przebieg__krok { position: relative; }

/* Wariant bez konturu jest tu wartoscia domyslna, nie awaryjna:
   -webkit-text-stroke to wlasciwosc niestandardowa, a cyfra z samym
   color: transparent i bez dzialajacego konturu znika calkowicie.
   Pelna cyfra jest wiec punktem wyjscia, kontur tylko ja nadpisuje. */
.ws-przebieg__cyfra {
    position: relative;
    display: inline-block;
    background: var(--ws-dark);
    padding-right: .8rem;
    font-size: 3rem;
    font-weight: 800;
    font-stretch: 104%;
    line-height: 1;
    letter-spacing: -.04em;
    color: #fff;
}
.ws-przebieg__zero { color: var(--ws-red); }

@supports (-webkit-text-stroke: 2px #fff) {
    .ws-przebieg__cyfra {
        color: transparent;
        -webkit-text-stroke: 2px #fff;
    }
    /* Zero potrzebuje wlasnego color: transparent. Dziedziczenie tu nie
       zadziala, bo regula awaryjna nadaje mu wlasny kolor wypelnienia,
       a wlasnosc bije dziedziczenie. Bez tego zero wychodzi pelne. */
    .ws-przebieg__zero {
        color: transparent;
        -webkit-text-stroke: 2px var(--ws-red);
    }
}

.ws-przebieg__kiedy {
    margin-top: 1.1rem;
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ws-red-text);
    font-stretch: 100%;
}

.ws-przebieg__krok h3 {
    margin-top: .45rem;
    font-size: 1.3125rem;
    color: #fff;
}
.ws-przebieg__krok p {
    margin-top: .45rem;
    color: var(--ws-dark-ink-2);
    font-size: .9375rem;
    line-height: 1.6;
}

.ws-przebieg__stopka {
    margin-top: 3.25rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--ws-dark-line);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem 2rem;
}
.ws-przebieg__stopka p { color: var(--ws-dark-ink-2); font-size: .9688rem; }

@media (max-width: 899px) {
    .ws-przebieg__siatka { grid-template-columns: 1fr 1fr; }
    /* Przy zawijaniu do dwoch rzedow jedna pozioma linia laczylaby kroki,
       ktore ze soba nie sasiaduja, wiec os znika. */
    .ws-przebieg__linia { display: none; }
}
@media (max-width: 519px) { .ws-przebieg__siatka { grid-template-columns: 1fr; } }

/* ══════════════════════════════════════════════════════
   USŁUGI Z OPERATOREM — stawka po lewej, roboty w kaflach

   Cała waga sekcji leży na dwóch liczbach. Stawka godzinowa dostaje
   największy stopień pisma i zostaje w polu widzenia przez całe
   przewijanie listy, bo lewa kolumna jest przyklejona. Siedem robót
   siedzi w białych kaflach z obrysem włosowym: ten sam promień 22 px
   i ta sama krawędź co karty w parku maszyn, więc obie sekcje czytają
   się jako jedna rodzina.

   Nie zamieniaj obrysu na sam cień. Biel i papier dzielą cztery punkty
   jasności; bez kreski kafel gubi krawędź w druku i na tanich matrycach,
   a cień byłby jedynym takim sposobem rysowania krawędzi w całym motywie.
   ══════════════════════════════════════════════════════ */
.ws-uslugi__grid {
    display: grid;
    grid-template-columns: .92fr 1.32fr;
    gap: clamp(2rem, 5vw, 4.5rem);
    align-items: start;
}

/* Panel ze stawka jest wysrodkowany w pionie wzgledem kolumny kafli.
   Wczesniej byl przyklejony do gornej krawedzi okna; przyklejenie
   i wysrodkowanie wykluczaja sie, bo sticky liczy pozycje od gory
   obszaru siatki, a nie od jego srodka. Wybrane wysrodkowanie. */
.ws-uslugi__intro { align-self: center; }

/* Otwarcie podstrony uslug. Stawka stoi obok naglowka, nie pod nim:
   to najczestsze pytanie tego wejscia. Kolumna z cena jest wezsza,
   bo trzyma dwie liczby, a nie tekst. */
.ws-uslugi-hero {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
}
.ws-uslugi-hero .ws-uslugi__cennik { margin-top: 0; }

@media (max-width: 899px) { .ws-uslugi-hero { grid-template-columns: 1fr; } }

.ws-uslugi__cennik {
    margin-top: 2rem;
    display: grid;
    gap: 1rem;
}
.ws-uslugi__stawka .ws-uslugi__co {
    display: block;
    font-size: .9375rem;
    color: var(--ws-ink-2);
}

/* Czerwień jako tekst, nie jako wypełnienie: --ws-red-text jaśnieje
   w trybie ciemnym, sama --ws-red dawałaby na grafitowym kaflu 3,8:1. */
.ws-uslugi__liczba {
    margin-top: .35rem;
    display: flex;
    align-items: baseline;
    gap: .4rem;
    font-weight: 800;
    font-stretch: 104%;
    line-height: .9;
    letter-spacing: -.04em;
}
.ws-uslugi__liczba b { font-size: 3.25rem; color: var(--ws-red-text); }
.ws-uslugi__jedn {
    font-size: 1rem;
    font-weight: 700;
    color: var(--ws-ink-2);
    letter-spacing: 0;
}
.ws-uslugi__od {
    font-size: 1rem;
    font-weight: 700;
    color: var(--ws-ink-3);
    letter-spacing: 0;
    align-self: center;
}

/* Odnosnik glebiej w serwis, nie przycisk konwersji. Ma wyglad
   odnosnika, bo przycisk stawialby go na rowni z para Zadzwon i Wycena,
   ktora w tej sekcji celowo nie wystepuje. */
.ws-uslugi__wiecej {
    margin-top: 1.75rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--ws-line);
}
.ws-uslugi__wiecej a {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-weight: 700;
    font-size: .9688rem;
    color: var(--ws-red-text);
    text-decoration: none;
}
.ws-uslugi__wiecej a:hover { text-decoration: underline; text-underline-offset: .18em; }
.ws-uslugi__strzalka {
    width: 1.1em;
    height: 1.1em;
    flex: none;
}
@media (prefers-reduced-motion: no-preference) {
    .ws-uslugi__strzalka { transition: transform .18s var(--ws-ease); }
    .ws-uslugi__wiecej a:hover .ws-uslugi__strzalka { transform: translateX(3px); }
}

.ws-uslugi__kafle {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}
.ws-uslugi__kafle li {
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-lg);
    padding: 1.4rem 1.3rem 1.5rem;
}
/* Najczęściej zamawiana robota bierze oba pola i dostaje czerwoną kreskę.
   Nad każdym kaflem kreska przestałaby cokolwiek wyróżniać. */
.ws-uslugi__kafle li:first-child { grid-column: 1 / -1; }
.ws-uslugi__kafle li:first-child::before {
    content: "";
    display: block;
    width: 2.25rem;
    height: 3px;
    background: var(--ws-red);
    border-radius: 2px;
    margin-bottom: 1rem;
}
.ws-uslugi__kafle li:first-child h3 { font-size: 1.3125rem; }
.ws-uslugi__kafle h3 { font-size: 1.0625rem; letter-spacing: -.01em; }
.ws-uslugi__kafle p {
    margin-top: .45rem;
    color: var(--ws-ink-2);
    font-size: .9375rem;
    line-height: 1.55;
}

@media (max-width: 899px) {
    .ws-uslugi__grid { grid-template-columns: 1fr; }
    .ws-uslugi__intro { align-self: start; }
}
@media (max-width: 599px) {
    .ws-uslugi__kafle { grid-template-columns: 1fr; }
    .ws-uslugi__kafle li:first-child { grid-column: auto; }
}

/* ══════════════════════════════════════════════════════
   CENNIK W SKRÓCIE + PYTANIA
   ══════════════════════════════════════════════════════ */
/* Cennik nad pytaniami.

   Trzy kafle z pojedynczymi liczbami ustąpiły miejsca tabeli, bo sekcja
   nazywa się cennikiem, a nie pokazywała ani jednej ceny za dobę. Pierwsze
   pytanie z listy brzmi „ile kosztuje wynajem minikoparki", więc odpowiedź
   pada, zanim ktokolwiek zdąży kliknąć w rozwijane pytanie.

   Nazwa maszyny może się zawijać, liczby nie. Przy 375 px zostaje na kolumnę
   nazwy około 150 px, czyli dwa wiersze, i tabela mieści się bez przewijania
   w poziomie. Jeśli dojdzie piąta kolumna, owiń tabelę w element
   z overflow-x: auto, bo wtedy przestanie się mieścić. */
.ws-cennik-tabela {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 1rem;
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-lg);
    overflow: hidden;
}
.ws-cennik-tabela caption {
    text-align: left;
    padding: 1.25rem 1.5rem .75rem;
    font-weight: 800;
    font-size: 1.0625rem;
}
.ws-cennik-tabela th,
.ws-cennik-tabela td {
    text-align: left;
    padding: .85rem 1.5rem;
    border-top: 1px solid var(--ws-line);
}
.ws-cennik-tabela thead th {
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ws-ink-3);
    font-stretch: 100%;
}
.ws-cennik-tabela tbody th { font-weight: 700; font-size: 1rem; }
.ws-cennik-tabela td { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ws-cennik-tabela__cena { font-weight: 800; font-size: 1.125rem; }
.ws-cennik-tabela__brak { color: var(--ws-ink-3); }

.ws-cennik-uwaga {
    margin-bottom: 2.5rem;
    color: var(--ws-ink-3);
    font-size: .875rem;
    line-height: 1.55;
}

@media (max-width: 599px) {
    .ws-cennik-tabela caption { padding-inline: 1rem; }
    .ws-cennik-tabela th,
    .ws-cennik-tabela td { padding-inline: 1rem; }
}

.ws-faq { max-width: 62rem; }

.ws-faq__poz {
    border-top: 1px solid var(--ws-line);
}
.ws-faq__poz:last-child { border-bottom: 1px solid var(--ws-line); }

.ws-faq__poz summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 1.35rem 0;
    cursor: pointer;
    list-style: none;
    font-weight: 700;
    font-size: clamp(1.0625rem, 1.8vw, 1.1875rem);
    font-stretch: 104%;
}
.ws-faq__poz summary::-webkit-details-marker { display: none; }

.ws-faq__znak {
    flex: none;
    width: 1.75rem; height: 1.75rem;
    border: 1px solid var(--ws-line-2);
    border-radius: 50%;
    display: grid;
    place-items: center;
    color: var(--ws-red-text);
    transition: transform .22s var(--ws-ease), border-color .22s var(--ws-ease);
}
.ws-faq__poz[open] .ws-faq__znak { transform: rotate(45deg); border-color: var(--ws-red); }

.ws-faq__odp {
    padding: 0 0 1.5rem;
    color: var(--ws-ink-2);
    max-width: 68ch;
}

/* ══════════════════════════════════════════════════════
   ZASIĘG — czarna karta na jasnej sekcji, obok własna mapa

   Karta jest tu jedynym miejscem, gdzie czerń wchodzi na jasną stronę
   poza pasem przebiegu najmu. To karta, nie pas, więc zasada jednego
   ciemnego pasa zostaje nienaruszona.

   Obie kolumny rozciągają się do tej samej wysokości. Bez tego mapa
   pływała w swojej połowie jako mały prostokąt, a karta kończyła się
   wyżej i sekcja rozjeżdżała się w pionie.
   ══════════════════════════════════════════════════════ */
.ws-zasieg__grid {
    display: grid;
    grid-template-columns: .88fr 1.28fr;
    gap: 1.25rem;
    align-items: stretch;
}

.ws-zasieg__karta {
    background: var(--ws-dark);
    color: var(--ws-dark-ink);
    border-radius: var(--ws-r-lg);
    padding: clamp(1.75rem, 3vw, 2.5rem);
    display: flex;
    flex-direction: column;
}
.ws-zasieg__karta .ws-naglowek-sekcji { color: #fff; max-width: 14ch; }
.ws-zasieg__karta .ws-lead { color: var(--ws-dark-ink-2); max-width: 40ch; }

.ws-zasieg__miasta {
    margin-top: 1.75rem;
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}
.ws-zasieg__miasta li {
    border: 1px solid var(--ws-dark-line);
    border-radius: 999px;
    padding: .4rem .95rem;
    font-size: .9375rem;
    font-weight: 600;
    color: var(--ws-dark-ink);
}
/* margin-top: auto dosuwa zdanie do dolnej krawedzi karty niezaleznie
   od tego, ile miejscowosci wpisano w panelu. */
.ws-zasieg__dopisek {
    margin-top: auto;
    padding-top: 1.75rem;
    color: var(--ws-dark-ink-2);
    font-size: .9375rem;
    max-width: 40ch;
}

.ws-zasieg__mapa {
    border-radius: var(--ws-r-lg);
    overflow: hidden;
    border: 1px solid var(--ws-line);
    background: var(--ws-card);
    min-height: 26rem;
}

/* preserveAspectRatio="slice" w SVG razem z height: 100% sprawia, że mapa
   wypełnia kolumnę i przycina się po bokach, zamiast zostawiać białe pasy.
   Treść rysunku trzyma się dlatego środka kadru. */
.ws-mapa-svg {
    display: block;
    width: 100%;
    height: 100%;
    font-family: var(--ws-font);
    font-weight: 700;
}
.m-woj path {
    fill: #EAE9E4;
    stroke: #C6C5BF;
    stroke-width: 1.1;
    stroke-linejoin: round;
}
.m-zasieg { fill: var(--ws-red); fill-opacity: .15; }
.m-ring {
    fill: none;
    stroke: var(--ws-red);
    stroke-width: 1.3;
    stroke-dasharray: 5 4.5;
    opacity: .75;
}
.m-kropka { fill: var(--ws-ink-2); }
.m-pin    { fill: var(--ws-red); }
.m-podpis { fill: var(--ws-ink-2); font-size: 4.6px; }
.m-podpis--glowny { fill: var(--ws-ink); font-size: 6.2px; }

@media (max-width: 899px) {
    .ws-zasieg__grid { grid-template-columns: 1fr; }
    .ws-zasieg__mapa { min-height: 20rem; }
}

/* ══════════════════════════════════════════════════════
   KONTAKT — telefon i formularz o równej wadze
   ══════════════════════════════════════════════════════ */
.ws-kontakt__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.25rem;
    align-items: stretch;
}

.ws-kontakt__tel {
    background: var(--ws-red);
    color: #fff;
    border-radius: var(--ws-r-lg);
    padding: clamp(1.75rem, 4vw, 2.75rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    overflow: hidden;
}
.ws-kontakt__tel::before {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(180deg, #E22525 0%, #C02026 100%);
}
.ws-kontakt__tel > * { position: relative; }

.ws-kontakt__tel p { color: rgba(255,255,255,.86); font-size: .9375rem; }

.ws-kontakt__numer {
    display: inline-block;
    margin: .5rem 0 .75rem;
    font-size: clamp(1.875rem, 4.6vw, 2.75rem);
    font-weight: 800;
    font-stretch: 108%;
    letter-spacing: -.03em;
    color: #fff;
    text-decoration: none;
    line-height: 1.1;
}
.ws-kontakt__numer:hover { text-decoration: underline; text-underline-offset: .12em; }

.ws-kontakt__mail {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid rgba(255,255,255,.28);
    font-size: .9375rem;
    color: rgba(255,255,255,.92);
}
.ws-kontakt__mail a { color: #fff; }

.ws-form {
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-lg);
    padding: clamp(1.5rem, 3.5vw, 2.25rem);
}

.ws-pole { display: grid; gap: .45rem; margin-bottom: 1.1rem; }

.ws-pole label {
    font-size: .875rem;
    font-weight: 700;
    color: var(--ws-ink);
}
.ws-pole__hint { font-size: .8125rem; color: var(--ws-ink-3); }

/* Kontrast: obramowanie --ws-line-2 i tekst --ws-ink na tle karty
   przechodzą AA; podpowiedź w polu jest tylko uzupełnieniem etykiety,
   nigdy jej nie zastępuje. */
.ws-pole input,
.ws-pole textarea,
.ws-pole select {
    width: 100%;
    font: inherit;
    font-size: 1rem;
    color: var(--ws-ink);
    background: var(--ws-paper);
    border: 1px solid var(--ws-line-2);
    border-radius: var(--ws-r-sm);
    padding: .8rem .95rem;
    min-height: 3rem;
    transition: border-color .16s var(--ws-ease), box-shadow .16s var(--ws-ease);
}
.ws-pole textarea { min-height: 7rem; resize: vertical; line-height: 1.55; }

.ws-pole input::placeholder,
.ws-pole textarea::placeholder { color: var(--ws-ink-3); }

.ws-pole input:focus,
.ws-pole textarea:focus,
.ws-pole select:focus {
    outline: none;
    border-color: var(--ws-red);
    box-shadow: 0 0 0 3px var(--ws-red-wash);
}

.ws-pole--blad input,
.ws-pole--blad textarea { border-color: var(--ws-red); }

.ws-pole__blad {
    font-size: .875rem;
    font-weight: 600;
    color: var(--ws-red-text);
}

.ws-zgoda {
    display: flex;
    gap: .7rem;
    align-items: flex-start;
    margin-bottom: 1.25rem;
    font-size: .875rem;
    color: var(--ws-ink-2);
    line-height: 1.5;
}
.ws-zgoda input {
    width: 1.25rem; height: 1.25rem;
    margin-top: .12rem;
    flex: none;
    accent-color: var(--ws-red);
}

/* Pułapka na boty. Ukryta przed człowiekiem i przed czytnikiem ekranu. */
.ws-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px; height: 1px;
    overflow: hidden;
}

.ws-komunikat {
    border-radius: var(--ws-r-sm);
    padding: .95rem 1.15rem;
    margin-bottom: 1.25rem;
    font-size: .9375rem;
    line-height: 1.55;
}
.ws-komunikat--ok {
    background: var(--ws-card);
    border: 1px solid var(--ws-line-2);
    border-top: 2px solid var(--ws-red);
    border-radius: 0;
}
.ws-komunikat--blad {
    background: var(--ws-red-wash);
    border: 1px solid var(--ws-red);
    color: var(--ws-ink);
}


@media (max-width: 899px) { .ws-kontakt__grid { grid-template-columns: 1fr; } }

/* ══════════════════════════════════════════════════════
   PODSTRONA MASZYNY
   ══════════════════════════════════════════════════════ */
.ws-sprzet__hero { padding-block: clamp(2rem, 4vw, 3.5rem) clamp(2.5rem, 5vw, 4rem); }

.ws-sprzet__grid {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    gap: clamp(2rem, 5vw, 3.5rem);
    align-items: center;
}

.ws-sprzet__tytul { font-size: clamp(2.125rem, 5vw, 3.5rem); }

.ws-sprzet__cena {
    margin-top: 2rem;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .5rem 1.5rem;
}
.ws-sprzet__cena b {
    font-size: clamp(2rem, 4.5vw, 2.75rem);
    font-weight: 800;
    font-stretch: 106%;
    letter-spacing: -.03em;
}
.ws-sprzet__cena span { color: var(--ws-ink-3); }

/* Pole jest kwadratowe, bo takie sa wycinki: 960x957, 758x836, 950x887
   i tylko laweta 952x744. Przy poziomym polu 4/3.2 o wielkosci maszyny
   decydowala wysokosc, a jedna trzecia szerokosci zostawala pusta.
   Zmierzone na TB 216V2 przy 1366 px: wycinka urosla z 366x365
   do 496x495, czyli o 84 procent powierzchni. Zadna z czterech maszyn
   na tej zmianie nie traci.

   Marginesu wewnetrznego nie zmniejszaj dalej. Wycinki maja rowna
   krawedz dolna i przy zerowym marginesie gasienice dotykaja krawedzi
   pola, przez co maszyna wyglada, jakby z niego spadala. */
.ws-sprzet__foto {
    background: var(--ws-red);
    border-radius: var(--ws-r-lg);
    aspect-ratio: 1 / 1;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: clamp(.75rem, 2vw, 1.25rem);
}
.ws-sprzet__foto::before {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(180deg, #E22525 0%, #C02026 100%);
}
.ws-sprzet__foto img {
    position: relative;
    width: 100%; max-height: 100%;
    object-fit: contain;
    object-position: bottom center;
}

/* Maszyny bez wycinki dostaja zwykle zdjecie wypelniajace kadr.
   Czerwone pole i wewnetrzny margines nie maja wtedy sensu. */
.ws-sprzet__foto--zdjecie { padding: 0; background: var(--ws-card); }
.ws-sprzet__foto--zdjecie::before { display: none; }
.ws-sprzet__foto--zdjecie img {
    width: 100%; height: 100%;
    max-height: none;
    object-fit: cover;
    object-position: center;
}

/* Galeria maszyny: siatka kafli, kazdy otwiera zdjecie w pelnym kadrze.

   Kadr 3:4, nie 21:9. Wszystkie zdjecia klienta sa pionowe, w proporcji
   od 0,61 do 0,75, a poziomy pas obcinal im od 68 do 74 procent wysokosci:
   zamiast maszyny zostawal poziomy pasek z jej srodka. Zmierzone przy
   kolumnie 1084 px. Jesli kiedys wejda tu zdjecia poziome, zmien proporcje,
   zamiast zostawiac pionowa i liczyc, ze sie ulozy.

   auto-fit z minmax sprawia, ze przy jednym zdjeciu siatka schodzi do
   jednego kafla i nie zostawia pustych komorek. Dzis kazda maszyna ma
   dokladnie jedno. */
.ws-galeria {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 1rem;
}
.ws-galeria__kafel {
    display: block;
    width: 100%;
    padding: 0;
    aspect-ratio: 3 / 4;
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r-lg);
    overflow: hidden;
    background: var(--ws-card);
    cursor: zoom-in;
}
.ws-galeria__kafel img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (prefers-reduced-motion: no-preference) {
    .ws-galeria__kafel img { transition: transform .35s var(--ws-ease); }
    .ws-galeria__kafel:hover img { transform: scale(1.04); }
}

/* Okno powiekszania. Zdjecie dostaje pelny kadr, bez przycinania:
   to jedyne miejsce, w ktorym pionowe zdjecie widac w calosci. */
.ws-lupa {
    border: 0;
    padding: 0;
    background: none;
    max-width: min(92vw, 60rem);
    max-height: 92vh;
}
.ws-lupa::backdrop { background: rgba(20, 20, 20, .88); }
.ws-lupa img {
    display: block;
    width: auto;
    max-width: 100%;
    max-height: 92vh;
    border-radius: var(--ws-r-lg);
}
.ws-lupa__zamknij {
    position: fixed;
    top: 1rem;
    right: 1rem;
    width: 2.75rem;
    height: 2.75rem;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .16);
    color: #fff;
    cursor: pointer;
}
.ws-lupa__zamknij:hover { background: rgba(255, 255, 255, .28); }
.ws-lupa__zamknij svg { width: 1.25rem; height: 1.25rem; }

.ws-parametry {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}
.ws-parametr {
    background: var(--ws-card);
    border: 1px solid var(--ws-line);
    border-radius: var(--ws-r);
    padding: 1.25rem 1.35rem;
}
.ws-parametr span { display: block; font-size: .875rem; color: var(--ws-ink-3); }
.ws-parametr b {
    display: block;
    margin-top: .3rem;
    font-size: 1.1875rem;
    font-weight: 800;
    letter-spacing: -.015em;
    line-height: 1.3;
}

.ws-atuty {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem 2.5rem;
}
.ws-atut { border-top: 2px solid var(--ws-red); padding-top: 1.15rem; }
.ws-atut h3 { font-size: 1.1875rem; }
.ws-atut p { margin-top: .5rem; color: var(--ws-ink-2); font-size: .9688rem; line-height: 1.6; }

.ws-warunki__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(1.5rem, 4vw, 3rem);
}
.ws-warunki h3 { font-size: 1.1875rem; margin-bottom: 1rem; }
.ws-warunki li {
    padding: .7rem 0 .7rem 1.75rem;
    border-top: 1px solid var(--ws-line);
    position: relative;
    color: var(--ws-ink-2);
}
.ws-warunki li::before {
    content: "";
    position: absolute;
    left: 0; top: 1.35rem;
    width: .625rem; height: .625rem;
    border-radius: 2px;
    background: var(--ws-red);
}

@media (max-width: 899px) {
    .ws-sprzet__grid { grid-template-columns: 1fr; }
    /* Kwadrat takze tutaj. Poziome pole 16/10 przy 335 px
       zbijalo wycinke do 169 px wysokosci. */
    .ws-sprzet__foto { order: -1; aspect-ratio: 1 / 1; }
    .ws-parametry { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 599px) {
    .ws-parametry,
    .ws-atuty,
    .ws-warunki__grid { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════
   STRONA TREŚCI (polityka prywatności, 404, wpisy)
   ══════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════
   404
   ══════════════════════════════════════════════════════ */
.ws-404 {
    display: grid;
    grid-template-columns: 1.15fr .85fr;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: start;
}
.ws-404 h1 { max-width: 14ch; }
.ws-404 .ws-lead { max-width: 42ch; }

.ws-404__spis h2 {
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ws-ink-3);
    font-stretch: 100%;
    margin-bottom: .5rem;
}
.ws-404__spis li { border-bottom: 1px solid var(--ws-line); }
.ws-404__spis a {
    display: block;
    padding: .85rem 0;
    color: var(--ws-ink);
    font-weight: 700;
    text-decoration: none;
}
.ws-404__spis a:hover { color: var(--ws-red-text); }

@media (max-width: 767px) { .ws-404 { grid-template-columns: 1fr; } }

.ws-tresc { max-width: 44rem; }
.ws-tresc h1 { font-size: clamp(2rem, 4.5vw, 3rem); margin-bottom: 1.5rem; }
.ws-tresc h2 { font-size: 1.5rem; margin: 2.5rem 0 .85rem; }
.ws-tresc h3 { font-size: 1.1875rem; margin: 2rem 0 .65rem; }
.ws-tresc p,
.ws-tresc ul,
.ws-tresc ol { margin-bottom: 1.15rem; color: var(--ws-ink-2); }
.ws-tresc ul { list-style: disc; padding-left: 1.25rem; }
.ws-tresc ol { list-style: decimal; padding-left: 1.25rem; }
.ws-tresc li { margin-bottom: .4rem; }
.ws-tresc a { color: var(--ws-red-text); text-underline-offset: .16em; }

/* Tresc strony maszyny. Sekcje wypisane przez [maszyna] ida na cala
   szerokosc, wiec kolumny nie moze narzucac rodzic; dostaja ja tylko
   akapity, ktore klient dopisal obok shortcode'a. Typografia zostaje
   ta sama, bo element nosi obie klasy naraz. */
.ws-tresc-maszyny { max-width: none; }

.ws-tresc-maszyny > *:not(section) {
    max-width: 44rem;
    margin-inline: auto;
    padding-inline: var(--ws-gut);
}

.ws-tresc-maszyny > section + *:not(section) { margin-top: 2.5rem; }
.ws-tresc-maszyny > *:not(section):last-child { margin-bottom: clamp(3rem, 6vw, 4.5rem); }

/* ══════════════════════════════════════════════════════
   STOPKA
   ══════════════════════════════════════════════════════ */
.ws-footer {
    background: var(--ws-dark);
    color: var(--ws-dark-ink);
    padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
}

/* Trzy kolumny, nie cztery. Lista miejscowosci wypadla ze stopki, bo te
   same nazwy stoja kafelkami w sekcji zasiegu bezposrednio nad nia.
   Pierwsza kolumna jest szersza, bo trzyma logotyp i zdanie o firmie. */
.ws-footer__grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr;
    gap: 2.5rem clamp(2rem, 5vw, 4rem);
}

.ws-footer h2 {
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ws-dark-ink-2);
    font-stretch: 100%;
    margin-bottom: 1rem;
}

/* Logotyp tekstowy w stopce dziedziczy jasny kolor, ale koncowka ".pl"
   ma wlasny, przyciemniony token - na grafitowym tle bylby nieczytelny. */
.ws-footer .ws-logo__tld { color: var(--ws-dark-ink-2); }

.ws-footer li { margin-bottom: .6rem; }
.ws-footer a { color: var(--ws-dark-ink); text-decoration: none; }
.ws-footer a:hover { text-decoration: underline; text-underline-offset: .18em; }
.ws-footer p { color: var(--ws-dark-ink-2); font-size: .9375rem; }

.ws-footer__o { color: var(--ws-dark-ink-2); font-size: .9375rem; max-width: 34ch; margin-top: 1rem; }

.ws-footer__spolecznosci { display: flex; gap: .6rem; margin-top: 1.25rem; }
.ws-footer__spolecznosci a {
    width: 2.5rem; height: 2.5rem;
    border: 1px solid var(--ws-dark-line);
    border-radius: var(--ws-r-sm);
    display: grid; place-items: center;
    transition: border-color .16s var(--ws-ease), background-color .16s var(--ws-ease);
}
.ws-footer__spolecznosci a:hover { border-color: var(--ws-red); background: var(--ws-red); }
.ws-footer__spolecznosci svg { width: 1.15rem; height: 1.15rem; }

.ws-footer__dol {
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--ws-dark-line);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: .75rem 1.5rem;
    font-size: .875rem;
    color: var(--ws-dark-ink-2);
}
/* Prawa autorskie i podpis wykonawcy trzymaja sie razem po lewej.
   Jako trzy osobne elementy rozjechalyby sie rowno po calej szerokosci
   i podpis wyladowalby na srodku, gdzie wyglada jak tresc, a nie stopka. */
.ws-footer__prawa {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1.5rem;
}
.ws-footer__prawa p { font-size: inherit; }

/* Na telefonie kazda z trzech rzeczy dostaje wlasny wiersz, a caly wiersz
   konczy sie przed przyciskiem powrotu na gore. Przycisk jest przyklejony
   do prawego dolnego rogu i bez tego marginesu odnosnik do polityki
   ladowal dokladnie pod nim. */
@media (max-width: 767px) {
    .ws-footer__dol {
        flex-direction: column;
        align-items: flex-start;
        gap: .5rem;
        padding-right: 3.75rem;
    }
    .ws-footer__prawa {
        flex-direction: column;
        gap: .35rem;
    }
}

@media (max-width: 899px) { .ws-footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 519px) { .ws-footer__grid { grid-template-columns: 1fr; } }

/* ══════════════════════════════════════════════════════
   PASEK AKCJI NA TELEFONIE

   Dwa równorzędne cele konwersji zawsze w zasięgu kciuka.
   Wysokość paska oddajemy stronie przez padding, żeby stopka
   nie chowała się pod nim.
   ══════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════
   PASEK PRZEWIJANIA

   Dwie skladnie, bo zadna nie pokrywa wszystkiego: standardowa
   scrollbar-color dziala w Firefoksie i nowszych Chrome, stara
   sciezka ::-webkit-scrollbar w Safari i starszych Chrome.
   Kolory ida z tokenow, wiec tryb ciemny nie wymaga niczego wiecej.

   Uchwyt zmienia sie na czerwony dopiero pod kursorem. Czerwony na
   stale robilby z paska najbardziej krzyczacy element kazdego ekranu.
   ══════════════════════════════════════════════════════ */
html {
    scrollbar-width: thin;
    scrollbar-color: var(--ws-line-2) var(--ws-paper);
}

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--ws-paper); }
::-webkit-scrollbar-thumb {
    background: var(--ws-line-2);
    border-radius: 999px;
    /* Obwodka w kolorze tla zwęża uchwyt bez zwezania obszaru chwytania. */
    border: 3px solid var(--ws-paper);
}
::-webkit-scrollbar-thumb:hover { background: var(--ws-red); }
::-webkit-scrollbar-corner { background: var(--ws-paper); }

/* ══════════════════════════════════════════════════════
   POWRÓT NA GÓRĘ
   ══════════════════════════════════════════════════════ */
.ws-do-gory {
    position: fixed;
    right: var(--ws-gut);
    bottom: 1.75rem;
    z-index: 40;            /* pod paskiem mobilnym, ktory ma 45 */
    width: 3rem;
    height: 3rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--ws-dark);
    color: #fff;
    border: 0;
    /* Dwie warstwy, bo przycisk przeplywa nad jasnymi i ciemnymi sekcjami.
       Jasny pierscien odcina go od ciemnego pasa przebiegu najmu i od
       czarnej karty zasiegu, cien od papieru. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .16),
                0 6px 20px -8px rgba(20, 20, 20, .45);
}
.ws-do-gory svg { width: 1.25rem; height: 1.25rem; }
.ws-do-gory:hover { background: var(--ws-red); border-color: var(--ws-red); }

/* Bez JavaScriptu przycisk jest widoczny od razu: skrypt steruje tylko
   tym, kiedy sie pojawia, a nie tym, czy w ogole dziala. */
.js .ws-do-gory {
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
}
.js .ws-do-gory--widoczny { opacity: 1; visibility: visible; transform: none; }

/* Na podstronach nie ma hero, wiec nie ma wartownika i klasa nigdy nie
   zostanie nadana. Tam przycisk jest widoczny od poczatku. */
.js body:not(.home) .ws-do-gory { opacity: 1; visibility: visible; transform: none; }

@media (prefers-reduced-motion: no-preference) {
    .ws-do-gory {
        transition: opacity .25s var(--ws-ease), transform .25s var(--ws-ease),
                    background-color .18s var(--ws-ease), border-color .18s var(--ws-ease);
    }
}

/* Pasek mobilny stoi na dole i zajmuje ten sam rog. Przycisk wchodzi
   nad niego, zamiast znikac: na telefonie strona jest najdluzsza. */
@media (max-width: 767px) {
    .ws-do-gory {
        /* Pasek mobilny ma okolo 81 px. 5,25rem zostawialo trzy piksele
           przerwy, co przy dotyku czyta sie jak jeden element. */
        bottom: calc(5.9rem + env(safe-area-inset-bottom));
        width: 2.75rem;
        height: 2.75rem;
    }
}

.ws-pasek-mobilny {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 45;
    display: none;
    gap: .6rem;
    padding: .7rem var(--ws-gut) calc(.7rem + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--ws-paper) 94%, transparent);
    backdrop-filter: blur(12px);
    border-top: 1px solid var(--ws-line);
}
.ws-pasek-mobilny .ws-btn { flex: 1; padding-inline: .75rem; }

@media (max-width: 767px) {
    .ws-pasek-mobilny { display: flex; }
    body { padding-bottom: 5.25rem; }
}

/* ══════════════════════════════════════════════════════
   WEJŚCIE SEKCJI

   MOTION_INTENSITY 4: jedno subtelne pojawienie się przy
   wejściu w widok, wyłącznie transform i opacity. Element bez
   JavaScriptu zostaje widoczny — brak skryptu nie może ukryć treści.
   ══════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {
    .js .ws-reveal {
        opacity: 0;
        transform: translateY(18px);
        transition: opacity .6s var(--ws-ease), transform .6s var(--ws-ease);
    }
    .js .ws-reveal[data-widoczne="1"] {
        opacity: 1;
        transform: none;
    }
}

/* ══════════════════════════════════════════════════════
   RUCH

   Wszystko poza otwarciem strony wisi na tym samym wyzwalaczu co
   pojawianie sie sekcji: obserwator ustawia data-widoczne="1", a CSS
   odpowiada. Zero nasluchu na zdarzeniu scroll, zero nowego skryptu.

   Kazdy efekt ma powod. Kolejno: sekwencja, znaczenie liczby,
   kierunek czytania, temat strony, informacja zwrotna. Jesli
   dokladasz tu cokolwiek nowego, najpierw napisz ten powod jednym
   zdaniem. Jesli sie nie da, animacji nie dokladaj.
   ══════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {

    /* 1. Os czasu rysuje sie od lewej, kroki zapalaja sie po kolei.
       Powod: sekcja opisuje kolejnosc zdarzen, wiec linia rosnie w te
       sama strone, w ktora sie ja czyta.

       Wlasne opacity i transform sa tu konieczne: regula .js .ws-reveal
       ustawia przesuniecie w pionie, ktore skasowaloby skalowanie. */
    .js .ws-przebieg__linia.ws-reveal {
        opacity: 1;
        transform: scaleX(0);
        transition: transform 1.1s var(--ws-ease);
    }
    .js .ws-przebieg__linia.ws-reveal[data-widoczne="1"] { transform: scaleX(1); }
    .js .ws-przebieg__krok.ws-reveal { transition-delay: calc(var(--i) * 120ms + 160ms); }

    /* 2. Obszar 80 km rozchodzi sie z Pulaw. Powod: pokazuje, co znaczy
       liczba w naglowku sekcji.

       transform-origin nie jest potrzebny: srodek okregu lezy w punkcie
       zero ukladu rysunku, czyli dokladnie w Pulawach. */
    .js .ws-zasieg__mapa .m-zasieg,
    .js .ws-zasieg__mapa .m-ring {
        transform: scale(0);
        transition: transform 1.2s var(--ws-ease);
    }
    .js .ws-zasieg__mapa .m-ring { transition-delay: .1s; }
    .js .ws-zasieg__mapa .m-kropka,
    .js .ws-zasieg__mapa .m-podpis {
        opacity: 0;
        transition: opacity .5s var(--ws-ease) .7s;
    }
    .js .ws-zasieg__mapa[data-widoczne="1"] .m-zasieg,
    .js .ws-zasieg__mapa[data-widoczne="1"] .m-ring { transform: scale(1); }
    .js .ws-zasieg__mapa[data-widoczne="1"] .m-kropka,
    .js .ws-zasieg__mapa[data-widoczne="1"] .m-podpis { opacity: 1; }

    /* 3. Kafle parku wchodza kaskadowo. Powod: kierunek czytania.
       Cztery kafle wjezdzajace naraz nie mowia, od ktorego zaczac. */
    .js .ws-kafle > li.ws-reveal { transition-delay: calc(var(--i) * 90ms); }

    /* 4. Wycinka wjezdza w otwarcie. Powod: maszyna jest tematem strony.

       Gra raz, przy wczytaniu, wiec stoi na @keyframes bez wyzwalacza.
       Naglowek i obrazek dostaja WYLACZNIE przesuniecie, bez krycia:
       oba sa kandydatami na najwiekszy element pierwszego widoku, a
       zaczynanie od opacity: 0 opoznia jego zapis w pomiarze wydajnosci.
       Przesuniecie tego nie robi, bo element jest juz narysowany. */
    @keyframes ws-wjazd { from { transform: translateY(34px); } }
    @keyframes ws-wejscie { from { opacity: 0; transform: translateY(12px); } }

    .js .ws-hero__maszyna img { animation: ws-wjazd .9s var(--ws-ease) both; }
    .js .ws-hero__tytul { animation: ws-wjazd .7s var(--ws-ease) both; }
    .js .ws-hero__tekst { animation: ws-wejscie .6s var(--ws-ease) .08s both; }
    .js .ws-hero__cta { animation: ws-wejscie .6s var(--ws-ease) .16s both; }
    .js .ws-hero__liczby { animation: ws-wejscie .6s var(--ws-ease) .24s both; }

    /* 5. Cena reaguje na przycisk. Powod: informacja zwrotna, wiaze
       kwote z dzialaniem. Zapytanie lapie takze obramowanie ogniskowej,
       wiec dziala z klawiatury. Bez obslugi :has() nie dzieje sie nic,
       co jest poprawnym zachowaniem zapasowym. */
    .ws-sprzet__grid:has(.ws-btn--pelny:hover) .ws-sprzet__cena,
    .ws-sprzet__grid:has(.ws-btn--pelny:focus-visible) .ws-sprzet__cena {
        transform: scale(1.06);
        color: var(--ws-red-text);
    }
}

.ws-sprzet__cena {
    transform-origin: left center;
    transition: transform .25s var(--ws-ease), color .25s var(--ws-ease);
}

/* ══════════════════════════════════════════════════════
   DRUK
   ══════════════════════════════════════════════════════ */
@media print {
    .ws-header, .ws-pasek-mobilny, .ws-form, .ws-footer__spolecznosci { display: none !important; }
    body { background: #fff; color: #000; padding-bottom: 0; }
    .ws-hero, .ws-sprzet__foto, .ws-kontakt__tel { background: none; border: 1px solid #000; }
    .ws-sprzet__foto::before, .ws-kontakt__tel::before { display: none; }
    .ws-hero, .ws-hero__tytul, .ws-hero__tekst, .ws-hero__liczba b { color: #000; }
    .ws-hero { margin-top: 0; padding-top: 0; }
    .ws-kontakt__tel, .ws-kontakt__numer, .ws-kontakt__tel p { color: #000; }
}


/* Mapa zasiegu w trybie ciemnym.

   Kropki i podpisy biora kolor z tokenow, wiec przelaczaja sie same.
   Zmiany wymagaja tylko dwie rzeczy: wypelnienie ladu, ktore jest
   zapisane wprost, i czerwien pinezki z pierscieniem. Te dwa ksztalty
   sa cienkie, wiec na grafitowym tle biora jasniejsza czerwien,
   te sama, ktora sluzy za czerwien tekstu. */
@media (prefers-color-scheme: dark) {
    .m-woj path { fill: #262624; stroke: #3E3D3A; }
    .m-zasieg { fill: #FF5A5C; fill-opacity: .17; }
    .m-ring   { stroke: #FF5A5C; }
    .m-pin    { fill: #FF5A5C; }
}

/* Ponizej 600 px kadr mapy ma okolo 335 px, czyli 1,6 piksela na kilometr,
   a podpisy miejscowosci schodza do siedmiu pikseli i przestaja byc
   czytelne. Nazwy stoja i tak w kafelkach tuz nad mapa, wiec na rysunku
   zostaja same kropki i jedna nazwa: Pulawy, srodek zasiegu. */
@media (max-width: 599px) {
    .m-podpis:not(.m-podpis--glowny) { display: none; }
    .m-podpis--glowny { font-size: 9px; }
}
