/*
 * Klasy stanów (do użycia w PHP/Twig):
 *   .input--success                  → zielona ramka + ikona ✓ w polu
 *   .input--error                    → czerwona ramka + ikona ⚠ w polu
 *   .field__error                    → komunikat błędu pod polem (dodaj <p> po .input)
 *   .toggle-row--error               → czerwone obrysowanie toggle (na .toggle-row)
 *   .btn--loading                    → spinner w buttonie, blokuje kliknięcia
 *   button[disabled]                 → jawnie wyłączony przycisk
 *
 * Stan disabled przycisku: gdy toggle zgody jest OFF, CSS automatycznie pokazuje
 * przycisk jako szary (przez :has). Toggle ON → button różowy.
 */

*,
*::before,
*::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-sans);
  color: var(--color-text-primary);
}

body {
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: var(--color-neutral-100);
  padding: var(--space-2xl);
}

/* Tło z grafiką panelu Tillio + biały fade overlay (na razie tylko step 8 — `<body class="body--app-bg">`) */
body.body--app-bg {
  background:
    linear-gradient(rgba(255, 255, 255, 0.82), rgba(255, 255, 255, 0.82)),
    url('/assets/img/tillio-app-background-opt.png') center center / cover no-repeat fixed;
}

/* ===== MODAL ===== */
.modal {
  width: 1086px;
  max-width: 100%;
  background: var(--color-bg-primary);
  border-radius: var(--radius-md);
  box-shadow:
    0 24px 60px rgba(17, 39, 59, 0.18),
    0 4px 16px rgba(17, 39, 59, 0.08);
  overflow: hidden;
}

.modal__inner {
  display: grid;
  grid-template-columns: 630px 1fr;
  min-height: 704px;
}

/* ===== LEFT: FORM COLUMN ===== */
.modal__form-col {
  padding: var(--space-4xl);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3xl);
}

/* Hero */
.hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}
.hero__title {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-h2-size);
  line-height: 1.2;
  color: var(--color-text-primary);
}
.hero__title-accent { color: var(--color-primary-600); }

/* Utility — pink akcent dla pojedynczych znaków/słów (np. "*" w opisie) */
.text-accent { color: var(--color-primary-600); }

.hero__description {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  background: var(--overlay-soft-3);
  padding: var(--space-xl);
  border-radius: var(--radius-md);
}
.hero__description-lead {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: 1.4;
  color: var(--color-text-primary);
}

/* Bullets */
.bullets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
}
.bullet {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-ui);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
  white-space: nowrap;
}
.bullet__icon { width: 20px; height: 20px; flex-shrink: 0; }

