/* ==========================================================================
   KOMPONENTY — słownik wizualny LP.
   Zasada: sekcja NIE definiuje własnego wyglądu przycisku, karty czy pola.
   Składa się z komponentów stąd. Nowy widok spoza Figmy budujemy z tych
   klocków — receptury w docs/DESIGN-SYSTEM.md.
   ========================================================================== */

/* ==========================================================================
   PRZYCISK — k-btn
   --------------------------------------------------------------------------
   Wspólne metryki pigułki z Figmy: padding 12/24, radius 64, tekst 12/16
   uppercase, letter-spacing -0.2 px, waga 700.

   Stany: na desktopie :hover, na dotyku :active („while pressing").
   Reguły hover zamykamy w @media (hover: hover), żeby na telefonie nie
   zostawały przyklejone po tapnięciu.

   Timing (--k-dur-btn + --k-ease-btn) jest zdjęty z belki oknoplast.com.pl:
   300 ms ease-in-out, symetrycznie w obie strony. Żaden wariant nie nadpisuje
   go na :hover — inaczej dojście i powrót przestałyby być jednakowe.
   ========================================================================== */

.k-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--k-space-2);
  min-height: 40px;
  padding: calc(12px - 1px) calc(24px - 1px);   /* 12/24 z Figmy minus 1 px obrysu */
  border: 1px solid transparent;
  border-radius: var(--k-radius-pill);
  font-family: var(--k-font-label);
  font-size: var(--k-fs-label);
  font-weight: var(--k-fw-bold);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-label);
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
  transition: background-color var(--k-dur-btn) var(--k-ease-btn),
              border-color var(--k-dur-btn) var(--k-ease-btn),
              color var(--k-dur-btn) var(--k-ease-btn),
              transform var(--k-dur-fast) var(--k-ease-out);
}

/* Wciśnięcie reaguje od razu — łagodny timing zostaje dla hoveru.
   `transition-duration` bez listy zbija do 160 ms wszystkie cztery
   własności z reguły wyżej, o to tu chodzi: pod palcem ma być natychmiast. */
.k-btn:active {
  transform: scale(0.98);
  transition-duration: var(--k-dur-fast);
}

/* Przycisk, który wjeżdża na scroll, musi mieć obie listy w JEDNEJ deklaracji.
   Reguła .k-js [data-reveal] z base.css (0-2-0) przykrywa shorthand z .k-btn
   (0-1-0) i skraca przejście do opacity+transform — bez tego CTA poradnika
   i „Sprawdź, gdzie kupić okno" z sekcji korzyści zmieniałyby kolor skokowo,
   jako jedyne przyciski na stronie.

   Nie da się tego naprawić regułą na .is-revealed: przeglądarka czyta timing
   ze stanu DOCELOWEGO, więc krótszy czas dla transform zacząłby obowiązywać
   już przy samym wjeździe i skrócił animację pojawiania z 520 ms do 160 ms.
   Nogi kolorów świadomie BEZ --k-reveal-delay: hover ma reagować od razu. */
.k-js .k-btn[data-reveal] {
  transition: opacity var(--k-dur-slow) var(--k-ease-out) var(--k-reveal-delay, 0ms),
              transform var(--k-dur-slow) var(--k-ease-out) var(--k-reveal-delay, 0ms),
              background-color var(--k-dur-btn) var(--k-ease-btn),
              border-color var(--k-dur-btn) var(--k-ease-btn),
              color var(--k-dur-btn) var(--k-ease-btn);
}

/* ---------- Primary: wypełnienie lime (Figma: Primary Buttons / normal) ---------- */

.k-btn--accent {
  background: var(--k-lime);
  border-color: var(--k-lime);
  color: var(--k-deep-mint);
}

.k-btn--accent:active,
.k-btn--accent[aria-pressed="true"] {
  background: transparent;
  color: var(--k-lime);
}

@media (hover: hover) {
  .k-btn--accent:hover {
    background: transparent;
    color: var(--k-lime);
  }
}

/* ---------- Primary odwrócony: obrys lime (hero „Znajdź salon") ---------- */

.k-btn--accent-outline {
  background: transparent;
  border-color: var(--k-lime);
  color: var(--k-lime);
}

.k-btn--accent-outline:active {
  background: var(--k-lime);
  color: var(--k-deep-mint);
}

@media (hover: hover) {
  .k-btn--accent-outline:hover {
    background: var(--k-lime);
    color: var(--k-deep-mint);
  }
}

/* ---------- Secondary: energy-mint (Figma: Secondary Buttons) ---------- */

.k-btn--primary {
  background: var(--k-energy-mint);
  border-color: rgba(16, 117, 103, 0.3);
  color: var(--k-white);
}

.k-btn--primary:active {
  background: var(--k-baby-mint);
  border-color: transparent;
  color: var(--k-deep-mint);
}

@media (hover: hover) {
  .k-btn--primary:hover {
    background: var(--k-baby-mint);
    border-color: transparent;
    color: var(--k-deep-mint);
  }
}

/* ---------- Soft: jasne tło (Figma: x3 Buttons) ---------- */

.k-btn--soft {
  background: var(--k-hl-mint);
  color: var(--k-deep-mint);
}

.k-btn--soft:active {
  background: var(--k-baby-mint);
}

@media (hover: hover) {
  .k-btn--soft:hover {
    background: var(--k-baby-mint);
  }
}

/* ---------- Glass: mała pigułka na tle zdjęcia (Figma: Button Small 32px) ---------- */

.k-btn--glass {
  min-height: 32px;
  padding: calc(8px - 1px) calc(16px - 1px);    /* 8/16 z Figmy minus 1 px obrysu */
  border-radius: var(--k-radius-md);
  background: var(--k-energy-mint);
  color: var(--k-white);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.k-btn--glass:active {
  background: var(--k-baby-mint);
  color: var(--k-deep-mint);
}

@media (hover: hover) {
  .k-btn--glass:hover {
    background: var(--k-baby-mint);
    color: var(--k-deep-mint);
  }
}

/* ---------- Ghost: „WSTECZ" w kreatorze (Figma: 355:4460, 567:7998) ----------
   Białe tło, brak obrysu. Etykieta jest miętowa, a wyszarza się dopiero wtedy,
   gdy nie ma dokąd wracać — tak pokazują to kolejne kroki w makiecie. */

.k-btn--ghost {
  background: var(--k-white);
  border-color: transparent;
  color: var(--k-energy-mint);
}

.k-btn--ghost:active {
  background: var(--k-baby-mint);
  color: var(--k-deep-mint);
}

@media (hover: hover) {
  .k-btn--ghost:hover {
    background: var(--k-baby-mint);
    color: var(--k-deep-mint);
  }
}

/* ---------- Na ciemnym tle: „WSTECZ" na karcie wyniku (Figma: 576:8041) ----------
   Obrys i napis baby-mint, pod kursorem rozjaśniają się do hl-mint. Zostaje obrysem —
   wypełnienie konkurowałoby z limonkowym CTA, które stoi tuż obok. */

.k-btn--on-deep {
  background: transparent;
  border-color: var(--k-baby-mint);
  color: var(--k-baby-mint);
}

.k-btn--on-deep:active {
  border-color: var(--k-hl-mint);
  color: var(--k-hl-mint);
}

@media (hover: hover) {
  .k-btn--on-deep:hover {
    border-color: var(--k-hl-mint);
    color: var(--k-hl-mint);
  }
}

.k-btn--block {
  display: flex;
  width: 100%;
}

.k-btn[disabled],
.k-btn[aria-disabled="true"] {
  opacity: 0.5;
  pointer-events: none;
}

/* Figma nie przygasza nieaktywnych przycisków kreatora — daje im własne kolory
   (Gray-300 na wypełnieniu, Gray-300 na etykiecie „WSTECZ"), więc te dwa warianty
   wychodzą spod reguły z opacity. */

.k-btn--primary[disabled],
.k-btn--primary[aria-disabled="true"] {
  opacity: 1;
  background: var(--k-gray-300);
  border-color: transparent;
  color: var(--k-white);
}

.k-btn--ghost[disabled],
.k-btn--ghost[aria-disabled="true"] {
  opacity: 1;
  color: var(--k-gray-300);
}

/* ---------- Ładowanie: spinner na przycisku (OKP-878, wysyłka formularza) ----------
   Etykieta zostaje w DOM z `visibility: hidden`, nie `display: none` — przycisk
   zachowuje dokładnie tę samą szerokość, więc spinner wjeżdża w jej miejsce bez
   skoku layoutu. Kolor spinnera to `currentColor`, żeby automatycznie pasował
   do dowolnego wariantu `.k-btn` (tu: `--primary` w stanie [disabled], stąd
   biały pierścień na szarym tle). Klasę `is-loading` nadaje i zdejmuje
   js/modules/form.js razem z atrybutem disabled. */

@keyframes k-spin {
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}

.k-btn__spinner,
.k-btn__progress {
  display: none;
}

/* `overflow: hidden`, żeby wypełnienie postępu nie wystawało poza pigułkę */
.k-btn.is-loading {
  position: relative;
  overflow: hidden;
}

.k-btn.is-loading .k-btn__label {
  visibility: hidden;
}

/* Postęp uploadu (OKP-878): wypełnienie od lewej w kolorze akcji na szarym tle
   [disabled]. Wartość 0–1 niesie zmienna `--k-upload-progress`, którą ustawia
   js/modules/form.js z `XMLHttpRequest.upload.onprogress`. `scaleX` zamiast
   `width`, bo to jedyna właściwość animowana na kompozytorze (bez reflow). */
.k-btn.is-loading .k-btn__progress {
  display: block;
  position: absolute;
  inset: 0;
  background: var(--k-energy-mint);
  transform-origin: left center;
  transform: scaleX(var(--k-upload-progress, 0));
  transition: transform var(--k-dur-fast) var(--k-ease-out);
  pointer-events: none;
}

.k-btn.is-loading .k-btn__spinner {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  /* nad wypełnieniem postępu */
  z-index: 1;
  width: var(--k-space-4);
  height: var(--k-space-4);
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--k-radius-pill);
  transform: translate(-50%, -50%);
  animation: k-spin var(--k-dur-spin) linear infinite;
}

