/* Omoda — Modele (Figma node 75:224 domyślny widok "pojedynczy model" /
   75:288 widok "siatka" po kliknięciu przełącznika w rogu). Oba widoki są
   w DOM naraz, przełącznik to tylko [data-view] na rootcie (CSS show/hide) —
   bez przeładowania strony, żeby filtr kategorii/karuzele nie resetowały się. */

.omoda-models {
    background: #f9f9f9;
    padding-block: 96px;
}

/* Widok pojedynczego modelu (Figma): górna część sekcji (nagłówek + zakładki +
   tytuł/cena, aż do ŚRODKA zdjęcia auta) ma tło #f9f9f9, reszta (dolna połowa
   zdjęcia + karta specyfikacji) jest już biała. Punkt podziału (--omoda-bg-
   split, px od góry sekcji) mierzony w JS (updateBackgroundSplit) na żywo,
   bo zależy od wysokości konkretnego zdjęcia modelu — statyczny (nie scroll-
   linked: liczony raz przy starcie/zmianie modelu/resize, nie w pętli scrolla,
   bo względna odległość sekcja→zdjęcie nie zmienia się przy przewijaniu, obie
   są w normalnym przepływie, nie sticky). Widok siatki i mobile (zawsze
   pokazuje siatkę/karuzelę, patrz media query niżej) mają JEDNOLITE #f9f9f9 —
   user: "w przypadku jak jest grid karuzela to #F9F9F9 po całości". */
.omoda-models[data-view="featured"] {
    background: linear-gradient(
        to bottom,
        #f9f9f9 0,
        #f9f9f9 var(--omoda-bg-split, 50%),
        #ffffff var(--omoda-bg-split, 50%),
        #ffffff 100%
    );
}

.omoda-models__header {
    text-align: center;
    margin-bottom: 40px;
}

.omoda-models__heading {
    font-size: 42px;
    font-weight: 700;
    color: #121212;
    margin: 0;
}

.omoda-models__subheading {
    font-size: 18px;
    font-weight: 400;
    color: #121212;
    margin: 12px 0 0;
}

/* Toolbar (filtr+przełącznik widoku) — element WSPÓLNY dla obu widoków (nie
   zagnieżdżony w .featured/.grid), więc żeby "grid nie ma fixed kategorii"
   (user), sticky+kondensowanie działa TYLKO w widoku pojedynczego modelu na
   desktopie (patrz override niżej) — domyślnie (grid, mobile) toolbar jest
   zwykłym, nieprzyklejonym elementem w normalnym przepływie strony. */
.omoda-models__toolbar {
    position: static;
}

/* Widok pojedynczego modelu (desktop): filtr wyśrodkowany, przełącznik przy
   prawej krawędzi, tło jak sekcja (bez cienia) — sticky pod headerem. Gdy
   sekcja się "skleja" (patrz .omoda-models__sticky niżej), ten toolbar
   PŁYNNIE zanika (opacity napędzane przez --omoda-stuck-progress, patrz JS —
   zatrzymuje się/cofa razem ze scrollem, nie jest to czasowy CSS transition),
   bo rolę przejmuje złączony pasek w .tabs-controls. */
.omoda-models[data-view="featured"] .omoda-models__toolbar {
    position: sticky;
    top: var(--omoda-models-header-offset, 80px);
    z-index: 4;
    background: #f9f9f9;
    padding-bottom: 10px;
    /* Zanika SZYBCIEJ niż reszta animacji (pełne 0 już w połowie drogi, nie
       dopiero na progress=1) — bo tabs-outer "wjeżdża" w to samo miejsce w
       TEJ SAMEJ 0-1 skali (patrz .omoda-models__sticky top, niżej); gdyby
       toolbar znikał w tym samym tempie, oba paski byłyby przez chwilę
       widoczne naraz, nachodząc na siebie (sprawdzone wizualnie — bez tego
       wyglądało na "podwójny" pasek w połowie scrolla). */
    opacity: calc(1 - var(--omoda-stuck-progress, 0) * 2);
    transition: background-color var(--omoda-transition-base), box-shadow var(--omoda-transition-base);
}

.omoda-models.is-stuck[data-view="featured"] .omoda-models__toolbar {
    background: #ffffff;
    box-shadow: 0 4px 24px 0 rgba(17, 12, 46, 0.08);
}

/* `pointer-events:none` NIE może wisieć na `.is-stuck` (progress>0, czyli od
   PIERWSZEGO piksela scrolla) — toolbar w tym momencie jest wciąż prawie
   w pełni nieprzezroczysty (opacity gaśnie dopiero do progress=0.5, patrz
   .omoda-models__toolbar wyżej) — user: "przełączanie omoda/jaecoo/wszystkie
   nie działa na widoku jak jest jedno auto": zmierzone wprost — przy 5px
   scrolla toolbar miał opacity 0.84 (widoczny), a mimo to już
   pointer-events:none (całkowicie nieklikalny). Osobna klasa
   .is-toolbar-hidden (JS, ustawiana dokładnie przy progress>=0.5, czyli
   dokładnie tam, gdzie opacity realnie dochodzi do 0) naprawia to. */
.omoda-models__toolbar.is-toolbar-hidden {
    pointer-events: none;
}

.omoda-models__toolbar-inner {
    position: relative;
    height: 56px;
    transition: height var(--omoda-transition-base);
}

.omoda-models.is-stuck[data-view="featured"] .omoda-models__toolbar-inner {
    height: 44px;
}

.omoda-models__filter {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    gap: 2px;
    /* Ten sam wygląd co .omoda-gallery-section__tabs (model-sections.css) —
       user: "podoba mi się styl w jakim zrobiłeś to, chcę żeby tak samo
       wyglądało to". Zawsze szare tło (nie tylko w stanie .is-stuck jak
       dawniej) — spójne z pigułką aktywną, która jest teraz biała, nie ciemna. */
    background: #f2f2f2;
    border-radius: 8px;
    padding: 4px;
    transition: left var(--omoda-transition-base), transform var(--omoda-transition-base), background-color var(--omoda-transition-base);
}

/* Gdy skondensowany: filtr zjeżdża spod przełącznika (który stoi przy prawej
   krawędzi) — te same 100% szerokości co przełącznik ma od prawej, mniejszy odstęp. */
.omoda-models.is-stuck[data-view="featured"] .omoda-models__toolbar .omoda-models__filter {
    left: auto;
    /* switch skondensowany ma 92px (2x42 + padding/gap) + 12px odstępu + 20px
       (switch ma teraz right:var(--omoda-container-padding), nie right:0 —
       patrz .omoda-models__switch wyżej), razem 124px. */
    right: 124px;
    transform: translateY(-50%);
}

.omoda-models__filter-btn {
    height: 38px;
    padding: 0 26px;
    border: 0 !important;
    /* !important — motyw narzuca własny border-radius na <button> z tą samą
       lub wyższą specyficznością (ten sam, wielokrotnie udokumentowany w tym
       pliku konflikt). */
    border-radius: 6px !important;
    background: transparent !important;
    box-shadow: none !important;
    /* Szary domyślnie, ciemny na hover/aktywna — jak .omoda-gallery-section__tab. */
    color: var(--omoda-color-text-muted) !important;
    font-family: var(--omoda-font-base);
    font-size: 14px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--omoda-transition-fast), height var(--omoda-transition-base), padding var(--omoda-transition-base), font-size var(--omoda-transition-base);
}

/* !important: mimo wyższej specyficzności (0,5,0) tej reguły vs (0,1,0) dla
   `[type="button"],...,button{padding:0.5rem 1rem}` z reset.css motywu,
   zmierzone wprost — computed padding/height/font-size dalej pokazywały
   wartości z RESETU, nie z tej reguły (znaleziony przy okazji naprawy
   marginesu switcha: filter w stanie skondensowanym nie kurczył się,
   przez co odstęp między filtrem a przełącznikiem wychodził dużo większy
   niż zamierzony). Bez ustalonej przyczyny (podobne do udokumentowanej
   wcześniej w projekcie anomalii specyficzności/z-index na potomkach
   position:sticky) — !important gwarantuje wygraną niezależnie od niej. */
.omoda-models.is-stuck[data-view="featured"] .omoda-models__toolbar .omoda-models__filter-btn {
    height: 30px !important;
    padding: 0 14px !important;
    font-size: 11px !important;
}

.omoda-models__filter-btn:hover {
    background: rgba(18, 18, 18, 0.06) !important;
    color: var(--omoda-color-text) !important;
}

.omoda-models__filter-btn.is-active,
.omoda-models__filter-btn.is-active:hover {
    background: #ffffff !important;
    color: var(--omoda-color-text) !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.omoda-models__switch {
    position: absolute;
    top: 50%;
    /* Nie `right:0` — zmierzone wprost: `right:0` na position:absolute
       dziecku umieszczało je DOKŁADNIE na granicy border-boxa rodzica
       (.toolbar-inner), ignorując jego padding-inline (20px), więc switch
       stykał się z samą krawędzią kontenera 1280px zamiast mieć od niej
       taki sam odstęp jak reszta treści — user: "switch wychodzi poza
       container 1280px" (wizualnie brak oddechu, nawet jeśli linia 1280px
       nie była fizycznie przekroczona). */
    right: var(--omoda-container-padding, 20px);
    transform: translateY(-50%);
    display: flex;
    gap: 2px;
    /* Ten sam wygląd co .omoda-gallery-section__tabs — patrz komentarz przy
       .omoda-models__filter wyżej. */
    background: #f2f2f2;
    border-radius: 8px;
    padding: 4px;
    transition: background-color var(--omoda-transition-base);
}

.omoda-models__switch-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 58px;
    height: 38px;
    border: 0 !important;
    border-radius: 6px !important;
    background: transparent !important;
    box-shadow: none !important;
    color: #121212 !important;
    cursor: pointer;
    transition: background-color var(--omoda-transition-fast), width var(--omoda-transition-base), height var(--omoda-transition-base);
}

