/* ============================================================
   Dashboard sprzedazy - MdP Serwis
   Kierunek wizualny: tabliczka znamionowa maszyny.
   Jasne tlo warsztatowe, krawedzie ciete (promien 3-4px),
   typografia w calosci techniczna - monospace na liczbach,
   etykietach i przyciskach, humanistyczny system-ui tylko
   w zdaniach do czytania.
   Kolory wyprowadzone z logo: zielen 2D6A2D i drewno 8B4513.
   Swiatlo zielone/zolte/czerwone ma trzy nosniki naraz:
   ksztalt (trojkat / romb / trojkat w dol / kolo), slowo
   i dopiero na koncu kolor - zeby dzialalo przy daltonizmie.
   ============================================================ */

:root {
  /* --- powierzchnie --- */
  --bg: #edeee9;          /* lakierowana obudowa maszyny */
  --bg-deep: #e3e5de;
  --card: #ffffff;
  --line: #d9dcd4;
  --line-strong: #bcc2b7;

  /* --- tekst --- */
  --ink: #171c18;
  --ink-soft: #39413a;
  --muted: #59625a;

  /* --- marka (z logo) --- */
  --brand: #2d6a2d;
  --timber: #8b4513;

  /* --- swiatla stanu --- */
  --green: #24702f;
  --yellow: #b9540a; /* pomaranczowy - stan "blisko progu" (dawniej zoltko-musztardowy) */
  --red: #a62a1f;
  --gray: #6a736b;
  --green-bg: #e8f1e7;
  --yellow-bg: #faeade;
  --red-bg: #f8e9e6;
  --gray-bg: #eaece7;

  /* --- dane na wykresach (neutralne, zeby nie mylily sie ze swiatlami) --- */
  --data: #3b564c;
  --data-soft: #a7bcb2;
  --data-line: #8b4513;
  --data-lost: #b4776e;
  /* linia sredniej na wykresach - niebieski, jedyny nie uzyty gdzie indziej odcien,
     zeby nie dalo sie jej pomylic z czerwonym progiem, brazowa linia wartosci ani
     zielonymi/czerwonawymi slupkami wygranych/przegranych (patrz Task UI-5, pkt 2) */
  --avg: #1f5fa6;

  /* --- typografia --- */
  --mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Consolas, "Liberation Mono", "DejaVu Sans Mono", monospace;
  --sans: system-ui, "Segoe UI", Roboto, Arial, sans-serif;

  /* --- rytm i ruch --- */
  --r: 4px;
  --pad: clamp(0.75rem, 3.2vw, 1.5rem);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ------------------------------------------------------------
   Podstawa
   ------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  max-width: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  /* delikatna siatka warsztatowa - widoczna dopiero z bliska */
  background-image:
    linear-gradient(var(--bg-deep) 1px, transparent 1px),
    linear-gradient(90deg, var(--bg-deep) 1px, transparent 1px);
  background-size: 48px 48px, 48px 48px;
}

.wrap {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding-inline: var(--pad);
}

img { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  background: var(--ink);
  color: #fff;
  padding: 0.6rem 1rem;
  font: 600 0.8rem/1 var(--mono);
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------
   Naglowek - plyta czolowa
   ------------------------------------------------------------ */
.topbar {
  background: var(--card);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 2px 0 var(--bg-deep);
}

/* Cienki pasek "zrodlo/dane" na samej gorze strony - jedna linia tekstu,
   zamiast dawnej "tabliczki znamionowej" ktora zajmowala ~70px wysokosci.
   #stan-danych zostaje tym samym elementem, do ktorego app.js wpisuje tresc. */
.topbar-strip {
  background: var(--bg-deep);
  border-bottom: 1px solid var(--line);
}
.topbar-strip-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.55rem;
  padding-block: 0.32rem;
  font: 500 0.68rem/1.3 var(--mono);
  color: var(--ink-soft);
  letter-spacing: 0.01em;
}
.strip-sep { color: var(--line-strong); }