/* ==========================================================================
   STREFA DOTYKU — 44 px bez zmiany wyglądu
   --------------------------------------------------------------------------
   Figma daje przyciskom 40 px wysokości, małym przyciskom 32, checkboxom 24,
   a linkom tekstowym 16–20. Apple HIG i WCAG 2.2 (2.5.8) chcą 44. Zamiast
   rozpychać makietę powiększamy sam obszar reagujący na dotyk: pseudoelement
   jest wyjęty z flow, więc nie rusza układu ani o piksel.

   Strefa ma STAŁE 44 px wysokości i jest centrowana na hoście — nie stały
   `inset`. Przy `inset` wynik zależałby od wysokości hosta, a ta waha się tu
   od 16 do 40 px, więc część elementów i tak zostałaby poniżej normy.

   Uwaga: `.k-check__input::after` jest zajęty przez znacznik „✓", dlatego
   checkbox dostaje `::before`. Ma `display: grid`, więc bez `position: absolute`
   pseudoelement stałby się elementem siatki i rozepchnął znacznik.
   ========================================================================== */

.k-btn,
.k-navi-top,
.k-link,
.k-form__more,
.k-header__logo,
.k-footer__logo,
.k-footer__policies a,
.k-check__input,
.k-stepper__dot,
.k-carousel__arrow {
  position: relative;
}

/* hosty szersze niż 44 px — rosną tylko w pionie */
.k-btn::after,
.k-link::after,
.k-form__more::after,
.k-header__logo::after,
.k-footer__logo::after,
.k-footer__policies a::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 44px;
  transform: translateY(-50%);
}

/* hosty węższe niż 44 px (checkbox 24×24, „TOP" 40×40, kropka steppera 36×36,
   strzałka karuzeli 40×40) — rosną w obu osiach */
.k-check__input::before,
.k-stepper__dot::after,
.k-navi-top::after,
.k-carousel__arrow::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

/* Świadomie POMINIĘTE:
   – linki w treści zdania (FAQ, klauzule zgód) — WCAG 2.5.8 wprost wyłącza
     „inline targets", a powiększenie zachodziłoby na sąsiednie wiersze tekstu;
   – linki produktowe w stopce (`.k-footer__tab`) — leżą w dwóch rzędach
     z odstępem 4 px, więc strefy 44 px zachodziłyby NA SIEBIE i tapnięcie
     trafiałoby w link z sąsiedniego rzędu. To byłoby gorsze niż mały cel. */

/* Loga są kotwicami (belka → góra LP, stopka → oknoplast.com.pl), a nie mają
   w Figmie żadnego stanu — ani hover, ani wciśnięcia. Po wygaszeniu plamy
   dotyku w base.css tapnięcie nie dawałoby nic, więc przygaszamy je na czas
   wciśnięcia. Krycie, nie kolor: to obrazki, nie tekst. */
.k-header__logo,
.k-footer__logo {
  transition: opacity var(--k-dur-fast) var(--k-ease-out);
}

.k-header__logo:active,
.k-footer__logo:active {
  opacity: 0.6;
}

/* ==========================================================================
   PRZYCISK OKRĄGŁY — k-btn-circle (Figma: Button Circle, Button X)
   48×48, ikona 22–24 px. Cztery warianty tła / obrysu.
   ========================================================================== */

.k-btn-circle {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border: 2px solid transparent;
  border-radius: 44px;
  transition: background-color var(--k-dur-btn) var(--k-ease-btn),
              border-color var(--k-dur-btn) var(--k-ease-btn),
              color var(--k-dur-btn) var(--k-ease-btn),
              transform var(--k-dur-fast) var(--k-ease-out);
}

/* Wciśnięcie jak w .k-btn — przycisk okrągły nie ma stanu hover w Figmie,
   więc na dotyku byłby zupełnie niemy (plamę gasi base.css). */
.k-btn-circle:active {
  transform: scale(0.94);
}

.k-btn-circle svg {
  width: 24px;
  height: 24px;
}

.k-btn-circle--v-full {
  background: var(--k-energy-mint);
  color: var(--k-white);
}

.k-btn-circle--w-full {
  background: var(--k-baby-mint);
  color: var(--k-deep-mint);
}

.k-btn-circle--v-stroke {
  border-color: var(--k-energy-mint);
  color: var(--k-energy-mint);
}

.k-btn-circle--w-stroke {
  border-color: var(--k-baby-mint);
  color: var(--k-baby-mint);
}

/* wariant zamknięcia — ikona obrócona o 45°, jak w Figmie (Button X) */
.k-btn-circle--close svg {
  transform: rotate(-45deg);
}

/* ==========================================================================
   POWRÓT NA GÓRĘ — k-navi-top (Figma: Navi, 40×40)
   ========================================================================== */

.k-navi-top {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 40px;
  height: 40px;                     /* rama komponentu z Figmy — treść wyśrodkowana */
  color: var(--k-energy-mint);
  font-size: 10px;
  font-weight: var(--k-fw-news);
  line-height: var(--k-lh-label);
  text-align: center;
  transition: color var(--k-dur-fast) var(--k-ease-out);
}

.k-navi-top:active {
  color: var(--k-baby-mint);
}

@media (hover: hover) {
  .k-navi-top:hover {
    color: var(--k-baby-mint);
  }
}

/* ==========================================================================
   BADGE INFORMACYJNY — k-badge-info (Figma: badge-informacja, 78×78)
   Koło z dwustopniowym tekstem. Blok tekstu ma stałe 75 px szerokości
   i siedzi 24 px od góry — nie jest wyśrodkowany w pionie.
   ========================================================================== */

/* Jedno pokrętło skali zamiast drugiego kompletu metryk na desktop — ta sama
   receptura co --k-badge-lg-scale niżej. Przy 1 każdy calc() daje dokładnie
   liczbę z frame'a mobilnego, a hero na desktopie podnosi je do 120/78
   (166:21641): 11 → 16,92, 14 → 21,54, 9 → 13,85, 12 → 18,46, top 24 → 36,92,
   szerokość 75 → 115,38 — co do setnej to, co podaje Figma.
   Transform odpada, bo jest zajęty przez wyśrodkowanie tekstu i przez
   animację pojawiania z base.css. */
.k-badge-info {
  --k-badge-scale: 1;
  position: relative;
  display: block;
  flex: 0 0 auto;
  width: calc(78px * var(--k-badge-scale));
  height: calc(78px * var(--k-badge-scale));
  border-radius: var(--k-radius-pill);
  background: var(--k-power-mint);
  color: var(--k-gray-800);
  box-shadow: var(--k-shadow-badge);
  transition: background-color var(--k-dur-base) var(--k-ease-out);
}

.k-badge-info__text {
  position: absolute;
  top: calc(24px * var(--k-badge-scale));
  left: 50%;
  width: calc(75px * var(--k-badge-scale));
  transform: translateX(-50%);
  font-size: calc(11px * var(--k-badge-scale));
  font-weight: var(--k-fw-medium);
  line-height: calc(14px * var(--k-badge-scale));
  letter-spacing: calc(var(--k-ls-label) * var(--k-badge-scale));
  /* ligatury wyłączone zgodnie z projektem — bez tego „PÓŹNIEJ" składa się inaczej */
  font-feature-settings: "liga" off, "clig" off;
  text-align: center;
  text-transform: uppercase;
}

.k-badge-info__strong {
  font-weight: var(--k-fw-bold);
}

.k-badge-info__rest {
  display: block;
  font-size: calc(9px * var(--k-badge-scale));
  font-weight: var(--k-fw-medium);
  line-height: calc(12px * var(--k-badge-scale));
}

/* Stany tylko dla wersji klikalnej. Koło „7 lat gwarancji" jest zwykłym <p>
   i nie prowadzi nigdzie — nie ma prawa reagować na kursor ani na dotknięcie. */
a.k-badge-info:active,
button.k-badge-info:active {
  background: var(--k-lime);
}

@media (hover: hover) {
  a.k-badge-info:hover,
  button.k-badge-info:hover {
    background: var(--k-lime);
  }
}

/* ---------- Wariant „7 LAT GWARANCJI" przy #benefity (Figma: 214:22149) ----------
   Dwustopniowy tekst, obie linie wersalikami.

   92, nie 96: ramka `badge-informacja` w Figmie ma 96 px, ale huguje razem
   z cieniem — samo koło (`Ellipse 27`) mierzy 92 px i tyle ma tu średnica.
   Tekst 88 px mieści się w nim z 2 px luzu z każdej strony, jak w projekcie. */

/* Jedno pokrętło skali zamiast osobnego kompletu metryk na desktop: na mobile
   --k-badge-lg-scale zostaje 1 i każdy calc() daje dokładnie dawną liczbę, a
   sekcja desktopowa podnosi je do 1,24 (114/92 z frame'a 214:22274). Transform
   odpada — jest zajęty przez animację pojawiania z base.css. */
.k-badge-info--lg {
  --k-badge-lg-scale: 1;
  width: calc(92px * var(--k-badge-lg-scale));
  height: calc(92px * var(--k-badge-lg-scale));
}