/* ===== FORM ===== */
.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}
.form__fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.field {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.field__label {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
}

.input {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: var(--radius-md);
  padding: 10px 14px;
  box-shadow: var(--shadow-xs);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.input:focus-within {
  border-color: var(--color-primary-600);
  box-shadow: 0 0 0 4px rgba(255, 10, 113, 0.1);
}
.input__icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.input__control {
  flex: 1 0 0;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  color: var(--color-text-primary);
}
.input__control::placeholder { color: var(--color-text-secondary); }

/* Wariant: phone input z prefiksem kraju + maska "___ ___ ___" */
.input--phone { padding: 0; gap: 0; }
.input__country {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xxs);
  padding: 10px 0 10px 14px;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  color: var(--color-text-primary);
}
.input__country-flag-wrap {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.input__country-flag {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.input__country-caret {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* Pole telefonu: display z typed+mask na spodzie, transparent input na górze */
.input--phone .input__field {
  position: relative;
  flex: 1 0 0;
  min-width: 0;
  padding: 10px 14px 10px 12px;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  font-variant-numeric: tabular-nums;
}
.input--phone .input__display {
  display: block;
  white-space: pre;
  pointer-events: none;
  user-select: none;
  color: var(--color-text-secondary);
}
.input--phone .input__display .typed { color: var(--color-text-primary); }
.input--phone .input__control {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: inherit;
  background: transparent;
  color: transparent;
  caret-color: var(--color-text-primary);
  border: 0;
  outline: 0;
  font: inherit;
  font-variant-numeric: inherit;
}
.input--phone .input__control::placeholder { color: transparent; }
.input--phone .input__control::selection {
  color: transparent;
  background: rgba(255, 10, 113, 0.2);
}

/* Stany walidacji pól */
.input--success {
  border-color: var(--color-success-600);
}
.input--error {
  border-color: var(--color-alert-600);
}
.input--success::after,
.input--error::after {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.input--success::after { background-image: url("/assets/icons/check-circle.svg"); }
.input--error::after   { background-image: url("/assets/icons/alert-circle.svg"); }

/* Phone i with-suffix variants: container ma padding 0, więc dorzucamy margin pod ikonę walidacji */
.input--phone.input--success::after,
.input--phone.input--error::after,
.input--with-suffix.input--success::after,
.input--with-suffix.input--error::after { margin-right: 14px; }

/* Loading spinner na inpucie (AJAX w locie) — nadpisuje ikonę walidacji */
.input--loading::after {
  content: "";
  display: block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background: none;
  border: 2px solid var(--color-neutral-200);
  border-top-color: var(--color-primary-600);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
.input--phone.input--loading::after,
.input--with-suffix.input--loading::after { margin-right: 14px; }

/* Komunikat błędu — absolute, żeby layout nie skakał. Mieści się w gap-32px do następnego elementu. */
/* Komunikat wisi POD polem (absolute), zeby jego pojawienie sie nie przesuwalo formularza.
   `min-height` rezerwuje miejsce na dwie linie: komentarze od AI potrafia byc dlugie
   ("Czy na pewno nazwa firmy to ...? :)") i przy trzech liniach wchodzily na etykiete
   nastepnego pola. Powyzej tego i tak przycinamy - dluzszy tekst nie jest komunikatem
   bledu, tylko wypracowaniem. */
/* Komunikat z walidacji W TLE (AI, NIP) idzie w NORMALNY UKLAD, nie absolutnie: teksty od
   modelu bywaja dlugie ("Czy na pewno nazwa firmy to ...? :)") i jako element oderwany
   od ukladu wchodzily na etykiete nastepnego pola. W flow rozsuwaja formularz zamiast go
   zaslaniac. Krotkie bledy walidacji formatu zostaja absolutne - tam skakanie ukladu
   przy kazdym blur bylo by gorsze. */
.field[data-async-error] .field__error {
  position: static;
  max-height: none;
  margin-top: var(--space-xs);
}
.field__error {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  max-height: 2.8em;
  overflow: hidden;
  margin: var(--space-xs) 0 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-alert-600);
  pointer-events: none;
}

/* Podpowiedź pod polem — ten sam układ co `.field__error`, ale to NIE jest błąd
   (np. „poprawiliśmy zapis nazwy firmy"). Kolor sukcesu, nie alarmu: pole jest już
   poprawne, a klient ma tylko zobaczyć, co zmieniliśmy. */
.field__hint {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: var(--space-xs) 0 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
  pointer-events: none;
}
.field__hint--ok { color: var(--color-success-600); }
/* Podpowiedz jako SAMODZIELNY BLOK tresci, nie dopisek pod inputem. Bazowy `.field__hint`
   jest `absolute` (wisi pod polem i nie rozpycha formularza) - w polu BEZ inputa, gdzie hint
   jest jedyna trescia, wypadal z ukladu i wchodzil na przycisk "Dalej" (krok 6 na sciezce
   Tillio: zdanie o imporcie zespolu z panelu). Tutaj ma zajmowac swoje miejsce. */
.field__hint--block {
  position: static;
  margin-top: var(--space-sm);
}

/* Komunikat pod formularzem (np. potwierdzenie ponownej wysyłki kodu na step3) —
   w flow formularza (nie absolute jak .field__error), wyśrodkowany jak .form-helper. */
.form-error {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-alert-600);
  text-align: center;
}
.form-error--success { color: var(--color-success-600); }

.toggle-row--error .toggle__switch {
  outline: 1px solid var(--color-alert-600);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ===== TOGGLE ===== */
.toggle-row {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  cursor: pointer;
}
.toggle__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.toggle__switch {
  position: relative;
  flex-shrink: 0;
  width: 36px;
  height: 20px;
  border-radius: var(--radius-sm);
  background: var(--color-neutral-200);
  padding: var(--space-xxs);
  transition: background 120ms ease;
}
.toggle__switch::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-sm);
  background: var(--color-fg-white);
  box-shadow: var(--shadow-sm);
  transition: transform 160ms ease;
}
.toggle__input:checked + .toggle__switch { background: var(--color-success-600); }
.toggle__input:checked + .toggle__switch::before { transform: translateX(16px); }
.toggle__input:focus-visible + .toggle__switch {
  box-shadow: 0 0 0 3px rgba(43, 152, 72, 0.2);
}

.toggle-row__text {
  flex: 1;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-xs-size);
  line-height: 1.4;
  color: var(--color-text-secondary);
}
.toggle-row__link {
  color: var(--color-primary-600);
  text-decoration: none;
}
.toggle-row__link:hover { text-decoration: underline; }

/* ===== ACTIONS ===== */
.form__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;  /* reset dla <a class="btn"> */
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
  box-shadow: var(--shadow-xs);
}
.btn--primary {
  background: var(--color-primary-600);
  color: var(--color-text-on-primary);
  cursor: pointer;
}
.btn--primary:hover { filter: brightness(0.95); }

/* Wariant outline (drugorzedny CTA: rejestracja przez Tillio, przyciski wstecz/dalej na ekranach info) */
.btn--ghost {
  background: #fff;
  color: var(--color-text-primary);
  border-color: var(--color-border-primary);
  cursor: pointer;
}
.btn--ghost:hover { background: var(--color-primary-50); border-color: var(--color-primary-600); color: var(--color-primary-600); }

/* ===== KAFLE WYBORU SCIEZKI (krok 1) =====
   Pierwsze pytanie rejestracji: konto Tillio czy swieze konto do samego Calls. Wybor
   siedzi na `input[type=radio]` + `:has()` - bez JS, wiec dziala z klawiatury i czyta
   sie poprawnie czytnikiem ekranu. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Honeypot: pole poza ekranem, ktorego czlowiek nie widzi ani nie zlapie tabem. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.path-tiles { border: 0; padding: 0; margin: 0; }
/* Krój, grubosc i kolor 1:1 z `.login-link` ("Masz juz konto?") - to na tym ekranie
   jedyny inny tekst tej rangi, a kazdy wlasny wariant szarosci dokladalby czwarty
   styl tekstu do widoku, ktory ma juz naglowek, opis i tresc kafli. */
.path-tiles__legend {
  padding: 0;
  margin-bottom: var(--space-md);
  font-family: var(--font-ui);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
}
.path-tiles__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
}
.path-tile { position: relative; display: block; cursor: pointer; }
.path-tile__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.path-tile__box {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  height: 100%;
  padding: var(--space-lg);
  border: 1px solid var(--color-border-primary);
  border-radius: var(--radius-lg);
  background: var(--color-bg-primary);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.path-tile:hover .path-tile__box { border-color: var(--color-neutral-400); transform: translateY(-1px); }
.path-tile__input:focus-visible + .path-tile__box { outline: 2px solid var(--color-secondary-600); outline-offset: 2px; }
.path-tile__input:checked + .path-tile__box {
  border-color: var(--color-primary-600);
  box-shadow: 0 0 0 1px var(--color-primary-600) inset;
  background: var(--color-primary-50);
}
/* Znak marki (kafel Tillio) i glif sluchawek (kafel Calls) stoja w tym samym slocie
   32x32 - bez szarego kafelka pod spodem, ktory na rozowym tle robil plame na plamie.
   Oba sa rozowe NIEZALEZNIE od zaznaczenia: kolorowa marka przy szarej ikonie obok
   robilaby z konta Tillio "te wlasciwa" opcje, a to sciezka mniejszosci. */
.path-tile__icon { display: block; width: 32px; height: 32px; color: var(--color-primary-600); }
.path-tile__icon svg { width: 100%; height: 100%; display: block; }
/* Kolory znaku marki na wypadek wariantu BEZ calls-theme.css - tamten arkusz maluje
   `.calls-mark__*` i bez niego kafel logo wyszedlby czarny. */
.path-tile__icon .calls-mark__plate { fill: var(--color-primary-600); }
.path-tile__icon .calls-mark__glyph { fill: var(--color-fg-white); }
.path-tile__icon .calls-mark__glyph--soft { fill: var(--color-neutral-200); }
/* Potwierdzenie wyboru pojawia sie TYLKO na zaznaczonym kaflu - pusty krazek przy
   niezaznaczonym wisial bez powodu i bil sie o uwage z ikona. */
.path-tile__check {
  position: absolute;
  top: var(--space-lg);
  right: var(--space-lg);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-primary-600);
  color: var(--color-fg-white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(.8);
  transition: opacity .15s ease, transform .15s ease;
}
.path-tile__input:checked + .path-tile__box .path-tile__check { opacity: 1; transform: none; }
.path-tile__check svg { width: 12px; height: 12px; }
.path-tile__title {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-semibold);
  font-size: 15px;
  line-height: 1.3;
  color: var(--color-text-primary);
}
.path-tile__desc { font-size: 13px; line-height: 1.45; color: var(--color-text-secondary); }