.topbar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  padding-block: 0.85rem 1rem;
}

.topbar-logo {
  height: 26px;
  width: auto;
  max-width: 45vw;
  object-fit: contain;
  margin-right: auto;
  animation: plate-in 0.7s var(--ease) both;
}

.topbar-title {
  flex: 1 1 100%;
  order: 3;
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(1.05rem, 4.2vw, 1.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  animation: plate-in 0.7s 0.1s var(--ease) both;
}

.topbar-actions {
  display: flex;
  gap: 0.5rem;
  animation: plate-in 0.7s 0.05s var(--ease) both;
}

/* ------------------------------------------------------------
   Przyciski
   ------------------------------------------------------------ */
button {
  font: 600 0.7rem/1 var(--mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--ink);
  border-radius: var(--r);
  background: var(--ink);
  color: #fff;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s var(--ease);
}
button:hover { background: var(--brand); border-color: var(--brand); }
button:active { transform: translateY(1px); }
button[disabled] { opacity: 0.55; cursor: progress; }

button.ghost {
  background: transparent;
  color: var(--ink-soft);
  border-color: var(--line-strong);
}
button.ghost:hover { background: var(--bg-deep); color: var(--ink); border-color: var(--ink); }

.topbar-actions form { margin: 0; }

/* ------------------------------------------------------------
   Komunikat bledu
   ------------------------------------------------------------ */
.blad {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  margin: 1.25rem 0 0;
  padding: 0.8rem 1rem;
  border: 1px solid var(--red);
  border-left-width: 4px;
  border-radius: var(--r);
  background: var(--red-bg);
  color: var(--red);
  font: 500 0.85rem/1.45 var(--mono);
}
.blad::before { content: "!"; font-weight: 700; }
.blad[hidden] { display: none; }

/* ------------------------------------------------------------
   Pasma tresci
   ------------------------------------------------------------ */
.band { padding-block: clamp(1.75rem, 5vw, 2.75rem); }
.band-first { padding-top: clamp(1.25rem, 4vw, 2rem); }
.band + .band { border-top: 1px solid var(--line); }

.band-head { margin-bottom: 1.1rem; }

.band-title {
  margin: 0;
  font: 700 0.72rem/1.2 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand);
}
.band-note {
  margin: 0.4rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  max-width: 62ch;
}

/* ------------------------------------------------------------
   Suwaki - panel nastaw
   ------------------------------------------------------------ */
.controls {
  display: grid;
  gap: 1rem;
  padding: 1rem;
  margin-bottom: 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
}

.ctrl { display: grid; gap: 0.5rem; min-width: 0; }

.ctrl-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.controls label {
  font: 600 0.66rem/1.3 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.controls output {
  font: 700 1.05rem/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.ctrl-hint {
  margin: 0;
  font-size: 0.74rem;
  color: var(--muted);
}

.controls input[type="range"] {
  width: 100%;
  margin: 0;
  height: 22px;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.controls input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 2px;
  background: var(--bg-deep);
  border: 1px solid var(--line);
}
.controls input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 2px;
  background: var(--bg-deep);
  border: 1px solid var(--line);
}
.controls input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -7px;
  border-radius: 2px;
  background: var(--brand);
  border: 1px solid #1e4c1e;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55);
  transition: transform 0.15s var(--ease);
}
.controls input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 2px;
  background: var(--brand);
  border: 1px solid #1e4c1e;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55);
}
.controls input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.1); }

/* ------------------------------------------------------------
   Kafelki KPI
   ------------------------------------------------------------ */
.kpi-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: 1fr;
}