/* 26, nie 24 z Figmy: „7 LAT" ma interlinię 16,4 px przy stopniu 18,75 px, więc
   glify wystają 4 px ponad swój wiersz — w górę, nie w dół. Przy 24 px tekst
   siadał o 4 px za wysoko (20 px nad, 24 px pod). Przesunięcie ramki o 2 px
   wyrównuje światło: 22 px z góry i z dołu. */
.k-badge-info--lg .k-badge-info__text {
  top: calc(26px * var(--k-badge-lg-scale));
  width: calc(88px * var(--k-badge-lg-scale));
  font-size: calc(var(--k-fs-guarantee) * var(--k-badge-lg-scale));
  font-weight: var(--k-fw-bold);
  line-height: calc(16.4px * var(--k-badge-lg-scale));
  letter-spacing: calc(-0.23px * var(--k-badge-lg-scale));
}

.k-badge-info--lg .k-badge-info__strong {
  display: block;
}

.k-badge-info--lg .k-badge-info__rest {
  font-size: calc(var(--k-fs-guarantee-sm) * var(--k-badge-lg-scale));
  font-weight: var(--k-fw-medium);
  line-height: calc(14px * var(--k-badge-lg-scale));
}

/* ---------- pojawianie się plakietki ----------
   Koło jest małe, więc skacze o połowę dystansu, co reszta strony.

   `transition` przepisujemy CELOWO, to nie duplikat: reguła .k-js [data-reveal]
   z base.css ma specyficzność 0-3-0 przeciw 0-1-0 samego .k-badge-info, więc
   skróciłaby listę do opacity+transform — klikalna plakietka hero straciłaby
   płynne przejście tła w hover/active. Noga background-color świadomie BEZ
   opóźnienia: hover ma reagować od razu, nie po 1,2 s.

   Dystans podmieniamy SAMĄ ZMIENNĄ. Deklaracja `transform` tutaj remisowałaby
   (0-3-0) z regułą .is-revealed w base.css, a że components.css ładuje się
   później — wygrałaby też po ujawnieniu i koło zostałoby przesunięte na stałe. */
.k-js .k-badge-info[data-reveal] {
  --k-reveal-shift: var(--k-reveal-shift-sm);
  transition: opacity var(--k-dur-slow) var(--k-ease-out) var(--k-reveal-delay, 0ms),
              transform var(--k-dur-slow) var(--k-ease-out) var(--k-reveal-delay, 0ms),
              background-color var(--k-dur-base) var(--k-ease-out);
}

/* Niewidoczna plakietka hero zostaje pełnowymiarowym celem 78×78 px nad rzędem
   licznika — bez tego przez 1,2 s łapie tapnięcia w pustkę. Tylko warianty
   klikalne: reguła na wszystkich [data-reveal] wyłączałaby interakcję
   w nieujawnionych kartach kalkulatora i formularza. */
.k-js a.k-badge-info[data-reveal]:not(.is-revealed),
.k-js button.k-badge-info[data-reveal]:not(.is-revealed) {
  pointer-events: none;
}

/* link tekstowy z podkreśleniem — „wypełnij formularz →" */
.k-link {
  display: inline-flex;
  align-items: center;
  gap: var(--k-space-2);
  color: var(--k-text-accent);
  font-weight: var(--k-fw-bold);
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: color var(--k-dur-fast) var(--k-ease-out);
}

@media (hover: hover) {
  .k-link:hover {
    color: var(--k-deep-mint);
  }
}

/* Na dotyku hover nie istnieje, a plamę podświetlenia gasimy w base.css —
   przyciemnienie na czas wciśnięcia jest jedynym potwierdzeniem tapnięcia.
   Ten sam kolor co hover: to ta sama informacja, tylko innym wejściem. */
.k-link:active {
  color: var(--k-deep-mint);
}

/* Link wpleciony w akapit — czyta się jak reszta treści, wyróżnia go samo
   podkreślenie. Bez koloru akcentu i bez pogrubienia, żeby nie rozbijał zdania. */
.k-link--plain {
  display: inline;
  color: inherit;
  font-weight: inherit;
  text-underline-offset: 3px;
}

@media (hover: hover) {
  .k-link--plain:hover {
    color: inherit;
    text-decoration-thickness: 2px;
  }
}

/* Wciśnięcie pogrubia samo podkreślenie. Kolor musi zostać przy `inherit`,
   bo .k-link:active jest bardziej specyficzne niż .k-link--plain i inaczej
   przemalowałoby link na miętę — czyli dokładnie to, czemu wariant zapobiega. */
.k-link--plain:active {
  color: inherit;
  text-decoration-thickness: 2px;
}

/* Link do zasobu poza LP (Figma: „Btn - External Link", 355:4772) —
   bez podkreślenia; ikona ma własny kolor, bo <img> nie dziedziczy currentColor. */
.k-link--ext {
  color: var(--k-gray-700);
  font-weight: var(--k-fw-news);
  font-size: var(--k-fs-sm);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-note);
  text-decoration: none;
}

.k-link--ext img {
  width: 12px;
  height: 12px;
}

/* „Czytaj więcej" pod zgodą — nie jest ozdobnym CTA, tylko dalszym ciągiem
   akapitu: ta sama waga i kolor co treść, od nowego wiersza, przy lewej
   krawędzi tekstu. Wyróżnia je wyłącznie podkreślenie. */
.k-form__more {
  display: block;
  justify-self: start;
  padding: 0;
  color: inherit;
  font: inherit;
  /* skrót `font` nie przenosi trackingu, a ten ma być taki sam jak w akapicie */
  letter-spacing: inherit;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 3px;
  /* zerujemy gap siatki zgód — „Czytaj więcej" ma być kolejnym wierszem
     akapitu, a nie osobnym blokiem; odstęp robi sama interlinia */
  margin-top: calc(-1 * var(--k-space-3));
}

@media (hover: hover) {
  .k-form__more:hover {
    text-decoration-thickness: 2px;
  }
}

/* Jak w hoverze — grubsze podkreślenie. Koloru nie ruszamy, bo „Czytaj więcej"
   ma czytać się jak dalszy ciąg akapitu, nie jak przycisk. */
.k-form__more:active {
  text-decoration-thickness: 2px;
}

/* ==========================================================================
   BADGE — k-badge (Figma: label, 24 px wysokości)
   Etykieta wersalikowa nad nagłówkiem sekcji.
   ========================================================================== */

.k-badge {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding-inline: 8px;
  border-radius: var(--k-radius-xs);
  background: var(--k-power-mint);
  color: var(--k-gray-800);
  font-size: var(--k-fs-label);
  font-weight: var(--k-fw-bold);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-label);
  text-transform: uppercase;
  white-space: nowrap;
}

.k-badge--lime {
  background: var(--k-lime);
}

.k-badge--soft {
  background: var(--k-baby-mint);
  color: var(--k-deep-mint);
}

/* Krok poradnika (Figma: 166:17871) — niższy kafelek, tekst 10 px z rozstrzeleniem.
   Tło to power-mint z 24 % krycia, nie osobny kolor z palety. */
.k-badge--step {
  /* własny wiersz — jako inline-flex dokładałby leading i krok rósłby o kilka px */
  display: flex;
  width: fit-content;
  height: 21px;
  padding-block: 4px;
  background: rgba(57, 255, 228, 0.24);
  color: var(--k-deep-mint);
  font-size: 0.625rem;
  font-weight: var(--k-fw-medium);
  line-height: normal;
  letter-spacing: 0.5px;
}

/* ==========================================================================
   KARTA — k-card
   ========================================================================== */

.k-card {
  padding: var(--k-space-5);
  border-radius: var(--k-radius-lg);
  background: var(--k-surface);
  box-shadow: var(--k-shadow-sm);
}

.k-card--bordered {
  box-shadow: none;
  border: 1px solid var(--k-border);
}

.k-card--mint {
  background: var(--k-surface-mint);
  box-shadow: none;
}

.k-card--deep {
  background: var(--k-surface-deep);
  color: var(--k-text-on-deep);
  box-shadow: none;
}

.k-card--elevated {
  box-shadow: var(--k-shadow-md);
}

/* ==========================================================================
   IKONA SEKCJI — k-icon (Figma: „Squircle" 48×48)
   --------------------------------------------------------------------------
   Squircle jest częścią eksportu z Figmy — i wariant z obrysem (#benefity-top),
   i wypełniony (#benefity) siedzą w jednym pliku SVG razem z glifem. Dlatego
   komponent tylko rezerwuje miejsce; nie maluje tła ani ramki.
   ========================================================================== */

.k-icon {
  display: block;
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
}

/* ==========================================================================
   POZYCJA Z IKONĄ — k-feature (ikona + treść w rzędzie)
   ========================================================================== */

.k-feature {
  display: flex;
  align-items: center;
  gap: 16px;
}

.k-feature__title {
  display: block;
  color: var(--k-gray-800);
  font-size: var(--k-fs-body);
  font-weight: var(--k-fw-bold);
  line-height: 20px;
  letter-spacing: var(--k-ls-note);
}

.k-feature__desc {
  display: block;
  margin-top: var(--k-space-1);
  color: var(--k-gray-500);
  font-size: var(--k-fs-note);
  font-weight: var(--k-fw-news);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-note);
}

/* ==========================================================================
   ODTWARZACZ — k-video (Figma: Controls 8221:370858 z UI Web 3.0)
   --------------------------------------------------------------------------
   Kadr z posterem i szklanym przyciskiem play. Zachowanie zdjęte z
   oknoplast.com.pl/okna/pixel/: klik odtwarza raz, bez dźwięku i bez
   natywnych kontrolek — sterowanie niesie js/modules/video.js.

   Nie budujemy tego na .k-btn-circle: tamten ma stałe 48×48, kolory miętowe
   i celowo zero stanu hover. Wspólny jest tylko kształt koła.
   ========================================================================== */

