/* ============================================================================
   WILCZY ŁUP — panel administracyjny · WARSTWA 2: KOMPONENTY
   panel_ui_v1 · 2026-08-09 · saas-ui-designer
   ----------------------------------------------------------------------------
   Wymaga `tokens.css` PRZED sobą.
   Zastępuje wszystko poniżej bloku `:root` w `workers/panel/public/app.css`.

   NAZWY KLAS SĄ TE SAME, CO W ŻYWYM PANELU. Integrator nakłada, nie przepisuje.
   Klasy DOCHODZĄCE (wymagają jednolinijkowej zmiany w `app.js`) są oznaczone
   komentarzem `[NOWA]` razem z miejscem, w które je wstawić.

   Język formy — trzy rzeczy, z których wynika reszta:
   • Marka jest KANCIASTA i DRUKOWANA: promień 0, kreska 2 px u góry płyty
     zamiast ramki 1 px dookoła, brak cieni, brak gradientów poza aplą 45°.
   • Trzy kroje pracują na trzech różnych robotach: Big Shoulders = nagłówek
     (krzyczy), Work Sans = zdanie i KWOTA (czyta się), JetBrains Mono =
     etykieta, identyfikator, kod (skanuje się wzrokiem).
   • Kolor jest KRESKĄ I IKONĄ, nigdy literą. Wyjątek: `down` (apla).
   ============================================================================ */

/* =========================== 0. BAZA ===================================== */

*,
*::before,
*::after { box-sizing: border-box; border-radius: var(--wl-radius); }

html { -webkit-text-size-adjust: 100%; background: var(--wl-canvas); }

body {
  margin: 0;
  font-family: var(--wl-font-body);
  font-size: var(--wl-type-body);
  line-height: var(--wl-type-body-lh);
  font-weight: 400;
  color: var(--wl-ink-900);
  background: var(--wl-canvas);
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Big Shoulders jest wąski i wersalikowy — leading 0,9 jest jego naturalnym
   krokiem, 1,5 rozjeżdża go na trzy piętra. */
h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--wl-font-display);
  font-weight: 900;
  line-height: var(--wl-type-display-lh);
  letter-spacing: -0.005em;
  text-transform: uppercase;
}
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }
a { color: inherit; }
a:where(.u-plain) { text-decoration: none; }
::selection { background: var(--wl-brand); color: var(--wl-black); }

/* — FOKUS. Projektowany, nie domyślny: 2 px biała obwódka (widoczna na każdej
     powierzchni, także na pomarańczowej apli) + 4 px pomarańczowa aureola.
     Jeden pierścień dla całego panelu — powłoka nie ma osobnego. — */
:focus-visible {
  outline: 2px solid var(--wl-white);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--wl-brand);
}
[data-theme="light"] :focus-visible {
  outline-color: var(--wl-black);
  box-shadow: 0 0 0 6px var(--wl-brand);
}

/* — IKONY. Sprite v2.1: siatka 24, kreska 2, butt, miter, promień 0.
     Ikona NIGDY nie jest pomarańczowa sama z siebie — kolor dziedziczy
     z rodzica (badge, stan) i tylko stamtąd. — */
.i {
  inline-size: var(--wl-icon-24);
  block-size: var(--wl-icon-24);
  vertical-align: var(--wl-icon-align);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  flex: none;
}
.i--16 { inline-size: var(--wl-icon-16); block-size: var(--wl-icon-16); }
.i--32 { inline-size: var(--wl-icon-32); block-size: var(--wl-icon-32); }
.i--48 { inline-size: var(--wl-icon-48); block-size: var(--wl-icon-48); }

/* Glify modułowe (nav-*, kebab, settings-rules) NIE MAJĄ mistrza 16 i poniżej
   24 px milkną (sprite v2.1, nagłówek). Pasek desktopowy renderuje je dziś
   przez `i--16` — nadpisujemy w CSS, żeby nie ruszać `app.js`. */
.wl-navbar__item .i,
.wl-tab .i { inline-size: var(--wl-icon-24); block-size: var(--wl-icon-24); }

/* — SKIP-LINKI — */
.wl-skip {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: 0;
  z-index: 60;
  padding: var(--wl-s12) var(--wl-s16);
  background: var(--wl-brand);
  color: var(--wl-black);
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: var(--wl-type-section);
  letter-spacing: var(--wl-type-section-ls);
  text-transform: uppercase;
  text-decoration: none;
}
.wl-skip:focus { inset-block-start: 0; }

/* =========================== 1. POWŁOKA ================================== */

.wl-shell {
  position: sticky;
  inset-block-start: 0;
  z-index: 30;
  background: var(--wl-shell-bg);
  color: var(--wl-shell-ink);
  padding-block-start: var(--wl-safe-t);
  border-block-end: 1px solid var(--wl-shell-line);
}
.wl-shell__bar {
  min-block-size: var(--wl-appbar-h);
  display: flex;
  align-items: center;
  gap: var(--wl-s12);
  padding-inline: max(var(--wl-s16), var(--wl-safe-l)) max(var(--wl-s16), var(--wl-safe-r));
  max-inline-size: var(--wl-content-max);
  margin-inline: auto;
}
.wl-shell__bar > * { min-inline-size: 0; }

/* — ZNAK. `.wl-plaque` niesie DWA warianty tej samej klasy:
     (a) sam tekst „WIL/CZY/ŁUP" — działa bez żadnej zmiany w `app.js`;
     (b) [NOWA] znak + wordmark: <a class="wl-plaque"><svg class="wl-plaque__mark">
         <use href="#wl-mark"></use></svg><span class="wl-plaque__word">…</span></a>
     Wariant (b) to ten sam plik znaku, co w sklepie (`assets/logo.svg`), więc
     panel i sklep mają JEDEN znak, a nie dwa podobne. — */
