/* ==========================================================================
   BASE — reset, fonty, typografia, warstwa użytkowa
   Ładowany po tokens.css, przed components.css
   ========================================================================== */

/* ---------- @font-face ----------
   Jedna rodzina „Clan Pro" z wagami, zamiast osobnych rodzin per krój.
   Dzięki temu w komponentach używamy font-weight, a nie font-family.

   Mapowanie krojów z Figmy na pliki, które są w repo:
     Clan Pro Book (300)   → FFClanProRegular.woff
     Clan Pro News (400)   → FFClanProRgNews.woff
     Clan Pro Medium (500) → FFClanProMedium.woff
     Clan Pro Bold (700)   → FFClanProBold.woff
     Clan Pro Black (900)  → FFClanProBlk.woff
     Clan N Bold (700)     → FFClanNBold.woff  ← osobna rodzina, patrz niżej

   Etykiety przycisków Figma składa krojem WĄSKIM („Clan N Bold (700)", styl
   Labels/Thick/Small+t), a nie Clan Pro. To jedyne miejsce, gdzie projekt schodzi
   z Clan Pro — nagłówki, treść i badge'e zostają szerokie. Dlatego „Clan N" jest
   osobną rodziną (token --k-font-label), a nie kolejną wagą w „Clan Pro":
   przy jednej rodzinie nie dałoby się mieć obu szerokości w wadze 700.
   Plik powstał z ClanNBold(700)-Bold.otf z licencjonowanego pakietu klienta.

   Pakiet webfontów z brand booka nie zawiera kroju Book, więc wagę 300 obsługuje
   Regular — ustalone z klientem. (Thin był rozważany i odrzucony: za lekki.)
   W repo leży też FFClanProRgNarNews.woff (Clan Pro Narr News) — na razie
   nieużywany; wejdzie, gdyby wąski krój był potrzebny także w wadze 400.
   Każdy krój jest w dwóch formatach: woff2 (Brotli, ok. 30 % mniej) jako pierwszy
   wpis i woff jako zapas dla starszych przeglądarek. Przeglądarka bierze pierwszy
   format, który zna, więc kolejność w `src` ma znaczenie.

   Pliki bez `@font-face` (ExtdBold, RgNarNews, Thin) i waga 900 NIE są pobierane —
   przeglądarka ściąga font dopiero, gdy jakiś element go użyje. Leżą w repo jako
   część licencjonowanego pakietu klienta i nie kosztują ani bajta transferu. */