.k-video {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  width: min(var(--k-media-square), 100%);
}

.k-video__media {
  width: 100%;
  height: 100%;
  /* contain, nie cover — poster ma 450×438, a wideo 360×360, więc kadrowanie
     obcięłoby okno przy przejściu z jednego na drugie */
  object-fit: contain;
}

/* Pozycjonowanie absolutne dotyczy wyłącznie osadzenia w kadrze — .k-video ma
   place-items: center, więc przycisk i tak leży na środku. Poza kadrem (paleta
   dev/components.html) stoi w normalnym przepływie. */
.k-video .k-video__play {
  position: absolute;
}

.k-video__play {
  display: grid;
  place-items: center;
  width: var(--k-btn-play);
  height: var(--k-btn-play);
  border: 1px solid var(--k-glass-border);
  border-radius: var(--k-radius-pill);
  background: var(--k-glass-bg);
  backdrop-filter: blur(var(--k-glass-blur));
  -webkit-backdrop-filter: blur(var(--k-glass-blur));
  box-shadow: var(--k-shadow-glass);
  color: var(--k-white);
  transition: color var(--k-dur-btn) var(--k-ease-btn),
              opacity var(--k-dur-btn) var(--k-ease-btn),
              box-shadow var(--k-dur-btn) var(--k-ease-btn),
              visibility var(--k-dur-btn) var(--k-ease-btn),
              transform var(--k-dur-fast) var(--k-ease-out);
}

/* Trójkąt jest optycznie cięższy z lewej, więc geometryczny środek wygląda
   na przesunięty. Przesuwamy o 2 px w prawo — tak samo robi referencja
   asymetrycznym paddingiem (0.5rem 0 0 0.7rem). */
.k-video__play svg {
  width: 22px;
  height: 27px;
  transform: translateX(2px);
  fill: currentColor;
  filter: drop-shadow(var(--k-shadow-glass));
}

/* Stan „Hover" (8221:370888) różni się od „Default" wyłącznie cieniem —
   ikona zostaje biała. Wzmacniamy ten sam cień, którym Figma opisuje
   Drops / Glass Button Shadow. */
@media (hover: hover) {
  .k-video__play:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16);
  }
}

/* Stan „Pushed" (8221:370891) — trójkąt ciemnieje do Gray-800 */
.k-video__play:active {
  color: var(--k-gray-800);
  transform: scale(0.94);
}

/* Po starcie przycisk schodzi z drogi. visibility zamiast display, żeby
   zniknięcie dało się wyciszyć — display nie podlega transition. */
.k-video.is-playing .k-video__play {
  opacity: 0;
  visibility: hidden;
}

/* ==========================================================================
   KROK PROCESU — k-step
   ========================================================================== */

.k-step {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: 16px;
}

.k-step__marker {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--k-radius-pill);
  background: var(--k-energy-mint);
  color: var(--k-white);
  font-size: 0.9722rem;             /* 15,556 px — tak wychodzi ze skalowania w Figmie */
  font-weight: var(--k-fw-medium);
}

.k-step__title {
  margin-top: 6px;
  color: var(--k-gray-800);
  font-size: 1.125rem;              /* 18 px */
  font-weight: var(--k-fw-bold);
  line-height: 22px;
}

.k-step__desc {
  margin-top: var(--k-space-2);
  color: var(--k-gray-800);
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-book);
  line-height: 20px;
  letter-spacing: var(--k-ls-tight);
}

/* ==========================================================================
   STATYSTYKA — k-stat
   ========================================================================== */

.k-stat__value {
  color: var(--k-hl-mint);
  font-size: var(--k-fs-stat);
  font-weight: var(--k-fw-bold);
  line-height: normal;
}

/* jednostka przy liczbie („mln") jest wyraźnie mniejsza od samej liczby */
.k-stat__unit {
  font-size: 0.6364em;
}

.k-stat__label {
  margin-top: var(--k-space-1);
  color: var(--k-power-mint);
  font-size: 0.6875rem;             /* 11 px */
  font-weight: var(--k-fw-news);
  line-height: 15px;
  text-transform: uppercase;
}

/* ==========================================================================
   PASEK POSTĘPU PRZEWIJANIA — k-scroll-progress
   --------------------------------------------------------------------------
   Wskaźnik w górnej belce: ile strony za nami. Wzorowany na pasku z LP
   „Nowe kolory okien", tam 5 px w kolorze marki; u nas 3 px w energy-mint —
   cieńsza kreska lepiej siada do reszty (kreski w navi karuzeli mają 3 px).

   NIE MYLIĆ z `.k-carousel__navi` — tamto pokazuje pozycję w karuzeli
   i pozwala nią sterować, ten pasek tylko postęp dokumentu w pionie.

   Wypełnienie ustawia `js/modules/stickybar.js` przez `--k-scroll-progress`
   (0–1). Świadomie `transform: scaleX()`, nie `width`: skalowanie obsługuje
   kompozytor, więc nie przelicza układu w każdej klatce przewijania.
   Bez `transition` — pasek ma iść dokładnie za palcem.
   ========================================================================== */

.k-scroll-progress {
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
}

.k-scroll-progress__fill {
  height: 100%;
  background: var(--k-energy-mint);
  transform: scaleX(var(--k-scroll-progress, 0));
  transform-origin: left center;
}

/* Tylko mobile — świadoma decyzja, nie ograniczenie. Pierwotny powód (belka
   chowała się na desktopie przy scrollu w dół, więc wskaźnik znikałby razem
   z nią) odpadł, odkąd belka zostaje na miejscu; włączenie wskaźnika wyżej
   jest teraz możliwe, ale to zmiana wizualna do osobnej decyzji. */
@media (min-width: 1024px) {
  .k-scroll-progress {
    display: none;
  }
}

/* ==========================================================================
   KARUZELA — k-slider (natywny scroll-snap, zero JS na przewijanie)
   ========================================================================== */

.k-slider {
  display: flex;
  gap: var(--k-space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--k-gutter);
  /* Tor jest bezpośrednim dzieckiem sekcji, nie .k-container — sam trzyma
     margines boczny, żeby kafle mogły wyjeżdżać poza krawędź ekranu. */
  padding-inline: var(--k-gutter);
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

.k-slider::-webkit-scrollbar {
  display: none;
}

/* Na czas animacji strzałką (rAF w js/modules/slider.js) snap schodzi z drogi —
   WebKit przerywa programowe przewijanie w kontenerze z x mandatory
   i dosnapowuje skokiem. Klasę zdejmuje slider.js po dojechaniu do celu. */
.k-slider.is-animating {
  scroll-snap-type: none;
}

.k-slider__item {
  flex: 0 0 auto;
  width: min(78%, 420px);
  scroll-snap-align: start;
}

/* --------------------------------------------------------------------------
   WARIANT WYŚRODKOWANY — k-slider--centered

   Domyślne `scroll-snap-align: start` zatrzymuje kafel LEWĄ krawędzią przy
   krawędzi toru. Przy karuzeli, w której naraz oglądamy jeden przedmiot
   (packshoty, realizacje), czyta się to jak przesunięcie w lewo: pierwszy
   kafel nie ma nic po swojej lewej stronie. Tutaj kafel staje na środku
   kadru, a sąsiedzi podglądają symetrycznie z obu stron.

   Padding musi dać PIERWSZEMU i OSTATNIEMU kaflowi szansę dojechać na środek —
   stąd połowa różnicy między torem a kaflem skrajnym. Kafle środkowe wychodzą
   na środek same, bo mają po bokach sąsiadów.

   --k-snap-w = szerokość kafla SKRAJNEGO, ustawiana per karuzela w sections.css.
   -------------------------------------------------------------------------- */

.k-slider--centered {
  padding-inline: calc((100% - var(--k-snap-w)) / 2);
  /* snapport = cały scrollport, żeby środek liczył się od krawędzi ekranu */
  scroll-padding-inline: 0;
}

.k-slider--centered > .k-slider__item {
  scroll-snap-align: center;
}

/* Powyżej 1024 px widać kilka kafli naraz — centrowanie jednego nic nie wnosi,
   a przy skrajnych zostawia kilkaset px pustki. Wracamy do rzędu od lewej.
   Wersja desktopowa dostanie własny projekt z Figmy; tu domykamy mobile. */
@media (min-width: 1024px) {
  .k-slider--centered {
    padding-inline: var(--k-gutter);
    scroll-padding-inline: var(--k-gutter);
  }

  .k-slider--centered > .k-slider__item {
    scroll-snap-align: start;
  }
}

/* --------------------------------------------------------------------------
   NAWIGACJA KARUZELI — k-carousel__navi (Figma: „navi", 590:8114)

   Zastąpiła bierny pasek postępu: po pasku nie dało się przewijać ani odczytać,
   ile jest kafli. Rachunek szerokości wprost z makiety:
   40 (strzałka) + 14 + 200 (kreski) + 14 + 40 (strzałka) = 308, a frame stoi
   na x=41 przy kadrze 390, czyli dokładnie (390 − 308) / 2 — wyśrodkowany.
   Rachunek dla 8 kresek (packshoty); przy innej liczbie (certyfikaty, galeria) navi jest węższa
   — `justify-content: center` na `.k-carousel__navi` trzyma ją na osi niezależnie od szerokości.

   Markup generuje js/modules/slider.js — bez JS-a strzałki byłyby martwymi
   kontrolkami. Liczba kresek: u packshotów i galerii tyle, co kafli (8 / 4) —
   każdy kafel ma tam osobno osiągalną pozycję przewijania. U certyfikatów
   mniej niż kafli (patrz zmierzStopy() w slider.js, OKP-886) — kilka
   logotypów mieści się razem na końcu toru, więc dzielą jedną kreskę.
   -------------------------------------------------------------------------- */

.k-carousel__navi {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* 18 px: frame packshotów kończy się na y=406, navi zaczyna na y=424.
     Skala --k-space-* nie ma 18 px, a tu trzymamy się makiety co do piksela. */
  margin-top: 18px;
}

/* Tor mieszczący się w kadrze nie potrzebuje nawigacji — slider.js zdejmuje
   ją atrybutem `hidden`. Bez tej reguły atrybut nie robi nic: `display: flex`
   wyżej pochodzi z arkusza autora i bije regułę przeglądarki
   `[hidden] { display: none }`, która jest tylko z UA. */
.k-carousel__navi[hidden] {
  display: none;
}

.k-carousel__arrow {
  width: 40px;
  height: 40px;
  background: transparent;
}

/* Ikona siedzi na ::before, nie na samym przycisku — maska przycięłaby też
   ::after ze strefą dotyku 44 px. Maska zamiast <img>, bo strzałka ma trzy
   stany kolorystyczne, a w pliku SVG kolor byłby wypalony na stałe. */
.k-carousel__arrow::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--k-energy-mint);
  mask: url("../images/icons/navi-arrow.svg") center / 40px 40px no-repeat;
  -webkit-mask: url("../images/icons/navi-arrow.svg") center / 40px 40px no-repeat;
  transition: background-color var(--k-dur-btn) var(--k-ease-btn);
}