.kpi-tile {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-content: start;
  gap: 0.15rem 0.6rem;
  background: var(--card);
  /* pelna obwodka + gruba lewa belka w kolorze swiatla - znacznie widoczniejsze
     niz dawna cienka kreska u gory (i niz pierwsza wersja z belka 6px - wlasciciel
     poprosil o ok. piec razy grubsza, wiec 30px). Plakietka ze strzalka (kpi-dot)
     zostaje jako nosnik ksztaltu+slowa dla daltonizmu, kolor obwodki to trzeci,
     dodatkowy sygnal. box-sizing: border-box (patrz reset wyzej w pliku) sprawia,
     ze poszerzenie belki automatycznie zmniejsza obszar tresci, a nie wystaje poza
     kafelek - padding-left jest dodatkowo podbity, zeby tekst mial oddech od belki
     tez na 375px (patrz test mobile w raporcie weryfikacji). */
  border: 2px solid var(--line-strong);
  border-left-width: 30px;
  border-radius: var(--r);
  padding: 0.9rem 1rem 1rem 1.3rem;
  min-width: 0;
  overflow: hidden;
  transition: border-color 0.35s ease;
}

.kpi-tile h3 {
  grid-column: 1;
  grid-row: 1;
  margin: 0 0 0.35rem;
  font: 600 0.66rem/1.35 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.kpi-value {
  grid-column: 1 / -1;
  grid-row: 2;
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(2rem, 8.5vw, 2.7rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  transition: color 0.35s ease;
  overflow-wrap: anywhere;
}

.kpi-sub, .kpi-note {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--muted);
}
.kpi-sub { grid-row: 3; margin-top: 0.5rem; }
.kpi-note {
  grid-row: 4;
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  border-top: 1px dashed var(--line);
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-soft);
}

/* --- swiatlo: ksztalt + slowo + kolor --- */
.kpi-dot {
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.28rem 0.5rem;
  border: 1px solid currentColor;
  border-radius: 2px;
  font: 700 0.68rem/1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--gray);
  background: var(--gray-bg);
  transition: color 0.35s ease, background 0.35s ease;
}
.kpi-dot::before { font-size: 0.85em; line-height: 1; }
.kpi-dot::after { content: "brak danych"; }
.kpi-dot::before { content: "\25CF"; }

[data-light="green"] .kpi-dot { color: var(--green); background: var(--green-bg); }
[data-light="green"] .kpi-dot::before { content: "\25B2"; }
[data-light="green"] .kpi-dot::after { content: "na celu"; }
[data-light="green"] .kpi-value { color: var(--green); }
[data-light="green"].kpi-tile { border-color: var(--green); }

[data-light="yellow"] .kpi-dot { color: var(--yellow); background: var(--yellow-bg); }
[data-light="yellow"] .kpi-dot::before { content: "\25C6"; }
[data-light="yellow"] .kpi-dot::after { content: "blisko"; }
[data-light="yellow"] .kpi-value { color: var(--yellow); }
[data-light="yellow"].kpi-tile { border-color: var(--yellow); }

[data-light="red"] .kpi-dot { color: var(--red); background: var(--red-bg); }
[data-light="red"] .kpi-dot::before { content: "\25BC"; }
[data-light="red"] .kpi-dot::after { content: "poniżej"; }
[data-light="red"] .kpi-value { color: var(--red); }
[data-light="red"].kpi-tile { border-color: var(--red); }

[data-light="gray"] .kpi-dot { color: var(--gray); background: var(--gray-bg); }
[data-light="gray"] .kpi-dot::before { content: "\25CF"; }
[data-light="gray"] .kpi-dot::after { content: "brak danych"; }
[data-light="gray"] .kpi-value { color: var(--gray); }
[data-light="gray"].kpi-tile { border-color: var(--line-strong); }

/* ------------------------------------------------------------
   Blok prognozy - wyroznione podsumowanie NAD kafelkami KPI.
   Odpowiada na "ile spodziewac sie sprzedazy w najblizsze ~N dni" - liczba
   glowna jest wazona skutecznoscia etapu (funnel), wiec jest optymistyczna
   z natury: model liczy prawie pewna wygrana kazdej szansie stojacej wysoko
   w lejku, nawet jesli stoi tam od miesiecy bez ruchu. Dlatego ostrzezenie
   o udziale szans przeterminowanych jest tu CELOWO tak samo widoczne jak
   liczba glowna (ta sama skala fontu w wariancie mobilnym, wlasna ramka),
   a nie odnosnik drobnym drukiem - bez niego liczba wprowadza w blad.
   ------------------------------------------------------------ */