.wl-plaque {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-block-size: var(--wl-touch-min);
  padding-block: var(--wl-plaque-guard);
  padding-inline: 0;
  color: var(--wl-shell-ink);
  text-decoration: none;
  font-family: var(--wl-font-display);
  font-weight: 900;
  font-size: 1.125rem;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 0;
}
.wl-plaque__mark {
  block-size: var(--wl-plaque-h);
  inline-size: auto;
  /* BEZ TEJ LINIJKI `inline-size: auto` NIE DZIAŁA. `viewBox` siedzi na <symbol>, a nie na <svg>,
     które go rysuje — więc zewnętrzny <svg> nie ma ŻADNEJ proporcji własnej i `auto` spada na
     domyślne 300 px zastępowanego elementu. Znak (apla ~kwadratowa) skalował się wtedy do wysokości
     wewnątrz pudełka 300 px i lądował WYŚRODKOWANY w tym pudełku — na szerokiej szpalcie logowania
     wyglądał jak apla rzucona na środek ekranu, oderwana od lockupu. Proporcja pochodzi z viewBoxa
     symbolu `#wl-mark` (49.45282 × 47.01741), czyli z tego samego pliku znaku, co w sklepie.
     Alternatywą było dopisanie `viewBox` do każdego <svg> w JS — jedna reguła jest tańsza i nie da
     się jej zapomnieć przy kolejnym użyciu znaku. */
  aspect-ratio: 49.45282 / 47.01741;
  display: block;
  /* Znak jest APLĄ z wyciętymi literami: `currentColor` maluje kwadrat,
     litery przepuszczają tło. Na czerni powłoki = biała plakietka. */
  fill: currentColor;
  flex: none;
}
.wl-plaque__word > i { font-style: normal; color: var(--wl-brand); }
.wl-plaque:hover { color: var(--wl-shell-ink); }

.wl-shell__title {
  font-family: var(--wl-font-mono);
  font-weight: 500;
  font-size: 0.75rem;
  line-height: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wl-shell-ink-muted);
  padding-inline-start: var(--wl-s12);
  border-inline-start: 1px solid var(--wl-shell-line);
  margin-inline-start: var(--wl-s4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wl-shell__spacer { margin-inline-start: auto; }

/* Rola: mono, wersaliki, kreska pomarańczowa z lewej. Czyta się jak stempel
   uprawnienia, a nie jak zapomniany podpis w rogu. */
.wl-shell__ident {
  font-family: var(--wl-font-mono);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wl-shell-ink-muted);
  padding-inline-start: var(--wl-s8);
  border-inline-start: 3px solid var(--wl-brand);
  max-inline-size: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wl-shell__acct {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wl-s8);
  min-block-size: var(--wl-touch-min);
  min-inline-size: var(--wl-touch-min);
  padding-inline: var(--wl-s12);
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: transparent;
  color: var(--wl-shell-ink);
  border: 1px solid var(--wl-shell-control-line);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--wl-motion-fade) var(--wl-ease);
}
.wl-shell__acct:hover { background: var(--wl-shell-hover); border-color: var(--wl-shell-ink); }
.wl-shell__acct:active { background: var(--wl-press-dark); transition: none; }
.wl-shell__acct-label { display: none; }

.wl-navbar { display: none; }

/* =========================== 2. PASEK ZAKŁADEK =========================== */

.wl-tabbar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 40;
  background: var(--wl-shell-bg);
  border-block-start: 1px solid var(--wl-shell-line);
  block-size: var(--wl-tabbar-total);
  padding-block-end: var(--wl-safe-b);
  padding-inline: var(--wl-safe-l) var(--wl-safe-r);
}
.wl-tabbar__list { display: flex; block-size: var(--wl-tabbar-h); }
.wl-tab {
  flex: 1 1 0;
  min-inline-size: 0;
  padding-inline: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-block-size: var(--wl-tabbar-h);
  color: var(--wl-shell-ink-muted);
  text-decoration: none;
  font-family: var(--wl-font-mono);
  font-size: var(--wl-type-tab);
  line-height: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  position: relative;
}
.wl-tab > span {
  max-inline-size: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wl-tab[aria-current="page"] { color: var(--wl-shell-ink); font-weight: 700; }
/* Aktywna zakładka: pomarańczowa kreska U GÓRY na pełną szerokość pola —
   dotyka krawędzi paska, więc czyta się jako „tu jesteś", a nie jako ozdoba. */
.wl-tab[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  background: var(--wl-brand);
}
.wl-tab:active { background: var(--wl-press-dark); transition: none; }

/* =========================== 3. TREŚĆ — RYTM ============================= */

.wl-main {
  display: block;
  container-type: inline-size;
  container-name: screen;
  padding-inline: max(var(--wl-s16), var(--wl-safe-l)) max(var(--wl-s16), var(--wl-safe-r));
  padding-block: var(--wl-s24) calc(var(--wl-tabbar-total) + var(--wl-s32));
  max-inline-size: var(--wl-content-max);
  margin-inline: auto;
  background: var(--wl-canvas);
}

.wl-h1 {
  font-size: var(--wl-type-display-2);
  letter-spacing: -0.01em;
}
.wl-h1::after {
  content: "";
  display: block;
  inline-size: 64px;
  block-size: 4px;
  background: var(--wl-brand);
  margin-block-start: var(--wl-s12);
}
.wl-lede {
  color: var(--wl-ink-700);
  font-size: 1.0625rem;
  font-weight: 300;
  line-height: 1.45;
  max-inline-size: var(--wl-measure);
  margin-block-start: var(--wl-s12);
}

/* [NOWA] `.wl-eyebrow` — etykieta nad wartością. Automatycznie stosowana też do
   pierwszego `.wl-meta` w płycie, żeby kafle liczb działały BEZ zmiany w JS. */
.wl-eyebrow,
.wl-tile > .wl-meta:first-child {
  display: block;
  font-family: var(--wl-font-mono);
  font-weight: 500;
  font-size: var(--wl-type-eyebrow);
  letter-spacing: var(--wl-type-eyebrow-ls);
  text-transform: uppercase;
  color: var(--wl-ink-700);
  margin-block-end: var(--wl-s8);
}

.wl-section { margin-block-start: var(--wl-s32); }
.wl-section__h {
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: var(--wl-type-section);
  letter-spacing: var(--wl-type-section-ls);
  text-transform: uppercase;
  color: var(--wl-ink-900);
  padding-block-end: var(--wl-s8);
  border-block-end: 2px solid var(--wl-ink-900);
  margin-block-end: var(--wl-s16);
  display: flex;
  align-items: center;
  gap: var(--wl-s8);
}
.wl-meta {
  color: var(--wl-ink-500);
  font-size: var(--wl-type-meta);
  line-height: 1.45;
}

/* — PŁYTA. Górna kreska 2 px + hairline z trzech stron: karta wygląda jak
     wydrukowana etykieta, nie jak kontrolka. `data-state` maluje TĘ kreskę
     (redundancja wobec badge'a — kolor nigdy nie jest jedynym nośnikiem). — */
.wl-tile {
  background: var(--wl-surface);
  border: 1px solid var(--wl-line);
  border-block-start: var(--wl-rule-w) solid var(--wl-line-strong);
  padding: var(--wl-tile-pad) var(--wl-tile-pad-inline);
}
.wl-tile + .wl-tile { margin-block-start: var(--wl-tile-gap); }
.wl-tile[data-state="ok"]        { border-block-start-color: var(--wl-state-ok); }
.wl-tile[data-state="degraded"]  { border-block-start-color: var(--wl-state-degraded); }
.wl-tile[data-state="down"]      { border-block-start-color: var(--wl-state-down-bg); }
.wl-tile[data-state="unknown"]   { border-block-start-color: var(--wl-state-unknown); }

.wl-grid { display: grid; gap: var(--wl-tile-gap); grid-template-columns: 1fr; }

/* =========================== 4. PRZYCISKI ================================ */

.wl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wl-s8);
  min-block-size: var(--wl-touch-min);
  padding-inline: var(--wl-s24);
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  /* Idiom sklepu §6: apla pomarańczowa, litery czarne (6,5:1). */
  border: 2px solid var(--wl-brand);
  background: var(--wl-brand);
  color: var(--wl-black);
  text-decoration: none;
  transition: none;
}
.wl-btn:hover { background: var(--wl-white); border-color: var(--wl-white); color: var(--wl-black); }
.wl-btn:active { background: var(--wl-ink-700); border-color: var(--wl-ink-700); }
.wl-btn .i { stroke-width: 2; }
.wl-btn--secondary {
  background: transparent;
  color: var(--wl-ink-900);
  border-color: var(--wl-line-strong);
}
.wl-btn--secondary:hover { background: var(--wl-surface-hover); border-color: var(--wl-ink-900); color: var(--wl-ink-900); }
.wl-btn[aria-disabled="true"] {
  background: transparent;
  color: var(--wl-ink-500);
  border-color: var(--wl-line);
  cursor: not-allowed;
}
.wl-btn--block { inline-size: 100%; }