.k-carousel__arrow--next::before {
  transform: scaleX(-1);
}

.k-carousel__arrow:disabled {
  cursor: default;
}

.k-carousel__arrow:disabled::before {
  background-color: var(--k-gray-200);
}

@media (hover: hover) {
  .k-carousel__arrow:not(:disabled):hover::before {
    background-color: var(--k-baby-mint);
  }
}

/* Strzałki są na LP obsługiwane głównie palcem, a hover wyżej jest wtedy
   martwy — bez tego wciśnięcie nie dawałoby żadnego sygnału (plamę dotyku
   gasi base.css). */
.k-carousel__arrow:not(:disabled):active::before {
  background-color: var(--k-baby-mint);
  transition-duration: var(--k-dur-fast);
}

.k-carousel__dots {
  display: flex;
  align-items: center;
  gap: 16px;
}

.k-carousel__dot {
  width: 8px;
  height: 3px;
  border-radius: var(--k-radius-pill);
  background: var(--k-gray-400);
  transition: width var(--k-dur-fast) var(--k-ease-out),
              background-color var(--k-dur-fast) var(--k-ease-out);
}

.k-carousel__dot.is-active {
  width: 32px;
  background: var(--k-energy-mint);
}

/* powyżej 1024 px karuzela zamienia się w siatkę */
@media (min-width: 1024px) {
  .k-slider--to-grid {
    display: grid;
    grid-template-columns: repeat(var(--k-grid-cols, 3), 1fr);
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
  }

  .k-slider--to-grid .k-slider__item {
    width: auto;
  }

  .k-slider--to-grid {
    padding-inline: 0;
  }

  .k-slider--to-grid + .k-carousel__navi {
    display: none;
  }
}

/* ==========================================================================
   POLE FORMULARZA — k-field
   ========================================================================== */

.k-field {
  display: block;
}

.k-field__label {
  display: block;
  margin-bottom: 8px;
  color: var(--k-gray-800);
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-medium);
  line-height: 20px;
  letter-spacing: var(--k-ls-note);
}

.k-field__control {
  width: 100%;
  /* 48 px z Figmy; padding liczony tak, żeby tekst 14/20 wypadł na środku */
  min-height: 48px;
  padding: 13px 15px;
  border: 1px solid var(--k-gray-300);
  border-radius: var(--k-radius-md);
  background: var(--k-white);
  box-shadow: var(--k-shadow-input);
  color: var(--k-gray-800);
  font-size: var(--k-fs-sm);
  line-height: 20px;
  letter-spacing: var(--k-ls-tight);
  transition: border-color var(--k-dur-fast) var(--k-ease-out),
              box-shadow var(--k-dur-fast) var(--k-ease-out);
}

.k-field__control::placeholder {
  color: var(--k-gray-400);
}

/* Krzyżyk czyszczący w polu type="search" (wyszukiwarka salonu). Bez tej reguły
   WebKit rysuje własny glif w systemowym szarobłękicie — jedyny element pola,
   który nie brał koloru z tokenów.

   Kolor niesie `background`, a kształt `mask`, więc energy-mint zostaje
   w zmiennej zamiast wsiąkać w data URI. Geometria jak w pozostałych ikonach
   projektu: viewBox 24, grubość 2, zaokrąglone końce — czyli to samo, co daje
   .k-btn-circle--close (plus obrócony o 45°).

   Firefox nie renderuje tu żadnego przycisku, więc reguła jest bezpiecznie
   bezczynna. */
.k-field__control[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  background: var(--k-energy-mint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E")
    center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E")
    center / contain no-repeat;
  cursor: pointer;
  transition: background-color var(--k-dur-fast) var(--k-ease-out);
}

@media (hover: hover) {
  .k-field__control[type="search"]::-webkit-search-cancel-button:hover {
    background: var(--k-deep-mint);
  }
}

textarea.k-field__control {
  /* block, nie domyślny inline-block: pole stoi wtedy na linii bazowej i pod
     nim zostaje ~7 px światła na wydłużenia dolne. Ta szczelina jest niewidoczna
     (pole ma białe tło jak sekcja), ale rozjeżdża uchwyt niżej — jest kotwiczony
     do dołu .k-field, a ten sięgał 7 px pod textareę. */
  display: block;
  min-height: 132px;
  resize: vertical;
}

/* ---------- uchwyt zmiany rozmiaru ----------
   Natywny uchwyt WebKita rysuje się w SAMYM ROGU ramki, więc przy promieniu
   16 px przecina łuk zaokrąglenia i wystaje poza widoczną krawędź pola.
   Gasimy go i rysujemy własny: trójkącik 7 × 7 w energy-mint, odsunięty
   o 8 px od obu krawędzi (kształt podany przez klienta). Sam obszar chwytania
   zostaje nietknięty — pole dalej da się rozciągnąć. */

textarea.k-field__control::-webkit-resizer {
  display: none;
}

/* Dekoracja wisi na .k-field, bo przeglądarki nie renderują pseudoelementów
   wewnątrz pól tekstowych. :has(textarea) zawęża ją do jedynego pola, które
   da się rozciągać. Kotwiczenie do dołu kontenera jest tu bezpieczne: pole
   „Wiadomość" nie ma ani `required`, ani elementu .k-field__error, więc dół
   .k-field zawsze pokrywa się z dołem textarei — także po rozciągnięciu. */
.k-field:has(textarea) {
  position: relative;
}

.k-field:has(textarea)::after {
  content: "";
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 7px;
  height: 7px;
  background: var(--k-energy-mint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 7 7'%3E%3Cpath fill='%23000' d='M6.58777 5.58789C6.58777 6.14018 6.14005 6.58789 5.58777 6.58789H1.00198C0.111077 6.58789 -0.33509 5.51075 0.294875 4.88078L4.88066 0.294995C5.51063 -0.334969 6.58777 0.1112 6.58777 1.0021V5.58789Z'/%3E%3C/svg%3E")
    center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 7 7'%3E%3Cpath fill='%23000' d='M6.58777 5.58789C6.58777 6.14018 6.14005 6.58789 5.58777 6.58789H1.00198C0.111077 6.58789 -0.33509 5.51075 0.294875 4.88078L4.88066 0.294995C5.51063 -0.334969 6.58777 0.1112 6.58777 1.0021V5.58789Z'/%3E%3C/svg%3E")
    center / contain no-repeat;
  /* klik i przeciągnięcie mają trafić w natywny uchwyt pod spodem */
  pointer-events: none;
}

/* Na ekranach dotykowych iOS Safari przybliża stronę, gdy pole ma czcionkę
   mniejszą niż 16 px — i po schowaniu klawiatury nie wraca do skali 1, przez co
   layout zostaje ucięty. Na dotyku pole idzie więc na 16 px; makieta (390 px
   w przeglądarce desktopowej) dalej pokazuje 14 px z Figmy. */
@media (pointer: coarse) {
  .k-field__control {
    font-size: var(--k-fs-input-touch);
  }
}

.k-field__control:focus {
  border-color: var(--k-border-strong);
  box-shadow: var(--k-shadow-input), 0 0 0 3px rgba(16, 169, 148, 0.15);
  outline: none;
}

.k-field__error {
  display: none;
  margin-top: var(--k-space-2);
  color: var(--k-error);
  font-size: var(--k-fs-sm);
}

.k-field.is-invalid .k-field__control {
  border-color: var(--k-error);
}

.k-field.is-invalid .k-field__error {
  display: block;
}

/* ==========================================================================
   ZAŁĄCZNIK — k-upload
   --------------------------------------------------------------------------
   Wiersz pliku z Figmy: 312 × 32 px, treść od 12 px, ikona 12 × 12 px przy
   prawej krawędzi, tekst 12/16 z tracking −0,4.
   Dwa stany: „wgrywanie" (622:8254 — biały wiersz + 2 px pasek postępu) oraz
   „wgrany" (622:8266 — pełny energy-mint). LP nie ma backendu, więc pokazuje
   wyłącznie stan wgrany; „wgrywanie" czeka gotowe na realny upload i żyje
   w dev/components.html.
   ========================================================================== */

.k-upload {
  display: grid;
  justify-items: start;
  gap: var(--k-space-3);
}

.k-upload__hint {
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-medium);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-tight);
}