/* Blok odslaniany przez wybor. Niewybrany WYPADA z ukladu (`display:none`), a nie zostaje
   jako zwiniete zero - inaczej `gap` formularza liczy go dalej i pod kaflami siedzi pusty pas. */
.path-reveal { display: none; flex-direction: column; gap: var(--space-xl); }
.form:has(#path-local:checked) .path-reveal--local,
.form:has(#path-tillio:checked) .path-reveal--tillio {
  display: flex;
  animation: path-reveal-in .2s ease both;
}
@keyframes path-reveal-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
.path-note {
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  background: var(--color-neutral-100);
  font-size: var(--text-sm-size);
  line-height: 1.5;
  color: var(--color-neutral-600);
}
@media (prefers-reduced-motion: reduce) {
  .path-tile__box, .path-tile__check { transition: none; }
  .form:has(#path-local:checked) .path-reveal--local,
  .form:has(#path-tillio:checked) .path-reveal--tillio { animation: none; }
}
/* Na telefonie dwie kolumny scisnelyby opis do slupka - kafle ida jeden pod drugim. */
@media (max-width: 480px) {
  .path-tiles__grid { grid-template-columns: 1fr; }
}

/* Rozdzielacz "lub" miedzy glownym CTA a logowaniem przez Tillio */
.form-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--color-text-secondary);
  font-size: var(--text-sm-size);
}
.form-divider::before,
.form-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--color-border-primary);
}

/* === Disabled style (standalone — żeby nie zostało invalid'owane przez nested :has w chain) === */
.btn--primary[disabled]:not(.btn--loading),
.btn--primary[aria-disabled="true"]:not(.btn--loading),
.form.form--cl-empty .btn--primary:not(.btn--loading) {
  background: var(--color-bg-disabled);
  border-color: var(--color-border-disabled);
  color: var(--color-text-disabled);
  cursor: not-allowed;
  filter: none;
}

/* CSS-only disabled checks (chain z :has — fallback gdy JS nie odpalił).
   UWAGA: chain może się invalid'ować w niektórych przeglądarkach przez nested :has.
   Dla pewności mamy też JS-driven [disabled] attr setter.
   Scope `[data-rule]` zapewnia że opcjonalne pola NIE blokują. */
/* `:not(:has(.path-tiles))` WYKLUCZA krok 1 z kaflami - ma on DWA komplety pol (jeden na
   ścieżkę), z których widoczny jest zawsze tylko jeden. Ogólna reguła patrzyła też na ten
   ukryty: pole e-mail ścieżki lokalnej jest puste, a zgoda ścieżki Tillio niezaznaczona,
   więc przycisk zostawał szary NIEZALEŻNIE od tego, co klient wypełnił. */
.form:not(:has(.path-tiles)):has([data-rule] .input__control:placeholder-shown) .btn--primary:not(.btn--loading),
.form:not(:has(.path-tiles)):has(.toggle__input:not(:checked)) .btn--primary:not(.btn--loading),
.form:has(.otp__digit:placeholder-shown) .btn--primary:not(.btn--loading),
/* Odrzut z walidacji w tle (AI, lookup NIP): kroki 4 i 5 robia natywny POST, wiec bez tego
   przycisk wygladalby na aktywny, klik przeladowywalby krok i klient tracilby wpisane haslo.
   Serwer i tak sprawdza werdykt - to jest warstwa, ktora oszczedza mu tej podrozy. */
.form:has(.field[data-async-error]) .btn--primary:not(.btn--loading),
.form:has(.password-rule:not(.password-rule--met)) .btn--primary:not(.btn--loading),
.form:has(select[required]:invalid) .btn--primary:not(.btn--loading),
/* Krok 1: liczy się WYŁĄCZNIE ścieżka, którą klient wybrał. */
.form:has(#path-local:checked):has(.path-reveal--local .input__control:placeholder-shown) .btn--primary:not(.btn--loading),
.form:has(#path-local:checked):has(.path-reveal--local .toggle__input:not(:checked)) .btn--primary:not(.btn--loading),
.form:has(#path-tillio:checked):has(.path-reveal--tillio .toggle__input:not(:checked)) .btn--primary:not(.btn--loading) {
  background: var(--color-bg-disabled);
  border-color: var(--color-border-disabled);
  color: var(--color-text-disabled);
  cursor: not-allowed;
  filter: none;
}

/* Loading: zostaje różowy, dodaje spinner, blokuje kliknięcia */
.btn--loading {
  cursor: wait;
  pointer-events: none;
}
.btn--loading::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: var(--space-md);
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.login-link {
  margin: 0;
  font-family: var(--font-ui);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
  display: inline-flex;
  gap: var(--space-xs);
}

/* "Wróć" link pod submitem (powrót do poprzedniego kroku) */
.form-back {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-primary-600);
  text-decoration: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.form-back:hover { text-decoration: underline; }

/* Helper text pod buttonem (np. "Twój numer zostanie wykorzystywany...") */
.form-helper {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
  text-align: center;
}
.form-helper__link {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
}
.form-helper__link:hover { text-decoration: underline; }

/* Link akcji (np. "Wyślij ponownie kod SMS-em") z ikoną */
.form-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-ui);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-primary-600);
  text-decoration: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.form-link:hover { text-decoration: underline; }