/* Cicha akcja tekstowa — wygląda jak odnośnik, bo nim jest. */
.wl-linkbtn {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--wl-touch-min);
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--wl-font-body);
  font-size: var(--wl-type-meta);
  color: var(--wl-ink-700);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
  cursor: pointer;
}
.wl-linkbtn:hover { color: var(--wl-ink-900); text-decoration-color: var(--wl-brand); }

/* =========================== 5. POLA ===================================== */

.wl-field { display: block; margin-block-start: var(--wl-s20); }
.wl-label {
  display: block;
  font-family: var(--wl-font-mono);
  font-weight: 500;
  font-size: var(--wl-type-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wl-ink-700);
  margin-block-end: var(--wl-s8);
}
.wl-input {
  inline-size: 100%;
  min-block-size: var(--wl-touch-comfort);
  padding: var(--wl-s12) var(--wl-s16);
  font-family: var(--wl-font-body);
  font-size: 1rem;
  color: var(--wl-ink-900);
  background: var(--wl-surface-sunken);
  border: 2px solid var(--wl-line-strong);
}
.wl-input::placeholder { color: var(--wl-ink-500); }
.wl-input:hover { border-color: var(--wl-ink-700); }
.wl-input:focus-visible { border-color: var(--wl-white); }
.wl-input[aria-invalid="true"] { border-color: var(--wl-brand); }
.wl-hint { color: var(--wl-ink-500); font-size: var(--wl-type-meta); margin-block-start: var(--wl-s8); }
.wl-hint:empty { display: none; }
/* Błąd formularza NIGDY samym kolorem i nigdy `--wl-brand` jako jedyny sygnał
   (Spec UX §6): kreska + wersalikowe „BŁĄD" przed zdaniem. */
.wl-hint[role="alert"]:not(:empty) {
  color: var(--wl-ink-900);
  border-inline-start: 3px solid var(--wl-brand);
  padding: var(--wl-s8) var(--wl-s12);
  background: var(--wl-attention-bg);
}
.wl-hint[role="alert"]:not(:empty)::before {
  content: "Błąd — ";
  font-family: var(--wl-font-mono);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* =========================== 6. BADGE STANU ==============================
   ZAWSZE ikona + słowo. Kolor siedzi w ikonie i w 3 px kresce z lewej.
   Litery zostają białe (18,9:1) — kolor nie jest tekstem.                   */

.wl-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--wl-s8);
  font-family: var(--wl-font-mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px var(--wl-s8) 5px var(--wl-s8);
  min-block-size: 26px;
  border: 1px solid var(--wl-line);
  border-inline-start: 3px solid var(--wl-state-unknown);
  background: var(--wl-surface-sunken);
  color: var(--wl-ink-900);
  white-space: nowrap;
}
.wl-badge .i { color: var(--wl-state-unknown); }