.k-upload__list {
  display: grid;
  gap: var(--k-space-2);
  width: 312px;                                 /* szerokość wiersza z Figmy */
  max-width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.k-upload__list:empty {
  display: none;
}

.k-upload__item {
  position: relative;                           /* kotwica paska postępu */
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--k-space-2);
  min-height: 32px;
  padding: 8px 12px;
  border-radius: var(--k-radius-xs);
  overflow: hidden;
  font-size: var(--k-fs-label);
  font-weight: var(--k-fw-medium);
  line-height: var(--k-lh-label);
  letter-spacing: var(--k-ls-note);
}

.k-upload__label {
  display: flex;
  align-items: baseline;
  gap: 5px;                                     /* odstęp nazwa → rozmiar z Figmy */
  min-width: 0;
}

.k-upload__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.k-upload__size {
  flex: none;
}

.k-upload__remove {
  display: grid;
  place-items: center;
  width: 24px;                                  /* pole dotyku; sama ikona ma 12 px */
  height: 24px;
  /* pole dotyku wychodzi poza wiersz, żeby zachować 32 px wysokości z Figmy */
  margin: -4px -6px -4px 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: opacity var(--k-dur-fast) var(--k-ease-out);
}

.k-upload__remove:active {
  opacity: 0.6;
}

@media (hover: hover) {
  .k-upload__remove:hover {
    opacity: 0.6;
  }
}

/* wgrywanie — biały wiersz, pasek postępu przy dolnej krawędzi */
.k-upload__item.is-uploading {
  background: var(--k-white);
  color: var(--k-gray-800);
}

.k-upload__item.is-uploading .k-upload__size,
.k-upload__item.is-uploading .k-upload__remove {
  color: var(--k-gray-500);
}

.k-upload__progress {
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--k-gray-200);
}

.k-upload__progress::before {
  content: "";
  display: block;
  width: var(--k-progress, 0%);
  height: 100%;
  background: var(--k-energy-mint);
}

/* wgrany — pełny energy-mint */
.k-upload__item.is-done {
  background: var(--k-energy-mint);
  color: var(--k-hl-mint);
}

/* Przycisk wyzwalający: pigułka 160 × 40 px przy lewej krawędzi formularza.
   `hidden` musi przebić `display: inline-flex` z .k-btn — stąd jawna reguła. */
.k-upload__trigger {
  width: 160px;
  min-height: 40px;
  cursor: pointer;
}

.k-upload__trigger[hidden] {
  display: none;
}

.k-upload__error {
  margin: 0;
  color: var(--k-error);
  font-size: var(--k-fs-sm);
}

.k-upload__error:empty {
  display: none;
}

/* ==========================================================================
   PODZIĘKOWANIE PO WYSŁANIU — k-form-success (Figma: 625:8463)
   --------------------------------------------------------------------------
   Zastępuje pola formularza: ilustracja 64 px, nagłówek H5 16/24 i akapit
   14/20, wszystko wyśrodkowane w kolumnie szerokiej na 239 px.
   ========================================================================== */

.k-form-success {
  /* w zmiennej, bo sekcja liczy z niej wyśrodkowanie na desktopie */
  --k-form-success-w: 239px;                    /* szerokość bloku z Figmy */
  display: grid;
  justify-items: center;
  width: var(--k-form-success-w);
  max-width: 100%;
  /* komunikat jest dużo niższy niż formularz — bez własnego oddechu siadałby
     na sekcji „Znajdź najbliższy salon" */
  margin: 0 auto var(--k-space-6);
  text-align: center;
}

.k-form-success[hidden] {
  display: none;
}

.k-form-success__icon {
  width: 64px;
  height: 64px;
  margin-bottom: 16px;                          /* 80 − 64 z Figmy */
}

.k-form-success__title {
  margin-bottom: 8px;                           /* 32 − 24 z Figmy */
  color: var(--k-gray-800);
  font-size: var(--k-fs-body);
  font-weight: var(--k-fw-medium);
  line-height: 24px;
  letter-spacing: var(--k-ls-h5);
}

.k-form-success__text {
  color: var(--k-gray-600);
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-medium);
  line-height: 20px;
  letter-spacing: var(--k-ls-tight);
}

/* checkbox / radio z własnym znacznikiem */
.k-check {
  display: grid;
  grid-template-columns: 24px 1fr;
  /* etykieta mieści się w jednym wierszu — równamy ją do środka znacznika */
  align-items: center;
  gap: var(--k-space-3);
  cursor: pointer;
}

.k-check__input {
  appearance: none;
  width: 24px;
  height: 24px;
  margin: 0;
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-xs);
  background: var(--k-white);
  display: grid;
  place-items: center;
  transition: border-color var(--k-dur-fast) var(--k-ease-out),
              background-color var(--k-dur-fast) var(--k-ease-out);
}

/* Zaznaczenie widać dopiero po puszczeniu palca (pojawia się „✓"), więc samo
   wciśnięcie potrzebuje własnego sygnału — obrys miętą. */
.k-check__input:active {
  border-color: var(--k-energy-mint);
}

/* `place-items: center` centruje NIEOBRÓCONY prostokąt 12×7, ale widoczna
   kreska (tylko lewa i dolna krawędź) leży w jego górnej-lewej części — po
   obrocie „ptaszek" wychodzi zauważalnie przesunięty względem pola.
   `translate(0.5px, -1px)` PRZED `rotate()` (czyli jeszcze w nieobróconym
   układzie) to koryguje — dobrane na oko, nie z tokenu, bo to optyczne
   wyśrodkowanie glifu, nie odstęp. */
.k-check__input::after {
  content: "";
  width: 12px;
  height: 7px;
  border-left: 2px solid var(--k-energy-mint);
  border-bottom: 2px solid var(--k-energy-mint);
  transform: translate(0.5px, -1px) rotate(-45deg) scale(0);
  transition: transform var(--k-dur-fast) var(--k-ease-out);
}

.k-check__input:checked {
  border-color: var(--k-energy-mint);
}

.k-check__input:checked::after {
  transform: translate(0.5px, -1px) rotate(-45deg) scale(1);
}

.k-check__text {
  /* ten sam drobny druk co treść zgód obok */
  font-size: var(--k-fs-label);
  letter-spacing: var(--k-ls-note);
}

/* ==========================================================================
   AKORDEON — k-accordion (Figma: Question / 02 Collapsed, 346×56/72)
   --------------------------------------------------------------------------
   Klikalny jest cały kafelek — trigger wypełnia kartę, a odstępy daje padding
   karty, nie przycisku.

   Stany:
     zwinięta          obrys Gray-200, pytanie Gray-800, ikona „+" Gray-800
     zwinięta · hover  obrys i pytanie energy-mint, ikona „+" energy-mint
     rozwinięta        obrys Gray-200, pytanie energy-mint, ikona „−" energy-mint

   Treść odpowiedzi idzie w Gray-800, nie w Gray-600 z makiety — patrz
   komentarz przy .k-accordion__content.
   ========================================================================== */

.k-accordion__item {
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-md);
  background: var(--k-white);
  transition: border-color var(--k-dur-hover) var(--k-ease-out);
}

.k-accordion__item + .k-accordion__item {
  margin-top: 24px;
}

/* obrys miętowy TYLKO pod kursorem — otwarcie sygnalizują kolor pytania i ikona */
@media (hover: hover) {
  .k-accordion__item:hover {
    border-color: var(--k-energy-mint);
  }
}

.k-accordion__item:active {
  border-color: var(--k-energy-mint);
}

.k-accordion__trigger {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  /* 16 px z Figmy minus 1 px obrysu — w projekcie obrys leży wewnątrz ramki */
  padding: calc(16px - 1px);
  text-align: left;
  color: var(--k-gray-800);
  /* ikona dziedziczy kolor przez currentColor, więc płynie razem z tekstem */
  transition: color var(--k-dur-hover) var(--k-ease-out);
}

.k-accordion__title {
  flex: 1;
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-medium);
  line-height: 20px;
  letter-spacing: var(--k-ls-tight);
}

@media (hover: hover) {
  .k-accordion__item:hover .k-accordion__trigger {
    color: var(--k-energy-mint);
  }
}

.k-accordion__item:active .k-accordion__trigger,
.k-accordion__item.is-open .k-accordion__trigger {
  color: var(--k-energy-mint);
}

/* ---------- ikona: dwie kreski 16×2 w polu 24×24 ----------
   Zwinięta: pozioma + pionowa = „+".
   Rozwinięta: OBIE kreski obracają się o +90°. Pozioma dojeżdża do pionu
   i gaśnie, pionowa dokręca do poziomu i zostaje jako „−". Dzięki temu kręci
   się cały plusik, a nie sama kreska, która i tak znika.
   Mechanizm i krzywe z .ivn-Accordion na oknoplast.com.pl/okna/pilar —
   tam transition nie podaje słowa kluczowego, więc jedzie na `ease`,
   czyli naszym --k-ease-glide. */

.k-accordion__icon {
  position: relative;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
}

.k-accordion__icon::before,
.k-accordion__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 2px;
  margin: -1px 0 0 -8px;
  background: currentColor;
  transition: transform var(--k-dur-accordion) var(--k-ease-glide),
              opacity var(--k-dur-accordion) var(--k-ease-glide);
}

.k-accordion__icon::after {
  transform: rotate(90deg);
}

