/* ═══════════════════════════════════════════════════════════════════════════
   ZIRAEL — system wizualny PANELU. Jedno źródło dla stron HTMX i dla miksera.

   PO CO. Do 2026-09-14 panel miał trzy osobne estetyki: mikser (czarny, Inter,
   wszystko 8–12 px), strony HTMX (białe, font systemowy, 14–24 px) i strona
   sprzedażowa zirael.pl (granat i szkło, Archivo + IBM Plex). Klient, który kupił
   ze strony, wchodził do czegoś, co wyglądało jak inny produkt. Ten plik przenosi
   kanon ze strony (`/opt/zirael-landing/src/styles/global.css`, BRIEF §6) do
   aplikacji — tam, gdzie ma to sens dla NARZĘDZIA PRACY, a nie dla strony sprzedaży.

   CZEGO NIE PRZENOSIMY ze strony i dlaczego:
     · rozmycia tła (`backdrop-filter`) na każdej karcie — mikser odświeża podgląd
       wideo, a rozmycie liczone co klatkę kosztuje wydajność tam, gdzie liczy się
       opóźnienie. Szkło zostaje na paskach i oknach dialogowych, nie na panelach;
     · reguła „jeden wypełniony przycisk na ekran” dotyczy WYŁĄCZNIE akcentu marki.
       W konsoli realizatora kolorowy WSKAŹNIK STANU (antena, solo, wyciszenie) jest
       funkcją, nie ozdobą — i musi być widoczny kątem oka.

   TRZY KOLORY MAJĄ ZNACZENIE I NIE WOLNO ICH UŻYWAĆ DO NICZEGO INNEGO:
     --akcent    marka i JEDNO wezwanie do działania na ekran
     --tally     WYŁĄCZNIE „to jest teraz na antenie”
     --ostrzezenie  stan wymagający uwagi (nagrywanie, limit, błąd platformy)
   Do 2026-09-14 karmazyn był jednocześnie kolorem marki, błędu i anteny — czyli
   nie znaczył nic.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ⚠️ KAŻDA rodzina ma DWA podzbiory: latin i latin-ext. Bez latin-ext polskie znaki
   (ą ć ę ł ń ó ś ź ż) wypadają poza `unicode-range` i przeglądarka bierze je z kroju
   systemowego — na POLSKIM interfejsie co drugie słowo szłoby dwoma krojami naraz
   (zmierzone na stronie 2026-09-05: `a` 22 px, `ą` 17,75 px). Nie usuwaj drugiego bloku. */