.wl-badge--ok            { border-inline-start-color: var(--wl-state-ok); }
.wl-badge--ok .i         { color: var(--wl-state-ok); }
.wl-badge--degraded,
.wl-badge--attention     { border-inline-start-color: var(--wl-state-degraded); background: var(--wl-attention-bg); }
.wl-badge--degraded .i,
.wl-badge--attention .i  { color: var(--wl-state-degraded); }
.wl-badge--info          { border-inline-start-color: var(--wl-state-info); }
.wl-badge--info .i       { color: var(--wl-state-info); }
.wl-badge--unknown       { border-inline-start-color: var(--wl-state-unknown); }
.wl-badge--unknown .i    { color: var(--wl-ink-500); }
/* `down` jako JEDYNY stan wychodzi aplą. Marka nie ma czerwieni, więc rolę
   „awaria" gra INWERSJA, nie nowy kolor: pomarańcz + czarne litery, 6,5:1.
   Zobacz też: decyzja projektowa 2 w raporcie. */
.wl-badge--down {
  background: var(--wl-state-down-bg);
  border-color: var(--wl-state-down-bg);
  border-inline-start-color: var(--wl-black);
  color: var(--wl-state-down-ink);
}
.wl-badge--down .i { color: var(--wl-state-down-ink); }
.wl-badge--lg { font-size: 0.75rem; min-block-size: 34px; padding-inline: var(--wl-s12); }

/* =========================== 7. KWOTY ==================================== */

.wl-money {
  font-family: var(--wl-font-money);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.wl-money--hero {
  display: block;
  font-size: var(--wl-type-money-hero);
  line-height: var(--wl-type-money-hero-lh);
  margin-block: var(--wl-s4) var(--wl-s8);
}
.wl-basis {
  font-family: var(--wl-font-mono);
  font-weight: 500;
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wl-ink-700);
  white-space: nowrap;
  border-block-end: 2px solid var(--wl-line-strong);
  padding-block-end: 1px;
}
/* BRAK KWOTY TO NIE ZERO — i nie awaria. Kreska w kolorze tekstu drugorzędnego,
   bez ramki alarmowej, bez pomarańczu. „Cicho" jest tu decyzją. */
.wl-nodata {
  color: var(--wl-ink-500);
  font-family: var(--wl-font-money);
  font-weight: 600;
}
.wl-money--hero.wl-nodata { color: var(--wl-ink-500); }

/* [NOWA] Kafel liczby okresu. Płyta + eyebrow + kwota + jedno zdanie.
   Działa też na obecnym markupie płyty bez tej klasy. */
.wl-tile--stat { display: flex; flex-direction: column; min-block-size: 148px; }
/* Wysokości kafli wyrównuje SIATKA (`align-items:stretch`), nie sztuczka z
   `margin-block-start:auto` — ta ostatnia zjeżdżała etykiecie na dół, kiedy
   `app.js` renderował ją jako `.wl-meta` zamiast `.wl-eyebrow`. */
.wl-tile--stat[data-state="nodata"] { border-block-start-style: dashed; }

/* =========================== 8. STAN SYSTEMU =============================
   [NOWA] `.wl-health` — układ karty stanu.
   Problem, który to rozwiązuje: „Nie wiem" pada dziś w czterech miejscach
   (badge, zdanie, przypis, lista składników). Tutaj stan jest powiedziany
   RAZ, w jednej linii nagłówka, a niżej są już tylko FAKTY: kiedy ostatni
   sygnał, ile składników, co z każdym z nich.                              */

.wl-health__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wl-s12);
  justify-content: space-between;
}
.wl-health__say {
  color: var(--wl-ink-700);
  font-size: 0.9375rem;
  line-height: 1.5;
  max-inline-size: var(--wl-measure);
  margin-block-start: var(--wl-s12);
}
/* Pasek składników: jeden segment = jeden czujnik. Świadomie `aria-hidden` —
   to REDUNDANTNA wizualizacja listy, która stoi pod spodem. Stan `unknown`
   nie jest szarą plamą, tylko skosem 45° — „pole niewypełnione", nie „pole
   puste". Ten sam skos, co w apli logowania. */
.wl-health__meter {
  display: flex;
  gap: 3px;
  margin-block-start: var(--wl-s16);
}
.wl-health__seg {
  flex: 1 1 0;
  block-size: 10px;
  border: 1px solid var(--wl-line-strong);
  background: transparent;
}
.wl-health__seg[data-state="ok"]       { background: var(--wl-state-ok); border-color: var(--wl-state-ok); }
.wl-health__seg[data-state="degraded"] { background: var(--wl-state-degraded); border-color: var(--wl-state-degraded); }
.wl-health__seg[data-state="down"]     { background: var(--wl-state-down-bg); border-color: var(--wl-black); }
.wl-health__seg[data-state="unknown"] {
  background: repeating-linear-gradient(
    45deg,
    var(--wl-line-strong) 0 1.5px,
    transparent 1.5px 5px
  );
}
.wl-health__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wl-s8) var(--wl-s20);
  margin-block-start: var(--wl-s12);
  font-family: var(--wl-font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wl-ink-500);
}
/* Lista składników: nazwa z lewej, stan z prawej. Bez powtarzania zdania
   ogólnego przy każdym wierszu — wiersz niesie SŁOWO stanu i datę sygnału. */
.wl-health__list { margin-block-start: var(--wl-s16); border-block-start: 1px solid var(--wl-line); }
.wl-health__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--wl-s4) var(--wl-s12);
  min-block-size: var(--wl-touch-min);
  padding-block: var(--wl-s12);
  border-block-end: 1px solid var(--wl-line);
}
.wl-health__name { font-weight: 600; }
.wl-health__when { grid-column: 1; color: var(--wl-ink-500); font-size: var(--wl-type-meta); font-variant-numeric: tabular-nums; }
.wl-health__st   { grid-column: 2; grid-row: 1 / span 2; }

/* =========================== 9. STANY W-6 ================================ */

.wl-state {
  border: 1px solid var(--wl-line);
  border-block-start: var(--wl-rule-w) solid var(--wl-line-strong);
  padding: var(--wl-s40) var(--wl-s24);
  text-align: center;
  background: var(--wl-surface);
}
/* Ikona stanu pustego dostaje pole ochronne i cieńszą kreskę optycznie
   (48 px przy kresce 2 = lekki rysunek), więc nie krzyczy. */