.k-accordion__item.is-open .k-accordion__icon::before {
  transform: rotate(90deg);
  opacity: 0;
}

.k-accordion__item.is-open .k-accordion__icon::after {
  transform: rotate(180deg);
}

/* ---------- panel ---------- */

.k-accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--k-dur-accordion) var(--k-ease-panel);
}

.k-accordion__item.is-open .k-accordion__panel {
  grid-template-rows: 1fr;
}

.k-accordion__panel > div {
  overflow: hidden;
}

.k-accordion__content {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 calc(16px - 1px) calc(16px - 1px);
  /* Gray-800, choć Figma podaje w bloku treści (166:18057) Gray-600 —
     świadome odstępstwo, decyzja klienta. Patrz docs/SEKCJE.md.
     Przy okazji znika rozjazd: lista wypunktowana miała Gray-800 już wcześniej
     i była ciemniejsza od akapitów wokół siebie. Teraz dziedziczy stąd. */
  color: var(--k-gray-800);
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-book);
  line-height: 20px;
  letter-spacing: var(--k-ls-tight);
}

/* pogrubienia w treści to Medium, nie Bold — tak jest w projekcie */
.k-accordion__content strong {
  font-weight: var(--k-fw-medium);
}

.k-accordion__content a {
  color: var(--k-energy-mint);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--k-dur-fast) var(--k-ease-out);
}

/* Link w treści odpowiedzi — jedyna kontrolka wewnątrz rozwiniętej karty.
   Bez własnego wciśnięcia (plamę gasi base.css) nie różniłby się niczym
   od zwykłego tekstu w chwili tapnięcia. */
.k-accordion__content a:active {
  color: var(--k-deep-mint);
}

/* wyróżnienie typu „Ważne:" */
.k-accordion__lead {
  color: var(--k-energy-mint);
  font-weight: var(--k-fw-medium);
}

/* separator oddzielający pytanie od odpowiedzi — pojawia się z treścią */
.k-accordion__separator {
  display: block;
  height: 1px;
  /* dopełnienie do 16 px odstępu z projektu: 15 px paddingu triggera + 1 px */
  margin-top: 1px;
  /* 8 px marginesu + 8 px gapu kontenera = 16 px do pierwszego akapitu */
  margin-bottom: 8px;
  background: var(--k-border);
}

.k-accordion__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding-left: 21px;
  list-style: disc;
  /* kolor dziedziczy z .k-accordion__content — jedno miejsce na całą treść */
}

/* ==========================================================================
   OPCJA WYBORU — k-choice (kalkulator, warianty produktu)
   ========================================================================== */

.k-choice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--k-space-4);
  width: 100%;
  min-height: 76px;
  /* 18 px z Figmy minus obrys; stan wybrany ma obrys 1,5 px, stąd oddzielna wartość */
  padding: calc(18px - 1px);
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-md);
  background: var(--k-white);
  text-align: left;
  transition: border-color var(--k-dur-fast) var(--k-ease-out),
              background-color var(--k-dur-fast) var(--k-ease-out),
              box-shadow var(--k-dur-fast) var(--k-ease-out);
}

/* Stan pod kursorem — w Figmie nie ma takiego wariantu; szarość dobrana tak, żeby
   wyraźnie odróżniała się od spoczynku (biel + Gray-200) i nie myliła ze stanem
   wybranym (mięta). `:not(.is-selected)` pilnuje, żeby nie zjadała wyboru. */
.k-choice:not(.is-selected):active {
  border-color: var(--k-gray-300);
  background: var(--k-gray-050);
  box-shadow: var(--k-shadow-sm);
}

@media (hover: hover) {
  .k-choice:not(.is-selected):hover {
    border-color: var(--k-gray-300);
    background: var(--k-gray-050);
    box-shadow: var(--k-shadow-sm);
  }
}

.k-choice__title {
  display: block;
  font-size: var(--k-fs-body);
  font-weight: var(--k-fw-bold);
  line-height: normal;
}

.k-choice__meta {
  display: block;
  margin-top: var(--k-space-1);
  font-size: 0.8125rem;             /* 13 px */
  font-weight: var(--k-fw-medium);
  line-height: normal;
}

.k-choice__mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-pill);
}

.k-choice.is-selected {
  padding: calc(18px - 1.5px);
  border-width: 1.5px;
  border-color: var(--k-border-strong);
  background: var(--k-surface-mint);
  box-shadow: 0 4px 6px rgba(0, 177, 235, 0.05);
}

.k-choice.is-selected .k-choice__title {
  color: var(--k-text-accent);
}

.k-choice.is-selected .k-choice__mark {
  border-color: transparent;
  background: var(--k-energy-mint);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 10px;
  background-position: center;
  background-repeat: no-repeat;
}

/* ==========================================================================
   SUWAK ZAKRESU — k-range
   ========================================================================== */

.k-range {
  display: flex;
  align-items: center;
  gap: var(--k-space-4);
}

.k-range__input {
  flex: 1;
  appearance: none;
  height: 6px;
  border-radius: var(--k-radius-pill);
  /* wypełnienie do pozycji kciuka — --k-range-fill ustawia JS */
  background: linear-gradient(
    to right,
    var(--k-energy-mint) var(--k-range-fill, 40%),
    var(--k-gray-200) var(--k-range-fill, 40%)
  );
}

/* Biały obrys oddziela kciuk od wypełnionej części ścieżki — bez niego mięta
   na miętę zlewa się w jedną plamę (Figma: 355:4441, stroke 1 px #FFFFFF).
   `box-sizing: border-box` trzyma zewnętrzne 20 px z makiety. */
.k-range__input::-webkit-slider-thumb {
  appearance: none;
  box-sizing: border-box;
  width: 20px;
  height: 20px;
  border: 1px solid var(--k-white);
  border-radius: var(--k-radius-pill);
  background: var(--k-energy-mint);
  cursor: pointer;
}

.k-range__input::-moz-range-thumb {
  box-sizing: border-box;
  width: 20px;
  height: 20px;
  border: 1px solid var(--k-white);
  border-radius: var(--k-radius-pill);
  background: var(--k-energy-mint);
  cursor: pointer;
}

.k-range__unit {
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-news);
}

/* Pole wartości (Figma: 166:17823) — 110×48, tło Gray-100, promień 8 */
.k-range__value {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 0 0 auto;
  width: 110px;
  height: 48px;
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-xs);
  background: var(--k-gray-100);
  color: var(--k-gray-800);
  font-size: 1.25rem;               /* 20 px */
  font-weight: var(--k-fw-bold);
  line-height: normal;
}

/* Pole liczbowe metrażu — wygląda jak dotychczasowa wartość przy suwaku,
   ale da się w nie wpisać z klawiatury (uwaga klienta z 2026-09-02, OKP-884). */
.k-range__number {
  width: 4ch;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: right;
  padding: 0;
}

/* Strzałki przeglądarki psują układ przy prawym wyrównaniu i są celem
   dotykowym poniżej 44 px — sterowanie zapewnia suwak obok. */
.k-range__number::-webkit-outer-spin-button,
.k-range__number::-webkit-inner-spin-button {
  appearance: none;
  margin: 0;
}
.k-range__number[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}

.k-range__number.is-invalid {
  color: var(--k-error);
  box-shadow: inset 0 -2px 0 var(--k-error);
}

/* Ta sama receptura, co .k-field__error — jeden wygląd błędu na całej
   stronie, nie drugi wynaleziony przy kalkulatorze. */
.k-range__error {
  margin-top: var(--k-space-2);
  color: var(--k-error);
  font-size: var(--k-fs-sm);
}

/* ==========================================================================
   STEPPER — k-stepper (kroki kalkulatora)
   ========================================================================== */

/* Odstęp stały, kreski elastyczne. Przy `space-between` i sztywnych 28 px było
   odwrotnie: na szerszym ekranie rosły odstępy, a kreski zostawały krótkie i
   wisiały w pustce. Teraz 14 px trzyma rytm na każdej szerokości, a nadmiar
   miejsca zbierają kreski. Przy 390 px wychodzi 27,3 px kreski — makieta ma 28. */
.k-stepper {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* `display: flex` bije domyślne `display: none` z [hidden] — krok 4 kreatora
   chowa stepper, bo w makiecie karty wyniku go nie ma. */
.k-stepper[hidden] {
  display: none;
}

.k-stepper__dot {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-pill);
  color: var(--k-gray-800);
  font-size: var(--k-fs-sm);
  font-weight: var(--k-fw-news);
  transition: background-color var(--k-dur-fast) var(--k-ease-out),
              border-color var(--k-dur-fast) var(--k-ease-out),
              color var(--k-dur-fast) var(--k-ease-out);
}

.k-stepper__dot.is-active {
  background: var(--k-energy-mint);
  border-color: transparent;
  color: var(--k-white);
  font-weight: var(--k-fw-medium);
}

/* Krok ukończony (Figma: 567:7970) — baby-mint w obrysie mięty, numer ustępuje
   miejsca „✓". Znacznik rysujemy tłem, tak samo jak w .k-choice__mark. */
.k-stepper__dot.is-done {
  background: var(--k-baby-mint);
  border-color: var(--k-border-strong);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2310a994' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 14px;
  background-position: center;
  background-repeat: no-repeat;
}

/* „✓" zastępuje numer tylko wizualnie — etykieta dla czytnika ekranu zostaje */
.k-stepper__dot.is-done .k-stepper__num {
  display: none;
}

/* Cofnięcie do wcześniejszego kroku — obrys miętą na czas wciśnięcia. Tylko
   dla kropek klikalnych: zablokowana nie ma reagować, a bieżąca (.is-active)
   nigdzie nie prowadzi, więc obie zostają bez zmian. */