.form-link:disabled { opacity: 0.6; cursor: not-allowed; }
.form-link:disabled:hover { text-decoration: none; }
.form-link__icon { width: 20px; height: 20px; flex-shrink: 0; }

/* Wariant ghost — wewnątrz pola, mniejszy nacisk wizualny */
.form-link--ghost {
  font-size: var(--text-xs-size);
  align-self: flex-start;
  margin-top: var(--space-md);
}
.form-link--ghost .form-link__icon { width: 16px; height: 16px; }

/* Step 3: dodatkowy odstęp 48px między linkiem resend a helperem
   (Figma: button + 16px + resend + 64px + helper. Standardowy gap 16px obejmuje pierwsze dwa, helper dostaje extra 48px) */
.form__actions .form-helper { margin-top: 48px; }

/* ===== INPUT z suffixem (np. workspace + ".tillio.app" + copy) ===== */
.input--with-suffix {
  padding: 0;
  gap: 0;
  /* .input ma align-items: center (default) — ::after centruje się pionowo. */
}
.input__main {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  align-items: center;
  gap: var(--space-md);
  padding: 10px 14px;
}
.input__suffix {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 10px 16px;
  background: var(--color-bg-primary);
  border: 0;
  border-left: 1px solid var(--color-border-primary);
  cursor: pointer;
  font-family: var(--font-ui);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  color: var(--color-text-primary);
  transition: background 120ms ease;
}
.input__suffix:hover { background: var(--color-neutral-100); }
.input__suffix-text { white-space: nowrap; }
.input__suffix-icon { width: 20px; height: 20px; flex-shrink: 0; }
.input__suffix--copied { background: var(--color-success-50); }

/* ===== INPUT typu select (custom dropdown) =====
   Native <select> zostaje w DOM (form submit + a11y fallback), ale wizualnie ukryty.
   JS (setupCustomSelect) injectuje .select-trigger + .select-dropdown obok. */
.input--select { position: relative; }
.input--select .input__control {
  /* Native select — widoczny tylko jak JS nie zadziała (graceful degradation) */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  padding: 0;
  margin: 0;
  min-height: 0;
}
.input--select .input__control:focus { outline: 0; }
.input--select .input__control:invalid { color: var(--color-text-secondary); }

/* Po inicjalizacji custom UI — chowamy native select wizualnie ale zostaje funkcjonalny */
.input--select.input--select-enhanced .input__control {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
}

/* Custom trigger (button widoczny zamiast native selecta) */
.select-trigger {
  flex: 1 0 0;
  min-width: 0;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  color: var(--color-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.select-trigger:focus { outline: 0; }
.select-trigger__value--placeholder { color: var(--color-text-secondary); }

/* Caret animuje obrót przy otwarciu */
.input__select-caret { transition: transform 160ms ease; }
.input--select-open .input__select-caret { transform: rotate(180deg); }

/* Dropdown panel — JS przenosi do <body> z position: fixed (escape modal overflow) */
.select-dropdown {
  list-style: none;
  margin: 0;
  padding: var(--space-xs);
  position: fixed;
  z-index: 9999;
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  max-height: 240px;
  overflow-y: auto;
  animation: select-dropdown-enter 160ms ease;
}
@keyframes select-dropdown-enter {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.select-dropdown__option {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-md-size);
  line-height: var(--text-md-line);
  color: var(--color-text-primary);
  transition: background 60ms ease;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}
.select-dropdown__option:hover,
.select-dropdown__option--active {
  background: var(--color-primary-50);
}
.select-dropdown__option[aria-selected="true"] {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
}
.select-dropdown__option[aria-selected="true"]::after {
  content: "✓";
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary-600);
  flex-shrink: 0;
}

/* ===== READONLY INPUT (pole pre-filled z poprzedniego kroku) ===== */
.input--readonly {
  background: var(--color-bg-disabled);
  cursor: default;
}
.input--readonly .input__control {
  cursor: default;
  color: var(--color-text-secondary);
}

/* ===== PASSWORD INPUT z eye toggle ===== */
.input--password .input__control {
  padding-right: 0;
}
.input__toggle-visibility {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--color-text-secondary);
}
.input__toggle-visibility:hover { color: var(--color-text-primary); }
.input__toggle-icon { width: 20px; height: 20px; }

/* ===== PASSWORD STRENGTH METER (3-segmentowy bar) ===== */
.password-strength {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-top: var(--space-sm);
}
.password-strength__bars {
  display: flex;
  gap: 4px;
  flex: 1;
}
.password-strength__bar {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--color-neutral-200);
  transition: background 160ms ease;
}
.password-strength__label {
  min-width: 64px;
  text-align: right;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-xs-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
}

.password-strength[data-level="1"] .password-strength__bar:nth-child(-n+1) { background: var(--color-alert-600); }
.password-strength[data-level="1"] .password-strength__label { color: var(--color-alert-600); }

.password-strength[data-level="2"] .password-strength__bar:nth-child(-n+2) { background: var(--color-tertiary-600); }
.password-strength[data-level="2"] .password-strength__label { color: var(--color-tertiary-600); }

.password-strength[data-level="3"] .password-strength__bar { background: var(--color-success-600); }
.password-strength[data-level="3"] .password-strength__label { color: var(--color-success-600); }

.password-strength[data-level="0"] .password-strength__label { visibility: hidden; }

/* ===== PASSWORD RULES (live validation list) ===== */
/* ===== DYMEK "ZAPISZ TO HASLO" (krok 4, po wygenerowaniu) =====
   Hasla z generatora nikt nie pamieta, a zaraz po rejestracji trzeba sie nim zalogowac
   (auto-loginu w calls nie ma - D7). Dymek pokazuje sie DOPIERO po kliknieciu generatora. */
/* MUSI byc przed regula z `display: flex` - inaczej klasa bije `[hidden]` z arkusza
   przegladarki i dymek wisi na ekranie od wejscia na krok. */