.wl-state__icon { color: var(--wl-ink-500); display: inline-block; }
.wl-state__title {
  font-family: var(--wl-font-display);
  font-weight: 900;
  text-transform: uppercase;
  font-size: 1.25rem;
  line-height: 1;
  margin-block-start: var(--wl-s16);
}
.wl-state__body {
  color: var(--wl-ink-700);
  font-size: 0.9375rem;
  margin-block-start: var(--wl-s8);
  margin-inline: auto;
  max-inline-size: 46ch;
}
.wl-state__actions {
  margin-block-start: var(--wl-s24);
  display: flex;
  gap: var(--wl-touch-gap);
  justify-content: center;
  flex-wrap: wrap;
}
.wl-state--error {
  background: var(--wl-attention-bg);
  border-block-start-color: var(--wl-brand);
}
.wl-state--error .wl-state__icon { color: var(--wl-brand); }

.wl-copy {
  display: inline-flex;
  align-items: center;
  gap: var(--wl-s8);
  min-block-size: var(--wl-touch-min);
  padding-inline: var(--wl-s12);
  font-family: var(--wl-font-mono);
  font-size: var(--wl-type-meta);
  font-weight: 500;
  letter-spacing: 0.04em;
  background: var(--wl-surface-sunken);
  border: 1px solid var(--wl-line-strong);
  color: var(--wl-ink-900);
  cursor: pointer;
}
.wl-copy:hover { border-color: var(--wl-white); background: var(--wl-surface-hover); }

/* Szkielet: nigdy spinner, nigdy zero (M8). */
.wl-skel {
  background: var(--wl-surface-hover);
  block-size: 1em;
  inline-size: 100%;
  display: block;
  animation: wl-pulse 1.2s var(--wl-ease) infinite alternate;
}
.wl-skel + .wl-skel { margin-block-start: var(--wl-s8); }
.wl-skel--sm { inline-size: 40%; }
.wl-skel--md { inline-size: 70%; }
.wl-skel--row { block-size: 56px; }
@keyframes wl-pulse { from { opacity: 1; } to { opacity: 0.45; } }

.wl-notice {
  display: flex;
  align-items: center;
  gap: var(--wl-s12);
  padding: var(--wl-s12) max(var(--wl-s16), var(--wl-safe-l));
  background: var(--wl-notice-bg);
  border-block: 1px solid var(--wl-line-strong);
  border-inline-start: 3px solid var(--wl-brand);
  font-size: var(--wl-type-meta);
}

/* =========================== 10. W-1 KOLEKCJA ============================ */

.wl-count {
  font-family: var(--wl-font-mono);
  font-size: var(--wl-type-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wl-ink-500);
  margin-block: var(--wl-s20) var(--wl-s8);
}
.wl-list { border-block-start: 1px solid var(--wl-line); }
.wl-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--wl-s4) var(--wl-s12);
  align-items: center;
  min-block-size: var(--wl-touch-min);
  padding: var(--wl-s12) var(--wl-s8);
  border-block-end: 1px solid var(--wl-line);
  text-decoration: none;
  color: inherit;
  position: relative;
}
.wl-row:hover { background: var(--wl-surface-hover); }
.wl-row:hover::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 3px;
  background: var(--wl-brand);
}
.wl-row:active { background: var(--wl-press-light); transition: none; }
.wl-row__title { font-family: var(--wl-font-mono); font-weight: 700; letter-spacing: 0.02em; }
.wl-row__meta { grid-column: 1; color: var(--wl-ink-500); font-size: var(--wl-type-meta); }
.wl-row__end {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  gap: var(--wl-s12);
  text-align: end;
}
.wl-row__end .i { color: var(--wl-ink-500); }
.wl-row:hover .wl-row__end .i { color: var(--wl-brand); }

.wl-table-wrap { display: none; }

/* =========================== 11. W-2 OBIEKT ============================== */

.wl-breadcrumbs { display: none; }
.wl-back {
  display: inline-flex;
  align-items: center;
  gap: var(--wl-s8);
  min-block-size: var(--wl-touch-min);
  text-decoration: none;
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: var(--wl-type-meta);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wl-ink-700);
}
.wl-back:hover { color: var(--wl-ink-900); }

.wl-ident {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wl-touch-gap);
  margin-block-start: var(--wl-s16);
}

/* — ŚCIEŻKA DECYZJI. Pięć kroków na pionowej szynie; znacznik jest KWADRATEM
     22×22 (promień 0), a nie kropką. Krok „nie dotyczy" jest wygaszony, ale
     nie znika — brak kroku też jest informacją. — */
.wl-path { border-inline-start: 2px solid var(--wl-line); margin-inline-start: 11px; margin-block-start: var(--wl-s8); }
.wl-path__step { position: relative; padding: 0 0 var(--wl-s24) var(--wl-s32); }
.wl-path__step:last-child { padding-block-end: 0; }
.wl-path__step::before {
  content: "";
  position: absolute;
  inset-inline-start: -13px;
  inset-block-start: 0;
  inline-size: 24px;
  block-size: 24px;
  background: var(--wl-surface);
  border: 2px solid var(--wl-line-strong);
}
.wl-path__mark {
  position: absolute;
  inset-inline-start: -13px;
  inset-block-start: 0;
  inline-size: 24px;
  block-size: 24px;
  display: grid;
  place-items: center;
  color: var(--wl-ink-500);
}
.wl-path__step--ok::before      { border-color: var(--wl-state-ok); }
.wl-path__step--ok .wl-path__mark { color: var(--wl-state-ok); }
.wl-path__step--missing::before { border-color: var(--wl-state-degraded); background: var(--wl-attention-bg); }
.wl-path__step--missing .wl-path__mark { color: var(--wl-state-degraded); }
.wl-path__step--na::before      { border-style: dashed; border-color: var(--wl-line); }
.wl-path__title {
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: var(--wl-type-meta);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-block-start: 2px;
}
.wl-path__detail { color: var(--wl-ink-700); font-size: 0.9375rem; margin-block-start: var(--wl-s4); max-inline-size: var(--wl-measure); }
.wl-path__step--na .wl-path__title,
.wl-path__step--na .wl-path__detail { color: var(--wl-ink-500); }

