/*
 * Skóra panelu to skóra Huba.
 *
 * Te same nazwy zmiennych co w WebLM-hub-main/web/src/styles/tokens.css i te
 * same wartości ciemnej gałęzi. Agencja przechodzi z Huba na saldo jednym
 * odnośnikiem w nawigacji i nie powinna zobaczyć, że to druga aplikacja.
 *
 * Hub przełącza motyw za systemem, panel bierze ciemny wprost: to jedna krótka
 * strona bez ustawień, a nazwy tokenów zostają takie same, więc dołożenie
 * jasnej gałęzi kiedyś to dopisanie drugiego bloku, nie przepisywanie arkusza.
 *
 * Kolor niesie znaczenie i tylko znaczenie — jak w Hubie:
 *   accent — akcja główna i informacja
 *   done   — pieniądz przyszedł
 *   error  — coś się nie udało albo pieniądz wyszedł
 */
:root {
  color-scheme: dark;

  --hub-bg: #14161b;
  --hub-surface: #1c1f26;
  --hub-raised: #21252d;
  --hub-line: #2a2e38;
  --hub-line-strong: #3a3f4d;
  --hub-ink: #e8eaf0;
  --hub-muted: #98a1b0;
  --hub-faint: #757e8e;

  --hub-accent: #8b9af7;
  --hub-accent-soft: #242a49;
  /* Fiolet agenta z Huba — tutaj wyłącznie na poświatę pod logowaniem, żeby
     ekran wejścia miał ten sam dwugłos barw co Hub. */
  --hub-agent: #b49bf0;
  /* Hub kładzie na akcencie biel; na jasnym błękicie ciemnej palety to 2,6:1,
     więc napis na przycisku bierze tusz tła i wychodzi 6,9:1. */
  --hub-accent-ink: #14161b;
  --hub-done: #5fc091;
  --hub-done-soft: #12291f;
  --hub-error: #e27b74;
  --hub-error-soft: #33191a;

  --hub-radius: 10px;
  --hub-radius-sm: 7px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  /* Hub wozi Instrument Sans w bundlu; panel jest statyczny i nie ma czym go
     podać, więc zostaje wspólny łańcuch zapasowy. */
  font-family: ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  background: var(--hub-bg);
  color: var(--hub-ink);
  font-size: 13.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: var(--hub-line-strong);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-track { background: transparent; }

:focus-visible { outline: 2px solid var(--hub-accent); outline-offset: 2px; border-radius: 4px; }

.app { max-width: 960px; margin: 0 auto; padding: 24px 20px 64px; }

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 12px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--hub-line);
}
.topbar h1 { font-size: 15px; font-weight: 600; margin: 0; }
.topbar .who { color: var(--hub-muted); font-size: 12.5px; }

.card {
  background: var(--hub-surface);
  border: 1px solid var(--hub-line);
  border-radius: var(--hub-radius);
  padding: 14px;
  margin-bottom: 14px;
}
/* Nagłówek karty jak w Hubie: pasek wersalikami nad treścią, nie tytuł w treści. */
.card h2 {
  margin: -14px -14px 14px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--hub-line);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hub-muted);
}
.card p { margin: 10px 0 0; }
.card > :last-child { margin-bottom: 0; }

/* ── ekran logowania ──────────────────────────────────────────────────────
 *
 * Jedyne miejsce w panelu, które ma prawo być efektowne: nic tu nie widać
 * poza jedną kartą, nikt tu nie pracuje, a przez tę bramę wchodzi się do
 * Nostero. Dalej, przy pieniądzach i historii, ruch tylko przeszkadza — i
 * dlatego kończy się na tej sekcji.
 *
 * Cały ruch jest na transform i opacity, więc nie przelicza układu strony,
 * a `prefers-reduced-motion` na końcu arkusza wyłącza go co do jednej klatki.
 */
/* Karta logowania jest większa niż reszta panelu, bo jest tu sama: cała uwaga
   idzie na dwa pola, a nie na gęstość ekranu roboczego. */
.login-card {
  max-width: 420px;
  margin: 10vh auto 0;
  padding: 28px;
  /* Nad poświatą (element pozycjonowany, później w drzewie) i punkt odniesienia
     dla przebłysku. */
  position: relative;
  overflow: hidden;
  animation: card-in 0.62s cubic-bezier(0.2, 0.75, 0.2, 1) both;
}

/* Nagłówek tej jednej karty to nie pasek sekcji, tylko znak firmowy — stąd
   pełna nadpiska nad regułą `.card h2`. */