@font-face{font-family:'Archivo';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/archivo-400_700-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Archivo';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/archivo-400_700-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/plex-sans-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url(/assets/fonts/plex-sans-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/plex-mono-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/plex-mono-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/plex-mono-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/plex-mono-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}

:root {
  /* ── kroje: trzy, trzy role ────────────────────────────────────────────── */
  --kroj-naglowek: 'Archivo', system-ui, sans-serif;
  --kroj-tresc: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  /* Liczby, które się PORÓWNUJE albo ODCZYTUJE NA ŻYWO (czas, dB, rozmiar, kod
     kanału) — krojem maszynowym o stałej szerokości cyfry, żeby nie skakały. */
  --kroj-liczby: 'IBM Plex Mono', ui-monospace, monospace;

  /* ── skala pisma: PIĘĆ stopni, nie sześć losowych ──────────────────────── */
  /* Mikser miał 8/9/10/11/12/14 px — sześć stopni, z których żaden nie budował
     hierarchii, bo różnica 1 px jest niewidoczna. Tu każdy kolejny jest o tyle
     większy, żeby było widać, który jest ważniejszy. */
  --pismo-mikro: 11px;   /* etykiety pól i plakietki — DOLNA GRANICA, niżej nie schodzimy */
  --pismo-male: 12px;  /* treść pomocnicza, opisy pod polami */
  --pismo-baza: 14px;    /* treść */
  --pismo-duze: 18px;    /* nagłówek panelu, nazwa źródła */
  --pismo-tytul: 26px;   /* tytuł strony */

  /* ── promienie: trzy rodziny, nie mieszać w obrębie typu komponentu ─────── */
  --r-karta: 12px;
  --r-plakietka: 6px;
  --r-pigulka: 999px;

  /* ── role kolorów niezależne od motywu ─────────────────────────────────── */
  --tally: #e0311f;          /* WYŁĄCZNIE „na antenie”. Nigdy jako ozdoba ani marka. */
  /* Ta sama rola przy WYPEŁNIENIU pod białym napisem: czysta czerwień daje tam 4,2:1,
     przyciemniona 6,3:1. Nie jest osobnym kolorem, tylko innym zastosowaniem. */
  --tally-ciemny: #b3261a;
  --ostrzezenie: #e8a33d;    /* uwaga: nagrywanie, limit, błąd platformy */
  --powodzenie: #34b37a;
}

/* ── MOTYW CIEMNY (kanoniczny — ten sam materiał co strona sprzedażowa) ───── */
:root, :root.dark {
  --tlo: #0b0f1f;            /* granat strony (--noc), nie czerń */
  --tlo-glab: #080c1a;
  --powierzchnia: #121a30;   /* panel/karta */
  --powierzchnia-2: #18223c; /* pole formularza, stan najechania */
  --wlos: rgba(186, 215, 247, 0.12);       /* obrys włosowy, nigdy pełny kolor */
  --wlos-mocny: rgba(186, 215, 247, 0.24);
  --tekst: #dfe6f2;          /* nigdy czysta biel */
  --tekst-naglowek: #eef3fb;
  /* ⚠️ Ten odcień jest NAJJAŚNIEJSZYM, jaki wolno dać tekstowi pomocniczemu:
     na --powierzchnia daje 4,9:1, czyli przechodzi próg WCAG AA dla 12,5 px.
     Poprzedni panel używał tu #6b7280 (3,0:1) i dlatego 181 napisów nie spełniało
     progu. Nie przyciemniaj „bo ładniej” — bramka odbioru to odrzuci. */
  --tekst-cichy: #9fb0cc;
  --akcent: #4d8dff;
  --akcent-jasny: #6ea1ff;
  /* Stan „ta pozycja jest wybrana” — ten sam akcent, przyciemniony. Nie jest osobnym
     kolorem: jest tym samym kolorem w innej roli (siatka źródeł, układ kolumn). */
  --akcent-ciemny: #2559c4;
  --akcent-tekst: #071022;   /* tekst NA wypełnieniu akcentem */
}

/* ── MOTYW JASNY ─────────────────────────────────────────────────────────── */
/* Nie jest „odwróconym ciemnym”: te same role, inne wartości. Kontrast tekstu
   pomocniczego liczony tak samo — #5b6b85 na białym to 5,3:1. */
:root:not(.dark) {
  --tlo: #eef1f7;
  --tlo-glab: #e4e9f2;
  --powierzchnia: #ffffff;
  --powierzchnia-2: #f4f6fb;
  --wlos: rgba(18, 34, 64, 0.12);
  --wlos-mocny: rgba(18, 34, 64, 0.24);
  --tekst: #16203a;
  --tekst-naglowek: #0d1530;
  --tekst-cichy: #5b6b85;
  /* ⚠️ Zmierzone 2026-09-15: #2f6bdd daje 4,35:1 jako tekst na bieli i 3,68:1 jako
     tło pod białym napisem — oba poniżej progu WCAG AA. Nie rozjaśniaj z powrotem;
     w motywie jasnym „jaśniejszy" wariant jest CIEMNIEJSZY, bo idzie w stronę
     większego kontrastu, a nie w stronę bieli. */
  --akcent: #2559c4;
  --akcent-jasny: #1e4ba8;
  --akcent-ciemny: #1e47a0;
  --akcent-tekst: #ffffff;
}

/* ── podstawa ────────────────────────────────────────────────────────────── */
body {
  background: var(--tlo);
  color: var(--tekst);
  font-family: var(--kroj-tresc);
  font-size: var(--pismo-baza);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--kroj-naglowek);
  color: var(--tekst-naglowek);
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* Liczby i kody: stała szerokość cyfry. Bez tego licznik czasu skacze co sekundę,
   a poziom w decybelach zmienia szerokość przy każdej zmianie wartości. */
.liczba, time, code, kbd, samp {
  font-family: var(--kroj-liczby);
  font-variant-numeric: tabular-nums;
}

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

/* ── przyciski ───────────────────────────────────────────────────────────── */
/* Jeden wypełniony akcentem na ekran. Reszta obrysowa — „siła wypełnionego maleje
   przy powtarzaniu”. Bramka `scripts/odbior-ui.mjs` liczy to i odmawia powyżej jednego. */
.przycisk {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  /* 36 px wysokości minimum: WCAG 2.2 wymaga 24 px, ale to jest narzędzie obsługiwane
     w pośpiechu, często jedną ręką na telefonie. */
  min-height: 36px;
  padding: 8px 16px;
  border-radius: var(--r-pigulka);
  border: 1px solid var(--wlos-mocny);
  background: transparent;
  color: var(--tekst);
  font: 600 var(--pismo-male)/1 var(--kroj-tresc);
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.przycisk:hover { border-color: var(--akcent); background: color-mix(in srgb, var(--akcent) 10%, transparent); }
.przycisk[disabled] { opacity: .45; cursor: not-allowed; }

.przycisk-glowny { background: var(--akcent); border-color: var(--akcent); color: var(--akcent-tekst); }
.przycisk-glowny:hover { background: var(--akcent-jasny); border-color: var(--akcent-jasny); }

/* Czynność nieodwracalna. Obrysowa, nie wypełniona — wypełnienie przyciąga klik,
   a to jest dokładnie ten przycisk, którego nie chcemy klikać odruchowo. */
.przycisk-groznie { border-color: color-mix(in srgb, var(--tally) 55%, transparent); color: var(--tally); }
/* ⚠️ `--tally` na jasnym tle to 4,38:1 przy 11 px — o włos poniżej progu. Napis
   przyciemniamy, obrys zostaje w kolorze roli. */
:root:not(.dark) .przycisk-groznie { color: #b3261a; }
.przycisk-groznie:hover { background: color-mix(in srgb, var(--tally) 12%, transparent); border-color: var(--tally); }

.przycisk-maly { min-height: 28px; padding: 5px 11px; font-size: var(--pismo-mikro); }

/* ── powierzchnie ────────────────────────────────────────────────────────── */
.karta {
  background: var(--powierzchnia);
  border: 1px solid var(--wlos);
  border-radius: var(--r-karta);
}

.plakietka {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px;
  border: 1px solid var(--wlos);
  border-radius: var(--r-plakietka);
  font: 500 var(--pismo-mikro)/1.5 var(--kroj-liczby);
  color: var(--tekst-cichy);
}

/* ── lampka „na antenie” — MUSI migać, nie stać ──────────────────────────── */
/* Stała kropka ginie w kadrze pełnym kolorowych elementów; ruch łapie oko kątem.
   Przy `prefers-reduced-motion` zostaje sam kolor — migotanie bywa nieprzyjemne,
   ale informacja „jesteś na antenie” nie może zniknąć. */
.lampka-antena {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--tally);
  animation: tally-puls 1.4s ease-in-out infinite;
  flex: none;
}
@keyframes tally-puls {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(224, 49, 31, .55); }
  50% { opacity: .5; box-shadow: 0 0 0 5px rgba(224, 49, 31, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .lampka-antena { animation: none; }
}

/* ── pola formularza ─────────────────────────────────────────────────────── */
/* `:where()` zeruje specyficzność, więc dowolna klasa Tailwinda w szablonie wygrywa. */
:where(input[type="text"], input[type="email"], input[type="password"], input[type="number"],
       input[type="url"], input[type="search"], input[type="tel"], input[type="date"],
       select, textarea) {
  background: var(--powierzchnia-2);
  color: var(--tekst);
  border: 1px solid var(--wlos);
  border-radius: 8px;
  padding: 9px 12px;
  font: 400 var(--pismo-baza)/1.4 var(--kroj-tresc);
  /* Długość wiersza: pole na 1130 px jest tak samo trudne do przeczytania jak
     akapit na całą szerokość ekranu. Szerokie pola dostają własną klasę. */
  max-width: 34rem;
  width: 100%;
}
:where(input, textarea)::placeholder { color: var(--tekst-cichy); opacity: .8; }
:where(input:focus, select:focus, textarea:focus) { border-color: var(--akcent); outline: none; }

/* Pole, które MUSI być szerokie (adres serwera, klucz strumienia) — świadomy wyjątek. */
.pole-szerokie { max-width: none; }

/* ── pozycja w menu pionowym ─────────────────────────────────────────────── */
/* Jedna klasa dla bocznego menu Ustawień i dla paska Administracji. Powstała
   2026-09-15, bo oba miejsca miały własny zestaw klas Tailwinda i własny sposób
   pokazywania „jesteś tutaj” — a w Ustawieniach ten sposób w ogóle nie działał:
   zawartość podmieniał HTMX, podświetlenie zostawało na pozycji sprzed kliknięcia.
   Stan bieżący niesie atrybut `aria-current="page"` — ten sam, który czyta czytnik
   ekranu. Dzięki temu nie da się pokazać podświetlenia, nie mówiąc tego na głos. */
.poz-menu {
  display: flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 8px 12px;
  border-radius: 8px;
  /* Nie `--tekst-cichy`: pozycja menu to nawigacja, nie przypis. Na `--tlo-glab`
     przygaszony odcień dawał 4,43:1, czyli poniżej progu WCAG AA. */
  color: var(--tekst);
  font-size: var(--pismo-baza);
  text-decoration: none;
  transition: background-color .15s ease, color .15s ease;
}
.poz-menu:hover { background: var(--wlos); color: var(--tekst); }
.poz-menu[aria-current="page"] {
  background: var(--akcent);
  color: var(--akcent-tekst);
  font-weight: 600;
}

/* ── zamknięcie okna dialogowego ─────────────────────────────────────────── */
/* Znak „×” ma naturalną szerokość jednego glifu — w oknie parowania wychodziło
   z tego 14×24 px, czyli połowa progu WCAG 2.2. Kwadrat 32 px z wyśrodkowanym
   znakiem jest tym samym elementem, tylko dającym się trafić palcem. */
.zamknij-okno {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 0; border-radius: var(--r-pigulka);
  background: transparent; color: var(--tekst-cichy);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.zamknij-okno:hover { background: var(--wlos); color: var(--tekst); }