/* — FAKTY —
   DWIE SZPALTY DOPIERO OD 600 px KONTENERA, nie od zera. Wartością w `dd` bywa
   `.wl-badge`, a badge jest z założenia `white-space: nowrap` (ikona i słowo nie
   mają prawa się rozjechać). Najdłuższa etykieta stanu — „NIE WIEM — BRAK
   ŚWIEŻEGO SYGNAŁU" — mierzy ~283 px, więc w szpalcie 55 % z 343 px (telefon
   375) nie mieści się i WYPYCHA CAŁĄ STRONĘ w poziomie: zmierzone
   `scrollWidth = 472` przy `clientWidth = 375`, czyli pasek belki i kafle
   uciekają za krawędź. Rozwiązaniem jest układ, nie łamanie badge'a: na wąskim
   kontenerze etykieta staje NAD wartością i badge dostaje pełną szerokość.
   Dwuszpaltowy wariant wraca w bloku `@container screen (min-width: 600px)`. */
.wl-dl { display: grid; grid-template-columns: 1fr; border-block-start: 1px solid var(--wl-line); }
.wl-dl > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--wl-s4);
  padding: var(--wl-s12) 0;
  border-block-end: 1px solid var(--wl-line);
  align-items: baseline;
}
.wl-dl dt {
  font-family: var(--wl-font-mono);
  font-size: var(--wl-type-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wl-ink-500);
}
/* Jednoszpaltowo wartość wyrównuje się do POCZĄTKU — `text-align: end` pod
   etykietą czyta się jak sierota, a przy `.wl-badge` (inline-flex) wypycha
   ramkę na prawą krawędź bez powodu. `end` wraca razem z drugą szpaltą. */
.wl-dl dd { margin: 0; text-align: start; font-variant-numeric: tabular-nums; min-inline-size: 0; }

/* — KSIĘGA. Para naliczenie/odwrócenie: naliczenie ma znacznik pełny,
     odwrócenie — pusty z pomarańczową obwódką. Kolor jest dodatkiem do
     kształtu i słowa, nie zamiast nich. — */
.wl-ledger { border-inline-start: 2px solid var(--wl-line); margin-inline-start: 7px; margin-block-start: var(--wl-s8); }
.wl-ledger__e { position: relative; padding: 0 0 var(--wl-s20) var(--wl-s24); }
.wl-ledger__e::before {
  content: "";
  position: absolute;
  inset-inline-start: -7px;
  inset-block-start: 6px;
  inline-size: 12px;
  block-size: 12px;
  background: var(--wl-ink-900);
}
.wl-ledger__e--reversal::before {
  background: var(--wl-surface);
  border: 2px solid var(--wl-brand);
}
.wl-ledger__head {
  display: flex;
  justify-content: space-between;
  gap: var(--wl-s12);
  align-items: baseline;
}
.wl-ledger__head > span:first-child {
  font-family: var(--wl-font-mono);
  font-weight: 700;
  font-size: var(--wl-type-meta);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.wl-ledger__sum {
  display: flex;
  justify-content: space-between;
  gap: var(--wl-s12);
  align-items: baseline;
  padding-block: var(--wl-s12);
  border-block-start: 1px solid var(--wl-line);
  font-family: var(--wl-font-mono);
  font-size: var(--wl-type-meta);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* Saldo — ostatnia suma — dostaje kreskę 2 px i większy stopień. To jest
   liczba, po którą człowiek tu przyszedł. */
.wl-ledger__sum:last-of-type {
  border-block-start: var(--wl-rule-w) solid var(--wl-ink-900);
  font-weight: 700;
}
.wl-ledger__sum:last-of-type .wl-money { font-size: 1.25rem; }

/* =========================== 12. LOGOWANIE ===============================
   Dwa warianty tej samej podstawy — wybór właściciela:
   A. `.wl-signin--split`  „WITRYNA": czarna szpalta marki + formularz obok.
   B. `.wl-signin`          „PLAKAT":  jedna kolumna, znak nad tytułem.
   Oba mają ten sam formularz i te same tokeny.                              */

.wl-signin {
  min-block-size: 100dvh;
  display: grid;
  place-items: center;
  padding: max(var(--wl-s32), var(--wl-safe-t)) max(var(--wl-s16), var(--wl-safe-l))
           max(var(--wl-s32), var(--wl-safe-b)) max(var(--wl-s16), var(--wl-safe-r));
  background: var(--wl-canvas);
}
.wl-signin__card { inline-size: min(420px, 100%); }
.wl-signin__brand { display: flex; align-items: center; gap: var(--wl-s12); margin-block-end: var(--wl-s24); }
.wl-signin__brand .wl-plaque__mark { block-size: 64px; }
.wl-signin .wl-h1 { font-size: var(--wl-type-display-1); }
.wl-signin .wl-lede { font-size: 1rem; }

/* [NOWA] szpalta marki.
   STAN BAZOWY = TELEFON: jedna kolumna, dwa WIERSZE — pas marki NAD formularzem, nigdy na nim.
   `grid-template-rows` jest tu jawne, żeby wiersz marki miał zadaną wysokość (~42 % ekranu) i żeby
   formularz dostał całą resztę zamiast dzielić się nią po równo. */
.wl-signin--split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(min-content, 42dvh) 1fr;
  place-items: stretch;
  padding: 0;
}
.wl-signin__aside {
  position: relative;
  overflow: hidden;
  background: var(--wl-black);
  color: var(--wl-white);
  padding: var(--wl-s32) var(--wl-s24);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--wl-s16);
  border-block-end: var(--wl-rule-w) solid var(--wl-brand);
}
/* `align-self` NIE jest tu kosmetyką: szpalta to kolumnowy flex, więc domyślne `align-items: stretch`
   rozciągnęłoby znak na całą jej szerokość mimo proporcji ustawionej wyżej. Dosunięcie do początku
   stawia go dokładnie nad lockupem, jak w projekcie. */
