/* ══════════════════════════════════════════════════════════════════════════
   YANKEE VISUAL SYSTEM — warstwa wspólna (L1 tokeny, L2 prymitywy)
   Faza 1, 08.09.2026. Plik NIE jest wpięty w żadną stronę produkcyjną;
   używa go wyłącznie UI Lab (`/ui-lab/`). Wpięcie w serwis to faza 2.

   PO CO POWSTAŁ. Audyt (docs/visual-system/00-audit.md) znalazł trzy komplety
   tokenów opisujące te same pojęcia różnymi nazwami i różnymi wartościami:
   serwis (`assets/system.css`), strona wzorcowa (`oferta-jeep/index.html`)
   i panel (`admin.html`). Ten plik jest warstwą SEMANTYCZNĄ: mówi „powierzchnia
   podniesiona", a nie „#1D1D21", i podpina pod to wartości.

   CZEGO NIE ROBI. Nie zastępuje `system.css` i nie rusza modeli składu
   C/E/F — te zostają. Wzorzec mówi, ile jest kolumn i jak szerokich; model
   składu mówi, co się dzieje z prozą wewnątrz kolumny.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── L1 · TOKENY ─────────────────────────────────────────────────────────── */
:root{
  /* POWIERZCHNIE. Nazwa mówi o roli, nie o kolorze — dlatego ten sam token
     działa w trybie jasnym i ciemnym po podmianie wartości niżej. */
  --vs-canvas:#0B0B0C;              /* tło całej strony */
  --vs-surface:#141417;             /* sekcja wyróżniona z tła */
  --vs-surface-elevated:#1D1D21;    /* karta, panel */
  /* Delikatne pole w kolorze akcentu. WARTOŚĆ MUSI STAĆ W KAŻDEJ KLASIE
     AKCENTU OSOBNO — ta sama pułapka podstawiania co przy `--vs-accent-text`:
     zapis przez `var()` w korzeniu utrwaliłby tu pomarańcz rdzenia i wybrana
     karta na akcencie zielonym miała zieloną ramkę na pomarańczowym polu.
     Zgłoszone przy budowie P12-P16. */
  --vs-surface-accent:rgba(255,95,31,.10);
  --vs-surface-glass:rgba(255,255,255,.07);
  --vs-canvas-light:#F7F7F5;
  --vs-surface-light:#FFFFFF;

  /* PISMO. `on-image` jest osobne, bo tekst na zdjęciu potrzebuje pełnej
     bieli i cienia, a nie koloru pisma z sekcji. */
  --vs-text:#EDE9E5;
  --vs-text-secondary:rgba(237,233,229,.80);
  --vs-text-muted:rgba(237,233,229,.58);
  --vs-text-on-image:#FFFFFF;
  /* Akcent UŻYWANY DO PISMA. Na ciemnym to ten sam kolor co wypełnienie;
     motyw jasny podmienia go na przyciemnioną odmianę (patrz `.vs-light`). */
  /* UWAGA NA PODSTAWIANIE. `--vs-accent-text:var(--vs-accent)` zapisane TUTAJ
     podstawia się wartością z `:root`, a potem dziedziczy się już jako gotowy
     kolor — więc każdy wariant akcentu dostawałby pomarańcz z korzenia.
     Dlatego wartość dla motywu ciemnego stoi w KAŻDEJ klasie akcentu osobno,
     a motyw jasny podmienia ją na odmianę przyciemnioną, też imiennie. */
  --vs-accent-ciemny:#A83400;
  --vs-accent-text:#FF5F1F;
  --vs-text-accent:var(--vs-accent-text);

  /* BARWY STANU. Systemu bez nich nie da się użyć w panelu, a doklejanie ich
     przy każdej karcie kończy się czterema odcieniami zieleni.
     ZASADA, KTÓRA IDZIE Z NIMI: stan niesie SŁOWO i KSZTAŁT, kolor jest
     trzeci. Informacja nie może zależeć wyłącznie od barwy. */
  --vs-stan-ok:#2E9E5B;      --vs-stan-ok-text:#1F7A44;
  --vs-stan-uwaga:#E2A400;   --vs-stan-uwaga-text:#8A6400;
  --vs-stan-blad:#D93A3A;    --vs-stan-blad-text:#B02525;
  --vs-stan-neutralny:#8A857D;

  /* AKCENT — SEMANTYCZNY, NIE „POMARAŃCZ". Wariant ustawia się klasą na
     dowolnym pojemniku (`.vs-accent--green` itd.), więc ten sam wzorzec
     obsługuje kategorię dziecięcą, biznes i sport bez kopiowania kodu.
     W jednej sekcji obowiązuje JEDEN akcent — to zasada L0, nie sugestia. */
  --vs-accent:#FF5F1F;
  --vs-accent-strong:#D9430A;
  --vs-accent-soft:rgba(255,95,31,.16);
  --vs-on-accent:#1A0A02;

  /* GEOMETRIA. Cztery promienie zamiast siedmiu przypadkowych.
     `--vs-radius-pill` osobno, bo to nie jest ten sam wymiar co narożnik karty. */
  --vs-radius-sm:6px;
  --vs-radius-md:10px;
  --vs-radius-lg:16px;
  --vs-radius-xl:24px;
  --vs-radius-pill:999px;
  --vs-border:1px solid rgba(255,255,255,.12);
  --vs-border-accent:1px solid var(--vs-accent);
  --vs-shadow-soft:0 10px 30px rgba(0,0,0,.28);
  --vs-shadow-media:0 24px 70px rgba(0,0,0,.45);
  --vs-blur-glass:14px;

  /* ODSTĘPY. Jedna skala bazowa i cztery nazwy ROLI zbudowane na niej —
     żeby „odstęp między sekcjami" nie był co chwila inną liczbą. */
  --vs-1:4px;  --vs-2:8px;   --vs-3:12px;  --vs-4:16px;
  --vs-5:24px; --vs-6:32px;  --vs-7:48px;  --vs-8:64px;
  --vs-9:96px; --vs-10:128px;
  --vs-section-space:clamp(56px,7vw,120px);
  --vs-cluster-space:clamp(24px,3vw,48px);
  --vs-card-gap:clamp(12px,1.4vw,20px);
  --vs-card-padding:clamp(20px,2.2vw,32px);
  --vs-text-gap:clamp(10px,1.1vw,16px);
  --vs-inline-gap:10px;

  /* SIATKA */
  --vs-container:1680px;
  --vs-container-narrow:1240px;
  --vs-gutter:clamp(20px,4vw,56px);

  /* KROJE — te same, co w serwisie. Identyfikacja zostaje. */
  --vs-font-display:'Anton','Anton zapas',Impact,sans-serif;
  --vs-font-body:'DM Sans','DM Sans zapas',system-ui,sans-serif;

  /* SKALA TYPOGRAFICZNA. `display` to krój nagłówkowy wersalikami; `data`
     to liczby w kaflach — celowo osobno, bo rządzi nimi inna czytelność. */
  --vs-display-1:clamp(40px,6vw,88px);
  --vs-display-2:clamp(32px,4.4vw,64px);
  --vs-h1:clamp(28px,3.6vw,50px);
  --vs-h2:clamp(24px,2.8vw,38px);
  --vs-h3:clamp(18px,1.7vw,24px);
  --vs-eyebrow:12px;
  --vs-lead:clamp(16px,1.3vw,19px);
  --vs-body-lg:17px;
  --vs-body:15px;
  --vs-caption:13px;
  --vs-data-xl:clamp(36px,4.6vw,68px);
  --vs-data-lg:clamp(26px,2.6vw,38px);
  --vs-lh-display:1.02;
  --vs-lh-heading:1.12;
  --vs-lh-text:1.62;
  --vs-track-display:.01em;
  --vs-track-eyebrow:.2em;

  /* CZAS. Jedna wartość na ruch mikro i jedna na wejście. */
  --vs-ruch:.16s ease;
  --vs-ruch-wejscie:.4s cubic-bezier(.2,.7,.3,1);
}