.login-card h2 {
  margin: -28px -28px 24px;
  padding: 26px 28px 20px;
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.025em;
  text-transform: none;
  text-align: center;
  color: var(--hub-ink);
}
.login-card h2 em {
  font-style: normal;
  color: var(--hub-agent);
}

.login-card .stack { gap: 14px; }
.login-card label { gap: 6px; font-size: 12.5px; }
.login-card input { padding: 10px 12px; font-size: 14.5px; }
.login-card .error { font-size: 13px; }
.login-card button[type='submit'] {
  width: 100%;
  padding: 11px 16px;
  font-size: 14.5px;
}

/* Poświata: trzy rozmyte plamy w barwach Huba, każda w innym rytmie, żeby tło
   nigdy nie wróciło do tej samej klatki. Fixed — nie bierze udziału w układzie,
   więc nie zrobi paska przewijania. */
.aurora {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.aurora span {
  position: absolute;
  display: block;
  width: 46vmax;
  height: 46vmax;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.28;
  will-change: transform;
}
.aurora span:nth-child(1) {
  background: radial-gradient(circle, var(--hub-accent), transparent 68%);
  top: -14vmax;
  left: 50%;
  margin-left: -36vmax;
  animation: drift-a 19s ease-in-out infinite alternate;
}
.aurora span:nth-child(2) {
  background: radial-gradient(circle, var(--hub-agent), transparent 68%);
  top: -6vmax;
  left: 50%;
  margin-left: -8vmax;
  animation: drift-b 23s ease-in-out infinite alternate;
}
.aurora span:nth-child(3) {
  background: radial-gradient(circle, var(--hub-done), transparent 70%);
  top: 26vmax;
  left: 50%;
  margin-left: -26vmax;
  opacity: 0.16;
  animation: drift-c 27s ease-in-out infinite alternate;
}

/* Przebłysk przechodzi po karcie raz, po jej wejściu. */
.login-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 42%, rgb(255 255 255 / 0.07) 50%, transparent 58%);
  transform: translateX(-130%);
  animation: sheen 1.5s 0.45s ease-out both;
}

/* Pola wjeżdżają po kolei — kolejność czytania, nie wszystko naraz. */
.login-card .stack > * { animation: field-in 0.5s ease-out both; }
.login-card .stack > *:nth-child(1) { animation-delay: 0.16s; }
.login-card .stack > *:nth-child(2) { animation-delay: 0.23s; }
.login-card .stack > *:nth-child(3) { animation-delay: 0.3s; }
.login-card .stack > *:nth-child(4) { animation-delay: 0.37s; }

.login-card input:focus {
  border-color: var(--hub-accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--hub-accent) 16%, transparent);
}

/* Czekanie na odpowiedź: pasek pod nagłówkiem karty i kółko w przycisku.
   Ruch mówi „pytam serwera", a nie „coś się dzieje". */
.login-card h2 { position: relative; overflow: hidden; }
.login-card.is-checking h2::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 42%;
  background: linear-gradient(90deg, transparent, var(--hub-accent), transparent);
  animation: sweep 1s linear infinite;
}
.login-card.is-checking button[type='submit']::before {
  content: '';
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--hub-accent-ink) 35%, transparent);
  border-top-color: var(--hub-accent-ink);
  animation: spin 0.7s linear infinite;
}

/* Złe hasło drga jednorazową animacją ze skryptu (app.js: shake) — reguła
   w arkuszu wznawiałaby po sobie animację wejścia karty. */

/* Wpuszczenie: karta odjeżdża do przodu, poświata rozbłyska. */
.login-stage.is-welcome .login-card { animation: card-out 0.42s cubic-bezier(0.4, 0, 1, 0.6) both; }
.login-stage.is-welcome .aurora span { animation: bloom 0.42s ease-out both; }

@keyframes card-in {
  from { opacity: 0; transform: translateY(16px) scale(0.975); }
  to { opacity: 1; transform: none; }
}
@keyframes card-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(-10px) scale(1.03); }
}
@keyframes field-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes sheen {
  to { transform: translateX(130%); }
}
@keyframes drift-a {
  to { transform: translate3d(6vmax, 8vmax, 0) scale(1.15); }
}
@keyframes drift-b {
  to { transform: translate3d(-9vmax, 5vmax, 0) scale(0.9); }
}
@keyframes drift-c {
  to { transform: translate3d(7vmax, -6vmax, 0) scale(1.1); }
}
@keyframes sweep {
  from { transform: translateX(-110%); }
  to { transform: translateX(340%); }
}
@keyframes spin {
  to { transform: rotate(1turn); }
}
@keyframes bloom {
  40% { opacity: 0.55; transform: scale(1.25); }
  to { opacity: 0; transform: scale(1.6); }
}