.password-copy[hidden] { display: none; }
.password-copy {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin-top: var(--space-lg);
  padding: var(--space-lg);
  border: 1px solid var(--color-primary-600);
  border-radius: var(--radius-md);
  background: var(--color-primary-50);
  /* Dymek ma sie ROZWINAC spod przycisku, nie wystrzelic (uwaga operatora 2026-08-07:
     .18s ease wygladalo agresywnie). Dluzej i miekko: `cubic-bezier(.16,1,.3,1)` hamuje
     na koncu, wiec ruch wytraca predkosc zamiast urwac sie w miejscu. `transform-origin`
     w lewym gornym rogu, czyli tam, gdzie siedzi ogonek - dymek rosnie od punktu
     zaczepienia przy generatorze, a nie ze srodka. */
  animation: password-copy-in .42s cubic-bezier(.16, 1, .3, 1) both;
  transform-origin: var(--space-2xl) top;
}
/* Ogonek do gory - wiaze dymek z przyciskiem generatora, zamiast zostawiac go w prozni. */
.password-copy::before,
.password-copy::after {
  content: "";
  position: absolute;
  bottom: 100%;
  left: var(--space-2xl);
  border: 7px solid transparent;
}
.password-copy::before { border-bottom-color: var(--color-primary-600); }
.password-copy::after {
  border-width: 6px;
  margin-left: 1px;
  border-bottom-color: var(--color-primary-50);
}
.password-copy__text {
  margin: 0;
  flex: 1;
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
}
.password-copy__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  flex: none;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--color-primary-600);
  border-radius: var(--radius-sm);
  background: var(--color-bg-primary);
  color: var(--color-primary-600);
  font-family: var(--font-ui);
  font-size: var(--text-sm-size);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.password-copy__btn:hover { background: var(--color-primary-600); color: var(--color-fg-white); }
.password-copy__btn:hover .password-copy__icon { filter: brightness(0) invert(1); }
.password-copy__icon { width: 16px; height: 16px; display: block; }
/* Potwierdzenie kopiowania: zielone, bo to sukces - a nie kolejny akcent marki. */
.password-copy__btn--copied,
.password-copy__btn--copied:hover {
  border-color: var(--color-success-600);
  background: var(--color-success-50);
  color: var(--color-success-600);
}
.password-copy__btn--copied .password-copy__icon { display: none; }
@keyframes password-copy-in {
  from { opacity: 0; transform: translateY(-6px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .password-copy { animation: none; }
}
@media (max-width: 560px) {
  .password-copy { flex-direction: column; align-items: stretch; }
  .password-copy__btn { justify-content: center; }
}

/* Wymagania hasla stoja W LINII pod polem, nie w kolumnie: cztery osobne wiersze rozpychaly
   krok 4 tak, ze przycisk "Dalej" schodzil ponizej zagiecia. Zawijaja sie same, gdy zabraknie
   szerokosci (waski modal, telefon). */
.password-rules {
  list-style: none;
  margin: var(--space-md) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-lg);
}
.password-rule {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-xs-size);
  line-height: var(--text-xs-line);
  color: var(--color-text-secondary);
  white-space: nowrap;
  transition: color 120ms ease;
}
.password-rule__icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}
.password-rule--met { color: var(--color-success-600); }

/* ===== STEPPER (postęp rejestracji) ===== */
.stepper { width: 100%; }
.stepper__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  position: relative;
}
.stepper__list::before {
  content: "";
  position: absolute;
  top: 12px;
  left: 24px;
  right: 24px;
  border-top: 1px dashed var(--color-border-primary);
  z-index: 0;
}
.stepper__item {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  background: var(--color-bg-primary);
  padding: 0 var(--space-md);
}
.stepper__icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-neutral-200);
  color: var(--color-text-secondary);
  font-family: var(--font-ui);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-xs-size);
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.stepper__item--done .stepper__icon {
  background: var(--color-success-600);
  color: var(--color-fg-white);
}
.stepper__item--active .stepper__icon {
  background: var(--color-primary-600);
  color: var(--color-fg-white);
}
.stepper__label {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
  white-space: nowrap;
}
.stepper__item--done .stepper__label,
.stepper__item--active .stepper__label {
  color: var(--color-text-primary);
}

/* ===== CHECKBOX-LIST (multi-select checkboxes z labelami, np. "cele") ===== */
.checkbox-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}
.checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  cursor: pointer;
  position: relative;
}
.checkbox__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
}
.checkbox__box {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: var(--space-xxs);
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: var(--radius-sm);
  position: relative;
  transition: background 120ms ease, border-color 120ms ease;
}
.checkbox:hover .checkbox__box { border-color: var(--color-text-primary); }
.checkbox__input:checked + .checkbox__box {
  background: var(--color-text-primary);
  border-color: var(--color-text-primary);
}
.checkbox__input:checked + .checkbox__box::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / 75% no-repeat;
}
.checkbox__input:focus-visible + .checkbox__box {
  box-shadow: 0 0 0 4px rgba(255, 10, 113, 0.15);
}
.checkbox__text {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
}
/* Pole z checkbox-list ma większy odstęp label→lista (16px zamiast domyślnych 6px).
   Error state nie zmienia checkboxów — tylko pojawia się komunikat .field__error w czerwieni. */
.field:has(> .checkbox-list) { gap: var(--space-lg); }

/* ===== CHIPS (single-select kwadratowe boxy, np. liczba osób) ===== */
.chip-group {
  display: flex;
  width: 100%;
  gap: var(--space-md);
}
.chip {
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 1 / 1;
  max-width: 64px;
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: 10px;
  box-shadow: var(--shadow-xs);
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: 18px;
  line-height: 1;
  color: var(--color-text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.chip:hover { border-color: var(--color-text-primary); }
.chip input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
}
.chip:has(input:checked) {
  border-color: var(--color-primary-600);
  background: var(--color-primary-50);
  color: var(--color-primary-600);
}
.chip:has(input:focus-visible) {
  box-shadow: 0 0 0 4px rgba(255, 10, 113, 0.15);
}
.chip-group--error .chip { border-color: var(--color-alert-600); }

/* ===== USER ROW (zaproszenie użytkownika do zespołu) ===== */
.user-rows-wrap { display: flex; flex-direction: column; gap: var(--space-md); }
.user-rows { display: flex; flex-direction: column; gap: var(--space-md); }
.user-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  background: var(--color-neutral-100);
  padding: var(--space-md);
  border-radius: var(--radius-md);
}
.user-row .input { flex: 1 1 0; min-width: 0; }
.user-row .user-row__role { flex: 0 0 180px; }
.user-row__error {
  flex-basis: 100%;
  margin: 0;
  padding-top: var(--space-xs);
  padding-left: var(--space-md);
  font-family: var(--font-sans);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-alert-600);
}