.forecast-block {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 6px solid var(--brand);
  border-radius: var(--r);
  padding: 1.1rem 1.15rem 1.25rem;
  margin-bottom: 1rem;
  min-width: 0;
}

.forecast-eyebrow {
  margin: 0;
  font: 700 0.68rem/1.3 var(--mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand);
}

.forecast-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem 1.5rem;
  margin-top: 0.5rem;
}

.forecast-figure {
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(2.1rem, 8.5vw, 3rem);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.forecast-figure-sub {
  margin: 0.3rem 0 0;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--muted);
  max-width: 60ch;
}

/* Zmiana m/m licza globalnym win rate (jedyny sposob odtworzenia szeregu
   wstecz - CRM zwraca tylko biezacy etap szansy, nie etap sprzed miesiecy),
   dlatego to inna metoda niz liczba glowna (wazona etapem) i musi to byc
   napisane wprost, zeby nikt nie porownywal ich 1:1. */
.forecast-delta {
  margin-left: auto;
  text-align: right;
  min-width: 0;
}
.forecast-delta-value {
  font: 700 1rem/1.2 var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.forecast-delta-value.lepiej { color: var(--green); }
.forecast-delta-value.gorzej { color: var(--red); }
.forecast-delta-note {
  margin: 0.2rem 0 0;
  font-size: 0.68rem;
  line-height: 1.4;
  color: var(--muted);
  max-width: 32ch;
}

/* Pasek proporcji swiezych/przeterminowanych szans w liczbie glownej -
   ten sam sygnal co tekst obok, ale jako ksztalt (drugi nosnik informacji,
   patrz komentarz o "trzech nosnikach" na gorze pliku). */
.forecast-gauge {
  display: flex;
  height: 10px;
  margin-top: 0.75rem;
  border-radius: 2px;
  overflow: hidden;
  background: var(--bg-deep);
  border: 1px solid var(--line-strong);
}
.forecast-gauge-fresh { background: var(--data); }
.forecast-gauge-stale { background: var(--yellow); }

.forecast-warning {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  margin-top: 0.85rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--yellow);
  border-left-width: 4px;
  border-radius: var(--r);
  background: var(--yellow-bg);
}
.forecast-warning-icon {
  flex: none;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--yellow);
}
.forecast-warning-body { min-width: 0; }
.forecast-warning-headline {
  margin: 0;
  font: 700 0.95rem/1.4 var(--mono);
  color: var(--yellow);
}
.forecast-warning p {
  margin: 0.3rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.forecast-warning a { color: var(--timber); }

.forecast-top { margin-top: 0.9rem; }
.forecast-top > summary {
  cursor: pointer;
  font: 600 0.74rem/1.3 var(--mono);
  letter-spacing: 0.04em;
  color: var(--brand);
  padding: 0.4rem 0;
  list-style: none;
}
.forecast-top > summary::-webkit-details-marker { display: none; }
.forecast-top > summary::before { content: "\25B8  "; }
.forecast-top[open] > summary::before { content: "\25BE  "; }
.forecast-top .table-wrap { margin-top: 0.5rem; }

/* znacznik przeterminowanej szansy w liscie top - ten sam diament co swiatlo
   "blisko" w kafelkach (kolor + ksztalt + slowo, nie sam kolor) */
.przeterminowana {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.08rem 0.35rem;
  color: var(--yellow);
  font: 700 0.6rem/1.3 var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px dotted var(--yellow);
  border-radius: 2px;
}
.przeterminowana::before { content: "\25C6 "; }

/* ------------------------------------------------------------
   Tabela KPI miesiac po miesiac (ostatnie 12 miesiecy) - komorki
   pokolorowane ta sama funkcja co kafelki (KPI.light), zeby progi
   nigdy sie nie rozjechaly. Kolor NIE jest jedynym nosnikiem: kazda
   komorka ma tez ikone (trojkat/romb/trojkat w dol/kolo) i wlasne tlo,
   dokladnie jak plakietka kpi-dot w kafelkach powyzej.
   ------------------------------------------------------------ */
.kpi-history-wrap { margin-bottom: 1rem; }
.cell-light {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: 0.15rem 0.4rem;
  border-radius: 2px;
  font-variant-numeric: tabular-nums;
}
.cell-light::before { font-size: 0.8em; }
.cell-light[data-light="green"] { color: var(--green); background: var(--green-bg); }
.cell-light[data-light="green"]::before { content: "\25B2"; }
.cell-light[data-light="yellow"] { color: var(--yellow); background: var(--yellow-bg); }
.cell-light[data-light="yellow"]::before { content: "\25C6"; }
.cell-light[data-light="red"] { color: var(--red); background: var(--red-bg); }
.cell-light[data-light="red"]::before { content: "\25BC"; }
.cell-light[data-light="gray"] { color: var(--gray); background: var(--gray-bg); }
.cell-light[data-light="gray"]::before { content: "\25CF"; }

/* miesiac niepelny - kreskowane tlo komorki miesiaca + slowny dopisek,
   ta sama logika co kreskowanie na wykresach (patrz .bar-partial) */
.miesiac-niepelny {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.05rem 0.3rem;
  color: var(--muted);
  font: 700 0.58rem/1.3 var(--mono);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  border: 1px dashed var(--line-strong);
  border-radius: 2px;
}
td.row-partial-cell { border-left: 3px solid var(--line-strong); }

/* ------------------------------------------------------------
   Karty (wykresy i tabele)
   ------------------------------------------------------------ */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1rem;
  margin: 0;
  min-width: 0;
}