.wl-signin__aside .wl-plaque__mark {
  block-size: 72px;
  align-self: start;
  position: relative;
  z-index: 1;
}
/* Lockup WIL/CZY/ŁUP — trzy sylaby, ukośnik pomarańczowy. Ten sam podział,
   co w nazwie panelu; na desktopie schodzi do trzech wierszy. */
.wl-signin__lockup {
  position: relative;
  z-index: 1;
  font-family: var(--wl-font-display);
  font-weight: 900;
  font-size: clamp(2.5rem, 1.5rem + 5vw, 5.5rem);
  line-height: 0.82;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}
.wl-signin__lockup i { font-style: normal; color: var(--wl-brand); }
/* Trzy wiersze to układ DESKTOPOWY. W pasie nad formularzem napis idzie jedną linią — inaczej sam
   lockup zjada pas i spycha formularz poniżej krawędzi ekranu. `<br>` w markupie zostaje; to CSS
   decyduje, czy łamie. Wraca w `@container signin (min-width: 1024px)`. */
.wl-signin__lockup br { display: none; }
.wl-signin__claim {
  position: relative;
  z-index: 1;
  font-family: var(--wl-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wl-ink-700);
  max-inline-size: 34ch;
}
/* APLA 45° — jedyny „obrazek" w panelu i jedyny gradient. Ten sam skos, co
   w segmencie `unknown` paska stanu i ta sama geometria, co w ikonach
   (0/90/45). Zero plików rastrowych, zero zewnętrznych zasobów. */
.wl-signin__hatch {
  position: absolute;
  inset-block-start: -20%;
  inset-inline-end: -30%;
  inline-size: 90%;
  block-size: 140%;
  background: repeating-linear-gradient(
    45deg,
    var(--wl-brand) 0 6px,
    transparent 6px 22px
  );
  opacity: 0.5;
  pointer-events: none;
}

/* =========================== 13. SZEROKOŚCI ==============================
   Treść mierzy się KONTENEREM (Spec UX §2.1), więc 400 % zoomu degraduje
   układ samo z siebie. Powłoka (pasek/zakładki) zostaje na `@media`, bo
   `container-type` na przodku zabiłby `position: fixed` paska zakładek.   */

@container screen (min-width: 600px) {
  .wl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .wl-dl > div { grid-template-columns: minmax(12rem, 34%) minmax(0, 1fr); gap: var(--wl-s12); }
  .wl-dl dd { text-align: end; }
  .wl-tile { padding: var(--wl-s20) var(--wl-s24); }
  .wl-health__head { flex-wrap: nowrap; }
}

@container screen (min-width: 1024px) {
  .wl-breadcrumbs {
    display: flex;
    gap: var(--wl-s8);
    align-items: center;
    font-family: var(--wl-font-mono);
    font-size: var(--wl-type-eyebrow);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--wl-ink-500);
    margin-block-end: var(--wl-s16);
    flex-wrap: wrap;
  }
  .wl-breadcrumbs a { color: inherit; }
  .wl-back { display: none; }

  /* W-1: tabela od 1024. Ta sama treść, co karta (C16). */
  .wl-table-wrap { display: block; }
  .wl-list--cards { display: none; }
  .wl-table { inline-size: 100%; border-collapse: collapse; font-size: 0.9375rem; }
  .wl-table caption { text-align: start; }
  .wl-table th,
  .wl-table td {
    text-align: start;
    padding: var(--wl-s12);
    border-block-end: 1px solid var(--wl-line);
    vertical-align: middle;
  }
  .wl-table thead th {
    background: var(--wl-surface-sunken);
    border-block-end: 2px solid var(--wl-ink-900);
    font-family: var(--wl-font-mono);
    font-size: var(--wl-type-eyebrow);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--wl-ink-700);
    position: sticky;
    inset-block-start: var(--wl-appbar-h);
    z-index: 1;
  }
  .wl-table tbody tr { min-block-size: var(--wl-touch-min); }
  .wl-table tbody tr:hover { background: var(--wl-surface-hover); }
  .wl-table td.u-end, .wl-table th.u-end { text-align: end; }
  .wl-table td .wl-money { font-variant-numeric: tabular-nums; }
  .wl-table a { text-decoration: none; font-family: var(--wl-font-mono); font-weight: 700; }
  .wl-table a:hover { text-decoration: underline; text-underline-offset: 3px; }

  .wl-tile { padding: var(--wl-s24) var(--wl-s32); }
  .wl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--wl-s24); }
}