.btn-icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  background: var(--color-bg-disabled);
  border: 1px solid var(--color-border-disabled);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-xs);
  transition: background 120ms ease, border-color 120ms ease;
  padding: 0;
}
.btn-icon:hover {
  background: var(--color-neutral-200);
  border-color: var(--color-text-secondary);
}
.btn-icon img { width: 20px; height: 20px; }

/* ===== OTP / kod 6-cyfrowy ===== */
.otp {
  display: flex;
  justify-content: space-between;
  width: 100%;
  gap: var(--space-md);
}
.otp__digit {
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 1 / 1;
  max-width: 64px;
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: 10px;
  box-shadow: var(--shadow-xs);
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: 32px;
  line-height: 60px;
  letter-spacing: -0.64px;
  color: var(--color-text-primary);
  text-align: center;
  padding: 2px 8px;
  outline: 0;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.otp__digit:focus {
  border-color: var(--color-text-primary);
  box-shadow: 0 0 0 4px rgba(17, 39, 59, 0.06);
}
.otp__hidden { display: none; }

/* Stany walidacji OTP — wszystkie 6 boxów dziedziczy kolor */
.otp--success .otp__digit { border-color: var(--color-success-600); }
.otp--error   .otp__digit { border-color: var(--color-alert-600); }
.otp--success .otp__digit:focus { box-shadow: 0 0 0 4px rgba(43, 152, 72, 0.12); }
.otp--error   .otp__digit:focus { box-shadow: 0 0 0 4px rgba(224, 36, 36, 0.12); }
.login-link__action {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
}
.login-link__action:hover { text-decoration: underline; }

/* ===== FULLSCREEN SPLIT (steps 1-3 — pre-verification, edge-to-edge) ===== */
body.body--fullscreen {
  display: block;
  padding: 0;
  background: var(--color-bg-primary);
}
.fullscreen-split {
  min-height: 100vh;
  width: 100%;
  display: grid;
  grid-template-columns: 58% 42%;
}
.fullscreen-split__form {
  background: var(--color-bg-primary);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: var(--space-4xl);
  gap: var(--space-3xl);
}
.fullscreen-split__form > * {
  width: 100%;
  max-width: 508px;
}
.fullscreen-split__visual {
  position: relative;
  background:
    radial-gradient(ellipse at 30% 35%, rgba(255, 10, 113, 0.45) 0%, transparent 55%),
    linear-gradient(180deg, #2A0A3A 0%, #0F0524 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 88px;
  overflow: hidden;
}
.fullscreen-split__logo {
  width: 152px;
  height: auto;
  flex-shrink: 0;
}

/* Wariant — gotowa grafika z wbudowanym logo.
   Specificity (klasa+atrybut) = 0,2,0 → pobija shorthand `background:` w .modal__visual / .fullscreen-split__visual.
   Pełen shorthand resetuje wszystkie background-* (size, position, repeat) jednym strzałem. */
/* Specificity 0,2,0 (klasa.klasa) → pobija .modal__visual (0,1,0) z padding-top: 88px.
   Inaczej background-origin: padding-box zostawia 88px białego paska na górze. */
.fullscreen-split__visual.fullscreen-split__visual--with-graphic,
.modal__visual.modal__visual--with-graphic {
  padding: 0;
  min-height: 100%;
  align-self: stretch;
}

.fullscreen-split__visual--with-graphic[data-bg="step1"],
.modal__visual--with-graphic[data-bg="step1"]      { background: url('/assets/img/step1_right.png') center / cover no-repeat; }
.fullscreen-split__visual--with-graphic[data-bg="step2"],
.fullscreen-split__visual--with-graphic[data-bg="step3"],
.modal__visual--with-graphic[data-bg="step2"],
.modal__visual--with-graphic[data-bg="step3"]      { background: url('/assets/img/step2_3_right.png') center / cover no-repeat; }
.modal__visual--with-graphic[data-bg="step4"]      { background: url('/assets/img/step4_right.png') center / cover no-repeat; }
.modal__visual--with-graphic[data-bg="step5"]      { background: url('/assets/img/step5_right.png') center / cover no-repeat; }
.modal__visual--with-graphic[data-bg="step6"]      { background: url('/assets/img/step6_right.png') center / cover no-repeat; }
.modal__visual--with-graphic[data-bg="step7"]      { background: url('/assets/img/step7_right.png') center / cover no-repeat; }

/* ===== PODSUMOWANIE KONTA na /done =====
   Trzy fakty zamiast trzech ogolnikow: co klient dostal, do kiedy i czym wchodzi.
   Uklad par (etykieta / wartosc), bo to dane, nie lista zalet - a dane czyta sie
   kolumnami, nie zdaniami. */
.done-summary {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.done-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--color-border-primary);
}
.done-summary__row:last-child { border-bottom: 0; padding-bottom: 0; }
.done-summary dt {
  font-family: var(--font-ui);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
}
.done-summary dd {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-primary);
  text-align: right;
}

/* ===== SUCCESS / SINGLE-COLUMN modal (np. step 8 — "Twoje konto jest gotowe!") ===== */
.modal--single .modal__inner {
  grid-template-columns: 1fr;
}
.modal--single .modal__visual { display: none; }
.modal--single .modal__form-col {
  align-items: center;
}
.modal--single .hero { align-items: center; }
.modal--single .hero__title { text-align: center; }
.modal--single .hero__description,
.modal--single .form,
.modal--single .form__actions {
  width: 100%;
  max-width: 508px;
}

/* Bullets w wariancie pionowym (success screen) */
.bullets--vertical {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: var(--space-lg);
}

/* Featured icon (pink halo + inner solid pink z białą ikoną) */
.featured-icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: var(--color-primary-50);
  border: 1px solid #ffdceb;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.featured-icon__inner {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--color-primary-600);
  display: flex;
  align-items: center;
  justify-content: center;
}
.featured-icon__inner img { width: 20px; height: 20px; }