.card h2, .card figcaption {
  margin: 0 0 0.15rem;
  font: 700 0.85rem/1.35 var(--mono);
  letter-spacing: -0.01em;
  color: var(--ink);
}

.charts, .tables {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: 1fr;
}

/* legenda pod tytulem wykresu - opisuje co jest czym, bez zgadywania */
.chart-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.9rem;
  margin: 0 0 0.6rem;
  font-size: 0.72rem;
  color: var(--muted);
}
.sw {
  display: inline-block;
  width: 14px;
  height: 10px;
  margin-right: 0.35rem;
  vertical-align: -1px;
  border-radius: 1px;
}
.sw-bar { background: var(--data); }
.sw-soft-bar { background: var(--data-soft); }
.sw-win { background: var(--green); }
.sw-lost { background: var(--data-lost); }
.sw-line { height: 0; border-top: 3px solid var(--data-line); }
.sw-soft { height: 0; border-top: 3px dashed var(--gray); }
.sw-thr { height: 0; border-top: 3px dashed var(--red); }
.sw-avg { height: 0; border-top: 3px dotted var(--avg); }

/* ------------------------------------------------------------
   Wykresy SVG
   ------------------------------------------------------------ */
/* Wykres ma sztywny viewBox 800x260 z marginesem 52 jednostek na podpisy osi.
   Dlugie podpisy kwotowe ("15,24 mln €") sie w nim nie miescily i byly ucinane
   na krawedzi SVG. Rozwiazanie: SVG dostaje 88% szerokosci i 6% marginesu z kazdej
   strony, a wylewajacy sie tekst jest widoczny (overflow: visible) i przyciety
   dopiero na granicy .chart - dzieki procentom zapas skaluje sie razem z wykresem,
   wiec dziala tak samo na telefonie i na monitorze. */
.chart { overflow: hidden; }
.chart-svg {
  width: 86%;
  margin-inline: 7%;
  height: auto;
  display: block;
  overflow: visible;
}