@container screen (min-width: 1440px) {
  .wl-detail-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--wl-s40);
    align-items: start;
  }
  .wl-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .wl-grid--halves { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* — POWŁOKA: przełączenie na pasek poziomy — */
@media (min-width: 1024px) {
  .wl-navbar {
    display: block;
    border-block-start: 1px solid var(--wl-shell-line);
  }
  .wl-navbar__list {
    display: flex;
    min-block-size: var(--wl-navbar-h);
    padding-inline: max(var(--wl-s16), var(--wl-safe-l)) max(var(--wl-s16), var(--wl-safe-r));
    max-inline-size: var(--wl-content-max);
    margin-inline: auto;
  }
  .wl-navbar__item {
    display: inline-flex;
    align-items: center;
    gap: var(--wl-s8);
    padding-inline: var(--wl-s16);
    min-block-size: var(--wl-touch-min);
    color: var(--wl-shell-ink-muted);
    text-decoration: none;
    font-family: var(--wl-font-mono);
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    position: relative;
    border-block-end: 3px solid transparent;
  }
  .wl-navbar__item:hover { background: var(--wl-shell-hover); color: var(--wl-shell-ink); }
  .wl-navbar__item[aria-current="page"] {
    color: var(--wl-shell-ink);
    font-weight: 700;
    border-block-end-color: var(--wl-brand);
    background: var(--wl-shell-hover);
  }
  .wl-tabbar { display: none; }
  .wl-main { padding-block-end: var(--wl-s72); padding-inline: var(--wl-s24); }
  .wl-shell__acct-label { display: inline; }
}

@media (min-width: 560px) { .wl-shell__acct-label { display: inline; } }
@media (max-width: 419px) { .wl-shell__ident { display: none; } }

/* — LOGOWANIE, wariant szpaltowy: na telefonie szpalta to PAS NAD FORMULARZEM, nigdy warstwa na nim.
     Warunek jest OKIENNY, nie kontenerowy, i to jest świadome: przełącznik siedzi na tym samym
     elemencie, który miałby być kontenerem (`.wl-signin--split`), a zapytanie kontenerowe nie
     stylizuje własnego kontenera — dałoby się to obejść dodatkowym opakowaniem, ale ten ekran nigdy
     nie jest osadzany węziej niż okno, więc opakowanie kupowałoby wyłącznie poprawność podglądu.
     (Podgląd `preview.html` pokazuje telefon jako ramkę 375 px w oknie 1440 px, więc łapie tam
     reguły desktopowe i szpalty wchodzą na siebie — to artefakt ramki, nie stan produkcji; przy
     prawdziwym oknie 375 px mierzone: pas 375×378 nad kartą 375×578, zero styku.) — */
@media (max-width: 1023px) {
  .wl-signin--split .wl-signin__card { padding: var(--wl-s32) var(--wl-s16) var(--wl-s40); margin-inline: auto; }
  /* Znak schodzi z 72 do 56 px — wartość z mobilnej klatki podglądu. W pasie 42 % wysokości
     telefonu apla 72 px zjada tyle miejsca, że claim ląduje przy samej krawędzi. */
  .wl-signin--split .wl-signin__aside .wl-plaque__mark { block-size: 56px; }
}

@media (min-width: 1024px) {
  .wl-signin--split {
    grid-template-columns: minmax(0, 1fr) minmax(480px, 0.8fr);
    grid-template-rows: minmax(0, 1fr);   /* dwie szpalty = JEDEN wiersz; bez tego pas 42dvh zostaje */
    min-block-size: 100dvh;
  }
  .wl-signin--split .wl-signin__aside {
    padding: var(--wl-s56);
    border-block-end: 0;
    border-inline-end: var(--wl-rule-w) solid var(--wl-brand);
  }
  .wl-signin--split .wl-signin__card {
    inline-size: min(420px, 100%);
    margin-inline: auto;
    align-self: center;
    padding: var(--wl-s56) var(--wl-s32);
  }
  /* Trzy sylaby w trzech wierszach — układ z projektu, tylko na pełnej szpalcie. */
  .wl-signin--split .wl-signin__lockup br { display: inline; }
}

/* =========================== 14. RUCH, DRUK, POMOCNICZE ================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0ms !important; transition-duration: 0ms !important; }
}

@media print {
  .wl-shell, .wl-tabbar, .wl-skip, .wl-signin__hatch { display: none !important; }
  .wl-main { padding: 0; max-inline-size: none; }
  .wl-tile, .wl-state { border: 1px solid #000; }
  .wl-badge--down { background: #FFF; color: #000; border: 2px solid #000; }
}

.u-visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.u-stack > * + * { margin-block-start: var(--wl-s12); }
.u-row { display: flex; align-items: center; gap: var(--wl-touch-gap); flex-wrap: wrap; }
.u-end { text-align: end; }
.u-mono { font-family: var(--wl-font-mono); letter-spacing: 0.04em; }

/* ============================================================================
   NAKŁADANIE NA ŻYWY PANEL — lista kroków, od najtańszego
   ----------------------------------------------------------------------------
   KROK 1 — bez jednej linijki w JS (80 % efektu):
     a) skopiuj 6 plików `.woff2` z `wilczylup-sklep-theme/fonts/`
        do `workers/panel/public/fonts/`;
     b) podmień `app.css` na `tokens.css` + `components.css` (w tej kolejności);
     c) podmień zawartość sprite'u w `index.html` na `ikony-panel.svg`
        (aliasy pokrywają wszystkie dzisiejsze identyfikatory `#wl-i-*`);
     d) `<meta name="color-scheme" content="dark">` zamiast `light dark`.

   KROK 2 — zmiany jednolinijkowe w `app.js` (dopiero one domykają projekt):
     1. `OrderOutcome`, `SystemHealth`, `PeriodState`, `SystemHealthComponentBadge`:
        dołóż modyfikator klasy do badge'a —
        accrued/ok → `wl-badge--ok` · pending/period-open → `wl-badge--info` ·
        inconsistent/degraded → `wl-badge--degraded` · down → `wl-badge--down` ·
        unknown → `wl-badge--unknown` · skipped → bez modyfikatora.
     2. Wszędzie, gdzie ikona jedzie z `i--16`, dopisz `-16` do nazwy symbolu
        (`check`→`check-16` itd.). Bez tego kreska renderuje się 1,33 px.
     3. `PeriodState`: `clock`→`period-open-16`, `check`→`period-closed-16`
        (dziś okres i zamówienie w toku mają ten sam rysunek — kolizja znaczeń).
     4. Kafle liczb okresu: `<p class="wl-meta">` etykiety → `class="wl-eyebrow"`
        (CSS ma zapasowy selektor, ale jawna klasa jest czytelniejsza).
     5. Płyta stanu systemu: `data-state="<status>"` na `.wl-tile` + struktura
        `.wl-health__*` (patrz `preview.html` §3 i §5).
     6. Znak marki: `.wl-plaque` z `<svg class="wl-plaque__mark"><use href="#wl-mark">`
        + `<span class="wl-plaque__word">`.
     7. Logowanie wariant A: dołóż `.wl-signin__aside` przed `.wl-signin__card`
        i klasę `wl-signin--split` na `<main>`.

   CZEGO NIE ROBIĆ:
     • nie dodawać `container-type` na `#app` — zabije `position:fixed` paska
       zakładek (dlatego powłoka została na `@media`, a treść jest kontenerowa);
     • nie renderować glifów modułowych (`nav-*`, `kebab`, `settings-rules`)
       poniżej 24 px;
     • nie malować ikony pomarańczem poza badge'em stanu i `:hover` wiersza.
   ========================================================================== */