.k-stepper__dot:not([disabled]):not(.is-active):active {
  border-color: var(--k-energy-mint);
}

/* Kropka kroku, do którego nie wolno jeszcze skoczyć — wygląda jak w makiecie,
   po prostu nie reaguje. */
.k-stepper__dot[disabled] {
  cursor: default;
}

/* Podpis kroku (Figma: 203:22072) — wchodzi dopiero na desktopie, gdzie karta
   ma na niego miejsce. Stoi pod okrągłym przyciskiem, a nie w nim, bo kropka ma
   sztywne 36 × 36 px i własne stany tła. */
.k-stepper__label {
  display: none;
}

@media (min-width: 1024px) {
  .k-stepper > li:not(.k-stepper__line) {
    display: grid;
    justify-items: center;
    gap: 8px;
  }

  .k-stepper__label {
    display: block;
    color: var(--k-gray-600);
    font-size: var(--k-fs-sm);
    font-weight: var(--k-fw-news);
    line-height: 21px;
    white-space: nowrap;
  }

  /* podpis kroku, w którym stoimy, jest czytelniejszy niż reszta */
  .k-stepper > li:has(.k-stepper__dot.is-active) .k-stepper__label {
    color: var(--k-gray-800);
    font-weight: var(--k-fw-medium);
  }
}

/* 28 px z makiety jest bazą, nie sztywną szerokością — kreska rośnie i kurczy się
   razem z kartą. `min-width: 0` pozwala jej zejść poniżej bazy na wąskich
   ekranach, zamiast wypychać kropki poza kartę. */
.k-stepper__line {
  flex: 1 1 28px;
  min-width: 0;
  height: 1px;
  background: var(--k-border);
}

/* ==========================================================================
   PANEL WYNIKU KALKULATORA — k-result-panel
   --------------------------------------------------------------------------
   Druga kolumna kalkulatora na desktopie: pusty szkielet (Figma: 696:5207,
   454 × 306) do czasu kliknięcia „Zobacz twój wynik", potem liczby i CTA
   (696:5217, 454 × 476). Metryki są te same co w mobilnej karcie wyniku —
   padding 32/24, odstęp 24 px — więc typografię niesie wspólne .k-result__*.
   Poniżej 1024 px panel w ogóle nie istnieje w układzie: liczby są w DOM-ie
   dwa razy, ale czytnik ekranu widzi tylko komplet z kroku 4.
   ========================================================================== */

.k-result-panel {
  display: none;
  flex-direction: column;
  gap: 24px;
  padding: 32px 24px;
  border-radius: var(--k-radius-md);
  background: var(--k-surface-deep);
  color: var(--k-hl-mint);
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.2);
}

@media (min-width: 1024px) {
  .k-result-panel {
    display: flex;
  }
}

.k-result-panel__empty {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* pasek etykiety 180 × 8 i blok wartości 180 × 44 z makiety, 10 px między nimi */
.k-result-panel__skeleton {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.k-result-panel__bar,
.k-result-panel__box {
  width: 180px;
  max-width: 100%;
  background: var(--k-energy-mint);
}

.k-result-panel__bar {
  height: 8px;
  border-radius: var(--k-radius-pill);
}

.k-result-panel__box {
  height: 44px;
  border-radius: var(--k-radius-xs);
}

.k-result-panel__hint {
  font-size: 0.6875rem;             /* 11 px — tak jak nota pod wynikiem */
  font-weight: var(--k-fw-news);
  line-height: var(--k-lh-label);
}

.k-result-panel__data {
  display: none;
  flex-direction: column;
  gap: 24px;
}

.k-result-panel.is-filled .k-result-panel__empty {
  display: none;
}

.k-result-panel.is-filled .k-result-panel__data {
  display: flex;
}

/* CTA trzyma się swojej etykiety, nie rozpycha się na całą szerokość panelu */
.k-result-panel__cta {
  align-self: start;
}

/* ==========================================================================
   LIGHTBOX — k-lightbox (markup tworzy js/modules/lightbox.js)
   ========================================================================== */

.k-lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--k-z-lightbox);
  display: grid;
  place-items: center;
  padding: var(--k-space-6);
  background: rgba(8, 26, 22, 0.92);
}

.k-lightbox[hidden] {
  display: none;
}

/* <picture> owija <img>, ale siatka .k-lightbox ma wyśrodkować samo zdjęcie —
   display: contents wyjmuje wrapper z układu, nie ruszając wyboru źródła.
   Przy display: contents rodzica Chrome przestaje ukrywać <source>: staje się
   on pełnoprawnym elementem siatki i spycha zdjęcie do drugiego wiersza,
   dlatego gasimy go jawnie. */
.k-lightbox picture {
  display: contents;
}

.k-lightbox picture source {
  display: none;
}

.k-lightbox__image {
  max-width: min(100%, 1200px);
  max-height: 86vh;
  width: auto;
  height: auto;
  border-radius: var(--k-radius-md);
}

.k-lightbox__close {
  position: absolute;
  top: var(--k-space-5);
  right: var(--k-space-5);
  width: 44px;
  height: 44px;
  border-radius: var(--k-radius-pill);
  background: rgba(255, 255, 255, 0.14);
  color: var(--k-white);
  font-size: 1.75rem;
  line-height: 1;
  /* Ten sam timing co przyciski (--k-dur-btn + --k-ease-btn) — krzyżyk jest
     jedyną akcją na tym ekranie i ma się zachowywać jak reszta akcji. */
  transition: background-color var(--k-dur-btn) var(--k-ease-btn),
              color var(--k-dur-btn) var(--k-ease-btn);
}

/* Kółko baby-mint z krzyżykiem energy-mint, jak stany hover w całym projekcie.
   Tło idzie z pełnego tokena, nie z półprzezroczystej bieli — na ciemnym
   overlayu przygaszona mięta straciłaby kolor. */
@media (hover: hover) {
  .k-lightbox__close:hover {
    background: var(--k-baby-mint);
    color: var(--k-energy-mint);
  }
}

/* ==========================================================================
   PRZYKLEJONY PASEK CTA — k-cta-bar (Figma: 331:4401, 390 × 80)
   --------------------------------------------------------------------------
   Dwa główne CTA znikają razem z hero i wracają dopiero przy formularzu.
   Pasek trzyma je pod ręką przez resztę strony. Komponent wyłącznie mobilny —
   powyżej 1024 px oba CTA są w zasięgu wzroku w belce i w treści.

   Zachowanie z referencji oknoplast.com.pl/pilar (.b-mobile-buttons):
   300 ms, BEZ transition-delay (sprawdzone — tam też go nie ma).

   Trójka visibility + opacity + transform jest celowa. Samo `opacity: 0`
   zostawiłoby pasek klikalnym i w kolejności Tab; `visibility: hidden`
   wyjmuje go z obu, a że jest animowalne dyskretnie, przełącza się dopiero
   po wygaszeniu i nie ucina przejścia.

   Klasę `is-visible` nadaje js/modules/cta-bar.js.
   ========================================================================== */

.k-cta-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--k-z-cta-bar);
  display: flex;
  justify-content: center;
  min-height: var(--k-cta-bar-h);
  padding: 20px var(--k-gutter);    /* 20 px z Figmy; boki idą za gutterem sekcji */
  background: var(--k-surface-deep);
  visibility: hidden;
  opacity: 0;
  transform: translateY(100%);
  transition: transform var(--k-dur-base) var(--k-ease-out),
              opacity var(--k-dur-base) var(--k-ease-out),
              visibility var(--k-dur-base) var(--k-ease-out);
}

.k-cta-bar.is-visible {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
}

/* Przy otwartym menu pasek schodzi z drogi. Sam z-index by wystarczył (90 < 1000),
   ale przezroczysta krawędź panelu potrafiłaby go przepuścić. */
.k-cta-bar.is-menu-open {
  visibility: hidden;
  opacity: 0;
  transform: translateY(100%);
}

.k-cta-bar__inner {
  display: flex;
  /* Figma daje 24 px przy kadrze 390. Na 320 px dwa przyciski po 160 px plus
     24 px odstępu nie mieszczą się w kadrze, więc odstęp jedzie z ekranem. */
  gap: clamp(16px, 6.15vw, 24px);
  width: 100%;
  max-width: 344px;                 /* 390 − 2 × 23 z Figmy */
}

.k-cta-bar__btn {
  /* 160 px z Figmy to sufit, nie sztywna szerokość — na wąskim ekranie
     przyciski schodzą równo, zamiast wypychać pasek poza kadr. */
  flex: 1 1 0;
  max-width: 160px;
  padding-inline: 12px;             /* jak .k-menu__btn — etykiety mieszczą się */
}

/* Etykieta „Kontakt z doradcą" ma 142,5 px szerokości naturalnej, a „Znajdź
   salon" 107. Przy odstępie clamp(16px, 6.15vw, 24px) i gutterze 16 px oba
   przyciski są równe dopiero od 338 px, a poniżej 300 px w ogóle przestają się
   mieścić obok siebie. Dlatego poniżej 360 px (z zapasem na metryki fontu)
   wchodzi krótsze „Kontakt" — wtedy przyciski są równe na każdym telefonie.

   Mobile-first: krótka etykieta jest domyślna, długa dochodzi od 360 px. */
.k-cta-bar__label--long {
  display: none;
}

@media (min-width: 360px) {
  .k-cta-bar__label--long {
    display: inline;
  }

  .k-cta-bar__label--short {
    display: none;
  }
}

/* Komponent mobilny: powyżej 1024 px nie istnieje. */
@media (min-width: 1024px) {
  .k-cta-bar {
    display: none;
  }
}