.grid { stroke: var(--line); stroke-width: 1; }
.tick { font-family: var(--mono); font-size: 13px; fill: var(--muted); }
.tick-l { text-anchor: end; }
.tick-r { text-anchor: start; }
.tick-x { text-anchor: middle; font-size: 16px; fill: var(--ink-soft); }
.tick-thr { fill: var(--red); font-size: 13px; font-weight: 700; }
.tick-avg { fill: var(--avg); font-size: 13px; font-weight: 700; }
/* Plytka pod etykietami progu/sredniej (tick-thr/tick-avg) - rozmiar i pozycja
   liczone w JS z realnego getBBox() tekstu (patrz charts.js/lineLabel), tu tylko
   kolor: tlo karty wykresu, zeby napis nigdy nie zlewal sie ze slupkami/liniami
   danych pod spodem (patrz Task UI-6 w raporcie, pkt 3). */
.label-bg { fill: var(--card); }

.bar { fill: var(--data); }
.bar-soft { fill: var(--data-soft); }
.bar-win { fill: var(--green); }
.bar-lost { fill: var(--data-lost); }
.line { stroke: var(--data-line); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.line-soft { stroke: var(--gray); stroke-width: 1.5; stroke-dasharray: 4 3; }
.threshold { stroke: var(--red); stroke-width: 1.5; stroke-dasharray: 5 4; }
/* linia sredniej z wyswietlanego zakresu (bez niepelnego okresu) - niebieska,
   kropkowana, wyraznie inna od czerwonego, kreskowanego progu celu powyzej,
   zeby obu linii nie dalo sie pomylic (patrz komentarz przy --avg). */
.avg-line { stroke: var(--avg); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1 4; }

.chart-svg .bar { transition: fill 0.15s ease; }
.chart-svg .bar:hover:not(.bar-partial) { fill: var(--brand); }

/* Oznaczenie niepelnego, biezacego miesiaca/kwartalu - slupek kreskowany
   (wzor #chart-hatch-pattern wstrzykiwany przez charts.js/ensureHatchDefs)
   zamiast pelnego wypelnienia, a linia dochodzaca do niego przerywana.
   Reguly ponizej musza byc zadeklarowane PO regulach .bar*/.line*, zeby przy
   tej samej specyficznosci (jedna klasa) wygraly kolejnoscia w arkuszu.
   Rozroznienie wzorem/kreskowaniem (nie samym odcieniem) dziala tez przy
   daltonizmie - patrz komentarz o "trzech nosnikach" na gorze pliku. */
.hatch-bg { fill: var(--bg-deep); }
.hatch-line { stroke: var(--muted); }
.bar-partial { fill: url(#chart-hatch-pattern); stroke: var(--ink-soft); stroke-width: 1; }
.line-partial { stroke-dasharray: 4 3; }

/* przelacznik zakresu - segmentowany, jak przelacznik na pulpicie */
.chart-range {
  display: inline-flex;
  gap: 0;
  margin-bottom: 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  overflow: hidden;
}
.chart-range button {
  padding: 0.35rem 0.6rem;
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  border: 0;
  border-radius: 0;
  background: var(--card);
  color: var(--muted);
}
.chart-range button + button { border-left: 1px solid var(--line-strong); }
.chart-range button:hover { background: var(--bg-deep); color: var(--ink); }
.chart-range button.active { background: var(--ink); color: #fff; }

.chart-note {
  margin: 0.6rem 0 0;
  padding-left: 0.6rem;
  border-left: 2px solid var(--timber);
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--muted);
}
/* Odczyt po dotknieciu slupka. Na telefonie to glowny sposob na dokladna
   liczbe - podpisy osi sa tam z koniecznosci male, wiec ten wiersz jest duzy. */
.chart-readout {
  margin: 0.6rem 0 0;
  min-height: 2.6em;
  display: flex;
  align-items: center;
  padding: 0.4rem 0.6rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand);
  border-radius: 2px;
  font: 600 0.82rem/1.35 var(--mono);
  color: var(--ink);
}
.chart-readout:empty::before {
  content: "Dotknij słupka, żeby zobaczyć dokładną wartość.";
  font-weight: 400;
  color: var(--muted);
}

/* ------------------------------------------------------------
   Tabele
   ------------------------------------------------------------ */
.table-wrap {
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.82rem;
}

th, td {
  padding: 0.5rem 0.7rem;
  text-align: right;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
th:first-child, td:first-child {
  text-align: left;
  position: sticky;
  left: 0;
  background: var(--card);
  z-index: 1;
}
tbody tr:hover td { background: var(--bg); }
tbody tr:hover td:first-child { background: var(--bg); }

th {
  cursor: pointer;
  user-select: none;
  position: sticky;
  top: 0;
  font: 600 0.64rem/1.35 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 2px solid var(--line-strong);
  background: var(--card);
  white-space: normal;
  vertical-align: bottom;
}
th:hover { color: var(--ink); }
th[data-sort="desc"]::after { content: " \2193"; color: var(--brand); }
th[data-sort="asc"]::after  { content: " \2191"; color: var(--brand); }

td.num, th.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* kierunek zmiany ma strzalke, nie tylko kolor */
.lepiej { color: var(--green); font-weight: 600; }
.gorzej { color: var(--red); font-weight: 600; }
.lepiej::after { content: " \25B2"; font-size: 0.75em; }
.gorzej::after { content: " \25BC"; font-size: 0.75em; }

/* Etykieta widoczna od razu (nie tylko przez title/hover) - na telefonie,
   glownym urzadzeniu odbiorcy, nie ma najechania kursorem. */
.mala-proba {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.08rem 0.35rem;
  color: var(--timber);
  cursor: help;
  font: 700 0.62rem/1.3 var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px dotted var(--timber);
  border-radius: 2px;
}

td a {
  color: var(--brand);
  text-decoration-color: var(--data-soft);
  text-underline-offset: 2px;
}
td a:hover { color: var(--timber); }

.uwaga {
  margin: 0 0 0.75rem;
  padding-left: 0.6rem;
  border-left: 2px solid var(--timber);
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--muted);
}
.table-wrap .uwaga {
  margin: 0;
  padding: 1rem 0;
  border: 0;
  text-align: center;
  font-family: var(--mono);
}

/* ------------------------------------------------------------
   Stopka
   ------------------------------------------------------------ */
.stopka {
  margin-top: 1rem;
  padding-block: 1.5rem 2.5rem;
  border-top: 1px solid var(--line);
  background: var(--card);
  font-size: 0.74rem;
  line-height: 1.6;
  color: var(--muted);
}
.stopka p { margin: 0; max-width: 70ch; }

/* ------------------------------------------------------------
   Logowanie
   ------------------------------------------------------------ */
.login-body {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--pad);
}
.login-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand);
  border-radius: var(--r);
  padding: 2rem 1.75rem;
  width: min(380px, 100%);
  box-shadow: 0 2px 0 var(--bg-deep);
}
.login-logo { height: 38px; margin-bottom: 1.25rem; }
.login-card h1 {
  margin: 0 0 1.5rem;
  font: 700 1.05rem/1.3 var(--mono);
  letter-spacing: -0.02em;
}
.login-card form { display: grid; gap: 0.3rem; }
.login-card label {
  font: 600 0.66rem/1.4 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.6rem;
}
.login-card input {
  font: 400 0.95rem/1.4 var(--mono);
  padding: 0.65rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--bg);
  color: var(--ink);
}
.login-card input:focus { background: var(--card); }
.login-card button { margin-top: 1.1rem; padding-block: 0.7rem; }
.login-error {
  display: flex;
  gap: 0.5rem;
  margin: 1rem 0 0;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--red);
  border-left-width: 4px;
  border-radius: var(--r);
  background: var(--red-bg);
  color: var(--red);
  font: 500 0.78rem/1.45 var(--mono);
}
.login-error::before { content: "!"; font-weight: 700; }
.login-error[hidden] { display: none; }