form.stack { display: grid; gap: 10px; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.card form + form { margin-top: 8px; }

label { display: grid; gap: 4px; font-size: 12px; font-weight: 500; }

input, select {
  font: inherit;
  padding: 6px 10px;
  border: 1px solid var(--hub-line-strong);
  border-radius: var(--hub-radius-sm);
  /* Pole odcina się od karty tłem, nie samą kreską — w ciemnym motywie kreska
     na tej samej płaszczyźnie ginie. */
  background: var(--hub-raised);
  color: var(--hub-ink);
  min-width: 0;
}
input::placeholder { color: var(--hub-faint); }

button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font: inherit;
  font-weight: 500;
  padding: 6px 12px;
  border: 1px solid var(--hub-accent);
  border-radius: var(--hub-radius-sm);
  background: var(--hub-accent);
  color: var(--hub-accent-ink);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease-out, opacity 0.15s ease-out;
}
button:hover, .button:hover { opacity: 0.9; }
button:disabled { opacity: 0.45; pointer-events: none; }
/* Drugi plan: ma być widoczny, ale nie ma konkurować z wpłatą. */
button.ghost {
  background: var(--hub-raised);
  border-color: var(--hub-line-strong);
  color: var(--hub-ink);
}
button.ghost:hover { background: var(--hub-line); opacity: 1; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--hub-line); }
thead th {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hub-muted);
}
tbody tr:hover td { background: var(--hub-raised); }
tbody tr:last-child td { border-bottom: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.ledger-more { margin-top: 12px; }

/* Saldo nie drga przy przeliczaniu — cyfry tej samej szerokości, jak w Hubie. */
.balance {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  margin: 2px 0 14px;
}
.amount-pos { color: var(--hub-done); }
.amount-neg { color: var(--hub-error); }

/* Doładowanie stoi w osobnym bloku pod kreską: kwota salda to stan, a to jest
   akcja — bez tej przerwy jedno wyglądało jak podpis drugiego. */
.topup {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--hub-line);
}
.topup-label {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hub-muted);
}
/* Pakiety to skróty, więc są równej szerokości i czytają się jak jeden zestaw;
   czasownik niesie nagłówek nad nimi, żeby nie powtarzać go trzy razy. */
.topup-packages { gap: 10px; }
.topup-packages button {
  min-width: 104px;
  padding: 9px 16px;
  font-variant-numeric: tabular-nums;
}
.topup-custom { margin-top: 12px; }
.topup-custom input { flex: 1 1 200px; max-width: 300px; }
.topup .error { margin-top: 10px; }
/* Reszta panelu rezerwuje wiersz na błąd, żeby formularz nie skakał. Tutaj ten
   pusty wiersz to była dziura w środku bloku — komunikat i tak pojawia się po
   kliknięciu, czyli wtedy, gdy strona już się zmienia. */
.topup .error:empty { display: none; }
.topup .muted { margin-top: 12px; max-width: 62ch; }

.kind {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 500;
  border: 1px solid var(--hub-line);
  background: var(--hub-raised);
  color: var(--hub-muted);
}
.kind-topup { background: var(--hub-done-soft); border-color: var(--hub-done-soft); color: var(--hub-done); }
.kind-charge { background: var(--hub-error-soft); border-color: var(--hub-error-soft); color: var(--hub-error); }

.error { color: var(--hub-error); font-size: 12.5px; min-height: 18px; }
.muted { color: var(--hub-muted); font-size: 12.5px; }
/* Kształt jak w powiadomieniach Huba: miękkie tło, kreska w tym samym kolorze,
   tekst w tonie. Po powrocie ze Stripe'a trafia tu i „zaksięgowane", i
   „anulowana", i „nie udało się potwierdzić" — więc ton jest informacyjny,
   nie zielony. */
.notice { background: var(--hub-accent-soft); border-color: var(--hub-accent-soft); color: var(--hub-accent); }

/* Kto prosi system o spokój, dostaje spokój: te same ekrany, bez klatki ruchu.
   Ta sama reguła co w Hubie (web/src/styles/tokens.css). Logowanie zna ją też
   po stronie skryptu — bez ruchu nie ma na co czekać przed przejściem. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