/* ===== RIGHT: VISUAL COLUMN ===== */
.modal__visual {
  position: relative;
  background:
    radial-gradient(ellipse at 30% 35%, rgba(255, 10, 113, 0.45) 0%, transparent 55%),
    linear-gradient(180deg, #2A0A3A 0%, #0F0524 100%);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 88px;
}

.modal__visual-logo {
  width: 152px;
  height: auto;
  flex-shrink: 0;
}

.close-btn {
  position: absolute;
  top: 32px;
  right: 32px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 120ms ease;
}
.close-btn:hover { background: rgba(255, 255, 255, 0.2); }

/* ============================================================
   MOBILE (≤ 768px) — desktop-first overrides
   Strategia: full-bleed modal/wrapper, ukrycie prawej kolumny visualu,
   zmniejszone paddingy, kompaktowy stepper (kropki + label aktywnego).
   ============================================================ */
/* Prog 980 px, nie 768: miedzy 769 a 1000 px split sie nie bronil - na 820 px (iPad Air
   w pionie) panel mial 344 px, tytuly kart urywaly sie na "Wid...", chipy lamaly sie
   na dwie linie. Tablety w pionie (768-834) dostaja wiec uklad mobilny, a split zaczyna
   sie od 1024 px (iPad Pro 12.9 w pionie, tablety w poziomie), gdzie faktycznie dziala. */
@media (max-width: 980px) {
  body { padding: 0; }

  /* App background overlay — niepotrzebny na mobile, content full-bleed */
  body.body--app-bg { background: var(--color-bg-primary); }

  /* === MODAL (step 4-8) — full bleed === */
  .modal {
    width: 100%;
    max-width: 100%;
    min-height: 100vh;
    border-radius: 0;
    box-shadow: none;
  }
  .modal__inner {
    grid-template-columns: 1fr;
    min-height: 100vh;
  }
  .modal__visual { display: none; }
  .modal__form-col {
    padding: 24px;
    gap: var(--space-2xl);
  }

  /* === FULLSCREEN SPLIT (step 1-3) — single col === */
  .fullscreen-split { grid-template-columns: 1fr; }
  .fullscreen-split__visual { display: none; }
  .fullscreen-split__form {
    padding: 24px;
    gap: var(--space-2xl);
    min-height: 100vh;
    justify-content: flex-start;
    padding-top: 48px;
  }

  /* === HERO — mniejszy nagłówek === */
  .hero__title { font-size: 22px; line-height: 1.25; }
  .hero__description-lead { font-size: 15px; }
  .hero__description { padding: 16px; }

  /* === STEPPER — kompaktowy (małe kropki, label aktywnego widoczny) === */
  .stepper__item { padding: 0; flex: 1; }
  .stepper__icon {
    width: 20px;
    height: 20px;
    font-size: 11px;
  }
  .stepper__icon svg { width: 11px; height: 11px; }
  .stepper__list::before { top: 10px; left: 12px; right: 12px; }
  .stepper__label {
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 64px;
  }

  /* === OTP — mniejsze boxy z mniejszą fontką === */
  .otp__digit {
    font-size: 24px;
    line-height: 1;
    max-width: 56px;
    padding: 0;
  }

  /* === CHIPS (step 6) — mniejsza fontka === */
  .chip { font-size: 14px; max-width: none; }
  .chip-group { gap: var(--space-sm); }

  /* === USER ROW (step 6) — email full width, role + trash w drugim rzędzie === */
  .user-row > .input:first-of-type { flex: 1 1 100%; }
  .user-row .user-row__role { flex: 1 1 0; max-width: none; }

  /* === FORM ACTIONS — buttons full width już są === */

  /* === BUTTONS — touch friendly height === */
  .btn { min-height: 48px; }
  .btn-icon { min-width: 48px; min-height: 48px; }

  /* === LOGIN LINK — może wrap === */
  .login-link { flex-wrap: wrap; justify-content: center; }

  /* === FEATURED ICON (step 8) — same size, OK === */

  /* === SELECT DROPDOWN (step 5) — full width gdy otwarty na mobile === */
  .select-dropdown {
    max-height: 50vh;
  }

  /* === PHONE INPUT — utrzymaj rozmiar tabular === */
  .input--phone .input__field {
    font-size: 15px;
  }
}

/* Bardzo małe ekrany (≤ 380px) — dodatkowe zmniejszenie === */
@media (max-width: 380px) {
  .modal__form-col,
  .fullscreen-split__form { padding: 16px; }
  .hero__title { font-size: 20px; }
  .otp__digit { font-size: 20px; max-width: 48px; }
  .stepper__label { display: none; }
  .stepper__item--active .stepper__label { display: inline; }
}

/* Ekran „masz już konto" (frontend/task-09): wybory stoją w kolumnie, jeden pod drugim —
   to nie jest para „dalej / anuluj", tylko równorzędne drogi. Pod każdą stoi jedno zdanie
   o tym, co się stanie — bez tego user wybiera w ciemno. */
.collision-choices {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  width: 100%;
}
.collision-choices .btn { width: 100%; }
/* JEDEN rozmiar tekstu pomocniczego na ekranie kolizji. Wczesniej staly tam obok siebie
   trzy klasy w trzech rozmiarach (16 / 14 / 12 px) i dwoch wyrownaniach - stad wrazenie
   przypadkowo dobranych czcionek. Zostaje 14 px, ten sam co `.form-helper`. */
.choice-hint {
  margin: var(--space-xs) 0 var(--space-lg);
  font-family: var(--font-sans);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
  color: var(--color-text-secondary);
}
.choice-hint--ok { color: var(--color-success-600); }
.choice-hint--center { text-align: center; }
.collision-choices .choice-hint:last-child { margin-bottom: 0; }

/* Lista workspace'ów: nazwa + rola + stan. Stan jest tu najważniejszą informacją —
   „wygasł" zmienia to, co user powinien zrobić dalej. */
.ws-list { list-style: none; margin: var(--space-lg) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-md); }
.ws-item {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--color-border-primary);
  border-radius: var(--radius-md);
  font-size: var(--text-sm-size);
}
.ws-item__name { font-weight: var(--font-weight-semibold); }
.ws-item__meta { color: var(--color-text-secondary); font-size: var(--text-xs-size); }
.ws-badge {
  margin-left: auto;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: var(--font-weight-semibold);
  background: var(--color-neutral-100);
  color: var(--color-text-secondary);
}
.ws-badge--active,
.ws-badge--trial { background: var(--color-success-50); color: var(--color-success-600); }
.ws-badge--expired,
.ws-badge--suspended { background: var(--color-tertiary-50); color: #8a6100; }

/* ============================================================
   /done — URUCHAMIANIE KONTA (backend/task-15)
   ============================================================
   Trzy stany jednego ekranu przełączane atrybutem `data-prov-state` na <body>.
   Stan początkowy renderuje serwer, JS (provisioning.js) tylko go przestawia —
   dzięki temu nie ma mrugnięcia przed startem skryptu, a przejście
   „uruchamiamy” → „gotowe” nie przebudowuje DOM.

   Style siedzą w app.css, a nie w arkuszu wariantu, bo dotyczą kolumny formularza,
   którą oba layouty (split i modal) mają wspólną. */

.prov__state { display: none; }
body[data-prov-state="running"] .prov__state--running,
body[data-prov-state="ready"]   .prov__state--ready,
body[data-prov-state="failed"]  .prov__state--failed { display: block; }

/* Pasek postępu. Procent liczy front z upływu czasu i ZATRZYMUJE go na 96% —
   setka wchodzi wyłącznie na realne „ready” z API, żeby licznik nigdy nie stał
   na 100% przy niedokończonym koncie. */
.prov-bar {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-top: var(--space-2xl);
}
.prov-bar__head { display: flex; align-items: baseline; gap: var(--space-md); }
.prov-bar__stage {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm-size);
  color: var(--color-text-primary);
}
.prov-bar__pct {
  margin-left: auto;
  font-size: var(--text-xs-size);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}