.omoda-models.is-stuck[data-view="featured"] .omoda-models__toolbar .omoda-models__switch-btn {
    width: 42px;
    height: 30px;
}

.omoda-models__switch-btn:hover {
    background: rgba(18, 18, 18, 0.06) !important;
}

.omoda-models__switch-btn.is-active,
.omoda-models__switch-btn.is-active:hover {
    /* Ten sam wygląd co pigułka aktywna .omoda-gallery-section__tab.is-active. */
    background: #ffffff !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.omoda-models__arrow {
    flex-shrink: 0;
    width: 46px;
    height: 46px;
    padding: 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    border: 0 !important;
    background: none !important;
    box-shadow: none !important;
    cursor: pointer;
    opacity: 0.45;
    transition: opacity var(--omoda-transition-base), visibility 0s;
}

.omoda-models__arrow:hover {
    opacity: 1;
}

.omoda-models__arrow img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    display: block;
}

/* Chowane, gdy karuzela/pasek jest już na początku/końcu (JS dokłada klasy
   is-at-start/is-at-end na *-outer) — zamiast martwego, klikalnego przycisku donikąd. */
.omoda-models__tabs-outer.is-at-start .omoda-models__arrow--prev,
.omoda-models__tabs-outer.is-at-end .omoda-models__arrow--next,
.omoda-models__grid-outer.is-at-start .omoda-models__arrow--prev,
.omoda-models__grid-outer.is-at-end .omoda-models__arrow--next {
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

/* ---------- Widok: pojedynczy model ---------- */

.omoda-models__grid {
    display: none;
    /* Bez tego siatka kart dotykała bezpośrednio dołu toolbara (zmierzone:
       0px odstępu) — user: "brakuje mi marginesu od dołu jak mam widok
       gridowy". */
    margin-top: 24px;
}

.omoda-models[data-view="grid"] .omoda-models__featured {
    display: none;
}

.omoda-models[data-view="grid"] .omoda-models__grid {
    display: block;
}

/* Pasek zakładek zostaje przyklejony (sticky), zawsze NAD zdjęciem (z-index —
   testowane: samo position:sticky bez z-index potrafi w tym środowisku
   przegrywać z warstwą zdjęcia mimo poprawnej hierarchii kontekstów, więc
   jawny z-index na CAŁYM bloku jest bezpieczniejszy niż różnicowanie go
   między dziećmi — TO SAMO dotyczy prób podniesienia z-index tylko na
   .tabs-outer, gdy jego rodzic .sticky ma z-index:auto: zmierzone wprost
   przez elementFromPoint — w tym środowisku takie dziecko i tak przegrywa z
   późniejszym w DOM-ie zdjęciem, mimo z-index wyższego niż "auto" — user:
   "jak mam ...sticky...is-stuck... to chce aby to było z-index wyżej niż
   samochód", zdjęcie zasłaniało cały pasek nawigacji w stanie sklejonym).
   Dlatego tytuł/cena (.omoda-models__selected) NIE jest już zagnieżdżony w
   tym elemencie (patrz PHP, render_featured) — to OSOBNY, niezależny sticky
   element (patrz .omoda-models__selected niżej) z WŁASNYM, jednolitym
   z-index, który w trybie "cover" może bezpiecznie zejść niżej bez wciągania
   za sobą paska zakładek. top: w spoczynku (progress=0) zostawia miejsce
   na wciąż widoczny samodzielny toolbar NAD sobą (+44px); w miarę jak toolbar
   płynnie zanika (patrz wyżej), ta szczelina się PŁYNNIE zamyka razem z nim
   (via --omoda-stuck-progress), tak że przy progress=1 pasek jest już
   dokładnie przyklejony pod headerem (0 odstępu) — bez tego zostawał martwy,
   44px prześwit, bo toolbar znikał, a ta wartość nie reagowała na to. */
.omoda-models__sticky {
    position: sticky;
    top: calc(var(--omoda-models-header-offset, 80px) + 44px * (1 - var(--omoda-stuck-progress, 0)));
    z-index: 3;
}

/* Pełna szerokość ekranu — tylko tak strzałki mogą stanąć POZA siatką 1280px. */
.omoda-models__tabs-outer,
.omoda-models__grid-outer {
    position: relative;
    display: flex;
    align-items: center;
}

/* Gdy scroll minął nagłówek sekcji (.omoda-models.is-stuck) I jesteśmy w widoku
   pojedynczego modelu: pasek zakładek dostaje biały pasek+cień na 100% szerokości
   (dokładnie to, co wcześniej miał samodzielny toolbar) — a samodzielny toolbar
   nad nim się chowa, bo jego filtr/przełącznik "dosiadają się" do tego samego
   wiersza co zakładki (patrz .tabs-controls niżej). */
.omoda-models.is-stuck[data-view="featured"] .omoda-models__tabs-outer {
    background: #ffffff;
    box-shadow: 0 4px 24px 0 rgba(17, 12, 46, 0.08);
}

/* UWAGA (2026-09-18): silnik renderujący w tym środowisku źle upraszcza
   głęboko zagnieżdżone `calc(max(...) * var(...) + (...) * var(...))` na
   `left`/`right` pozycjonowanych absolutnie elementów — zamiast finalnej
   wartości px, getComputedStyle zwracał ZNIEKSZTAŁCONY, nierozwiązany
   łańcuch calc() (zweryfikowane: ten sam ogólny wzorzec matematyczny na
   .omoda-models__tabs-row (padding, suma dwóch członów mnożonych przez
   progress) działa poprawnie — problem dotyczy konkretnie `left`/`right`
   na position:absolute, nie calc() w ogóle). Dlatego strzałki NIE są tu
   interpolowane płynnie przez --omoda-stuck-progress jak reszta paska —
   pozycja przełącza się progowo na .is-stuck (prosty, jednowarstwowy
   calc(), bez zagnieżdżonego max()*var()), z osobnym `transition:` żeby
   mimo to nie skakała bez animacji. */
.omoda-models__tabs-outer .omoda-models__arrow--prev,
.omoda-models__grid-outer .omoda-models__arrow--prev {
    position: absolute;
    left: max(4px, calc((100% - var(--omoda-container-width, 1280px)) / 2 - 60px));
    z-index: 1;
    transition: left var(--omoda-transition-base);
}

.omoda-models__tabs-outer .omoda-models__arrow--next,
.omoda-models__grid-outer .omoda-models__arrow--next {
    position: absolute;
    right: max(4px, calc((100% - var(--omoda-container-width, 1280px)) / 2 - 60px));
    z-index: 1;
    transition: right var(--omoda-transition-base);
}

.omoda-models.is-stuck[data-view="featured"] .omoda-models__tabs-outer .omoda-models__arrow--prev {
    left: 6px;
}

/* Prawa strzałka w stanie sklejonym: NIE do krawędzi ekranu (tam ląduje
   daleko za złączonym filtrem — user: "strzałki powinny być przy
   omoda-models__tabs-track, nie po całej szerokości") — tylko tuż PRZED
   .tabs-controls (filtr), z tym samym odstępem bocznym (32px) i gapem
   między elementami wiersza (24px, patrz .tabs-row gap) co reszta paska.
   Szerokość .tabs-controls mierzona w JS przez ResizeObserver do zmiennej
   --omoda-tabs-controls-width (0 gdy jeszcze niewidoczny/nieznany). */
.omoda-models.is-stuck[data-view="featured"] .omoda-models__tabs-outer .omoda-models__arrow--next {
    right: calc(32px + var(--omoda-tabs-controls-width, 0px) + 24px);
}

/* Wiersz: zakładki (rosną, zajmują resztę miejsca) + kontrolki (filtr/
   przełącznik — widoczne TYLKO gdy .is-stuck, patrz niżej). Domyślnie w
   kontenerze 1280px (jak .omoda-container), płynnie (via --omoda-stuck-progress)
   rozszerza się na 100% szerokości EKRANU w miarę sklejania — boczny padding
   przechodzi z "wyśrodkowanego 1280px" na stały 32px. */
.omoda-models__tabs-row {
    display: flex;
    align-items: center;
    gap: 24px;
}

.omoda-models[data-view="featured"] .omoda-models__tabs-row {
    max-width: none;
    width: 100%;
    margin-inline: 0;
    box-sizing: border-box;
    /* Przy progress=0 to musi dać DOKŁADNIE ten sam odstęp co zwykłe
       .omoda-container (max-width:1280+margin:auto+padding:20px) — czyli
       20px WŁASNEGO paddingu + ewentualna połowa nadwyżki nad 1280px
       (centrowanie), NIE sam odstęp centrujący (stąd 20px + max(0, …), a
       nie max(20px, …), które gubiło te 20px na szerokich ekranach). */
    padding-inline: calc(
        (var(--omoda-container-padding, 20px) + max(0px, (100% - var(--omoda-container-width, 1280px)) / 2)) * (1 - var(--omoda-stuck-progress, 0))
        + 32px * var(--omoda-stuck-progress, 0)
    );
}

.omoda-models__tabs {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    border-top: 1px solid var(--omoda-color-border, #e5e5e5);
    border-bottom: 1px solid var(--omoda-color-border, #e5e5e5);
    height: 65px;
    position: relative;
}

/* Druga kopia filtra/przełącznika (patrz PHP) — ukryta w spoczynku, pokazuje
   się (płynnie, opacity via --omoda-stuck-progress) TYLKO gdy pasek jest
   sklejony (wtedy samodzielny toolbar płynnie znika, patrz wyżej). Zawsze w
   wersji skondensowanej (nie ma własnego stanu "duży/mały") i NIE jest
   position:absolute — to zwykłe dziecko tego flex-rzędu, po prawej stronie
   zakładek. */
.omoda-models__tabs-controls {
    display: none;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
    /* Wysokość ma dorównywać całemu wierszowi (.tabs-row, czyli faktycznie
       .tabs, 65px) — bez tego .tabs-controls jest tylko tak wysoki jak jego
       treść (36px), więc jako flex item wyśrodkowany w wyższym wierszu
       wygląda jakby "wystawał"/pływał w oderwaniu od paska zakładek (user:
       "to jest jakby poza tym kontenerem"). align-items:center (wyżej)
       nadal centruje SAME przyciski wewnątrz tej rozciągniętej wysokości. */
    align-self: stretch;
    /* Pojawia się SZYBCIEJ niż cała animacja (pełne 1 już w połowie drogi) —
       symetrycznie do zanikania toolbara (patrz wyżej), żeby złączony pasek
       był już w pełni widoczny, zanim tabs-outer skończy "wjeżdżać" pod
       header. */
    opacity: calc(var(--omoda-stuck-progress, 0) * 2);
}

.omoda-models.is-stuck[data-view="featured"] .omoda-models__tabs-controls {
    display: flex;
}

/* Dopóki nawigacja jest "sklejona", nie ma już możliwości przełączenia na
   widok siatki (user: "jak jest fixed kategorie to nie ma być już
   możliwości przełączenia na grid") — w złączonym pasku zostaje tylko filtr
   kategorii, przełącznik widoku znika (dostępny znów dopiero po przewinięciu
   z powrotem do góry, gdy pasek się odklei). */
.omoda-models.is-stuck[data-view="featured"] .omoda-models__tabs-controls .omoda-models__switch {
    display: none;
}

.omoda-models__tabs-controls .omoda-models__filter,
.omoda-models__tabs-controls .omoda-models__switch {
    position: static;
    transform: none;
    background: #f2f2f2;
}

.omoda-models__tabs-controls .omoda-models__filter-btn {
    height: 32px;
    padding: 0 14px;
    font-size: 11px;
}

.omoda-models__tabs-controls .omoda-models__switch-btn {
    width: 40px;
    height: 32px;
}

.omoda-models__tabs-track {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 40px;
    overflow-x: auto;
    /* Jawne, bo bez tego przeglądarka sama dolicza overflow-y:auto (spec: gdy
       jedna oś ma wartość inną niż visible, druga "visible" liczy się jako
       auto) — łapało pionowy swipe na mobile i blokowało scroll strony. */
    overflow-y: hidden;
    scrollbar-width: none;
    height: 100%;
    scroll-behavior: smooth;
}

.omoda-models__tabs-track::-webkit-scrollbar {
    display: none;
}

.omoda-models__tab {
    flex-shrink: 0;
    /* `height:100%` na <button> BEZ jawnego pionowego centrowania renderuje
       się (w tym motywie/resecie) jako zwykły blok — tekst siada u GÓRY
       63px-owego pudełka zamiast na środku ("przyklejone do górnej części
       paska", zgłoszone przez usera). display:flex+align-items:center
       wymusza pionowe centrowanie niezależnie od domyślnego renderowania
       przycisku w danej przeglądarce/resecie motywu. !important konieczny:
       reset.css motywu ma `[type="button"], button{display:inline-block}` —
       selektor atrybutu ma TĘ SAMĄ specyficzność co pojedyncza klasa (0,1,0),
       a reset.css ładuje się PO CSS wtyczki, więc bez !important wygrywa on
       (potwierdzony, powtarzający się wzorzec w tym projekcie). */
    height: 100%;
    display: flex !important;
    align-items: center;
    padding: 0 !important;
    border: 0 !important;
    border-bottom: 2px solid transparent !important;
    background: none !important;
    box-shadow: none !important;
    color: #121212 !important;
    font-family: var(--omoda-font-base);
    font-size: 16px;
    font-weight: 400;
    white-space: nowrap;
    cursor: pointer;
    transition: opacity var(--omoda-transition-fast);
    opacity: 0.55;
}

.omoda-models__tab:hover {
    opacity: 0.85;
}

.omoda-models__tab.is-active {
    opacity: 1;
    font-weight: 700;
    border-bottom-color: #121212 !important;
}

/* !important: baza `.omoda-models__tab{display:flex!important}` (wyżej)
   BIJE natywne zachowanie atrybutu `[hidden]` (UA stylesheet: `[hidden]
   {display:none}`, bez !important) — bez tego dodatkowego !important tu,
   przefiltrowane zakładki DALEJ renderowały się jako `display:flex`
   (potwierdzone: `hidden===true`, ale `getComputedStyle().display==="flex"`
   i realna szerokość/wysokość > 0) — filtr TECHNICZNIE działał (stan/klasy
   się zmieniały poprawnie), ale WIZUALNIE nic nie znikało, więc user
   (patrząc na ekran, nie w DevTools) widział to jako "filtr nie działa".
   Dotyczyło TYLKO widoku featured (zakładki) — siatka używa innej klasy
   (.is-filtered-out) bez tego konfliktu, stąd user zgłosił "działa tylko
   w grid". */
.omoda-models__tab[hidden] {
    display: none !important;
}

.omoda-models__tabs-fade {
    pointer-events: none;
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 80px;
    background: linear-gradient(to right, rgba(249, 249, 249, 0), #f9f9f9);
    transition: opacity var(--omoda-transition-fast);
}

/* Koniec przewijania — nie ma już nic do zasłonięcia, gradient znika, żeby
   nie zakrywał ostatniej pozycji. */
.omoda-models__tabs-outer.is-at-end .omoda-models__tabs-fade {
    opacity: 0;
}

/* Tytuł/cena/badge: DOMYŚLNIE wyśrodkowane (trochę niżej — między paskiem
   zakładek a zdjęciem), płynnie PRZESUWAJĄ SIĘ do lewej krawędzi kontenera
   wraz ze sklejaniem (user: "nadal nie ma płynnej animacji między domyślną
   pozycją a jak leci w lewo"). text-align nie da się płynnie interpolować
   (skok center->left w jednej klatce), więc każda linia dostaje KLASYCZNY
   TRICK centrowania nieznanej szerokości (`left:50%;transform:translateX(
   -50%)`), z obiema wartościami interpolowanymi przez --omoda-stuck-progress
   — 50%/-50% (idealnie wyśrodkowane) przy progress=0, 0%/0% (zwykłe
   wyrównanie do lewej) przy progress=1.

   UWAGA: ten trick musi być zastosowany OSOBNO na KAŻDEJ linii (tytuł, cena,
   badge), NIE na jednym wspólnym wrapperze wokół wszystkich naraz — user:
   "nazwa modelu i cena... i badge nie powinna być wyrównana do lewej strony"
   — zmierzone bezpośrednio (getBoundingClientRect): przy wspólnym wrapperze
   (.selected-inner jako CAŁOŚĆ wyśrodkowana, dzieci text-align:left) wrapper
   ma szerokość NAJSZERSZEJ linii (zwykle tytułu), więc KRÓTSZE linie (cena,
   badge) — mimo że sam wrapper poprawnie się przesuwał — renderowały się
   przyklejone do LEWEJ krawędzi TEJ WSPÓLNEJ szerokości, czyli wizualnie NIE
   na środku, tylko przesunięte w lewo względem tytułu. `display:table` (jak
   inline-block: kurczy się do szerokości własnej treści, ale zostaje
   block-level, więc nie wchodzi w linię z rodzeństwem jak inline-block by
   mógł) na KAŻDYM dziecku z osobna daje każdej linii WŁASNĄ szerokość i
   WŁASNE, niezależne centrowanie/przesunięcie. Padding na .selected płynnie
   się zmniejsza wraz z --omoda-stuck-progress. Opacity NIE ma czasowego
   `transition` na bazowej regule — sterowana jest SCROLL-LINKED zmienną
   --omoda-selected-fade (JS, updateCardFade, liczona od środka
   .omoda-models__image). .is-switching (fade przy zmianie modelu klikiem —
   inna sytuacja, NIE scroll) dostaje WŁASNY, faktycznie czasowy transition,
   z !important, żeby na chwilę nadpisać scroll-linked opacity. */
/* position:sticky WŁASNY (nie zagnieżdżony w .omoda-models__sticky, patrz
   komentarz przy tamtej regule) — top to DOKŁADNIE ten sam punkt, w którym
   .sticky "kleiłby się" do góry, PLUS wysokość paska zakładek (.tabs-outer,
   stała ~65px — patrz .omoda-models__tabs { height:65px }, bez animacji
   wysokości przy "sklejaniu", tylko padding-inline/tło się zmieniają), żeby
   nadal wizualnie siedzieć TUŻ POD paskiem, tak jak wcześniej w normalnym
   przepływie wewnątrz wspólnego kontenera. z-index:3 domyślnie (jak .sticky)
   — w trybie "cover" schodzi do auto niżej, patrz override. */
.omoda-models__selected {
    position: sticky;
    top: calc(var(--omoda-models-header-offset, 80px) + 44px * (1 - var(--omoda-stuck-progress, 0)) + 65px);
    z-index: 3;
    text-align: left;
    /* +15px od góry (user) na całym zakresie interpolacji — 48->63px w
       spoczynku, 16->31px sklejone — zachowuje ten sam kształt animacji
       (zmniejsza się o 32px), tylko przesunięty jednolicie w dół. */
    padding-top: calc(63px - 32px * var(--omoda-stuck-progress, 0));
    padding-bottom: calc(8px + 8px * var(--omoda-stuck-progress, 0));
}

/* Opacity NIE jest na bazowej regule wyżej — element ma teraz też (odkąd jest
   własnym, niezależnym sticky elementem, patrz wyżej) atrybut data-omoda-reveal
   (wejściowy fade-in, jak reszta bloków sekcji). Reguła scroll-reveal w
   omoda-core.css (`[data-omoda-reveal].is-revealed { opacity: 1; }`) ma
   DOKŁADNIE TĘ SAMĄ specyficzność (0,2,0) co gdyby to opacity siedziało na
   samym `.omoda-models__selected` (0,1,0 — NIŻSZA, więc bazowa reguła w ogóle
   by przegrała, niezależnie od kolejności ładowania arkuszy) — zmierzone
   wprost: --omoda-selected-fade poprawnie liczyło się na 0, ale
   getComputedStyle(...).opacity uparcie pokazywało "1" (fade w trybie "cover"
   przestawał cokolwiek chować). Podniesienie do (0,2,0) przez dopisanie
   .is-revealed tutaj też — przy RÓWNEJ specyficzności wygrywa arkusz
   załadowany PÓŹNIEJ w kaskadzie, a ten plik zależy od (czyli ładuje się PO)
   omoda-core.css, więc ta reguła bije bazową regułę reveal. */
.omoda-models__selected.is-revealed {
    opacity: var(--omoda-selected-fade, 1);
}

/* Celowo KAŻDA linia z osobna (nie wrappery [data-omoda-selected-price] ani
   [data-omoda-selected-badges], które w PHP owijają PO DWIE linie naraz —
   cenę+omnibus, samo badge) — inaczej ten sam problem (opisany wyżej)
   powtórzyłby się jedno piętro głębiej: cena i omnibus mają RÓŻNE szerokości
   (omnibus zwykle dłuższy tekst), więc krótsza z nich znów byłaby przyklejona
   do lewej wewnątrz wspólnej szerokości wrappera. */
.omoda-models__selected-inner .omoda-models__badges,
.omoda-models__selected-inner .omoda-models__title,
.omoda-models__selected-inner .omoda-models__price,
.omoda-models__selected-inner .omoda-models__omnibus {
    display: table;
    position: relative;
    left: calc(50% * (1 - var(--omoda-stuck-progress, 0)));
    transform: translateX(calc(-50% * (1 - var(--omoda-stuck-progress, 0))));
}

/* display:table wyżej (potrzebny do triku z centrowaniem) ubija flexboxowy
   `gap: 8px` z bazowej reguły .omoda-models__badges (gap nie działa w table) —
   przy 2+ badge'ach sklejały się bez odstępu. Odstęp odtworzony marginesem. */
.omoda-models__selected-inner .omoda-models__badges .omoda-models__badge {
    margin-right: 8px;
}

.omoda-models__selected-inner .omoda-models__badges .omoda-models__badge:last-child {
    margin-right: 0;
}

.omoda-models__selected.is-hidden {
    pointer-events: none;
}

/* Tryb alternatywny (Omoda PGD → Ustawienia globalne → "Modele — nazwa/cena
   wybranego modelu: chowaj się ZA zdjęciem przy scrollu"): user NIE chce
   przesuwania w lewo ("to nie chce aby zmieniało to pozycji") — blok
   nazwy/ceny/badge ma zostać na swoim (wyśrodkowanym) miejscu przez CAŁY
   scroll, a "znikanie" ma być wyłącznie efektem tego, że nadjeżdżające
   zdjęcie modelu ma WYŻSZY z-index i go zasłania ("tak aby za tym zdjęciem
   się chowało" / "z-index dla tego tekstu ma być NIŻSZY niż zdjęcia").

   .omoda-models__selected jest teraz WŁASNYM, niezależnym sticky elementem
   (nie zagnieżdżonym w .omoda-models__sticky — patrz PHP i komentarz przy
   .omoda-models__sticky w CSS: różnicowanie z-index MIĘDZY DZIEĆMI jednego
   position:sticky nie działa niezawodnie w tym środowisku, sprawdzone
   wprost). Dzięki temu jego WŁASNY, jednolity z-index (bazowo 3, jak pasek
   zakładek) może tu bezpiecznie zejść do auto, BEZ wciągania za sobą paska
   nawigacji (.omoda-models__sticky, osobny element, zachowuje swoje z-index:3
   zawsze — user: "jak mam ...sticky...is-stuck... to chce aby to było
   z-index wyżej niż samochód"). Bez progu/opóźnienia — auto wygrywa
   dokładnie od pierwszego piksela geometrycznego nachodzenia zdjęcia. */
.omoda-models[data-selected-mode="center"] .omoda-models__selected,
.omoda-models[data-selected-mode="cover"] .omoda-models__selected {
    z-index: auto;
}

/* Samo obniżenie z-index (wyżej) NIE WYSTARCZA — zasłania tytuł/cenę tylko
   dopóki zdjęcie/karta FAKTYCZNIE geometrycznie go zasłaniają. .selected jest
   position:sticky, więc zostaje przyklejone w tym samym miejscu ekranu, a
   zdjęcie/karta (zwykły, nie-sticky scroll) w końcu przewijają się DALEJ i
   znikają z tamtego miejsca — user: "nie było [...] efektu że scrolluje się
   tak długo, że pojawia się pod autem" — bez dodatkowego, TRWAŁEGO ukrycia
   tytuł/cena po prostu wyłaniałyby się z powrotem, gdy auto zdąży już
   przejechać dalej. Dlatego opacity NIE jest tu nadpisywane na stałe 1 —
   zostaje BAZOWA reguła `.omoda-models__selected { opacity: var(--omoda-
   selected-fade, 1); }` (patrz niżej), czyli DOKŁADNIE ten sam, już
   przetestowany scroll-linked mechanizm co w trybie "slide"
   (updateCardFade() w JS) — liczony od środka .omoda-models__image
   (user: "jak mam zdjęcie to już w połowie zdjęcia ten tekst ma zniknąć"),
   z zabezpieczeniem przed nachodzeniem na kartę specyfikacji. Raz schowane
   (opacity=0, klasa .is-hidden) zostaje schowane — TRWALE, niezależnie od
   tego, czy auto akurat geometrycznie na nie nachodzi — aż do scrolla z
   powrotem w górę (w pełni odwracalne, liczone na nowo w każdej klatce). */

/* Nadpisuje interpolację left/transform sterowaną --omoda-stuck-progress
   (patrz reguła bazowa wyżej) na stałe, wyśrodkowane 50%/-50% — bez tego
   ten sam trick centrowania nadal przesuwałby każdą linię do lewej krawędzi
   w miarę "sklejania się" paska nawigacji. Tryby "center" i "cover" (fixed). */
.omoda-models[data-selected-mode="center"] .omoda-models__selected-inner .omoda-models__badges,
.omoda-models[data-selected-mode="cover"] .omoda-models__selected-inner .omoda-models__badges,
.omoda-models[data-selected-mode="center"] .omoda-models__selected-inner .omoda-models__title,
.omoda-models[data-selected-mode="cover"] .omoda-models__selected-inner .omoda-models__title,
.omoda-models[data-selected-mode="center"] .omoda-models__selected-inner .omoda-models__price,
.omoda-models[data-selected-mode="cover"] .omoda-models__selected-inner .omoda-models__price,
.omoda-models[data-selected-mode="center"] .omoda-models__selected-inner .omoda-models__omnibus,
.omoda-models[data-selected-mode="cover"] .omoda-models__selected-inner .omoda-models__omnibus {
    left: 50%;
    transform: translateX(-50%);
}

/* Tryb "cover" (w PGD: "nie scrolluje się wcale") — blok jest ZWYKŁYM elementem
   w przepływie strony (bez sticky/fixed/absolute): jedzie w górę razem ze
   stroną jak każdy inny blok, a gdy dojeżdża do paska zakładek
   (.omoda-models__sticky, z-index:3, biały po sklejeniu), chowa się POD nim
   (z-index:auto wyżej). Bez żadnego fade'u — user: "ma po prostu schować się
   zza tabs-row". Padding zamrożony na stanie spoczynkowym (bez interpolacji
   przez --omoda-stuck-progress). */
.omoda-models[data-selected-mode="cover"] .omoda-models__selected {
    position: relative;
    top: auto;
    padding-top: 63px;
    padding-bottom: 8px;
}

.omoda-models[data-selected-mode="cover"] .omoda-models__selected.is-revealed {
    opacity: 1;
}

/* Krótki fade-out przed podmianą tytułu/ceny przy zmianie modelu (JS,
   updateSelectedContent) — zamiast twardego, natychmiastowego skoku treści.
   !important: na chwilę musi wygrać ze scroll-linked --omoda-selected-fade. */
.omoda-models__selected.is-switching {
    opacity: 0 !important;
    transition: opacity 320ms var(--omoda-ease);
}

/* Etykiety (badge) nad nazwą modelu — user: "podobnie jak mamy w sliderze",
   ten sam wzorzec (repeater tekst+kolor) i te same wymiary co
   .omoda-hero-slider__badge, żeby wyglądały spójnie w całej witrynie. */
.omoda-models__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 10px;
}

.omoda-models__badges:empty {
    display: none;
    margin: 0;
}

.omoda-models__badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 12px;
    border-radius: 3px;
    color: #ffffff;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* "Pigułki" korzyści (np. "Gwarancja 8 lat") — ten sam wzorzec wizualny co
   .omoda-pricing__benefits/__benefit w Ceniku (kopia pod własną klasą, bez
   twardej zależności od wtyczki Cennika — patrz Omoda_Models_Section::
   benefits_html()), reużywana m.in. w widoku "Lista" sekcji Modele. */
.omoda-models__benefits {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.omoda-models__benefit {
    background: #daf7ff;
    border-radius: 2px;
    padding: 4px 12px;
    font-size: 12px;
    font-weight: 600;
    color: #121212;
    white-space: nowrap;
}

.omoda-models__title {
    margin: 0;
    font-size: 32px;
    font-weight: 700;
    color: #121212;
}

.omoda-models__price {
    margin: 10px 0 0;
    text-align: center;
}

/* Regularna NAD promocyjną (nie obok) — promocyjna w tym samym rozmiarze/grubości
   co cena "solo" (gdy nie ma promocji), tylko czerwona, żeby wizualnie nie
   wyglądała jak inna kategoria informacji, tylko jak "ta sama cena, w promocji". */
.omoda-models__price--sale {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

/* .price--sale jest WEWNĘTRZNIE flex-column (regularna nad promocyjną) —
   w .selected-inner potrzebuje inline-flex (kurczy się do treści tak jak
   `display:table` na sąsiednich liniach, ale zostaje flex-em, nie traci
   pionowego stosu) — 3 klasy, wyższa specyficzność niż `display:table`
   z reguły ".selected-inner .price" (2 klasy) niżej, więc na pewno wygrywa.
   align-items zostaje `center` (dziedziczone z reguły bazowej wyżej) —
   NIE `flex-start` (jak było tu wcześniej, z czasów gdy cały ten blok był
   text-align:left — od kiedy tytuł/cena wróciły do wyśrodkowania, ta stara
   wartość tu została jako zapomniany relikt: user, OMODA 5 — "już od 116 500
   zł" przekreślona cena regularna trzymała się lewej krawędzi boxa zamiast
   być wyśrodkowana NAD (krótszą) ceną promocyjną pod spodem). */
.omoda-models__selected-inner .omoda-models__price.omoda-models__price--sale {
    display: inline-flex;
}

.omoda-models__price-regular {
    font-size: 12px;
    font-weight: 400;
    color: #959595;
}

/* Przekreślona jest tylko liczba (cyfry) — "od", "zł" itp. zostają bez kreski. */
.omoda-models__price-num {
    text-decoration: line-through;
}

.omoda-models__price-sale {
    font-size: 22px;
    font-weight: 400;
    color: #d81f26;
}

.omoda-models__price-solo {
    font-size: 22px;
    font-weight: 400;
    color: #121212;
}

.omoda-models__omnibus {
    margin: 6px 0 0;
    text-align: center;
    font-size: 11px;
    color: #959595;
}

.omoda-models__selected-inner .omoda-models__omnibus {
    text-align: left;
}

.omoda-models__panels {
    position: relative;
    /* Dodatkowy zapas miejsca u dołu: .sticky (nawigacja+cena) "odklei" się
       (przestanie być position:sticky) dopiero, gdy w tym kontenerze
       zabraknie na to miejsca — a to musi nastąpić PO tym, jak karta+zdjęcie
       i tytuł/cena zdążą się już całkiem wyfadeować (JS, updateCardFade),
       inaczej panel z nawigacją "urywa się" i nachodzi na nadjeżdżającą
       kartę, zanim zdąży zniknąć. */
    padding-bottom: 220px;
}


.omoda-models__panel {
    display: none;
}

.omoda-models__panel.is-active {
    display: block;
}

/* Poprzedni panel, zanim zniknie z DOM-owego przepływu (JS zdejmuje .is-active
   dopiero PO tej animacji, patrz PANEL_EXIT_MS w models-section.js) — delikatnie
   znika w lewo. Musi zostać `display:block` przez ten czas (stąd też
   .is-exiting w tym selektorze), inaczej zniknąłby natychmiast, zanim zdąży
   się to zobaczyć. */
.omoda-models__panel.is-exiting {
    display: block;
}

.omoda-models__panel[hidden] {
    display: none !important;
}

/* .image-wrap zawiera i zdjęcie (.image-link > .image), i pływającą kartę
   (.card, position:absolute w środku) — chowając JEDEN wspólny element (jego
   opacity, scroll-linked), oba znikają razem przy scrollu, dokładnie jak
   proszone: "karta... znika wraz ze zdjęciem". Trigger: JS, gdy .card jest
   140px od góry viewportu (scroll).

   Animacja wjazdu/wyjazdu przy ZMIANIE MODELU (klik) jest INNA i celowo
   NIE wisi na .image-wrap jako całości: zdjęcie i karta poruszają się
   NIEZALEŻNIE OD SIEBIE — <img> ślizga się w bok (lewo/prawo, patrz
   .omoda-models__image-link niżej), ALE karta ma się "nie slide left right,
   tylko delikatny fade in out z delikatnym slide up" (user) — patrz
   .omoda-models__card niżej, osobna animacja (opacity + translateY, nie
   translateX). Poprzednio (błędnie) obie rzeczy jechały razem jako jedna
   grupa na .image-wrap — naprawione tu przez rozdzielenie na dwa niezależne
   cele animacji. PANEL_EXIT_MS w JS musi być równe czasowi trwania
   .is-exiting niżej (150ms, na obu — skrócone z 300ms, user: "szybciej"). */
.omoda-models__image-wrap {
    position: relative;
    /* Zmniejszone z 32px — user: "samochod jest za nisko" (zbyt duży odstęp
       między ceną/tytułem a autem). */
    margin-top: 8px;
    /* Scroll-linked (JS, --omoda-card-fade) — BEZ czasowego `transition`.
       Poprzednio `transition:opacity 500ms` dawało realne opóźnienie
       względem pozycji scrolla (user scrolluje dalej, zanim 500ms dobiegnie
       końca) — user zgłosił to jako ".selected nachodzi na kartę", co było
       raczej skutkiem TEGO opóźnienia niż samego progu .selected. */
    opacity: var(--omoda-card-fade, 1);
}

.omoda-models__image-wrap.is-hidden {
    pointer-events: none;
}

.omoda-models__panel.is-exiting .omoda-models__image-link {
    transform: translateX(-32px);
    opacity: 0;
    transition: transform 150ms var(--omoda-ease), opacity 150ms var(--omoda-ease);
}

/* Wjazd: DWIE fazy, bo trzeba najpierw "po cichu" (bez transition) ustawić
   stan startowy (przesunięte+niewidoczne), zanim odpali się faktyczna
   animacja do stanu spoczynkowego (patrz JS, playImageEntrance — dwie
   klatki rAF między .is-entering a .is-entering-active). */
.omoda-models__panel.is-entering .omoda-models__image-link {
    transform: translateX(70px);
    opacity: 0;
    transition: none;
}

.omoda-models__panel.is-entering-active .omoda-models__image-link {
    transform: translateX(0);
    opacity: 1;
    transition: transform 150ms var(--omoda-ease), opacity 150ms var(--omoda-ease);
}

/* Karta specyfikacji/przycisków: NIE jedzie w bok razem ze zdjęciem — dostaje
   WŁASNĄ, delikatną animację (opacity + lekkie translateY, "slide up"),
   niezależną od poziomego ślizgu zdjęcia obok (user: "omoda-models__card to
   ma się nie slide left right tylko delikatny fade in out z delikatnym
   slide up"). Ten sam dwufazowy wzorzec wjazdu co zdjęcie/inne elementy. */
.omoda-models__panel.is-exiting .omoda-models__card {
    transform: translateY(-12px);
    opacity: 0;
    transition: transform 150ms var(--omoda-ease), opacity 150ms var(--omoda-ease);
}

.omoda-models__panel.is-entering .omoda-models__card {
    transform: translateY(12px);
    opacity: 0;
    transition: none;
}

.omoda-models__panel.is-entering-active .omoda-models__card {
    transform: translateY(0);
    opacity: 1;
    transition: transform 150ms var(--omoda-ease), opacity 150ms var(--omoda-ease);
}

.omoda-models__image-link {
    display: block;
    width: 100%;
    height: 100%;
    max-width: 870px;
    margin: 0 auto;
    cursor: pointer;
}

.omoda-models__image {
    display: block;
    width: 100%;
    height: auto;
    /* Tylko hover-scale zostaje na <img> (transform/opacity całej grupy
       image+card przeniesione na .image-wrap, wyżej) — transition na BAZOWEJ
       regule (nie tylko na :hover), żeby powrót po zjechaniu myszką też był
       płynny, nie tylko wejście w hover. */
    transition: transform 550ms var(--omoda-ease);
}

.omoda-models__image-link:hover .omoda-models__image {
    transform: scale(1.015);
}

.omoda-models__card {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 20px;
    background: #ffffff;
    box-shadow: 0 48px 100px 0 rgba(17, 12, 46, 0.15);
    padding: 20px 28px 20px 46px;
}

.omoda-models__specs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

.omoda-models__spec {
    display: flex;
    flex-direction: column;
    padding-inline: 32px;
}

.omoda-models__spec:first-child {
    padding-left: 0;
}

.omoda-models__spec + .omoda-models__spec {
    border-left: 1px solid var(--omoda-color-border, #e5e5e5);
}

.omoda-models__spec-value {
    font-size: 24px;
    font-weight: 700;
    color: #121212;
    font-variant-numeric: tabular-nums;
}

.omoda-models__spec-label {
    font-size: 16px;
    color: #959595;
}

.omoda-models__featured-buttons {
    display: flex;
    gap: 10px;
    flex-shrink: 0;
}

.omoda-models__featured-buttons .omoda-btn {
    padding: 0 32px !important;
    height: 44px;
    box-shadow: none !important;
}

/* Core .omoda-btn--outline/--primary są myślane pod ciemne tło (hero slider,
   header): biały obrys/tekst, białe wypełnienie. Karty w tej sekcji są białe,
   więc oba warianty muszą się tu odwrócić — dokładnie jak w Figmie (outline:
   ciemny obrys/tekst; primary: czarne wypełnienie/biały tekst). */
.omoda-models__card .omoda-btn--outline,
.omoda-models__card-item .omoda-btn--outline {
    color: #121212;
    border-color: rgba(18, 18, 18, 0.3);
}

.omoda-models__card .omoda-btn--outline:hover,
.omoda-models__card-item .omoda-btn--outline:hover {
    background-color: rgba(18, 18, 18, 0.06);
    border-color: #121212;
    color: #121212;
}

/* :focus osobno od :hover (user: "po kliknięciu dropdown znika, wygląda na
   to że jest biały font/strzałka na białym tle") — .omoda-btn--outline:focus
   w omoda-core.css wymusza !important (patrz tam, walka z [type="button"]
   motywu), więc TU też trzeba !important, inaczej (mimo wyższej
   specyficzności 0-3-0 vs 0-2-0) reguła bazowa i tak by wygrała — !important
   bije zawsze przed specyficznością, niezależnie od niej. Bez tego przycisk
   .omoda-btn--outline (np. .omoda-models__dropdown-toggle) w karcie dostawał
   po kliknięciu (:focus) biały tekst z reguły bazowej (myślanej pod ciemne
   tło) zamiast ciemnego — niewidoczny na białym tle karty. */
.omoda-models__card .omoda-btn--outline:focus,
.omoda-models__card-item .omoda-btn--outline:focus {
    background-color: rgba(18, 18, 18, 0.06) !important;
    border-color: #121212 !important;
    color: #121212 !important;
}

.omoda-models__card .omoda-btn--primary,
.omoda-models__card-item .omoda-btn--primary {
    background-color: #121212;
    border-color: #121212;
    color: #ffffff;
}

.omoda-models__card .omoda-btn--primary:hover,
.omoda-models__card-item .omoda-btn--primary:hover {
    background-color: #2b2b2b;
    border-color: #2b2b2b;
    color: #ffffff;
}

/* Analogicznie do outline:focus wyżej — patrz ten komentarz. */
.omoda-models__card .omoda-btn--primary:focus,
.omoda-models__card-item .omoda-btn--primary:focus {
    background-color: #121212 !important;
    border-color: #121212 !important;
    color: #ffffff !important;
}

/* Przycisk z rozwijaną listą linków (np. broszury/PDF-y) — zachowuje się jak
   zwykły przycisk (ta sama klasa .omoda-btn na <button>), po kliknięciu
   pokazuje popover z listą linków. Otwierane/zamykane przez JS (klasa
   is-open), tak jak dropdown w headerze (omoda-section-header/header.css). */
.omoda-models__dropdown-btn {
    position: relative;
    display: flex;
}

/* Trójkącik łączący przycisk z popoverem (user, druga tura: "jakiś pomysł
   na ten wewnętrzny dropdown?" → "strzałka/wskaźnik nad popoverem") —
   klasyczna technika: kwadrat 10x10 obrócony 45deg, w połowie schowany ZA
   menu (z-index niższy niż menu, menu go "obcina" swoją krawędzią), widoczny
   tylko czubek. Wyśrodkowany względem PRZYCISKU (.dropdown-btn, nie samego
   menu) — menu (min-width:220px) i przycisk rzadko mają identyczną
   szerokość, a to ma zawsze wskazywać na środek przycisku, niezależnie od
   różnicy szerokości. */
.omoda-models__dropdown-btn::before {
    content: '';
    position: absolute;
    left: 50%;
    top: calc(100% + 3px);
    width: 10px;
    height: 10px;
    background: #ffffff;
    transform: translateX(-50%) rotate(45deg);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: 19;
    transition: opacity var(--omoda-transition-base), visibility 0s var(--omoda-duration-base);
}

.omoda-models__dropdown-btn.is-open::before {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--omoda-transition-base), visibility 0s;
}

/* Odwrócony (czubek w dół, do przycisku) i przy dole, gdy popover otwiera
   się w górę (.is-drop-up, patrz niżej). */
.omoda-models__dropdown-btn.is-drop-up::before {
    top: auto;
    bottom: calc(100% + 3px);
}

.omoda-models__dropdown-toggle {
    /* user (druga tura): "niepotrzebnie label przycisku jest do lewej,
       ma być wyśrodkowany" — poprzednie justify-content:space-between
       (etykieta lewo/strzałka prawo) faktycznie przesuwało tekst od środka.
       Strzałka wychodzi więc CAŁKOWICIE z przepływu flex (position:absolute
       na .omoda-models__dropdown-caret niżej, przypięta do prawego
       paddingu) — flex ma wtedy tylko JEDNO "dziecko" (etykietę), więc
       justify-content:center centruje naprawdę, niezależnie od strzałki. */
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.omoda-models__dropdown-caret {
    /* Ten sam SVG (stroke, nie border-trick) co .omoda-header__chevron —
       user: poprzedni border(45deg)-na-<span> wyglądał "brzydko, nierówno"
       (inline element ignorujący width/height + subpixelowe krzywizny przy
       7px). SVG ma stałą, czystą geometrię niezależnie od rozmiaru czcionki. */
    position: absolute;
    top: 50%;
    /* Dopasowane do poziomego paddingu przycisku w każdym kontekście (20px
       karta, 32px featured — patrz reguły .omoda-models__card-buttons/
       .omoda-models__featured-buttons .omoda-btn niżej/wyżej), żeby strzałka
       miała ten sam "oddech" od krawędzi co reszta treści przycisku —
       position:absolute liczy się od padding boxa, więc bez tego lądowałaby
       dokładnie na krawędzi obramowania. */
    right: 20px;
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    transform: translateY(-50%);
    transition: transform var(--omoda-transition-fast);
}

.omoda-models__featured-buttons .omoda-models__dropdown-caret {
    right: 32px;
}

/* Ten przycisk (jedyny z ikoną w .featured-buttons) auto-szerokości — bez
   tej reguły padding zostawał 0 32px z .featured-buttons .omoda-btn wyżej,
   czyli DOKŁADNIE tyle, ile zajmuje sama etykieta + prawy padding, bez
   żadnego zapasu na strzałkę (position:absolute, right:32px — czyli w
   PRAWO od granicy content-boxa, więc nachodziła na ostatnie znaki tekstu).
   +22px z każdej strony (symetrycznie, żeby tekst został wyśrodkowany)
   robi miejsce na strzałkę (14px) + odstęp (8px), bez zmiany right:32px
   strzałki powyżej (ta liczona jest od krawędzi przycisku, niezależnie od
   jego paddingu). */
.omoda-models__featured-buttons .omoda-models__dropdown-toggle {
    padding: 0 54px !important;
}

.omoda-models__dropdown-btn.is-open .omoda-models__dropdown-caret {
    transform: translateY(-50%) rotate(180deg);
}

.omoda-models__dropdown-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    /* 100% (nie sztywne 220px) — user: "chcę żeby był minimum szerokości
       przycisku select". Containing block dla position:absolute to
       .omoda-models__dropdown-btn (position:relative), czyli DOKŁADNIE box
       przycisku — 100% = ta sama szerokość, jako DOLNA granica (menu i tak
       może być szersze, treść linków go rozciąga, patrz max-width niżej). */
    min-width: 100%;
    max-width: min(280px, calc(100vw - 32px));
    background: #ffffff;
    border-radius: 8px;
    /* Odchudzony cień (był 0 12px 32px / .18 — dużo mocniejszy niż nowy,
       delikatny cień karty obok, patrz .omoda-models__card-item) — user
       (druga tura): "nie podoba mi się ten wew dropdown", spójność z resztą
       to pierwszy krok; patrz też propozycje w odpowiedzi na czacie. */
    box-shadow: 0 8px 24px rgba(18, 18, 18, 0.1);
    padding: 10px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(-6px);
    z-index: 20;
    transition: opacity var(--omoda-transition-base), transform var(--omoda-transition-base), visibility 0s var(--omoda-duration-base);
}

.omoda-models__dropdown-btn.is-open .omoda-models__dropdown-menu {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
    transition: opacity var(--omoda-transition-base), transform var(--omoda-transition-base), visibility 0s;
}

/* "Ucina się jak się kończy dropdown" (user) — dotyczy głównie mega menu w
   nagłówku, gdzie karty są wewnątrz przewijanego (overflow-y:auto) panelu:
   popover karty z ostatniego wiersza nie mieścił się w widocznym obszarze
   poniżej przycisku. JS (models-section.js) dolicza .is-drop-up, gdy nad
   przyciskiem jest więcej miejsca niż pod nim — wtedy popover otwiera się
   W GÓRĘ zamiast w dół, tym samym mechanizmem co is-open (te same
   opacity/transform, tylko top/bottom zamienione miejscami). */
.omoda-models__dropdown-btn.is-drop-up .omoda-models__dropdown-menu {
    top: auto;
    bottom: calc(100% + 8px);
    transform: translateY(6px);
}

.omoda-models__dropdown-btn.is-drop-up.is-open .omoda-models__dropdown-menu {
    transform: translateY(0);
}

.omoda-models__dropdown-item {
    /* flex (nie block) — user: "ikonka pliku przy każdym linku, łatwiej
       rozpoznać co to za link". Ikona + etykieta w rzędzie, wyśrodkowane
       w pionie. */
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    border-radius: 5px;
    color: #121212;
    text-decoration: none !important;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background-color var(--omoda-transition-fast);
}

.omoda-models__dropdown-item:hover {
    background-color: rgba(18, 18, 18, 0.06);
}

.omoda-models__dropdown-item-icon {
    flex-shrink: 0;
    color: #5c5c5c;
}

/* ---------- Widok: siatka kart ---------- */

.omoda-models__grid-row {
    flex: 1;
    min-width: 0;
}

.omoda-models__grid-track {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
}

/* height:100% + flex column = wszystkie karty w tym samym rzędzie (grid) albo
   w tej samej karuzeli (mobile, flex row) mają jednakową wysokość niezależnie
   od tego, czy doszedł wiersz omnibusa — CSS Grid/Flex domyślnie rozciąga
   elementy w poprzek osi (align-items:stretch), więc wystarczy nie ustawiać
   sztywnej wysokości i dać przyciskom margin-top:auto (patrz niżej). */
.omoda-models__card-item {
    position: relative;
    background: #ffffff;
    /* Bardzo delikatny cień (user: "delikatny shadow bardzo delikatny") —
       tylko tyle, żeby karta odrywała się od jasnego tła (#f9f9f9 sekcji,
       teraz też mega menu w nagłówku), bez wyraźnej "unoszącej się" karty. */
    box-shadow: 0 2px 10px rgba(18, 18, 18, 0.06);
    height: 100%;
    display: flex;
    flex-direction: column;
    padding: 16px;
}

.omoda-models__card-item.is-filtered-out,
.omoda-models__card-item.is-hidden-page {
    display: none;
}

/* Ślizganie przy zmianie strony siatki (strzałki/kropki) — user: "przy
   karuzeli powinno przy slide right/left być animacja ładna". Sekwencyjnie:
   aktualne karty najpierw znikają w stronę kierunku (JS dodaje .is-page-
   exiting-next/-prev na czas GRID_PAGE_EXIT_MS), DOPIERO PO tym nowe karty
   stają się widoczne i wjeżdżają z przeciwnej strony (.is-page-entering-*,
   zdjęte po dwóch klatkach rAF, żeby faktycznie zagrała tranzycja do stanu
   spoczynkowego) — ten sam wzorzec co przy zmianie modelu w widoku featured. */
.omoda-models__card-item.is-page-exiting {
    display: flex;
    transition: transform 220ms var(--omoda-ease), opacity 220ms var(--omoda-ease);
}

.omoda-models__card-item.is-page-exiting-next {
    transform: translateX(-24px);
    opacity: 0;
}

.omoda-models__card-item.is-page-exiting-prev {
    transform: translateX(24px);
    opacity: 0;
}

.omoda-models__card-item.is-page-entering {
    transition: none;
    opacity: 0;
}

.omoda-models__card-item.is-page-entering-next {
    transform: translateX(24px);
}

.omoda-models__card-item.is-page-entering-prev {
    transform: translateX(-24px);
}

.omoda-models__card-item:not(.is-page-entering):not(.is-page-exiting) {
    transition: transform 260ms var(--omoda-ease), opacity 260ms var(--omoda-ease);
}

.omoda-models__card-image-wrap {
    aspect-ratio: 271 / 152;
    overflow: hidden;
}

/* Badge (np. "NOWOŚĆ") w widoku gridowym — nałożony na zdjęcie, jako
   bezpośrednie dziecko .card-item (position:relative niżej), NIE zagnieżdżony
   w .card-image-wrap (które ma overflow:hidden — user chciał uniknąć
   jakiegokolwiek przycinania badge'a przez ten box). */
.omoda-models__card-item > .omoda-models__badges {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 2;
    margin: 0;
}

/* Obrazek w rogu (np. logo technologii) — ten sam wzorzec co "Galeria
   dodatkowa" w Hero Sliderze (stała wysokość), tylko prawy GÓRNY róg.
   Wysokość sterowana globalnie (Omoda PGD → Ustawienia globalne, patrz
   Omoda_Models_Section::print_global_style_vars()) przez
   --omoda-corner-image-height na :root, nie sztywną wartością tutaj.
   Właściwości WIZUALNE (wysokość/proporcje) na GOŁEJ klasie, BEZ wymogu
   konkretnego rodzica — ten sam obrazek renderuje się w dwóch różnych
   kontekstach z różnym bezpośrednim rodzicem (.omoda-models__card-item w
   siatce/mega menu, .omoda-pricing__row-actions w widoku listy Cennika),
   więc reguła zawężona do jednego z nich (jak było tu wcześniej) nie łapała
   drugiego — zmierzone wprost: w Cenniku obrazek renderował się z wysokością
   ~111px (przejęte auto/max-width:100% z resetu motywu/Elementora) zamiast
   zadanych 40px, bo selektor `.card-item > .corner-image` po prostu nie
   pasował do `.row-actions > .corner-image`. Pozycjonowanie (position/top/
   right/z-index) zostaje osobno, per kontekst — patrz reguły niżej i w
   pricing-section.css. !important na height/width/max-width — Elementor ma
   własny reset ".elementor img{max-width:100% !important... }" (ten sam,
   udokumentowany problem co przy .omoda-hero-slider__gallery-img). */
.omoda-models__corner-image {
    height: var(--omoda-corner-image-height, 40px) !important;
    width: auto !important;
    max-width: none !important;
    display: block;
    border-radius: 2px;
    pointer-events: none;
}

/* z-index WYŻEJ niż samo zdjęcie modelu (2 > brak/auto na .card-image, które
   nie jest position:owane) — user: ma być zawsze nad zdjęciem, nigdy pod nim. */
.omoda-models__card-item > .omoda-models__corner-image {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 2;
}

.omoda-models__card-image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Auto "odjeżdża" w lewo i "wjeżdża" z prawej na hover (user) — .card-image-wrap
   ma overflow:hidden (patrz wyżej), więc translateX poza granice wrapa jest
   naturalnie przycinany, dając efekt zjazdu z ekranu/wjazdu zza kadru BEZ
   fade (user: "ma nie być fade in out").
   Historia dostrajania dystansu (kolejne tury feedbacku):
   900px → auto pokonywało go w tym samym czasie co później 450px, więc
   widoczna jazda była bardzo szybka, a nadmiar dystansu to czysty "martwy"
   czas bez niczego na ekranie.
   450px → wciąż ZA DUŻO: auto znikało (przy typowej szerokości karty w tym
   gridzie, ~260-300px) na długo PRZED dotarciem do -450px, więc dalej jechało
   "w próżni" zanim nastąpił skok — user: "jak zniknie auto, ma pojawić się
   OD RAZU z prawej strony", czyli zero przerwy między zniknięciem a
   ponownym wjazdem.
   320px — dystans BLISKI faktycznej szerokości karty (+ margines), więc skok
   następuje niemal DOKŁADNIE w momencie zniknięcia, nie po dodatkowej,
   niewidocznej jeździe.
   PRAWDZIWY, NATYCHMIASTOWY skok w połowie: DWIE klatki na tym samym offsecie
   (wcześniejsza próba: 50%/50%) NIE działają jak dwustronna nieciągłość —
   w @keyframes druga reguła na TYM SAMYM offsecie po prostu NADPISUJE
   pierwszą (jak zwykła kaskada CSS), więc cała animacja jechała tylko w
   JEDNĄ stronę (0→+320→0), bez żadnego skoku w lewo — zmierzone wprost
   klatka po klatce. Właściwa technika: `animation-timing-function:
   steps(1, jump-start)` USTAWIONE NA KLATCE 50% — steruje sposobem
   przejścia DO NASTĘPNEJ klatki (50.01%), wymuszając natychmiastową zmianę
   wartości na starcie tego mikroskopijnego segmentu (0.01% = ~0.075ms z
   750ms) zamiast płynnej interpolacji. Segmenty PRZED (0-50%, zjazd w lewo)
   i PO (50.01-100%, wjazd z prawej) używają domyślnego ease-in-out (user:
   "ease in ease out") z animation shorthand niżej — tylko sam skok jest
   `steps`. Włącznik/wyłącznik i wysokość obrazka w rogu — patrz komentarz
   przy .corner-image wyżej, ta sama globalna opcja steruje wyłączeniem
   animacji (Omoda PGD).

   Trigger to `.is-driving` (JS, dodawane na mouseenter, zdejmowane dopiero
   w `animationend`), NIE `:hover` bezpośrednio — user: "jak zejdę kursorem
   z tego, to ta animacja ma się dokończyć, a nie przerywać". Samo `:hover`
   nie potrafi tego dać: w momencie zjechania kursorem przestaje pasować,
   więc `animation` natychmiast znika z elementu (twardy skok do stanu
   spoczynkowego w połowie jazdy) — patrz models-section.js. */
@keyframes omoda-models-card-drive-by {
    0% {
        transform: translateX(0);
    }
    50% {
        transform: translateX(-320px);
        animation-timing-function: steps(1, jump-start);
    }
    50.01% {
        transform: translateX(320px);
    }
    100% {
        transform: translateX(0);
    }
}

.omoda-models__card-image-wrap.is-driving .omoda-models__card-image {
    animation: omoda-models-card-drive-by 750ms ease-in-out;
}

.omoda-models__card-body {
    margin-top: 16px;
}

.omoda-models__card-title {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: #121212;
}

.omoda-models__card-body .omoda-models__price {
    align-items: flex-start;
    text-align: left;
    margin-top: 4px;
}

.omoda-models__card-body .omoda-models__price-sale,
.omoda-models__card-body .omoda-models__price-solo {
    font-size: 16px;
}

/* Przyciski zawsze do dołu karty (margin-top:auto zjada resztę wolnej
   przestrzeni ponad nimi) — omnibus jest teraz WEWNĄTRZ .card-body, tuż pod
   ceną (user), więc nie wpływa na to wyrównanie: przyciski to osobny flex
   item, dociskany do dołu niezależnie od wysokości .card-body. */
.omoda-models__card-buttons {
    margin-top: auto;
    padding-top: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.omoda-models__card-item .omoda-models__omnibus {
    margin-top: 10px;
    text-align: left;
}

.omoda-models__card-buttons .omoda-btn {
    width: 100%;
    padding: 0 20px !important;
    height: 42px;
    font-size: 14px !important;
    box-shadow: none !important;
}

/* Kreski jak w Hero Sliderze (nie kropki) — nieaktywna: cienki ciemny obrys,
   aktywna/hover: pełne wypełnienie. Widoczne tylko na desktopie/tablecie —
   mobile ma cienki pasek postępu zamiast tego (patrz media query niżej). */
.omoda-models__dots {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 32px;
}

.omoda-models__dot {
    width: 28px !important;
    height: 3px !important;
    padding: 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    border: 0 !important;
    background: transparent !important;
    box-shadow: inset 0 0 0 1px rgba(18, 18, 18, 0.3) !important;
    cursor: pointer;
    transition: background-color var(--omoda-transition-fast);
}

.omoda-models__dot:hover,
.omoda-models__dot.is-active {
    background: #121212 !important;
    box-shadow: none !important;
}

.omoda-models__progress {
    display: none;
    margin-top: 24px;
    height: 2px;
    background: #e5e5e5;
    position: relative;
    overflow: hidden;
}

.omoda-models__progress span {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background: #121212;
    transition: width var(--omoda-transition-base), left var(--omoda-transition-base);
}

/* ---------- Mobile / tablet ---------- */

@media (max-width: 1024px) {
    .omoda-models__grid-track {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 767px) {
    .omoda-models {
        padding-block: 56px;
    }

    /* Mobile pokazuje ZAWSZE karuzelę/siatkę niezależnie od [data-view]
       (patrz .featured{display:none!important} niżej) — więc, tak jak widok
       grid na desktopie, tło ma być JEDNOLITE #f9f9f9 (user: "na mobile te
       taby [tło] też"), a nie gradient myślany pod widok pojedynczego modelu. */
    .omoda-models[data-view="featured"] {
        background: #f9f9f9;
    }

    .omoda-models__heading {
        font-size: 30px;
    }

    /* Na mobile nie ma przełącznika widoku (usunięty — zawsze karuzela kart,
       patrz niżej) — filtr kategorii zawsze wyśrodkowany (nie ma switcha,
       więc nawet w .is-stuck nie ma potrzeby odjeżdżać w prawo — inaczej
       .is-stuck .filter{right:104px} rezerwowałby miejsce dla nieistniejącego
       przełącznika i wypychał pigułki poza ekran). */
    .omoda-models__switch {
        display: none;
    }

    /* Mobile pokazuje ZAWSZE karuzelę/siatkę (patrz .featured{display:none!important}
       niżej), niezależnie od [data-view] zapisanego w atrybucie (ustawianego
       z desktopowego przełącznika) — więc, tak jak w widoku "grid" na
       desktopie, toolbar nie ma tu ŻADNEGO sticky/kondensowania (user: "jak
       jest grid to nie ma fixed kategorii"). Nadpisuje z !important reguły
       scope'owane pod [data-view="featured"], które inaczej wciąż by się
       łapały (atrybut data-view bywa "featured" nawet na mobile). */
    .omoda-models__toolbar {
        position: static !important;
        opacity: 1 !important;
        background: transparent !important;
        box-shadow: none !important;
        pointer-events: auto !important;
        padding-bottom: 0 !important;
    }

    .omoda-models__filter {
        left: 50% !important;
        right: auto !important;
        transform: translate(-50%, -50%) !important;
    }

    .omoda-models__filter-btn {
        padding: 0 14px;
        font-size: 12px;
    }

    /* Zawsze widok "siatka" (= karuzela kart) na mobile, niezależnie od
       [data-view] (ustawianego z adminu/przełącznika desktopowego) —
       pojedynczy model z paskiem zakładek jest zbyt ciasny na małym ekranie. */
    .omoda-models__featured {
        display: none !important;
    }

    .omoda-models__grid {
        display: block !important;
    }

    .omoda-models__arrow {
        width: 34px;
        height: 34px;
    }

    /* Siatka na mobile: prawdziwa przewijana karuzela (natywny scroll-snap —
       płynniejszy i bardziej "realistyczny" niż JS-owe pokazywanie/ukrywanie
       stron), bez strzałek (sterowanie dotykiem), kolejna karta delikatnie
       widoczna z prawej (card < 100% szerokości toru). Pasek postępu zamiast
       kresek pod spodem. */
    .omoda-models__grid-outer .omoda-models__arrow {
        display: none;
    }

    .omoda-models__grid-track {
        display: flex;
        overflow-x: auto;
        /* Jawne — patrz komentarz przy .omoda-models__tabs-track wyżej w tym
           pliku (ten sam problem: pionowy scrollbar/swipe-capture na mobile). */
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        scroll-behavior: smooth;
        gap: 14px;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .omoda-models__grid-track::-webkit-scrollbar {
        display: none;
    }

    .omoda-models__card-item {
        flex: 0 0 84%;
        width: 84%;
        scroll-snap-align: start;
    }

    /* Na mobile karuzela steruje się scrollem, nie JS-paginacją — karty
       zawsze widoczne (paginacja "is-hidden-page" dotyczy tylko desktopu). */
    .omoda-models__card-item.is-hidden-page {
        display: flex;
    }

    /* Delikatne "wejście" treści karty, gdy karta wjeżdża na środek ekranu
       (JS dodaje .is-in-view przez IntersectionObserver). */
    .omoda-models__card-body,
    .omoda-models__card-buttons {
        opacity: 0;
        transform: translateY(10px);
        transition: opacity var(--omoda-transition-base), transform var(--omoda-transition-base);
    }

    .omoda-models__card-item.is-in-view .omoda-models__card-body {
        opacity: 1;
        transform: none;
    }

    .omoda-models__card-item.is-in-view .omoda-models__card-buttons {
        opacity: 1;
        transform: none;
        transition-delay: 70ms;
    }

    .omoda-models__dots {
        display: none;
    }

    .omoda-models__progress {
        display: block;
    }
}


/* Tryb "auto" paska zakładek/filtrów (Omoda PGD → Ustawienia globalne → "Modele — pasek ...
   przy scrollu"): JS przełącza --omoda-stuck-progress między 0 a 1 po przewinięciu o N px,
   a ponieważ zmienna jest ZAREJESTROWANA jako <number>, przeglądarka animuje ją płynnie
   (wszystkie calc(... * var(--omoda-stuck-progress)) w tym pliku jadą razem). W trybie
   domyślnym ("scroll") nie ma transition — wartość podąża za scrollem klatka po klatce. */
@property --omoda-stuck-progress {
    syntax: '<number>';
    inherits: true;
    initial-value: 0;
}

.omoda-models[data-sticky-mode="auto"] {
    transition: --omoda-stuck-progress 380ms var(--omoda-ease, cubic-bezier(0.22, 1, 0.36, 1));
}

/* Tryb "auto": --omoda-stuck-progress zmienia się BEZ udziału scrolla, a padding bloku
   nazwy/ceny (.omoda-models__selected) jest liczony z tej zmiennej — gdy się
   zmniejsza (-24px wysokości w przepływie), cała treść poniżej (zdjęcie, karta)
   "przeskakiwała" w górę o tyle pikseli, mimo że nikt nie scrolluje. Margines
   dokładnie równoważy zmianę wysokości (padding-top -32px·p, padding-bottom +8px·p),
   więc wysokość bloku w przepływie jest stała, a sam napis nadal płynnie "siada"
   bliżej paska. W trybie "cover" padding jest zamrożony — kompensacja zbędna. */
.omoda-models[data-sticky-mode="auto"] .omoda-models__selected {
    margin-bottom: calc(24px * var(--omoda-stuck-progress, 0));
}

.omoda-models[data-sticky-mode="auto"][data-selected-mode="cover"] .omoda-models__selected {
    margin-bottom: 0;
}

/* To samo dla samodzielnego toolbara (filtr + przełącznik widoku): jego wysokość
   też maleje z postępem (66px → 54px, -12px·p) — bez kompensacji treść poniżej
   skakała o te 12px w trakcie animacji. */
.omoda-models[data-sticky-mode="auto"][data-view="featured"] .omoda-models__toolbar {
    margin-bottom: calc(12px * var(--omoda-stuck-progress, 0));
}

@media (prefers-reduced-motion: reduce) {
    .omoda-models[data-sticky-mode="auto"] {
        transition: none;
    }
}