/* TRYB CIEMNY WEWNĄTRZ JASNEJ STRONY (08.09.2026, faza 2).
   Ciemny pas w środku jasnej strony to nie wyjątek, tylko stały chwyt:
   tak zbudowany jest pas kontaktu na podstronach oferty i tak działa wezwanie
   na końcu strony. Bez tej klasy trzeba by ustawiać kolory ręcznie — a wtedy
   pierwsze, co się psuje, to formularz: białe pismo zostaje na jasnym tle.
   Wartości są przepisane z korzenia, bo `var()` w tym miejscu podstawiłoby
   wartość już nadpisaną przez `.vs-light` wyżej — ta sama pułapka, co przy
   `--vs-accent-text`. */
.vs-light .vs-dark, .vs-dark{
  --vs-canvas:#0B0B0C;
  --vs-surface:#141417;
  --vs-surface-elevated:#1D1D21;
  --vs-surface-glass:rgba(255,255,255,.07);
  --vs-text:#EDE9E5;
  --vs-text-secondary:rgba(237,233,229,.80);
  --vs-text-muted:rgba(237,233,229,.58);
  --vs-border:1px solid rgba(255,255,255,.12);
  --vs-shadow-soft:0 18px 50px rgba(0,0,0,.45);
}

/* TRYB JASNY — te same nazwy ról, inne wartości. Nie ma osobnego systemu. */
.vs-light{
  --vs-canvas:#F7F7F5;
  --vs-surface:#FFFFFF;
  --vs-surface-elevated:#FFFFFF;
  --vs-surface-glass:rgba(20,17,13,.05);
  --vs-text:#14110D;
  --vs-text-secondary:#4A443C;
  --vs-text-muted:#6B645C;
  --vs-border:1px solid #E3DED7;
  --vs-shadow-soft:0 10px 30px rgba(20,17,13,.10);
}