.prov-bar__track {
  height: 8px;
  border-radius: 999px;
  background: var(--color-neutral-100);
  overflow: hidden;
}
/* `display: block` jest tu KONIECZNE — to <span>, a element liniowy ignoruje
   szerokość (pasek stałby w miejscu mimo poprawnego procentu). */
.prov-bar__fill {
  display: block;
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--color-primary-600) 0%, #b02ea8 60%, #5830aa 100%);
  transition: width 0.45s ease;
}

/* Lista etapów: zrobione (ptaszek) → w toku (kręcący się pierścień) → przyszłe (szare). */
.prov-checks {
  list-style: none;
  margin: var(--space-2xl) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}
.prov-check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: var(--text-sm-size);
  color: var(--color-text-disabled);
  transition: color 0.3s ease;
}
.prov-check__dot {
  position: relative;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border-disabled);
  background: var(--color-bg-primary);
  display: grid;
  place-items: center;
  transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.prov-check__dot svg { width: 10px; height: 10px; opacity: 0; transition: opacity 0.25s ease; }
.prov-check.is-active { color: var(--color-text-primary); font-weight: var(--font-weight-semibold); }
.prov-check.is-active .prov-check__dot {
  border-color: var(--color-success-600);
  box-shadow: 0 0 0 3px var(--color-success-50);
}
/* Pierścień kręci się TYLKO przy etapie w toku. Animowany jest wyłącznie
   `transform` — reguła z frontend/task-05 po zacinaniu w Firefoksie. */
.prov-check.is-active .prov-check__dot::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--color-success-600);
  border-right-color: var(--color-success-600);
  animation: prov-spin 0.85s linear infinite;
  will-change: transform;
}
.prov-check.is-done { color: var(--color-text-secondary); }
.prov-check.is-done .prov-check__dot {
  background: var(--color-success-600);
  border-color: var(--color-success-600);
}
.prov-check.is-done .prov-check__dot svg { opacity: 1; }

@keyframes prov-spin { to { transform: rotate(360deg); } }

/* Przypis siada na dole kolumny — tam go oko szuka, a nie w rytmie czytania. */
.prov-note {
  margin: var(--space-2xl) 0 0;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border-disabled);
  font-size: var(--text-xs-size);
  line-height: var(--text-xs-line);
  color: var(--color-text-secondary);
}
.prov-note b { font-weight: var(--font-weight-semibold); color: var(--color-text-primary); }

/* Ścieżka ratunkowa — konkret zamiast białej strony. */
.prov-fallback {
  margin-top: var(--space-xl);
  padding: var(--space-lg) 17px;
  border-left: 3px solid var(--color-primary-600);
  border-radius: var(--radius-md);
  background: var(--color-neutral-100);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
}
.prov-fallback b { display: block; margin-bottom: var(--space-xs); }
.prov-fallback__contact { margin: var(--space-md) 0 0; color: var(--color-text-secondary); }
.prov-bar__step { font-size: var(--text-xs-size); color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }

/* Konto gotowe MIMO ostrzeżeń to poprawny stan docelowy (kontrakt calls), więc ostrzeżenia
   stoją OBOK sukcesu, a nie zamiast niego — stonowane, bez czerwieni awarii. */
.done-warnings {
  margin: var(--space-xl) 0 0;
  padding: var(--space-lg) 17px;
  border-left: 3px solid var(--color-tertiary-600);
  border-radius: var(--radius-md);
  background: var(--color-tertiary-50);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-line);
}
.done-warnings b { display: block; margin-bottom: var(--space-xs); }
.done-warnings ul { margin: 0; padding-left: var(--space-xl); }
.done-warnings li + li { margin-top: var(--space-xs); }

@media (prefers-reduced-motion: reduce) {
  .prov-bar__fill { transition: none; }
  .prov-check.is-active .prov-check__dot::after {
    animation: none;
    /* Bez ruchu urwany łuk czytałby się jak usterka — domykamy go w pełne kółko. */
    border-color: var(--color-success-600);
  }
}

/* ===== SALUT NA /done ===== */
/* Warstwa jest CZYSTO dekoracyjna, więc nie może przejąć ani jednego kliknięcia:
   `pointer-events: none` pilnuje, żeby przycisk "Przejdź do Tillio Calls" pod spodem
   dał się nacisnąć także w trakcie animacji. Canvas usuwa się sam po ostatnim papierku
   (patrz confetti.js) - to zabezpieczenie na wypadek, gdyby coś przerwało pętlę. */
.konfetti {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 60;
}

/* Wariant graficzny "calls" (frontend/task-03 -> task-04) mieszka w osobnym pliku
   `calls-theme.css`, ładowanym tylko gdy wariant jest aktywny. Tutaj go nie ma
   celowo: app.css opisuje wyłącznie wersję domyślną. */