@font-face {
  font-family: "Clan Pro";
  src: url("../fonts/FFClanProRegular.woff2") format("woff2"),
       url("../fonts/FFClanProRegular.woff") format("woff");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clan Pro";
  src: url("../fonts/FFClanProRgNews.woff2") format("woff2"),
       url("../fonts/FFClanProRgNews.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clan Pro";
  src: url("../fonts/FFClanProMedium.woff2") format("woff2"),
       url("../fonts/FFClanProMedium.woff") format("woff");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clan Pro";
  src: url("../fonts/FFClanProBold.woff2") format("woff2"),
       url("../fonts/FFClanProBold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clan Pro";
  src: url("../fonts/FFClanProBlk.woff2") format("woff2"),
       url("../fonts/FFClanProBlk.woff") format("woff");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* Wąski krój etykiet — używa go wyłącznie .k-btn (token --k-font-label) */
@font-face {
  font-family: "Clan N";
  src: url("../fonts/FFClanNBold.woff2") format("woff2"),
       url("../fonts/FFClanNBold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Reset ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Natywna „plama dotyku" WebKit/Blink: półprzezroczysty prostokąt malowany na
     całym pudełku klikalnego elementu. Nie da się jej ostylować poza kolorem,
     ignoruje promienie naszych kontrolek, a przy przyciskach z powiększoną do
     44 px strefą dotyku (::after w components.css) wychodzi poza sam przycisk.
     Gasimy ją na <html>, bo właściwość dziedziczy — żaden element jej nie ominie.

     UWAGA przy dokładaniu kontrolek: skoro plamy nie ma, potwierdzenie dotknięcia
     niesie WYŁĄCZNIE stan :active z arkusza. Każda klikalna kontrolka musi go mieć,
     inaczej tapnięcie nie daje żadnej reakcji. Pola tekstowe są wyjątkiem —
     tam sprzężenie zwrotne robi kursor i obwódka focusu. */
  -webkit-tap-highlight-color: transparent;
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd,
ul, ol {
  margin: 0;
}

/* :where() zeruje specyficzność selektora — bez tego `ul[class]` (0,1,1) wygrywa
   z regułami komponentów (0,1,0) i kasuje im punktory oraz wcięcia.
   Reset ma ustępować komponentom, nie odwrotnie. */
:where(ul[class], ol[class]) {
  padding: 0;
  list-style: none;
}

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

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

/* <picture> jest tylko opakowaniem na warianty formatu — nie może wprowadzać
   własnego pudełka do układu, bo reguły sekcji celują w <img> i zakładają, że
   to on jest dzieckiem kontenera (figure, li, div). */
picture {
  display: contents;
}

/* ---------- Dokument ---------- */

body {
  margin: 0;
  background: var(--k-surface);
  color: var(--k-text);
  font-family: var(--k-font-sans);
  font-size: var(--k-fs-body);
  font-weight: var(--k-fw-regular);
  line-height: var(--k-lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Kotwice CTA nie mogą chować się pod sticky barem */
[id] {
  scroll-margin-top: calc(var(--k-header-h) + var(--k-space-4));
}

/* ---------- Typografia ---------- */

h1, h2, h3, h4 {
  font-weight: var(--k-fw-bold);
  line-height: var(--k-lh-heading);
  text-wrap: balance;
}

h1 {
  font-size: var(--k-fs-display);
  line-height: var(--k-lh-heading);
  letter-spacing: var(--k-ls-display);
}

/* H2 i H4 mają w Figmie stałą interlinię (26/32 i 20/28), więc na mobile
   trzymamy piksele, a od 768 px wracamy do proporcjonalnej. */
h2 {
  font-size: var(--k-fs-h2);
  line-height: var(--k-lh-h2);
  letter-spacing: var(--k-ls-heading);
}

h3 { font-size: var(--k-fs-h3); }

h4 {
  font-size: var(--k-fs-h4);
  font-weight: var(--k-fw-medium);
  line-height: var(--k-lh-h4);
  letter-spacing: var(--k-ls-heading);
}

@media (min-width: 768px) {
  h2,
  h4 {
    line-height: var(--k-lh-heading);
  }
}

p {
  text-wrap: pretty;
}

strong, b {
  font-weight: var(--k-fw-bold);
}

/* ---------- Focus ---------- */

:focus-visible {
  outline: 3px solid var(--k-focus-ring);
  outline-offset: 3px;
  border-radius: var(--k-radius-xs);
}

/* ---------- Warstwa użytkowa ---------- */

.k-container {
  width: 100%;
  max-width: var(--k-container);
  margin-inline: auto;
  padding-inline: var(--k-gutter);
}

.k-container--narrow {
  max-width: var(--k-container-narrow);
}

/* Szerszy wariant dla kalkulatora: Figma daje sekcji 1200 px TREŚCI, a nie
   szerokości pudełka — stąd doliczony gutter po obu stronach. Przy oknie 1440 px
   wychodzi margines 120 px, dokładnie jak w makiecie (203:22072). */
.k-container--wide {
  max-width: calc(var(--k-container-wide) + 2 * var(--k-gutter));
}

.k-section {
  padding-block: var(--k-section-y);
}

/* Od 1024 px rytm jest STAŁY, nie płynny. Płynna skala zastępuje breakpointy
   poniżej tej szerokości, ale wyżej szkodzi: clamp osiąga 80 px dopiero przy
   ~1520 px okna, więc na laptopie dawał 76,8 px i rozjeżdżał się z sekcjami,
   które 80 px mają wpisane wprost (--k-space-10 w sections.css).
   Wyjątki (#certyfikaty, blok produktowy) wygrywają kolejnością arkuszy —
   sections.css ładuje się po base.css. */
@media (min-width: 1024px) {
  .k-section {
    padding-block: var(--k-space-10);
  }
}

.k-section--mint { background: var(--k-surface-mint); }
.k-section--mint-strong { background: var(--k-surface-mint-strong); }
.k-section--alt { background: var(--k-surface-alt); }
.k-section--deep {
  background: var(--k-surface-deep);
  color: var(--k-text-on-deep);
}

/* Kolorowe tło kończy się tam, gdzie tło hero — obie krawędzie na
   --k-container. Limit siedzi przy modyfikatorach tła, bo dotyczy wyłącznie
   sekcji, które w ogóle mają co przycinać; biała sekcja niczym się nie różni
   od tła strony. Poniżej 1440 px reguła jest bez efektu (okno węższe niż
   limit), więc nie ma jej w bloku desktopowym.
   Rogi zostają ostre: hero też nie ma border-radius, a chodzi o zgranie
   krawędzi, nie o kartę. */
.k-section--mint,
.k-section--mint-strong,
.k-section--alt,
.k-section--deep {
  max-width: var(--k-container);
  margin-inline: auto;
}

/* Opcjonalne odroczenie renderu sekcji — NIE stosujemy domyślnie.
   Przy tej długości strony zysk jest nieudowodniony, a odroczony render
   utrudniał weryfikację wizualną (sekcje bywały puste w chwili zrzutu).
   Włączać punktowo, na sekcjach bez interakcji i dopiero po zmierzeniu
   realnego wpływu na LCP/INP. */
.k-section--deferred {
  content-visibility: auto;
  contain-intrinsic-size: auto 900px;
}

/* Akapit wprowadzający — Figma: Paragraphs / Mobile / Medium - Basic (14/20 Book) */
.k-lead {
  color: var(--k-text);
  font-size: var(--k-fs-lead);
  font-weight: var(--k-fw-book);
  line-height: var(--k-lh-lead);
  letter-spacing: var(--k-ls-tight);
}

@media (min-width: 768px) {
  .k-lead {
    line-height: var(--k-lh-body);
  }
}

.k-muted { color: var(--k-text-muted); }
.k-accent { color: var(--k-text-accent); }

.k-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.k-stack > * + * {
  margin-top: var(--k-space-4);
}

/* ---------- Ruch: wyłącznik ruchu DEKORACYJNEGO ----------
   Uzupełnia wyłączenie GSAP-a po stronie JS (js/modules/motion.js).
   Gasi reveal, liczniki i przejścia CSS. Ruch FUNKCJONALNY — karuzela po
   strzałce, zjazd do kotwicy, scroll formularza/kalkulatora — celowo NIE
   podlega tym regułom: prowadzi go pętla rAF w js/modules/scroll.js,
   która przy „Ogranicz ruch" sama skraca animację do --k-dur-scroll-reduced.
   `scroll-behavior: auto` musi tu zostać — to warunek, żeby natywny fallback
   kotwic nie animował po systemowemu, gdy JS przejmuje przewijanie. */

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    /* Skrócenie czasu nie wystarcza — bez wyzerowania opóźnienia plakietka
       hero i tak czekałaby swoje 1,2 s (--k-delay-hero-badge), tyle że potem
       pojawiłaby się skokowo. Tak samo warstwy KV na desktopie
       (--k-delay-hero-okno, --k-delay-hero-chlopiec). Innych opóźnień
       w projekcie nie ma. */
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Reveal przy scrollu ----------
   Stan początkowy nakładamy tylko wtedy, gdy JS wystartował (klasa na <html>),
   żeby przy wyłączonym JS treść była normalnie widoczna.

   UWAGA przy zagnieżdżaniu: --k-reveal-delay DZIEDZICZY SIĘ. Element
   [data-reveal] wewnątrz innego [data-reveal] przejmie inline'owy stagger
   rodzica, jeśli sam nie zadeklaruje własnego opóźnienia (tak robi
   .k-guarantee__badge w sections.css). */

.k-js [data-reveal] {
  opacity: 0;
  /* dystans z tokenu, żeby komponent mógł go podmienić SAMĄ ZMIENNĄ —
     nadpisanie `transform` remisowałoby ze specyficznością reguły
     .is-revealed niżej i element zostałby przesunięty na stałe */
  transform: translateY(var(--k-reveal-shift));
  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);
  will-change: opacity, transform;
}

.k-js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

.k-motion-off [data-reveal] {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  /* Klasę k-motion-off można włączyć W TRAKCIE sesji (motion.js nasłuchuje
     zmiany „Ogranicz ruch"). Element staje się wtedy widoczny, ale nigdy nie
     dostaje klasy is-revealed — bez tej linii wyłączone wskazywanie
     (components.css) zostałoby na nim na stałe i link byłby nieklikalny. */
  pointer-events: auto !important;
}

/* Reguła wyżej gasi tylko [data-reveal], a więc ruch, który KOŃCZY SIĘ po
   wejściu. Nieskończone pętle trzeba wyłączyć osobno — dziś jest jedna
   (kołysanie chłopca w KV hero), ale selektor celowo łapie każdą animację
   w drzewie, żeby kolejna nie została przeoczona. Przy prefers-reduced-motion
   robi to blok wyżej (animation-iteration-count: 1). */
.k-motion-off *,
.k-motion-off *::before,
.k-motion-off *::after {
  animation: none !important;
}