/* ------------------------------------------------------------
   Animacje
   ------------------------------------------------------------ */
@keyframes plate-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes rule-in {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes grow-bar {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}
@keyframes draw-line {
  to { stroke-dashoffset: 0; }
}

/* wejscie w kadr */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* schodkowanie - sasiedzi wchodza z lekkim opoznieniem */
.kpi-grid .reveal:nth-child(2)  { transition-delay: 0.06s; }
.kpi-grid .reveal:nth-child(3)  { transition-delay: 0.12s; }
.kpi-grid .reveal:nth-child(4)  { transition-delay: 0.18s; }
.charts .reveal:nth-of-type(2n) { transition-delay: 0.08s; }
.tables .reveal:nth-of-type(2n) { transition-delay: 0.08s; }

/* rysowanie wykresu po wejsciu w kadr */
.is-visible .bar {
  animation: grow-bar 0.62s var(--ease) backwards;
}
.is-visible .line,
.is-visible .threshold,
.is-visible .avg-line {
  animation: draw-line 1.15s 0.12s ease-out forwards;
}

/* ------------------------------------------------------------
   Uklad na wiekszych ekranach
   ------------------------------------------------------------ */
/* Na telefonie karty z wykresami ida od krawedzi do krawedzi -
   SVG dostaje o kilkanascie procent wiecej szerokosci, wiec podpisy
   osi robia sie czytelne. Ujemny margines rowna sie paddingowi .wrap,
   wiec strona nadal nie przewija sie w poziomie. */
@media (max-width: 639px) {
  .charts .card {
    margin-inline: calc(var(--pad) * -1);
    padding-inline: 0.7rem;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
  /* Wykres jest wtedy wezszy w pikselach, wiec podpisy osi musza byc wieksze
     w jednostkach viewBox, zeby na ekranie wyszly na to samo. */
  .tick { font-size: 16px; }
  .tick-x { font-size: 22px; }
  .tick-thr { font-size: 16px; }
  .tick-avg { font-size: 16px; }
  /* Na waskim ekranie zmiana m/m nie miesci sie obok liczby glownej -
     schodzi pod spod, wyrownana do lewej jak reszta bloku. */
  .forecast-delta { margin-left: 0; text-align: left; }
}

@media (min-width: 640px) {
  .controls { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; padding: 1.15rem 1.25rem; }
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
  .charts, .tables { gap: 1rem; }
  button { font-size: 0.72rem; padding: 0.55rem 0.8rem; }
}

@media (min-width: 900px) {
  .topbar-inner {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    padding-block: 1.25rem;
  }
  .topbar-logo { grid-column: 1; grid-row: 1; height: 34px; margin-right: 0; }
  .topbar-title { grid-column: 2; grid-row: 1; order: 0; flex: none; margin: 0 0 0 1.5rem; }
  .topbar-actions { grid-column: 3; grid-row: 1; }

  .charts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tables { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* szerokie tabele dostaja caly wiersz - inaczej kolumny sie nie mieszcza */
  #tb-sources, #tb-stale, #tb-owners, #tb-stages { grid-column: 1 / -1; }
}

@media (min-width: 1180px) {
  .kpi-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ------------------------------------------------------------
   Ograniczony ruch - wszystko widoczne od razu
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; transition: none; }
  .topbar-logo, .topbar-actions, .topbar-title { animation: none; opacity: 1; transform: none; }
  .is-visible .bar, .is-visible .line, .is-visible .threshold, .is-visible .avg-line { animation: none; }
  /* JS ustawia stroke-dashoffset inline pod animacje rysowania - tu trzeba je zdjac */
  .line, .threshold { stroke-dashoffset: 0 !important; }
}