/* WARIANTY AKCENTU. Dowód, że wzorce nie są przywiązane do jednego koloru.

   DWIE POPRAWKI Z 08.09.2026, obie z policzonego kontrastu, nie z wrażenia:

   1. PISMO NA AKCENCIE (przycisk główny, plakietka) musiało wyjść ponad 4,5:1.
      Zmierzone wcześniej: clay 4,07 · red 4,17 · blue 4,50 — czyli dwa warianty
      poniżej progu i jeden dokładnie na nim. Po zmianie wszystkie mają zapas:
      core 6,47 · clay 4,55 · green 5,77 · blue 4,75 · red 4,55 · yellow 8,94.

      ODCIEŃ DO PISMA MIERZONY NA NAJJAŚNIEJSZYM TLE, NA KTÓRYM STOI, a nie na
      płótnie. Pierwsza kalibracja brała `--vs-canvas` (#0B0B0C) i wyglądała
      dobrze; na sekcji wyróżnionej (#141417) clay spadał do 4,25, a blue do
      4,44 — oba pod progiem. Po przeliczeniu wobec powierzchni I karty:
      clay #D4664C (5,08 / 4,64) i blue #3E8BEE (5,37 / 4,91).

      TO SAMO PO STRONIE JASNEJ. Odcienie dla motywu jasnego byly liczone na
      bieli i papierze, ale nie na POLU AKCENTU (`--vs-surface-accent`, czyli
      np. #F8DFD3). Tam core spadal do 4,13, green do 4,20, yellow do 4,22 —
      zmierzone na P07. Po przeliczeniu: core #A83400, green #186237,
      yellow #7A5800; wszystkie ponad 5,2 takze na polu akcentu.

   2. AKCENT JAKO KOLOR PISMA NIE NADAJE SIĘ NA JASNE TŁO. Core na bieli daje
      3,04:1, yellow 2,20:1 — nadtytuł w motywie jasnym był nieczytelny.
      Stąd `--vs-accent-text`: na ciemnym to ten sam akcent, na jasnym jego
      przyciemniona odmiana (5,26 do 6,69 na bieli). Kolor wypełnienia zostaje
      jasny — zmienia się tylko odcień UŻYWANY DO PISMA. */
.vs-accent--core  {--vs-accent:#FF5F1F;--vs-accent-strong:#D9430A;--vs-accent-soft:rgba(255,95,31,.16);--vs-on-accent:#0B0B0C;--vs-accent-ciemny:#A83400;--vs-accent-text:#FF5F1F;--vs-surface-accent:rgba(255,95,31,.10)}
.vs-accent--clay  {--vs-accent:#C8563C;--vs-accent-strong:#A03F29;--vs-accent-soft:rgba(200,86,60,.16);--vs-on-accent:#0B0B0C;--vs-accent-ciemny:#A03F29;--vs-accent-text:#D4664C;--vs-surface-accent:rgba(200,86,60,.10)}
.vs-accent--green {--vs-accent:#2E9E5B;--vs-accent-strong:#1F7A44;--vs-accent-soft:rgba(46,158,91,.16);--vs-on-accent:#0B0B0C;--vs-accent-ciemny:#186237;--vs-accent-text:#2E9E5B;--vs-surface-accent:rgba(46,158,91,.10)}
.vs-accent--blue  {--vs-accent:#2C7BE5;--vs-accent-strong:#1D5CB8;--vs-accent-soft:rgba(44,123,229,.16);--vs-on-accent:#0B0B0C;--vs-accent-ciemny:#1D5CB8;--vs-accent-text:#3E8BEE;--vs-surface-accent:rgba(44,123,229,.10)}
/* Czerwony jako PISMO na ciemnym musial sie rozjasnic dwa razy. #D93A3A daje
   na plotnie 4,33 — pod progiem. #E04B4B poprawil plotno do 4,94, ale na
   karcie (#1D1D21) spadal do 4,22, bo pierwsza kalibracja brala tylko plotno.
   #E85C5C trzyma prog na wszystkich trzech tlach: 5,73 / 5,36 / 4,89.
   Wypelnienie zostaje #D93A3A — zmienia sie tylko odcien uzywany do liter. */
.vs-accent--red   {--vs-accent:#D93A3A;--vs-accent-strong:#B02525;--vs-accent-soft:rgba(217,58,58,.16);--vs-on-accent:#FFFFFF;--vs-accent-ciemny:#B02525;--vs-accent-text:#E85C5C;--vs-surface-accent:rgba(217,58,58,.10)}
.vs-accent--yellow{--vs-accent:#E2A400;--vs-accent-strong:#B88300;--vs-accent-soft:rgba(226,164,0,.18);--vs-on-accent:#0B0B0C;--vs-accent-ciemny:#7A5800;--vs-accent-text:#E2A400;--vs-surface-accent:rgba(226,164,0,.10)}

/* AKCENT W ROLI PISMA NA JASNYM TLE — imiennie dla każdej pary motyw + akcent.
   Zapis `var()` w `.vs-light` działałby tylko wtedy, gdy obie klasy stoją na
   TYM SAMYM elemencie; przy akcencie ustawionym na potomku motyw by przegrał.
   Dwanaście selektorów jest brzydsze, ale nie zależy od tego, kto gdzie stoi.
   Zmierzone na białym: 5,26 · 6,49 · 5,35 · 6,41 · 6,69 · 5,38. */
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--core),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--core{--vs-accent-text:#A83400}
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--clay),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--clay{--vs-accent-text:#A03F29}
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--green),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--green{--vs-accent-text:#186237}
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--blue),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--blue{--vs-accent-text:#1D5CB8}
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--red),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--red{--vs-accent-text:#B02525}
:is(.vs-light,.vs-tryb--mlodziez) :is(.vs-accent--yellow),
:is(.vs-light,.vs-tryb--mlodziez).vs-accent--yellow{--vs-accent-text:#7A5800}

/* AKCENT DO PISMA W CIEMNYM PASIE WEWNĄTRZ JASNEJ STRONY.
   Reguła `.vs-light .vs-accent--X` wyżej przyciemnia odcień pisma, bo na
   jasnym płótnie jasny akcent jest nieczytelny. Ciemny pas w środku takiej
   strony jest jednak nadal ciemny — i tam ten sam przyciemniony odcień daje
   2,5–3,0:1. Zmierzone na pilocie /oferta/mentalne: nadtytuł „02" 2,96:1,
   „03" 2,56:1, odnośnik powrotny 2,96:1. Dlatego `.vs-dark` przywraca
   wartość z motywu ciemnego. Wartości wypisane wprost, nie przez `var()` —
   ta sama pułapka podstawiania, co przy pierwszej wersji tokena. */
.vs-dark.vs-accent--core,
.vs-dark .vs-accent--core{--vs-accent-text:#FF5F1F}
.vs-dark.vs-accent--clay,
.vs-dark .vs-accent--clay{--vs-accent-text:#D4664C}
.vs-dark.vs-accent--green,
.vs-dark .vs-accent--green{--vs-accent-text:#2E9E5B}
.vs-dark.vs-accent--blue,
.vs-dark .vs-accent--blue{--vs-accent-text:#3E8BEE}
.vs-dark.vs-accent--red,
.vs-dark .vs-accent--red{--vs-accent-text:#E85C5C}
.vs-dark.vs-accent--yellow,
.vs-dark .vs-accent--yellow{--vs-accent-text:#E2A400}


/* TRYB PRODUKTOWY (panele). Ta sama rodzina, inna gęstość: mniej powietrza,
   mniejszy nagłówek, mniej rozmycia, wyższy kontrast danych. */
.vs-tryb--produkt{
  --vs-section-space:clamp(24px,2.4vw,40px);
  --vs-cluster-space:clamp(14px,1.4vw,20px);
  --vs-card-padding:clamp(14px,1.4vw,20px);
  --vs-radius-lg:12px;
  --vs-radius-xl:14px;
  --vs-blur-glass:0px;
  --vs-h1:clamp(20px,2vw,26px);
  --vs-h2:clamp(17px,1.5vw,21px);
  --vs-h3:16px;
  --vs-display-1:clamp(24px,2.4vw,32px);
  --vs-display-2:clamp(20px,2vw,26px);
  --vs-font-display:var(--vs-font-body);   /* w panelu nie krzyczymy wersalikami */

  /* SKALA LICZB TEŻ SCHODZI. Bez tego `--vs-data-xl` zostawało 68 px także
     w panelu, gdzie kafel ma 200 px szerokości — liczba wychodziła poza kafel
     albo zjadała opis. Zgłoszone przy budowie P19. */
  --vs-data-xl:clamp(24px,2.6vw,34px);
  --vs-data-lg:clamp(20px,2vw,26px);

  /* CZEGO TU CELOWO NIE MA: KOLORÓW.
     Tryb odpowiada za GĘSTOŚĆ, motyw za BARWĘ. Do 08.09.2026 stało tu
     `--vs-text-muted` z wartością z motywu ciemnego. `.vs-tryb--produkt`
     ma tę samą siłę selektora co `.vs-light` i stoi w arkuszu później, więc
     wygrywał — przygaszone pismo w JASNYM panelu miało kontrast 1,1:1,
     czyli było praktycznie niewidoczne. Tryb i motyw są prostopadłe i żaden
     nie może przejmować roli drugiego. */
}

/* TRYB MŁODZIEŻOWY. Jaśniej i żywiej, ale bez infantylności: zmieniają się
   powierzchnie i akcent, nie zmienia się struktura ani skala. */
.vs-tryb--mlodziez{
  --vs-canvas:#FBF7F0;
  --vs-surface:#FFFFFF;
  --vs-surface-elevated:#FFFFFF;
  --vs-text:#14110D;
  --vs-text-secondary:#4A443C;
  --vs-text-muted:#6B645C;
  --vs-border:1px solid #EBE3D6;
  --vs-radius-lg:20px;
  --vs-radius-xl:28px;
  --vs-shadow-soft:0 10px 30px rgba(20,17,13,.10);
}

/* ── L2 · PRYMITYWY ──────────────────────────────────────────────────────── */
.vs{background:var(--vs-canvas);color:var(--vs-text);
  font-family:var(--vs-font-body);font-size:var(--vs-body);line-height:var(--vs-lh-text);
  /* Adres pocztowy, odnosnik albo nazwa pliku to jedno slowo bez spacji.
     Bez tej linii takie slowo rozpycha kolumne i cala strona zaczyna sie
     przewijac w bok — wyszlo na probie bardzo dlugiej tresci (P12, P19).
     Wlasnosc jest dziedziczona, wiec wystarczy raz, na korzeniu systemu. */
  overflow-wrap:break-word}
.vs *{box-sizing:border-box}

.vs-sekcja{padding:var(--vs-section-space) 0;background:var(--vs-canvas)}
.vs-sekcja--surface{background:var(--vs-surface)}
.vs-in{max-width:var(--vs-container);margin:0 auto;padding:0 var(--vs-gutter)}
.vs-in--waska{max-width:var(--vs-container-narrow)}

/* SectionEyebrow — nadtytuł z kreską. Kreska jest częścią wzorca, nie ozdobą:
   to ona odróżnia otwarcie sekcji od zwykłej etykiety. */
.vs-eyebrow{display:flex;align-items:center;gap:var(--vs-3);margin:0 0 var(--vs-3);
  font-size:var(--vs-eyebrow);font-weight:700;letter-spacing:var(--vs-track-eyebrow);
  text-transform:uppercase;color:var(--vs-accent-text)}
.vs-eyebrow::before{content:"";width:36px;height:2px;background:currentColor;flex:none}
.vs-eyebrow--bez-kreski::before{display:none}

.vs-h1,.vs-h2,.vs-h3,.vs-display{margin:0;font-family:var(--vs-font-display);
  font-weight:400;text-transform:uppercase;letter-spacing:var(--vs-track-display);
  line-height:var(--vs-lh-heading);color:var(--vs-text)}
.vs-display{font-size:var(--vs-display-1);line-height:var(--vs-lh-display)}
.vs-display--2{font-size:var(--vs-display-2)}
.vs-h1{font-size:var(--vs-h1)}
.vs-h2{font-size:var(--vs-h2)}
.vs-h3{font-size:var(--vs-h3);font-family:var(--vs-font-body);font-weight:700;
  text-transform:none;letter-spacing:0}
.vs-tryb--produkt :is(.vs-h1,.vs-h2,.vs-display){text-transform:none;font-weight:700}

.vs-lead{margin:var(--vs-text-gap) 0 0;font-size:var(--vs-lead);
  line-height:var(--vs-lh-text);color:var(--vs-text-secondary)}
.vs-body{margin:var(--vs-text-gap) 0 0;color:var(--vs-text-secondary)}
.vs-caption{font-size:var(--vs-caption);color:var(--vs-text-muted)}

.vs-divider{height:1px;border:0;margin:var(--vs-6) 0;background:rgba(255,255,255,.12)}
.vs-light .vs-divider{background:#E3DED7}

/* PLAKIETKA. Tło liczone WOBEC PŁÓTNA, nie wobec tego, co akurat jest pod
   spodem. Przy przezroczystej barwie tło plakietki sumowało się z tłem karty,
   która sama bywa w kolorze akcentu — dwie warstwy tego samego odcienia dawały
   jaśniejszy brąz i kontrast spadał do 4,27:1 (zmierzone na P07 i P09).
   `color-mix` domyka to raz: kolor plakietki nie zależy od tego, gdzie stoi.
   Pierwsza deklaracja zostaje jako zapas dla przeglądarek bez `color-mix`. */
.vs-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;
  border-radius:var(--vs-radius-pill);background:var(--vs-surface-accent);
  color:var(--vs-accent-text);font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase}
@supports (background:color-mix(in srgb,red 10%,blue)){
  .vs-badge{background:color-mix(in srgb,var(--vs-accent) 14%,var(--vs-canvas))}
}
.vs-pill{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;
  border-radius:var(--vs-radius-pill);border:var(--vs-border);
  font-size:12px;color:var(--vs-text-secondary)}

.vs-numer{font-family:var(--vs-font-display);font-size:var(--vs-data-lg);
  line-height:1;color:var(--vs-accent-text)}
.vs-metric{display:flex;flex-direction:column;gap:6px}
.vs-metric__x{font-family:var(--vs-font-display);font-size:var(--vs-data-xl);
  line-height:1;color:var(--vs-text)}
.vs-metric__opis{font-size:var(--vs-caption);color:var(--vs-text-muted)}
.vs-metric__pasek{height:4px;border-radius:var(--vs-radius-pill);
  background:rgba(255,255,255,.12);overflow:hidden}
.vs-metric__pasek i{display:block;height:100%;background:var(--vs-accent)}

/* PRZYCISKI. Wysokość 48 px to cel dotykowy, nie estetyka — poniżej 44 px
   przycisk przestaje być wygodny na telefonie (WCAG 2.5.8). */
.vs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:48px;padding:0 22px;border:1px solid transparent;
  border-radius:var(--vs-radius-sm);font-family:var(--vs-font-body);
  font-size:14px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  text-decoration:none;cursor:pointer;transition:background var(--vs-ruch),border-color var(--vs-ruch)}
.vs-btn--main{background:var(--vs-accent);color:var(--vs-on-accent)}
.vs-btn--ram{background:transparent;color:var(--vs-text);border-color:rgba(255,255,255,.25)}
.vs-light .vs-btn--ram{border-color:#D8D2CA;color:var(--vs-text)}
/* PRZYCISK RAMKOWY NA FOTOGRAFII bierze pismo z palety obrazu, nie z sekcji.
   Bez tego w motywie jasnym `--vs-text` jest prawie czarny i przycisk stojący
   na ciemnym zdjęciu znika. Zgłoszone przy budowie P02, dotyczy też P01
   i każdego innego wzorca z wezwaniem na kadrze. */
.vs-scrim .vs-btn--ram,
.vs-glass .vs-btn--ram,
.vs-light .vs-scrim .vs-btn--ram,
.vs-light .vs-glass .vs-btn--ram{color:var(--vs-text-on-image);
  border-color:rgba(255,255,255,.42)}
.vs-link{color:var(--vs-accent-text);text-decoration:underline;text-underline-offset:3px;
  transition:color var(--vs-ruch),text-decoration-color var(--vs-ruch)}

/* NAJECHANIE KURSOREM. Przycisk główny miał odpowiedź od początku, ramkowy
   i odnośnik nie miały żadnej — a to one niosą większość wezwań w katalogu
   (P01, P07, P17, P18, P20). Test stanów przeszedł kursorem po każdym
   wezwaniu i pokazał, że dziesięć z nich nie reaguje w ogóle.
   `@media (hover:hover)` jest tu konieczne: na ekranie dotykowym stan
   najechania zostaje po stuknięciu i przycisk wygląda na zaznaczony. */
@media (hover:hover){
  .vs-btn--main:hover{background:var(--vs-accent-strong)}
  .vs-btn--ram:hover{border-color:var(--vs-accent);color:var(--vs-accent-text);
    background:var(--vs-surface-accent)}
  .vs-scrim .vs-btn--ram:hover,
  .vs-glass .vs-btn--ram:hover{color:var(--vs-text-on-image);
    border-color:#fff;background:rgba(255,255,255,.14)}
  .vs-link:hover{color:var(--vs-accent-strong);text-decoration-thickness:2px}
}

/* OGNISKO — jedno miejsce dla całego systemu. `:focus-visible`, nie `:focus`,
   żeby obwódka nie pojawiała się po kliknięciu myszą. */
.vs :is(a,button,summary,input,select,textarea,[tabindex]):focus-visible{
  outline:3px solid var(--vs-accent);outline-offset:3px;border-radius:2px}

/* MEDIA. Proporcja jest tokenem wzorca, nie decyzją na miejscu. */
.vs-media{position:relative;overflow:hidden;border-radius:var(--vs-radius-lg);
  background:var(--vs-surface-elevated)}
.vs-media img,.vs-media video{display:block;width:100%;height:100%;object-fit:cover}
.vs-media--16-9{aspect-ratio:16/9}
.vs-media--3-2{aspect-ratio:3/2}
.vs-media--4-3{aspect-ratio:4/3}
.vs-media--1-1{aspect-ratio:1/1}
.vs-media--pion{aspect-ratio:3/4}
/* CIEMNA PODSTAWA POD FOTOGRAFIĄ. Tekst na zdjęciu jest biały, więc dopóki
   zdjęcie się nie wczyta — albo gdy się nie wczyta w ogóle — pod spodem musi
   być ciemno. Bez tego w motywie jasnym biały tekst stoi przez chwilę (albo
   na stałe) na jasnym płótnie: zmierzone 1,07:1 na P13, gdy fotografia jeszcze
   nie doszła. Jedna deklaracja zamyka całą tę klasę awarii. */
.vs-scrim{background-color:#0B0B0C}

/* Przyciemnienie pod tekstem na zdjęciu. Bez niego kontrast zależy od tego,
   co akurat jest na fotografii — czyli od przypadku. */
.vs-scrim::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.15) 0%,rgba(0,0,0,.72) 100%)}

/* SZKŁO. Zasady: jeden poziom rozmycia, obowiązkowy zapas bez `backdrop-filter`,
   nigdy szkło na szkle. Sprawdzenie „na szkle" jest w regule niżej. */
.vs-glass{position:relative;z-index:1;
  background:rgba(11,11,12,.62);
  border:1px solid rgba(255,255,255,.16);
  border-radius:var(--vs-radius-lg);
  padding:var(--vs-card-padding);
  box-shadow:var(--vs-shadow-soft)}
@supports (backdrop-filter:blur(2px)){
  .vs-glass{background:var(--vs-surface-glass);
    backdrop-filter:blur(var(--vs-blur-glass)) saturate(1.12);
    -webkit-backdrop-filter:blur(var(--vs-blur-glass)) saturate(1.12)}
}
/* Szkło w szkle to zakaz systemowy — tu tylko go widać, w UI Lab jest opisany. */
.vs-glass .vs-glass{backdrop-filter:none;-webkit-backdrop-filter:none;
  background:rgba(255,255,255,.06);box-shadow:none}

/* KARTY. Cztery typy semantyczne, nie cztery style ramki. */
.vs-karta{display:flex;flex-direction:column;gap:var(--vs-text-gap);
  padding:var(--vs-card-padding);border:var(--vs-border);
  border-radius:var(--vs-radius-lg);background:var(--vs-surface-elevated);
  color:inherit;text-decoration:none;transition:transform var(--vs-ruch),border-color var(--vs-ruch)}
@media (hover:hover){
  .vs-karta--interaktywna:hover{transform:translateY(-2px);border-color:var(--vs-accent)}
}
.vs-karta--wybrana{border-color:var(--vs-accent);background:var(--vs-surface-accent)}
.vs-karta--metryka{gap:var(--vs-2)}
.vs-karta--szkło{background:var(--vs-surface-glass);border-color:rgba(255,255,255,.16)}
.vs-karta[aria-disabled="true"]{opacity:.5;pointer-events:none}

/* SIATKI. Przejścia 4→2→1 i 3→2→1 są świadome i wpisane raz. */
.vs-siatka{display:grid;gap:var(--vs-card-gap)}
.vs-siatka--2{grid-template-columns:repeat(2,minmax(0,1fr))}
.vs-siatka--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.vs-siatka--4{grid-template-columns:repeat(4,minmax(0,1fr))}
.vs-para{display:grid;gap:var(--vs-cluster-space);align-items:center}
.vs-para--5-7{grid-template-columns:minmax(0,5fr) minmax(0,7fr)}
.vs-para--6-6{grid-template-columns:minmax(0,6fr) minmax(0,6fr)}
.vs-para--7-5{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}
@media(max-width:1023px){
  .vs-siatka--4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .vs-siatka--3{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:768px){
  .vs-siatka--2,.vs-siatka--3,.vs-siatka--4{grid-template-columns:minmax(0,1fr)}
  .vs-para,.vs-para--5-7,.vs-para--6-6,.vs-para--7-5{grid-template-columns:minmax(0,1fr)}
}

/* RUCH. Kto prosił system o mniej ruchu, dostaje stronę bez animacji —
   łącznie z wejściami sekcji, bo to one najbardziej męczą. */
@media(prefers-reduced-motion:reduce){
  .vs *,.vs *::before,.vs *::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}
