/* =====================================================================
   CRM BŁAMO - arkusz stylow

   Paleta wychodzi ze znaku firmowego: grafit liternictwa #15171b niesie
   tresc, blekit z okregu #0091d2 jest jedynym akcentem interfejsu,
   limonka #b2d235 oznacza to, co zrobione, a czerwien #e1121f zostaje
   przy bledach. Tla sa chlodna biela, zeby kolory znaku mialy gdzie
   wybrzmiec.

   Sidebar jest grafitowy, bo na ciemnym tle okrag ze znaku swieci
   wszystkimi trzema kolorami naraz. Na blekitnym tle by zniknal.

   Odstepstwa od znaku, swiadome i policzalne:
   - jasniejsze odcienie grafitu (#22262d, #2e333c) na stan hover i pozycje
     aktywna w sidebarze - znak takich stanow nie zna,
   - kolor ostrzezenia (#8a5a12 na #faf2e0) - znak zna tylko "tak" i "nie",
     a panel potrzebuje trzeciego stopnia,
   - granat dla poczty w kolejce (#2a5d9f) - musi odrozniac sie od blekitu
     akcentu, inaczej wiadomosc wyslana zlewa sie z przyciskiem.

   Bez zewnetrznych zasobow: fonty leza w /assets/fonts, zadnego CDN.
   ===================================================================== */

/* ---------- Inter - tresc (plik zmienny, cala os wag) --------------- */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-var-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: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-var-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;
}

/* ---------- League Spartan - naglowki (plik zmienny) ---------------- */
@font-face {
  font-family: 'League Spartan';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/spartan-var-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: 'League Spartan';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/spartan-var-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;
}

:root {
  /* paleta podstawowa */
  --grafit: #15171b;
  --grafit-2: #22262d;
  --grafit-3: #2e333c;
  --blekit: #0091d2;
  --blekit-deep: #0072a8;
  --blekit-light: #4fb8e8;
  --mgla: #d2d8df;
  --papier: #eef2f6;

  /* powierzchnie */
  --bg: #f5f7f9;
  --card: #fff;
  --line: #dee3e9;
  --line-2: #e9edf2;

  /* tekst */
  --ink: #15171b;
  --ink-2: #2b2f36;
  --muted: #5d636e;

  /* stany */
  --ok: #3f7d1e;
  --ok-akcent: #7fb02a;
  --ok-bg: #eef5e3;
  --warn: #8a5a12;
  --warn-akcent: #0091d2;
  --warn-bg: #faf2e0;
  --err: #b3423c;
  --err-akcent: #c9564f;
  --err-bg: #f9eae9;
  /* Niebieski wychodzi poza palete witryny swiadomie. Wiadomosc
     czekajaca w kolejce musi odrozniac sie od odebranej, a cala reszta
     palety jest ciepla i zlewalaby sie z ostrzezeniem. */
  --kolejka: #2a5d9f;
  --kolejka-bg: #e8eff8;

  /* geometria - za witryna: 4 px pola i przyciski, 8 px karty */
  --r: 4px;
  --r-lg: 8px;
  --shadow: 0 1px 2px rgba(21, 23, 27, .05), 0 2px 8px rgba(21, 23, 27, .04);
  --shadow-lg: 0 18px 44px rgba(21, 23, 27, .13);

  /* typografia - League Spartan niesie naglowki, Inter cala reszte */
  --sans: 'League Spartan', system-ui, -apple-system, "Segoe UI", sans-serif;
  --text: 'Inter', system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  font: 15px/1.6 var(--text);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blekit-deep); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { margin: 0; font-family: var(--sans); font-weight: 700; letter-spacing: -.01em; }
h1 { font-size: 25px; }
h2 { font-size: 16px; }

code {
  font: 13px/1.4 ui-monospace, "SFMono-Regular", Consolas, monospace;
  background: var(--line-2); padding: 2px 6px; border-radius: 4px;
}

.muted { color: var(--muted); }
.small { font-size: 13px; }
.hide-sm { display: inline; }
.inline { display: inline; }

/* --- ikony --------------------------------------------------------- */
.ico { width: 20px; height: 20px; flex: 0 0 auto; }
.ico.sm { width: 16px; height: 16px; }
.ico.lg { width: 40px; height: 40px; }

/* --- banery globalne ---------------------------------------------- */
.banner-http, .banner-imp {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 18px; font-size: 13.5px; font-weight: 500;
}
.banner-http { background: var(--warn-bg); color: var(--warn); border-bottom: 1px solid #bde2f5; }
.banner-imp  { background: var(--grafit); color: #d2d8df; }
.banner-imp strong { color: #fff; }

.link-btn {
  background: none; border: 0; padding: 0; margin-left: 6px;
  font: inherit; color: inherit; text-decoration: underline; cursor: pointer;
}

/* =====================================================================
   Ekran logowania
   ===================================================================== */
.login-body {
  min-height: 100vh;
  display: grid; place-items: center;
  /* Sam gradient marki: grafit przechodzi w blekit.
     Gdyby kiedys mialo tu byc zdjecie, dorzuca sie je jako warstwe posrodku:
       url("/assets/img/login-bg.jpg") center / cover no-repeat,
     ale dopiero razem z wgraniem pliku. Odwolanie do pliku, ktorego nie ma,
     wchodzilo do front controllera i psulo przekierowanie po zalogowaniu. */
  background:
    linear-gradient(180deg, rgba(21, 23, 27, .2), rgba(21, 23, 27, .5)),
    linear-gradient(135deg, #15171b 0%, 1b2a33 45%, #0091d2 100%);
  padding: 24px;
}

.login-wrap { width: 100%; max-width: 430px; }

.login-card {
  background: #fcfdfe;
  border-radius: 8px;
  padding: 38px 34px 26px;
  box-shadow: 0 24px 60px rgba(21, 23, 27, .35);
  text-align: center;
}

.login-logo { width: 210px; max-width: 80%; height: auto; margin: 0 auto 22px; display: block; }
.login-h1 { font-size: 20px; margin-bottom: 6px; }
.login-sub { color: var(--ink-2); font-size: 14px; margin: 0 0 18px; }

.login-card form { text-align: left; }

.field {
  display: flex; align-items: center; gap: 10px;
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--r); padding: 0 12px;
  margin-bottom: 12px; color: var(--muted);
  transition: border-color .15s, box-shadow .15s;
}
.field:focus-within { border-color: var(--blekit); box-shadow: 0 0 0 3px rgba(0, 145, 210, .18); }
.field input {
  flex: 1; border: 0; outline: 0; background: none;
  padding: 13px 0; font: inherit; color: var(--ink); min-width: 0;
}
.peek { background: none; border: 0; cursor: pointer; color: var(--muted); padding: 4px; display: flex; }
.peek:hover { color: var(--ink-2); }

.login-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 4px 0 18px; font-size: 13.5px;
}
.check { display: flex; align-items: center; gap: 7px; color: var(--ink-2); cursor: pointer; }
.check input { accent-color: var(--blekit-deep); width: 15px; height: 15px; }

.btn-primary {
  display: block; width: 100%; border: 0; cursor: pointer;
  background: var(--blekit-deep); color: #ffffff;
  font: 700 15px/1 var(--text); padding: 14px;
  border-radius: var(--r); transition: background .15s, transform .05s;
}
.btn-primary:hover { background: #005c88; }
.btn-primary:active { transform: translateY(1px); }

.login-err, .login-warn {
  text-align: left; font-size: 13.5px; border-radius: 4px;
  padding: 10px 12px; margin: 0 0 16px;
}
.login-err { background: var(--err-bg); color: var(--err); border: 1px solid #f0d3d1; }
.login-warn {
  background: var(--warn-bg); color: var(--warn); border: 1px solid #bde2f5;
  display: flex; gap: 8px; align-items: flex-start; line-height: 1.45;
}
.login-warn .ico { margin-top: 2px; }

.pass-rules {
  margin: 0 0 16px; padding-left: 18px;
  color: var(--muted); font-size: 13px; line-height: 1.7;
}

.login-hint { font-size: 13px; color: var(--muted); margin: 16px 0 0; }
.login-foot { font-size: 12px; color: #8b8f97; margin: 18px 0 0; }

/* =====================================================================
   Szkielet panelu
   ===================================================================== */
.shell { display: flex; min-height: 100vh; }

/* --- sidebar ------------------------------------------------------- */
.side {
  width: 244px; flex: 0 0 244px;
  background: var(--grafit); color: #d7d3ca;
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}

.side-brand { padding: 22px 20px 18px; display: block; }
.side-brand img { width: 100%; max-width: 178px; height: auto; display: block; }

.side-nav { flex: 1; overflow-y: auto; padding: 4px 10px 16px; }
.side-nav::-webkit-scrollbar { width: 6px; }
.side-nav::-webkit-scrollbar-thumb { background: #3c414a; border-radius: 3px; }

.side-link {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; margin-bottom: 2px;
  border-radius: 4px; color: #d2d8df;
  font-size: 14.2px; text-decoration: none;
  transition: background .13s, color .13s;
}
.side-link:hover { background: var(--grafit-2); color: #fff; text-decoration: none; }
/* Pozycja aktywna bierze ciemniejszy blekit. Na grafitowym tle odcien tla
   (#2e333c) byl ledwie widoczny, a to jedyny wskaznik tego, gdzie sie
   jest. Biel na #0072a8 daje 5,3:1, wiec napis zostaje czytelny - samo
   #0091d2 zatrzymywalo sie na 3,5:1 i bylo za jasne pod biel. */
.side-link.is-active { background: var(--blekit-deep); color: #fff; font-weight: 500; }
.side-link.is-active .ico { color: #fff; }
.side-link.is-active:hover { background: #005c88; }

.side-user {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-top: 1px solid #2e333c;
}
.side-user-txt { display: flex; flex-direction: column; min-width: 0; }
.side-user-txt strong { font-size: 13.5px; color: #fff; font-weight: 600; }
.side-user-txt small { font-size: 12px; color: #4fb8e8; }

.avatar {
  width: 36px; height: 36px; flex: 0 0 36px;
  border-radius: 50%; background: var(--blekit-deep); color: #ffffff;
  display: grid; place-items: center;
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
}
.avatar.sm { width: 30px; height: 30px; flex-basis: 30px; font-size: 11.5px; }

/* --- glowna kolumna ----------------------------------------------- */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.top {
  display: flex; align-items: center; gap: 14px;
  background: #fff; border-bottom: 1px solid var(--line);
  padding: 12px 24px; position: sticky; top: 0; z-index: 20;
}

.top-search {
  flex: 1; max-width: 460px;
  display: flex; align-items: center; gap: 9px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 4px; padding: 0 12px; color: var(--muted);
}
.top-search:focus-within { border-color: var(--blekit); background: #fff; }
.top-search input {
  flex: 1; border: 0; outline: 0; background: none;
  padding: 9px 0; font: inherit; color: var(--ink); min-width: 0;
}

.top-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }

.top-icon { position: relative; color: var(--ink-2); display: flex; padding: 6px; border-radius: 4px; }
.top-icon:hover { background: var(--bg); }
.dot {
  position: absolute; top: 0; right: 0;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 4px; background: var(--err); color: #fff;
  font-size: 10.5px; font-weight: 700;
  display: grid; place-items: center;
}

.top-user { display: flex; align-items: center; gap: 9px; }
.top-user-txt { display: flex; flex-direction: column; line-height: 1.3; }
.top-user-txt strong { font-size: 13.5px; font-weight: 600; }
.top-user-txt small { font-size: 11.5px; color: var(--muted); }

.btn-ghost {
  display: flex; align-items: center; gap: 7px;
  background: none; border: 1px solid var(--line);
  border-radius: 4px; padding: 7px 12px;
  font: 500 13.5px var(--text); color: var(--ink-2); cursor: pointer;
}
.btn-ghost:hover { background: var(--bg); color: var(--ink); }

.burger { display: none; background: none; border: 0; cursor: pointer; padding: 6px; }
.burger span { display: block; width: 20px; height: 2px; background: var(--ink-2); margin: 4px 0; border-radius: 2px; }

.page { flex: 1; padding: 24px; max-width: 1440px; width: 100%; }
.foot { padding: 18px 24px; color: var(--muted); font-size: 12.5px; }

/* --- naglowek strony ---------------------------------------------- */
.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; margin-bottom: 20px;
}
.page-head p { margin: 3px 0 0; font-size: 14px; }
.badge {
  display: inline-block; padding: 5px 12px; border-radius: 999px;
  background: var(--grafit); color: #d2d8df;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
}

/* --- komunikaty --------------------------------------------------- */
.alert { padding: 11px 14px; border-radius: 4px; font-size: 14px; margin-bottom: 18px; }
.alert-ok  { background: var(--ok-bg);  color: var(--ok);  border: 1px solid #cfe5d8; }
.alert-err { background: var(--err-bg); color: var(--err); border: 1px solid #f0d3d1; }

/* --- kategorie ---------------------------------------------------- */
.cat-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden; margin-bottom: 20px;
  box-shadow: var(--shadow);
}
.cat {
  display: flex; align-items: center; gap: 12px;
  padding: 18px 20px; color: var(--ink);
  border-right: 1px solid var(--line-2);
  transition: background .13s;
}
.cat:last-child { border-right: 0; }
.cat:hover { background: #fafbfc; text-decoration: none; }
.cat .ico { color: var(--ink-2); }
.cat-txt { display: flex; flex-direction: column; }
.cat-txt strong { font-size: 14.5px; font-weight: 600; }
.cat-txt small { font-size: 12.5px; color: var(--muted); }

/* --- kafle statystyk ---------------------------------------------- */
.tiles {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 16px; margin-bottom: 20px;
}
.tile {
  display: flex; align-items: center; gap: 14px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 18px;
  box-shadow: var(--shadow);
}
.tile-ico {
  width: 44px; height: 44px; flex: 0 0 44px;
  border-radius: 50%; background: #eef2f6; color: var(--blekit-deep);
  display: grid; place-items: center;
}
.tile-txt { display: flex; flex-direction: column; min-width: 0; }
.tile-txt small { font-size: 12.5px; color: var(--muted); }
.tile-txt strong { font-size: 27px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; }
.tile-txt em { font-style: normal; font-size: 12px; }
.tile-txt em.neutral { color: var(--muted); }
.tile-txt em.warn { color: var(--warn); font-weight: 600; }
.tile.is-warn { border-color: #bde2f5; background: var(--warn-bg); }
.tile.is-warn .tile-ico { background: #e3f2fb; color: var(--warn); }

/* --- karty -------------------------------------------------------- */
.grid-2 { display: grid; grid-template-columns: 1.35fr 1fr; gap: 16px; }

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow); overflow: hidden;
}
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--line-2);
}
.card-head a { font-size: 13px; }

.empty { padding: 26px 18px; color: var(--muted); font-size: 14px; text-align: center; margin: 0; }

/* --- lista aktywnosci --------------------------------------------- */
.feed { list-style: none; margin: 0; padding: 0; }
.feed li {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 18px; border-bottom: 1px solid var(--line-2);
}
.feed li:last-child { border-bottom: 0; }
.feed-txt { flex: 1; font-size: 13.8px; color: var(--ink-2); min-width: 0; }
.feed-txt strong { color: var(--ink); font-weight: 600; }
.feed time { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* --- szybkie akcje ------------------------------------------------ */
.quick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 16px 18px; }
.quick-btn {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 13px; border: 1px solid var(--line);
  border-radius: 4px; background: #fafbfc;
  font-size: 13.5px; font-weight: 500; color: var(--ink);
}
.quick-btn:hover { border-color: var(--blekit); background: #eef2f6; text-decoration: none; }
.quick-btn .ico { color: var(--blekit-deep); }

.stage-note {
  margin: 0 18px 18px; padding: 13px 15px;
  background: #eef2f6; border: 1px solid var(--line);
  border-left: 3px solid var(--blekit);
  border-radius: 4px; font-size: 13.3px; color: var(--ink-2); line-height: 1.55;
}
.stage-note strong { color: var(--ink); }

/* --- ekrany stanu (404, 403, moduly w budowie) -------------------- */
.state-box {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
  padding: 46px 32px; text-align: center; max-width: 620px; margin: 10px auto;
}
.state-box .ico.lg { color: var(--blekit); margin-bottom: 14px; }
.state-box h1, .state-box h2 { font-size: 19px; margin-bottom: 8px; }
.state-box p { margin: 0 auto 10px; max-width: 460px; font-size: 14px; }
.state-box .btn-primary { max-width: 220px; margin: 18px auto 0; }

/* =====================================================================
   Responsywnosc
   ===================================================================== */
@media (max-width: 1100px) {
  .grid-2 { grid-template-columns: 1fr; }
  .tiles { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 780px) {
  .side {
    position: fixed; z-index: 60; left: 0; top: 0;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: var(--shadow-lg);
  }
  .side.is-open { transform: none; }
  .burger { display: block; }
  .page { padding: 16px; }
  .top { padding: 10px 14px; }
  .tiles, .cat-row { grid-template-columns: 1fr; }
  .cat { border-right: 0; border-bottom: 1px solid var(--line-2); }
  .cat:last-child { border-bottom: 0; }
  .quick { grid-template-columns: 1fr; }
  .top-user-txt, .hide-sm { display: none; }
  h1 { font-size: 21px; }
}

/* =====================================================================
   Komponenty modułów (etapy 2-6)
   ===================================================================== */

.mb { margin-bottom: 18px; }
.mt { margin-top: 18px; }
.pad { padding: 16px 18px; }
.bt { border-top: 1px solid var(--line-2); }
.ta-r { text-align: right; }
.nowrap { white-space: nowrap; }
.block { display: block; }
.strong { font-weight: 600; }
.txt-warn { color: var(--warn); font-weight: 600; }
.txt-ok { color: var(--ok); font-weight: 600; }
.req { color: var(--err); font-weight: 600; }
.spacer { flex: 1; }
.stack { display: flex; flex-direction: column; gap: 16px; }
.crumbs { margin: 0 0 6px; font-size: 13px; }
.crumbs a { color: var(--muted); }
.inline-form { display: inline-block; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; }
.prose p { margin: 0 0 10px; }
.prose p:last-child { margin-bottom: 0; }

.page-head-side { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.btn-inline { display: inline-flex; align-items: center; gap: 7px; width: auto; }

.btn-dark {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--grafit); color: #fff; border: 0; cursor: pointer;
  font: 700 14px var(--text); padding: 10px 18px; border-radius: 4px;
}
.btn-dark:hover { background: var(--grafit-2); }

.btn-danger {
  background: #fff; color: var(--err); border: 1px solid #eecdca; cursor: pointer;
  font: 700 13.5px var(--text); padding: 9px 16px; border-radius: 4px;
}
.btn-danger:hover { background: var(--err-bg); }

.btn-mini {
  display: inline-block; padding: 5px 10px; border-radius: 4px;
  border: 1px solid var(--line); background: #fff; cursor: pointer;
  font: 500 12.5px var(--text); color: var(--ink-2); text-decoration: none;
}
.btn-mini:hover { border-color: var(--blekit); color: var(--ink); text-decoration: none; }

.alert-warn { background: var(--warn-bg); color: var(--warn); border: 1px solid #bde2f5; }
.alert-info { background: #eef2f6; color: #0072a8; border: 1px solid #eadfc2; }

/* --- znaczniki ----------------------------------------------------- */
.chip {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap; line-height: 1.5;
}
.chip-ok    { background: var(--ok-bg);   color: var(--ok); }
.chip-warn  { background: var(--warn-bg); color: var(--warn); }
.chip-err   { background: var(--err-bg);  color: var(--err); }
.chip-info  { background: #eef2f6;        color: #0072a8; }
.chip-muted { background: var(--line-2);  color: var(--muted); }
.chip-blue  { background: var(--kolejka-bg); color: var(--kolejka); }

.file-kind {
  display: inline-block; min-width: 34px; text-align: center;
  background: var(--grafit); color: #fff; border-radius: 4px;
  font-size: 10px; font-weight: 700; padding: 2px 5px; margin-right: 6px;
}

/* --- filtry -------------------------------------------------------- */
.filters {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
  padding: 16px 18px; margin-bottom: 18px;
}
.filter-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px;
}
.filter-actions { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }

/* --- pola formularzy ----------------------------------------------- */
.fld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.fld > span { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.fld input[type="text"], .fld input[type="email"], .fld input[type="password"],
.fld input[type="search"], .fld input[type="number"], .fld input[type="date"],
.fld input[type="datetime-local"], .fld select, .fld textarea {
  width: 100%; border: 1px solid var(--line); border-radius: 4px;
  padding: 9px 11px; font: inherit; color: var(--ink); background: #fff;
  transition: border-color .15s, box-shadow .15s;
}
.fld input:focus, .fld select:focus, .fld textarea:focus {
  outline: 0; border-color: var(--blekit); box-shadow: 0 0 0 3px rgba(0, 145, 210, .16);
}
.fld input:disabled, .fld select:disabled { background: var(--bg); color: var(--muted); }
.fld textarea { resize: vertical; min-height: 80px; line-height: 1.55; }
.fld input[type="file"] { padding: 8px; background: var(--bg); }

/* Pole liczbowe z wyborem jednostki obok (powierzchnia dzialki). */
/* Edycja opisu pliku rozwijana przy pozycji listy. */
.edit-row > td, .edit-row { background: var(--bg); }
.edit-form {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px; padding: 14px 4px;
}
.edit-form .span-2 { grid-column: span 2; }
.edit-actions { display: flex; gap: 10px; align-items: flex-end; }
.doc-akcje { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.btn-mini-err { color: var(--err); border-color: #f1dbd9; }
.btn-mini-err:hover { background: var(--err-bg); border-color: var(--err); }
.btn-mini-ok { color: var(--ok); border-color: #cfe4d8; }
.btn-mini-ok:hover { background: var(--ok-bg); border-color: var(--ok); }

@media (max-width: 700px) {
  .edit-form { grid-template-columns: 1fr; }
  .edit-form .span-2 { grid-column: span 1; }
}

/* Okno wysylki - wiersze naglowka jak w programie pocztowym. */
.mail-head { padding: 4px 18px 14px; }
.mail-row {
  display: flex; align-items: center; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--line-2);
}
.mail-row > span:first-child {
  flex: 0 0 96px; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
}
.mail-row input, .mail-row select { border: 0; padding: 4px 0; background: none; flex: 1 1 auto; min-width: 0; }
.mail-row input:focus, .mail-row select:focus { outline: 0; box-shadow: none; }
.mail-to { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; }
.mail-to select { flex: 1 1 auto; min-width: 0; }
.mail-tools { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }

@media (max-width: 700px) {
  .mail-row { flex-direction: column; align-items: stretch; gap: 4px; }
  .mail-row > span:first-child { flex: none; }
}

/* Tresc wiadomosci z poczty - obcy HTML nie moze rozepchac ukladu. */
.mail-body { font-size: 14px; line-height: 1.6; overflow-x: auto; word-break: break-word; }
.mail-body img { max-width: 100%; height: auto; }
.mail-body table { max-width: 100%; border-collapse: collapse; }
.mail-body blockquote {
  margin: 10px 0; padding: 2px 0 2px 12px;
  border-left: 3px solid var(--line); color: var(--muted);
}
.mail-body a { word-break: break-all; }
.mail-body * { max-width: 100%; }

/* Lista pozycji do zaznaczenia - co dolaczyc do wysylanej oferty. */
.pick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; }
.pick {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r); padding: 10px 12px;
  background: #fff; transition: border-color .15s, background .15s;
}
.pick:hover { border-color: var(--blekit); background: #eef2f6; }
.pick input { margin: 2px 0 0; flex: 0 0 auto; }
.pick-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pick-txt strong { font-size: 13.5px; font-weight: 600; }
.pick-txt em { font-size: 11.5px; color: var(--muted); font-style: normal; }
/* Dziennik techniczny - stale odstepy, zeby kolumny sie zgadzaly. */
.log-box { max-height: 62vh; overflow: auto; padding: 4px 0; }
.log-line {
  font: 12px/1.55 ui-monospace, "SF Mono", Consolas, monospace;
  white-space: pre; padding: 2px 18px; color: var(--ink-2);
  border-left: 3px solid transparent;
}
.log-line:hover { background: var(--bg); }
.log-line.is-uwaga { color: var(--warn); border-left-color: var(--warn); background: var(--warn-bg); }
.log-line.is-blad { color: var(--err); border-left-color: var(--err); background: var(--err-bg); font-weight: 600; }

.pick.is-warn { border-color: #a9d8f1; background: var(--warn-bg); }
.pick.is-warn:hover { border-color: var(--warn); }
.pick.is-warn .pick-txt em { color: var(--warn); }
.pick.is-off { background: var(--bg); border-style: dashed; cursor: default; opacity: .65; }
.pick.is-off:hover { border-color: var(--line); background: var(--bg); }

.warn-box { border-color: #a9d8f1; background: var(--warn-bg); text-align: left; }
.warn-box strong { color: var(--warn); }

.input-unit { display: flex; gap: 8px; }
.input-unit input { flex: 1 1 auto; min-width: 0; }
.input-unit select { flex: 0 0 auto; width: auto; }
.hint { font-size: 11.5px; color: var(--muted); line-height: 1.45; }
.hint.warn-txt { color: var(--warn); font-weight: 600; }
.chk-fld .check { font-size: 13.5px; margin-top: 2px; }

.form-card { padding: 0; }
.form-card fieldset { border: 0; border-bottom: 1px solid var(--line-2); margin: 0; padding: 18px; }
.form-card fieldset:last-of-type { border-bottom: 0; }
.form-card legend { font-size: 13px; font-weight: 700; color: var(--grafit); text-transform: uppercase; letter-spacing: .04em; padding: 0; }

/* Sekcja formularza zwijana na zadanie.
   Metryki obiektu i kwot nie wypelnia sie przy kazdym zleceniu, a pola
   stojace otworem sugeruja, ze trzeba. Zwiniete zajmuja jeden wiersz
   i otwieraja sie klinieciem - a sekcja, w ktorej cos juz jest, otwiera
   sie sama (atrybut `open` z widoku). Wyglada jak <fieldset>, bo to jest
   ta sama rzecz - tylko z klapka. */
.form-card .fieldset-zwijana {
  border-bottom: 1px solid var(--line-2); padding: 0;
}
.form-card .fieldset-zwijana:last-of-type { border-bottom: 0; }
.form-card .fieldset-zwijana > summary {
  list-style: none; cursor: pointer; padding: 16px 18px;
  font-size: 13px; font-weight: 700; color: var(--grafit);
  text-transform: uppercase; letter-spacing: .04em;
  display: flex; align-items: center; gap: 8px;
}
.form-card .fieldset-zwijana > summary::-webkit-details-marker { display: none; }
.form-card .fieldset-zwijana > summary::before {
  content: "+"; font-size: 15px; line-height: 1; width: 16px;
  color: var(--blekit); font-weight: 700;
}
.form-card .fieldset-zwijana[open] > summary::before { content: "\2212"; }
.form-card .fieldset-zwijana > summary small { text-transform: none; letter-spacing: 0; font-weight: 400; }
.form-card .fieldset-zwijana > summary:hover { background: #fafbfc; }
.form-card .fieldset-zwijana > .form-grid { margin: 0; padding: 0 18px 18px; }

/* Odstep wewnetrzny karty daje zwykle <fieldset>. Formularze bez sekcji
   (wiadomosci, zadania, kalendarz) zostawaly bez niego i pola dotykaly
   krawedzi karty. */
.form-card.slim,
.form-card:not(:has(fieldset)) { padding: 18px; }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 12px; }
.form-grid .span-2 { grid-column: span 2; }
.form-card.slim > .form-grid:first-of-type,
.form-card:not(:has(fieldset)) > .form-grid:first-of-type { margin-top: 0; }

.form-actions {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 16px 18px; border-top: 1px solid var(--line-2); background: #fafbfc;
}
.form-card.slim .form-actions,
.form-card:not(:has(fieldset)) .form-actions { border: 0; background: none; padding: 16px 0 0; }

/* --- dopisanie rekordu bez opuszczania formularza -------------------- */
.fld-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 22px; }
.lnk-mini {
  border: 1px solid var(--line); background: #fff; border-radius: 999px;
  padding: 3px 11px; cursor: pointer; font-family: inherit;
  font-size: 11.5px; font-weight: 600; line-height: 1.4; color: var(--grafit);
  transition: background .15s, border-color .15s, color .15s;
}
.lnk-mini:hover { border-color: var(--blekit); color: var(--blekit-deep); background: #eef2f6; }
.lnk-mini:focus-visible { outline: 2px solid var(--blekit); outline-offset: 1px; }
.lnk-mini.is-open { background: var(--grafit); border-color: var(--grafit); color: #fff; }

.quick-add {
  border: 1px dashed var(--line); border-radius: var(--r-lg);
  background: var(--bg); padding: 14px 16px; margin-top: 16px;
}
.quick-add-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.quick-add-head strong { font-size: 13px; color: var(--grafit); }
.quick-add-head a { font-size: 12px; }
.quick-add-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.quick-add-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 12px 0 8px; }
.quick-add-msg { margin: 12px 0 0; font-size: 13px; min-height: 0; }
.quick-add-msg:empty { display: none; }
.quick-add-msg.is-ok { color: var(--ok); }
.quick-add-msg.is-err { color: var(--err); }

.danger-zone {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: #fff; border: 1px solid #f1dbd9; border-radius: var(--r-lg);
  padding: 16px 18px; margin-top: 18px;
}
.danger-zone p { margin: 2px 0 0; }

/* --- tabele -------------------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl { width: 100%; border-collapse: collapse; font-size: 13.8px; }
.tbl th {
  text-align: left; font-size: 11.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
  padding: 11px 14px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.tbl td { padding: 12px 14px; border-bottom: 1px solid var(--line-2); vertical-align: top; }
.tbl tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: #fafbfc; }
.tbl .th-sort { color: var(--muted); }
.tbl .th-sort:hover { color: var(--ink); text-decoration: none; }
.row-late { background: #f7f2f0; }
.user-cell { display: flex; align-items: center; gap: 9px; }

/* --- paginacja ----------------------------------------------------- */
.pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; margin-top: 16px; flex-wrap: wrap;
}
.pg-info { font-size: 13px; color: var(--muted); }
.pg-links { display: flex; gap: 5px; flex-wrap: wrap; }
.pg-item {
  display: inline-block; padding: 7px 12px; border-radius: 4px;
  border: 1px solid var(--line); background: #fff;
  font-size: 13px; color: var(--ink-2); text-decoration: none;
}
.pg-item:hover { border-color: var(--blekit); text-decoration: none; }
.pg-item.is-active { background: var(--blekit-deep); color: #fff; border-color: var(--blekit-deep); }
.pg-item.is-off { opacity: .4; }

/* --- listy definicji ----------------------------------------------- */
.deflist { margin: 0; padding: 6px 18px 16px; }
.deflist > div {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--line-2);
}
.deflist > div:last-child { border-bottom: 0; }
.deflist dt { font-size: 13px; color: var(--muted); flex: 0 0 auto; }
.deflist dd { margin: 0; font-size: 13.8px; text-align: right; min-width: 0; word-break: break-word; }

.note-box {
  margin: 0 18px 18px; padding: 13px 15px;
  background: #eef2f6; border-left: 3px solid var(--blekit); border-radius: 4px; font-size: 13.5px;
}
.note-box p { margin: 6px 0 0; color: var(--ink-2); }

/* --- listy skrocone ------------------------------------------------ */
.mini-list { list-style: none; margin: 0; padding: 0; }
.mini-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 18px; border-bottom: 1px solid var(--line-2); font-size: 13.6px;
}
.mini-list li:last-child { border-bottom: 0; }
.mini-list li.col { flex-direction: column; align-items: stretch; gap: 6px; }

.notif-list { list-style: none; margin: 0; padding: 0; }
.notif-list li {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 14px 18px; border-bottom: 1px solid var(--line-2);
}
.notif-list li:last-child { border-bottom: 0; }
.notif-list li.is-new { background: #eef2f6; border-left: 3px solid var(--blekit); }
.notif-list time { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* --- paski postępu ------------------------------------------------- */
.bar { height: 6px; background: var(--line-2); border-radius: 3px; overflow: hidden; }
.bar span { display: block; height: 100%; background: var(--blekit); border-radius: 3px; }
.bar-lg { height: 10px; }
.bar-thin { height: 4px; margin-top: 4px; max-width: 90px; }

/* --- kafle wariantowe ---------------------------------------------- */
.tiles-3 { grid-template-columns: repeat(3, 1fr); }
.tiles-4 { grid-template-columns: repeat(4, 1fr); }
.tile-sm { font-size: 19px !important; }

/* --- wykres słupkowy ----------------------------------------------- */
.chart {
  display: flex; align-items: flex-end; gap: 4px;
  height: 190px; padding: 18px 18px 8px;
}
/* min-width: 0 jest tu konieczne. Bez niego kolumna nie kurczy sie ponizej
   szerokosci swojego podpisu, trzydziesci slupkow nie miesci sie w karcie,
   a karta ma overflow: hidden - wykres tracil koncowke, czyli dzisiaj. */
.chart-col {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  height: 100%; justify-content: flex-end;
}
.chart-bar {
  width: 100%; max-width: 34px;
  background: linear-gradient(180deg, var(--blekit) 0%, #0072a8 100%);
  border-radius: 4px 4px 0 0; min-height: 3px;
}
.chart-col small { font-size: 11px; color: var(--muted); white-space: nowrap; min-height: 14px; }

.donut-total { text-align: center; margin: 0 0 14px; }
.donut-total strong { display: block; font-size: 30px; font-weight: 700; letter-spacing: -.02em; }
.donut-total small { color: var(--muted); font-size: 12.5px; }
.legend { list-style: none; margin: 0; padding: 0; }
.legend li { display: flex; align-items: center; gap: 9px; padding: 6px 0; font-size: 13.5px; }
.legend-lbl { flex: 1; }
.legend-val { color: var(--muted); font-size: 12.5px; }
.dot-c { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 10px; }
.dot-0 { background: var(--grafit); }
.dot-1 { background: var(--blekit); }
.dot-2 { background: #4fb8e8; }
.dot-3 { background: #d2d8df; }

/* --- karty ofert --------------------------------------------------- */
.cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 16px; }
.offer-card {
  display: block; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 16px 18px; box-shadow: var(--shadow);
  color: var(--ink); transition: border-color .15s, transform .1s;
}
.offer-card:hover { border-color: var(--blekit); text-decoration: none; transform: translateY(-1px); }
.offer-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.offer-type { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.offer-card h3 { font-size: 15.5px; margin-bottom: 4px; }
.offer-price { font-size: 17px; font-weight: 700; color: var(--blekit-deep); margin: 10px 0 6px; }
.offer-meta { display: flex; gap: 9px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin: 0; }

/* --- zakładki ------------------------------------------------------ */
.tabs { display: flex; gap: 4px; flex-wrap: wrap; padding: 14px 18px 0; border-bottom: 1px solid var(--line-2); }
.tab {
  background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer;
  font: 700 13.5px var(--text); color: var(--muted); padding: 8px 12px;
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--grafit); border-bottom-color: var(--blekit); }
.tab-panel { display: none; padding: 16px 18px; }
.tab-panel.is-active { display: block; }
.form-card .tab-panel { padding: 16px 0 0; }

.subtabs { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 18px; border-bottom: 1px solid var(--line); }
.subtab {
  padding: 10px 16px; font-size: 14px; font-weight: 500;
  color: var(--muted); border-bottom: 2px solid transparent;
}
.subtab:hover { color: var(--ink); text-decoration: none; }
.subtab.is-active { color: var(--grafit); font-weight: 600; border-bottom-color: var(--blekit); }

/* --- kalendarz ----------------------------------------------------- */
.cal { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-h {
  padding: 10px; text-align: center; font-size: 11.5px; font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid var(--line);
}
.cal-d {
  min-height: 96px; padding: 6px; border-right: 1px solid var(--line-2);
  border-bottom: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 3px;
}
.cal-d:nth-child(7n+7) { border-right: 0; }
.cal-d.is-empty { background: #fafbfc; }
.cal-d.is-today { background: #eef2f6; }
.cal-n { display: flex; align-items: center; justify-content: space-between; font-size: 12px; color: var(--muted); font-weight: 600; }
.cal-d.is-today .cal-n { color: var(--blekit-deep); }
.cal-add { opacity: 0; font-size: 15px; line-height: 1; color: var(--muted); padding: 0 3px; }
.cal-d:hover .cal-add { opacity: 1; }
.cal-ev {
  display: block; background: var(--grafit); color: #fff; border-radius: 4px;
  padding: 3px 5px; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-ev:hover { background: var(--grafit-2); text-decoration: none; }
.cal-ev b { color: var(--mgla); margin-right: 3px; }

/* Termin kontaktu z karty klienta. Grafit jest zajety przez wydarzenia,
   wiec przypomnienie dostaje blekit - ten sam akcent, ktory w calym
   panelu oznacza "nasze dzialanie". Termin przekroczony przechodzi na
   kolor ostrzezenia, tak jak zalegly termin zadania na dashboardzie. */
.cal-ev.is-contact { background: var(--blekit-deep); color: #fff; }
.cal-ev.is-contact:hover { background: var(--blekit-deep); }
.cal-ev.is-contact b { color: var(--mgla); }
.cal-ev.is-contact.is-late { background: var(--warn-bg); color: var(--warn); border: 1px solid #bde2f5; padding: 2px 4px; }
.cal-ev.is-contact.is-late:hover { background: #ddf0fa; }
.cal-ev.is-contact.is-late b { color: var(--warn-akcent); }

.cal-legend {
  display: flex; flex-wrap: wrap; gap: 16px;
  padding: 12px 16px; border-top: 1px solid var(--line-2);
  font-size: 12px; color: var(--muted);
}
.cal-legend span { display: inline-flex; align-items: center; gap: 6px; }
.cal-key { width: 11px; height: 11px; border-radius: 3px; background: var(--grafit); flex: 0 0 11px; }
.cal-key.is-contact { background: var(--blekit); }
.cal-key.is-contact.is-late { background: var(--warn-bg); border: 1px solid #bde2f5; }

/* --- pozostałe ----------------------------------------------------- */
.actions-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.log {
  background: var(--grafit); color: #dcdce6; padding: 14px; border-radius: 4px;
  font: 12px/1.6 ui-monospace, Consolas, monospace; overflow-x: auto; max-height: 320px;
}
.tbl-map select { min-width: 190px; }
details summary { cursor: pointer; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 16px; }

/* =====================================================================
   Wersja mobilna: tabele zamieniają się w karty
   ===================================================================== */
@media (max-width: 1100px) {
  .grid-3 { grid-template-columns: 1fr; }
  .tiles-3, .tiles-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 780px) {
  .form-grid { grid-template-columns: 1fr; }
  .form-grid .span-2 { grid-column: span 1; }
  .tiles-3, .tiles-4 { grid-template-columns: 1fr; }
  .cards-grid { grid-template-columns: 1fr; }
  .page-head { flex-direction: column; align-items: stretch; }
  .page-head-side { justify-content: flex-start; }
  .danger-zone { flex-direction: column; align-items: stretch; gap: 12px; }
  .filter-grid { grid-template-columns: 1fr; }
  .quick-add-grid { grid-template-columns: 1fr; }

  /* Tabela przestaje być tabelą - każdy wiersz to osobna karta,
     a nagłówki kolumn wracają jako etykiety z atrybutu data-label. */
  .table-wrap { overflow: visible; }
  .tbl, .tbl thead, .tbl tbody, .tbl tr, .tbl th, .tbl td { display: block; }
  .tbl thead { display: none; }
  .tbl tr {
    border: 1px solid var(--line); border-radius: 8px;
    padding: 6px 2px; margin: 0 0 12px; background: #fff;
  }
  .tbl tbody tr:hover { background: #fff; }
  .tbl td { border: 0; padding: 7px 14px; display: flex; gap: 12px; align-items: flex-start; }
  .tbl td::before {
    content: attr(data-label);
    flex: 0 0 40%; max-width: 40%;
    font-size: 11.5px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: .03em; padding-top: 2px;
  }
  .tbl td:not([data-label]) { display: none; }
  .tbl td.ta-r { text-align: left; }
  .tbl td.nowrap { white-space: normal; }

  .deflist > div { flex-direction: column; gap: 2px; }
  .deflist dd { text-align: left; }

  /* Kalendarz: z siatki miesięcznej na listę dni z wydarzeniami. */
  .cal { grid-template-columns: repeat(7, 1fr); }
  .cal-d { min-height: 58px; padding: 3px; }
  .cal-ev { font-size: 0; padding: 3px; }
  .cal-ev b { font-size: 9px; }
  .cal-add { display: none; }

  .pager { flex-direction: column; align-items: stretch; gap: 10px; }
  .subtabs { overflow-x: auto; flex-wrap: nowrap; }
  .subtab { white-space: nowrap; }
  .chart { height: 150px; gap: 5px; padding: 14px 10px 6px; }
  .notif-list li { flex-direction: column; gap: 4px; }
}

@media (max-width: 460px) {
  .tbl td { flex-direction: column; gap: 2px; }
  .tbl td::before { max-width: 100%; flex-basis: auto; }
  .cal-h { font-size: 9.5px; padding: 6px 2px; }
}

/* --- diagnostyka i integracje (etapy 7-8) -------------------------- */
.diag { list-style: none; margin: 0; padding: 0; }
.diag li {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 15px 18px; border-bottom: 1px solid var(--line-2);
}
.diag li:last-child { border-bottom: 0; }
.diag-dot { width: 11px; height: 11px; border-radius: 50%; flex: 0 0 11px; margin-top: 5px; }
.diag-ok   .diag-dot { background: var(--ok-akcent); }
.diag-warn .diag-dot { background: var(--warn-akcent); }
.diag-err  .diag-dot { background: var(--err-akcent); }
.diag-info .diag-dot { background: #4fb8e8; }
.diag-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.diag-txt strong { font-size: 14.5px; }
.diag-val { font-size: 13.5px; color: var(--ink-2); }
.diag-err .diag-val { color: var(--err); font-weight: 600; }
.diag-warn .diag-val { color: var(--warn); font-weight: 600; }
.diag-hint { font-size: 12.5px; color: var(--muted); line-height: 1.5; margin-top: 2px; }

.tab-badge {
  display: inline-block; min-width: 18px; margin-left: 6px; padding: 1px 6px;
  border-radius: 4px; background: var(--err); color: #fff;
  font-size: 11px; font-weight: 700; text-align: center;
}

.token-box {
  font: 13px/1.5 ui-monospace, Consolas, monospace;
  background: var(--grafit); color: #d2d8df;
  padding: 12px 14px; border-radius: 4px; margin: 10px 0 0;
  word-break: break-all; user-select: all;
}

.rodo-row { padding: 6px 0; gap: 18px; align-items: flex-start; }
.rodo-row.bt { border-top: 1px solid var(--line-2); margin-top: 12px; padding-top: 16px; }
.rodo-row p { margin: 3px 0 0; max-width: 60ch; }

/* --- zaznaczanie i akcje zbiorcze ---------------------------------- */
.col-check { width: 34px; }
.col-check input { width: 16px; height: 16px; accent-color: var(--blekit-deep); cursor: pointer; }
.tbl tr.is-picked { background: #eef2f6; }

.bulkbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--grafit); color: #e9e9f6;
  padding: 12px 16px; border-radius: var(--r-lg) var(--r-lg) 0 0;
  font-size: 13.5px; position: sticky; top: 62px; z-index: 15;
}
.bulk-count strong { color: var(--blekit-light); font-size: 15px; }
.bulk-act { display: flex; align-items: center; gap: 6px; }
.bulkbar select {
  border: 1px solid #3c414a; border-radius: 4px; padding: 7px 9px;
  background: #26262e; color: #e9e9f6; font: inherit; max-width: 200px;
}
.bulkbar .btn-ghost { border-color: #3c414a; color: #e9e9f6; background: transparent; }
.bulkbar .btn-ghost:hover { background: #26262e; color: #fff; }
.bulkbar .bulk-del { border-color: #5b2a26; color: #f0a9a4; background: transparent; }
.bulkbar .bulk-del:hover { background: #3a1b18; color: #fff; }
.bulkbar a { color: var(--blekit-light); }
.bulkbar + .card { border-top-left-radius: 0; border-top-right-radius: 0; }

@media (max-width: 780px) {
  .bulkbar { position: static; border-radius: var(--r-lg); flex-direction: column; align-items: stretch; }
  .bulk-act { flex-direction: column; align-items: stretch; }
  .bulkbar select { max-width: none; }
  /* Zaznaczanie dziala takze na telefonie - komorka staje sie pierwszym
     wierszem karty, z etykieta jak pozostale pola. */
  .col-check { width: auto; }
}

/* --- galeria zdjęć oferty ------------------------------------------ */
.gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px; padding: 16px 18px;
}
.gal-item {
  margin: 0; position: relative; border: 1px solid var(--line);
  border-radius: 8px; overflow: hidden; background: var(--bg);
}
.gal-item.is-cover { border-color: var(--blekit); box-shadow: 0 0 0 2px rgba(0, 145, 210, .22); }
.gal-item img { display: block; width: 100%; height: 118px; object-fit: cover; }
.gal-badge {
  position: absolute; top: 7px; left: 7px;
  background: var(--blekit-deep); color: #ffffff;
  font-size: 10.5px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
}
.gal-item figcaption {
  display: flex; gap: 5px; flex-wrap: wrap;
  padding: 7px; background: #fff; border-top: 1px solid var(--line-2);
}

.offer-thumb { display: block; margin: -16px -18px 12px; }
.offer-thumb img { display: block; width: 100%; height: 150px; object-fit: cover; }

@media (max-width: 460px) {
  .gallery { grid-template-columns: repeat(2, 1fr); }
  .gal-item img { height: 96px; }
}

/* --- szybka notatka na karcie podmiotu ----------------------------- */
.quicknote { padding: 14px 18px; border-bottom: 1px solid var(--line-2); background: #fafbfc; }
.quicknote textarea {
  width: 100%; border: 1px solid var(--line); border-radius: 4px;
  padding: 10px 12px; font: inherit; resize: vertical; min-height: 62px; background: #fff;
}
.quicknote textarea:focus {
  outline: 0; border-color: var(--blekit); box-shadow: 0 0 0 3px rgba(0, 145, 210, .16);
}
.quicknote-row { display: flex; align-items: flex-end; gap: 10px; margin-top: 9px; flex-wrap: wrap; }
.quicknote-row select, .qn-date input {
  border: 1px solid var(--line); border-radius: 4px; padding: 8px 10px; font: inherit; background: #fff;
}
.qn-date { display: flex; flex-direction: column; gap: 3px; }
.qn-date span { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.quicknote-row button { margin-left: auto; }

@media (max-width: 780px) {
  .quicknote-row { flex-direction: column; align-items: stretch; }
  .quicknote-row button { margin-left: 0; }
  .quicknote-row select, .qn-date input { width: 100%; }
}

/* --- przełącznik zakresu dat na dashboardzie ----------------------- */
.daterange {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
  padding: 12px 16px; margin-bottom: 18px;
}
.dr-presets { display: flex; gap: 4px; flex-wrap: wrap; }
.dr-btn {
  padding: 7px 13px; border-radius: 999px; border: 1px solid var(--line);
  font-size: 13px; color: var(--ink-2); background: #fff;
}
.dr-btn:hover { border-color: var(--blekit); text-decoration: none; }
.dr-btn.is-active { background: var(--blekit-deep); color: #fff; border-color: var(--blekit-deep); font-weight: 600; }
.dr-form { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.dr-form label { display: flex; flex-direction: column; gap: 3px; }
.dr-form span { font-size: 11px; color: var(--muted); font-weight: 600; }
.dr-form input {
  border: 1px solid var(--line); border-radius: 4px; padding: 7px 9px; font: inherit; background: #fff;
}
.dr-info { margin-left: auto; font-size: 12.5px; color: var(--muted); }

@media (max-width: 780px) {
  .daterange { flex-direction: column; align-items: stretch; }
  .dr-presets { justify-content: flex-start; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }
  .dr-btn { white-space: nowrap; }
  .dr-form { flex-direction: column; align-items: stretch; }
  .dr-form input, .dr-form button { width: 100%; }
  .dr-info { margin-left: 0; }
}

/* --- raport duplikatów --------------------------------------------- */
.sec-title { font-size: 15px; margin: 22px 0 12px; color: var(--ink-2); }
.dup-group { margin-bottom: 16px; }
.dup-group input[type="radio"], .dup-group input[type="checkbox"] {
  width: 16px; height: 16px; accent-color: var(--blekit-deep); cursor: pointer;
}
.dup-chip {
  display: inline-block; margin: 0 6px 4px 0; padding: 3px 9px;
  background: var(--line-2); border-radius: 999px; font-size: 12.5px;
}

/* --- pozycja pliku na karcie klienta ------------------------------- */
.doc-line { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.doc-line a { word-break: break-word; }

/* --- kafle klikalne i nowe zgłoszenia ------------------------------ */
a.tile { color: var(--ink); }
a.tile:hover { border-color: var(--blekit); text-decoration: none; }
a.tile.is-on { border-color: var(--blekit); box-shadow: 0 0 0 2px rgba(0, 145, 210, .16); }
.tbl tr.row-new { background: #eef2f6; }
.tbl tr.row-new td:first-child { box-shadow: inset 3px 0 0 var(--blekit); }

/* =====================================================================
   Tryb prezentacji - "Ukryj dane"

   Wlaczany przyciskiem w pasku gornym, pamietany w localStorage. Sluzy
   do pokazywania systemu na ekranie, gdy w sali siedzi ktos, kto nie ma
   prawa widziec nazw klientow, kwot ani kontaktow.

   Zasada: rozmywamy cale komorki z danymi, a nie pojedyncze pola -
   inaczej przy kazdej nowej kolumnie trzeba by pamietac o dopisaniu
   klasy, a zapomniana kolumna to wyciek. Wyjatki sa trzy i wszystkie
   celowe:
     - komorki z przyciskami zostaja ostre, bo trzeba w nie klikac,
     - komorka z elementem .jawna rozmywa sie tylko czesciowo (nazwa
       zachowuje pierwsza litere - da sie powiedziec "ten na L"),
     - naglowki tabel i etykiety pol zostaja, bo pokazuja, o czym mowa.

   To zaslona na ekran, nie zabezpieczenie danych: tresc nadal jest
   w kodzie strony. Do prezentacji wystarczy, do ochrony przed kims,
   kto ma dostep do przegladarki - nie.
   ===================================================================== */
.top-icon .ukryj-txt { font-size: 13.5px; font-weight: 500; margin-left: 6px; }
#ukryjDane { background: none; border: 0; cursor: pointer; font: inherit; align-items: center; }
#ukryjDane[aria-pressed="true"] { background: var(--blekit-deep); color: #fff; }
#ukryjDane[aria-pressed="true"]:hover { background: var(--blekit-deep); }

html.dane-ukryte .poufne,
html.dane-ukryte .tbl tbody td:not(.col-check):not(:has(button)):not(:has(.btn-mini)):not(:has(.jawna)),
html.dane-ukryte .deflist dd:not(:has(.jawna)),
html.dane-ukryte .tile-txt strong,
html.dane-ukryte .donut-total strong,
html.dane-ukryte .legend-val,
html.dane-ukryte .legend-lbl,
html.dane-ukryte .offer-price,
html.dane-ukryte .offer-card h3,
html.dane-ukryte .feed-txt,
html.dane-ukryte .mini-list li,
html.dane-ukryte .notif-list li p,
html.dane-ukryte .mail-body,
html.dane-ukryte .mail-row input,
html.dane-ukryte .quicknote textarea,
html.dane-ukryte .page-head p.muted,
html.dane-ukryte .side-user-txt,
html.dane-ukryte .top-user-txt,
html.dane-ukryte .cal-ev,
html.dane-ukryte .prose,
html.dane-ukryte .log-box,
html.dane-ukryte .diag-val {
  filter: blur(5px);
  user-select: none;
}

/* Nazwa wlasna: pierwsza litera zostaje, reszta znika. */
html.dane-ukryte .jawna { filter: none; }

/* Pola formularzy - inaczej dane widac przy edycji rekordu. */
html.dane-ukryte .fld input:not([type="checkbox"]):not([type="radio"]),
html.dane-ukryte .fld textarea,
html.dane-ukryte .field input {
  filter: blur(5px);
}
html.dane-ukryte .fld input:focus,
html.dane-ukryte .fld textarea:focus {
  filter: none;   /* to, co wlasnie wpisujesz, musisz widziec */
}

/* Pasek stanu, zeby nie dalo sie zapomniec o wlaczonym trybie. */
html.dane-ukryte body::after {
  content: "Dane ukryte - tryb prezentacji";
  position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%);
  z-index: 200; pointer-events: none;
  background: var(--blekit-deep); color: #fff;
  font: 600 12.5px var(--text); letter-spacing: .02em;
  padding: 7px 16px; border-radius: 999px;
  box-shadow: var(--shadow-lg);
}


/* =====================================================================
   BŁAMO - elementy dolozone ponad silnik
   ===================================================================== */

/* --- sidebar: naglowek marki i grupy pozycji ----------------------- */
.side-brand { display: flex; align-items: center; gap: 11px; }
.side-brand img { width: 38px; height: auto; }
.side-brand-txt { display: flex; flex-direction: column; line-height: 1.25; }
.side-brand-txt strong {
  font-family: var(--sans); font-size: 15px; font-weight: 700;
  letter-spacing: .08em; color: #fff;
}
.side-brand-txt small { font-size: 11px; color: var(--blekit-light); letter-spacing: .04em; }

/* Naglowek grupy jest cichy celowo - ma dzielic liste, a nie konkurowac
   z pozycjami, ktore sie klika. */
.side-group {
  margin: 18px 0 6px; padding: 0 12px;
  font-family: var(--sans); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: #6f7480;
}
.side-nav > .side-group:first-child { margin-top: 6px; }

/* --- termin z odliczaniem ------------------------------------------ */
/* Sama data wymaga policzenia w glowie; chip obok mowi wprost, ile
   zostalo. Nie zawijaja sie na dwie linie, bo w tabeli rozjezdzaja wiersz. */
.termin { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }

/* --- kafle pieniedzy na pulpicie ----------------------------------- */
/* Trzy liczby odpowiadaja na trzy rozne pytania i nie sumuja sie w jedna,
   dlatego dostaja rowne kolumny, a nie jeden pasek z podzialem. */
.money-grid {
  display: grid; gap: 14px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.money {
  display: block; padding: 18px 20px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow); transition: border-color .15s, box-shadow .15s;
}
.money:hover { border-color: var(--mgla); box-shadow: var(--shadow-lg); text-decoration: none; }
.money-top { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
.money-top .ico { width: 18px; height: 18px; color: var(--blekit-deep); }
.money-label {
  font-family: var(--sans); font-size: 11.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.money-value {
  font-family: var(--sans); font-size: 27px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink); line-height: 1.15;
}
.money-sub { margin-top: 6px; font-size: 13px; color: var(--muted); }
.money-hint { margin-top: 10px; font-size: 12.5px; font-weight: 500; }
.money-hint.ok { color: var(--ok); }
.money-hint.warn { color: var(--warn); }
.money-hint.err { color: var(--err); }
.money-hint.info { color: var(--blekit-deep); }
.money-hint.neutral { color: var(--muted); }

/* --- lejek szans ---------------------------------------------------- */
.lejek { display: flex; flex-direction: column; gap: 8px; }
.lejek-row { display: flex; align-items: center; gap: 12px; font-size: 13.5px; }
.lejek-name { flex: 0 0 132px; color: var(--ink-2); }
.lejek-bar { flex: 1 1 auto; height: 8px; background: var(--line-2); border-radius: 999px; overflow: hidden; }
.lejek-fill { display: block; height: 100%; background: var(--blekit); border-radius: 999px; }
.lejek-val { flex: 0 0 auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.lejek-n { flex: 0 0 34px; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }

/* --- droga przez urzad --------------------------------------------- */
/* Pionowa os z kropkami: etapy czyta sie jako ciag, a nie jako zbior
   niezaleznych wierszy - kolejnosc jest tu trescia. */
.droga { position: relative; margin: 0; padding: 0 0 0 26px; list-style: none; }
.droga::before {
  content: ""; position: absolute; left: 7px; top: 10px; bottom: 10px;
  width: 2px; background: var(--line);
}
.droga-item { position: relative; padding: 11px 0; border-bottom: 1px solid var(--line-2); }
.droga-item:last-child { border-bottom: 0; }
.droga-item::before {
  content: ""; position: absolute; left: -23px; top: 16px;
  width: 12px; height: 12px; border-radius: 50%;
  background: #fff; border: 2px solid var(--line);
}
.droga-item.is-done::before   { background: var(--ok-akcent); border-color: var(--ok-akcent); }
.droga-item.is-wait::before   { background: var(--warn-akcent); border-color: var(--warn-akcent); }
.droga-item.is-active::before { background: var(--blekit); border-color: var(--blekit); }
.droga-item.is-err::before    { background: var(--err-akcent); border-color: var(--err-akcent); }
.droga-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.droga-name { font-weight: 600; }
.droga-meta { margin-top: 3px; font-size: 12.5px; color: var(--muted); }

/* --- pozycje wyceny w kreatorze ------------------------------------ */
.poz-row { display: grid; gap: 8px; align-items: start; margin-bottom: 8px;
  grid-template-columns: 1.5fr .8fr 68px 80px 96px 104px 104px 34px; }
.poz-row input, .poz-row select { width: 100%; }
.poz-head { font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); }
.poz-sum { text-align: right; font-variant-numeric: tabular-nums; padding: 9px 0; font-weight: 600; }
@media (max-width: 900px) {
  .poz-row { grid-template-columns: 1fr 1fr; }
  .poz-head { display: none; }
}

/* --- pasek postepu etapow ------------------------------------------ */
.postep { display: flex; align-items: center; gap: 8px; }
.postep-bar { flex: 1 1 auto; height: 6px; background: var(--line-2); border-radius: 999px; overflow: hidden; min-width: 60px; }
.postep-fill { display: block; height: 100%; background: var(--ok-akcent); border-radius: 999px; }
.postep-txt { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- lista definicji na kartach ------------------------------------ */
/* Metryka obiektu to kilkanascie par etykieta-wartosc. Tabela bylaby tu
   przesada, a same akapity nie daja sie wyrownac do jednej krawedzi. */
.dl { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 6px 14px; margin: 0 0 14px; }
.dl dt { font-size: 13px; color: var(--muted); }
.dl dd { margin: 0; font-size: 13.5px; font-weight: 500; }

/* --- checkbox w pasku filtrow -------------------------------------- */
.filters .chk { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; color: var(--ink-2); }
.filters .chk input { width: 16px; height: 16px; accent-color: var(--blekit); cursor: pointer; }

/* --- rozwijana stopka karty ---------------------------------------- */
/* Formularz dopisywania etapu albo transzy jest schowany, bo przy
   przegladaniu karty przeszkadza, a przy edycji rozwija sie jednym
   klikiem i sam przewija na siebie. */
.card-foot { border-top: 1px solid var(--line-2); background: #fafbfc; }
.card-foot > summary {
  padding: 12px 18px; cursor: pointer; font-size: 13.5px; font-weight: 500;
  color: var(--blekit-deep); list-style: none;
}
.card-foot > summary::-webkit-details-marker { display: none; }
.card-foot > summary::before { content: "+ "; font-weight: 700; }
.card-foot[open] > summary::before { content: "\2212 "; }
.card-foot > summary:hover { background: var(--papier); }
.card-foot .form-grid { padding-top: 4px; }

/* --- kreator wyceny: pasek pod pozycjami --------------------------- */
.inline-select { padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--r); background: #fff; font: inherit; max-width: 320px; }
.poz-total { margin-left: auto; font-size: 14px; color: var(--muted); }
.poz-total strong { font-family: var(--sans); font-size: 19px; color: var(--ink); margin-left: 6px; }
.poz-del { padding: 8px 10px; line-height: 1; }

/* Pozycja wyłączona w cenniku: widoczna, ale wyraźnie cichsza -
   skasowanie jej zabrałoby ślad po tym, że kiedyś była w użyciu. */
.tbl tr.dim td { opacity: .55; }

/* --- nagłówek grupy w tabeli terminów ------------------------------ */
/* Jedyny podział, który ma tu znaczenie: co już przepadło, a co dopiero
   przed nami. Wiersz-nagłówek zamiast trzech osobnych tabel, bo
   sortowanie po dacie musi przechodzić przez granicę bez przerwy. */
.tbl tr.grupa td {
  padding: 14px 12px 6px; border-bottom: 1px solid var(--line);
  font-family: var(--sans); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
  background: #fafbfc;
}

/* =====================================================================
   Pasek filtrów w wersji płaskiej
   =====================================================================
   Listy zleceń, wycen, płatności i terminów wkładają pola wprost do
   `.filters`, bez `.filter-grid`. Wcześniej te pola nie łapały żadnej
   reguły i przeglądarka rysowała natywne selektory - szare, w innym
   foncie, z systemową strzałką, każdy innej wysokości.

   Reguły są celowo zawężone do bezpośrednich dzieci: warianty
   z `.filter-grid` (katalog projektów, klienci) mają własny układ
   i nie wolno im tego popsuć. */

.filters {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}

/* Wariant siatkowy zostaje pionowy - tam pola mają etykiety nad sobą.
   Druga reguła jest zapasem na wypadek przeglądarki bez :has() - siatka
   dostaje wtedy całą szerokość i układ wygląda tak samo. */
.filters:has(> .filter-grid) { display: block; }
.filters > .filter-grid { flex: 1 1 100%; }

.filters > input[type="search"],
.filters > input[type="text"],
.filters > input[type="month"],
.filters > input[type="date"],
.filters > input[type="number"],
.filters > select {
  height: 38px; padding: 0 11px; margin: 0;
  border: 1px solid var(--line); border-radius: var(--r);
  font: inherit; font-size: 13.5px; color: var(--ink); background: #fff;
  transition: border-color .15s, box-shadow .15s;
}

.filters > input[type="search"] { flex: 1 1 230px; min-width: 180px; }
.filters > input[type="month"],
.filters > input[type="date"] { flex: 0 0 auto; }

/* Natywna strzałka selektora jest tym, co najbardziej kłuło w oczy -
   w każdej przeglądarce inna i zawsze obca reszcie panelu. Podmieniamy
   ją na własną, tego samego szarego co etykiety. */
.filters > select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%235d636e' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
}

.filters > input:hover, .filters > select:hover { border-color: var(--line-strong, var(--mgla)); }

.filters > input:focus, .filters > select:focus {
  outline: 0; border-color: var(--blekit);
  box-shadow: 0 0 0 3px rgba(0, 145, 210, .16);
}

.filters > input::placeholder { color: var(--muted); }

/* Przyciski trzymają tę samą wysokość co pola i nie rozpychają wiersza.
   `.btn-ghost` ma poza tym paskiem `display:flex`, przez co jako element
   flex rozciągał się na całą szerokość i lądował w osobnej linii. */
.filters > .btn-dark,
.filters > .btn-ghost,
.filters > button {
  height: 38px; display: inline-flex; align-items: center;
  flex: 0 0 auto; white-space: nowrap;
}
.filters > .btn-dark { margin-left: auto; }
.filters > .btn-ghost { text-decoration: none; }

/* Zaznaczenie w pasku - wyrównane do pól, nie do tekstu. */
.filters > .chk { height: 38px; display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto; }

@media (max-width: 720px) {
  .filters > input[type="search"] { flex: 1 1 100%; }
  .filters > select,
  .filters > input[type="month"] { flex: 1 1 calc(50% - 5px); }
  .filters > .btn-dark { margin-left: 0; flex: 1 1 auto; justify-content: center; }
  .filters > .btn-ghost { flex: 1 1 auto; justify-content: center; }
}

/* =====================================================================
   Telefon - poprawki układu
   =====================================================================
   Pulpit rozjeżdżał się w poziomie: jeden element szerszy od ekranu
   wystarczy, żeby przewijała się cała strona razem z paskiem górnym.
   Poniżej najpierw zabezpieczenie ogólne, potem konkretne komponenty,
   które to powodowały. */

/* Zabezpieczenie na poziomie dokumentu.
   `clip`, a nie `hidden`: `hidden` robi z elementu kontener przewijania
   i wtedy `position: sticky` w środku przestaje trzymać się okna -
   odkleiłby się pasek górny i sidebar. `clip` obcina bez tego skutku. */
html { overflow-x: clip; }

/* Bez tego element potomny szerszy od ekranu rozpycha kolumnę, zamiast
   zostać przycięty albo przewinąć się we własnym pudełku. */
.main, .page { min-width: 0; }
.card, .table-wrap { min-width: 0; }

@media (max-width: 780px) {
  /* Pasek zakresu dat. Guziki przewijają się w poziomie we własnym
     pudełku - `max-width` jest tu konieczne, bo bez niego pasek
     rozpychał kartę zamiast się przewijać. */
  .dr-presets { max-width: 100%; min-width: 0; }
  .dr-form { width: 100%; min-width: 0; }
  .dr-form label { min-width: 0; }
  .dr-form input { min-width: 0; max-width: 100%; box-sizing: border-box; }
  .dr-info { order: 3; }

  /* Kwoty na kaflach pieniędzy bywają długie ("6 500 PLN / mies.") -
     na wąskim ekranie mają się łamać, a nie wychodzić poza kartę. */
  .money-value { font-size: 24px; overflow-wrap: anywhere; }
  .money-grid { grid-template-columns: 1fr; }
}

/* Lejek szans i rozbicie wpływów. Na szerokim ekranie to jeden wiersz:
   nazwa, pasek, kwota, sztuki. Na telefonie nazwa i liczby nie mieszczą
   się obok siebie, więc nazwa idzie nad pasek, a liczby zostają w linii
   pod nią - zamiast ściskać wszystko do nieczytelności. */
@media (max-width: 560px) {
  .lejek-row { flex-wrap: wrap; gap: 6px 10px; }
  .lejek-name { flex: 1 1 100%; font-weight: 600; color: var(--ink); }
  .lejek-bar { flex: 1 1 100%; order: 3; }
  .lejek-val { flex: 0 0 auto; }
  .lejek-n { flex: 1 1 auto; text-align: right; }

  /* Lista definicji na kartach - dwie kolumny są za ciasne poniżej 560 px. */
  .dl { grid-template-columns: 1fr; gap: 2px; }
  .dl dt { margin-top: 8px; }
  .dl dt:first-child { margin-top: 0; }

  /* Pasek postępu w komórce tabeli nie może wymuszać szerokości kolumny. */
  .postep-bar { min-width: 40px; }

  /* Droga przez urząd: mniejsze wcięcie, żeby zostało miejsce na treść. */
  .droga { padding-left: 20px; }
  .droga::before { left: 5px; }
  .droga-item::before { left: -19px; }
}

/* =====================================================================
   Pozycje wyceny - wygląd pól
   =====================================================================
   Pola w wierszu pozycji leżą wprost w `.poz-row`, poza `.fld`, więc nie
   łapały żadnej reguły i przeglądarka rysowała je po swojemu: inny font,
   inna wysokość, systemowa strzałka w selektorach. Ten sam błąd co
   wcześniej w pasku filtrów. */

.poz-row input[type="text"],
.poz-row select {
  height: 38px; width: 100%; padding: 0 11px; margin: 0;
  border: 1px solid var(--line); border-radius: var(--r);
  font: inherit; font-size: 13.5px; color: var(--ink); background: #fff;
  box-sizing: border-box;
  transition: border-color .15s, box-shadow .15s;
}

.poz-row select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 30px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%235d636e' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}

.poz-row input:hover, .poz-row select:hover { border-color: var(--mgla); }
.poz-row input:focus, .poz-row select:focus {
  outline: 0; border-color: var(--blekit);
  box-shadow: 0 0 0 3px rgba(0, 145, 210, .16);
}

/* Liczby wyrównane do prawej i tabelarycznie - kolumna kwot ma się
   czytać jak kolumna, a nie jak zbiór przypadkowych napisów. */
.poz-row .poz-qty, .poz-row .poz-price { text-align: right; font-variant-numeric: tabular-nums; }
.poz-sum { font-variant-numeric: tabular-nums; }

.poz-del {
  height: 38px; width: 34px; padding: 0; display: inline-flex;
  align-items: center; justify-content: center; font-size: 17px; line-height: 1;
}

/* --- telefon: wiersz staje się kartą -------------------------------
   Dwie kolumny bez nagłówka (poprzedni układ) dawały siatkę bezimiennych
   pól - nie dało się poznać, które jest ilością, a które ceną. Teraz
   pozycja czyta się z góry na dół, a kwota stoi przy przycisku usuwania. */
@media (max-width: 900px) {
  .poz-row {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 12px; margin-bottom: 12px;
    border: 1px solid var(--line); border-radius: var(--r-lg);
    background: #fafbfc;
  }
  .poz-head { display: none; }

  /* Nazwa i rodzaj prac przez całą szerokość - to one opisują pozycję. */
  .poz-row > input[name="item_name[]"],
  .poz-row > select[name="item_service[]"] { grid-column: 1 / -1; }

  /* Ilość i jednostka w jednej linii, cena pod nimi przez całą szerokość. */
  .poz-row > .poz-price { grid-column: 1 / -1; }

  .poz-sum {
    grid-column: 1; align-self: center;
    text-align: left; font-size: 16px; font-weight: 700; color: var(--ink);
    padding: 0;
  }
  .poz-sum::before { content: "Wartość: "; font-size: 12px; font-weight: 500; color: var(--muted); }

  .poz-del { grid-column: 2; justify-self: end; }
}

/* =====================================================================
   Pasek górny na telefonie
   =====================================================================
   Hamburger, wyszukiwarka i cztery ikony po prawej nie mieszczą się
   w jednej linii na ekranie 360 px - pasek rozpychał stronę w poziomie,
   a razem z nią przewijała się cała treść.

   Ściskanie wyszukiwarki do 90 px dawało pole, w którym nic nie widać.
   Zamiast tego schodzi ona do własnego wiersza: na górze zostaje menu
   i ikony, pod spodem pełnowymiarowe pole szukania. */

@media (max-width: 640px) {
  .top { flex-wrap: wrap; gap: 10px; row-gap: 8px; }

  .top-search {
    order: 3; flex: 1 1 100%; max-width: none; min-width: 0;
  }

  /* Ikony ciaśniej, ale nadal w zasięgu kciuka (min. 40 px na dotyk). */
  .top-right { gap: 6px; }
  .top-icon { padding: 8px; }
  .top-right .btn-ghost { padding: 8px 10px; }

  /* Awatar bez ramki wokół - na tej szerokości liczy się każdy piksel. */
  .top-user { padding: 0; }
}

/* Poniżej 380 px wyszukiwarka i tak zajmuje cały wiersz, więc pasek
   górny może oddać resztę miejsca ikonom. */
@media (max-width: 380px) {
  .top { padding: 10px 10px; }
  .top-right { gap: 4px; }
}

/* =====================================================================
   Rozwój po spotkaniu 27.08.2026
   ===================================================================== */

/* --- własne oznaczenia (flagi) ------------------------------------- */
/* Znaczniki przy nagłówku karty i checkboxy w formularzu. Kolor bierze
   się z tego samego zestawu tonów co reszta systemu - nowa flaga nie
   wprowadza nowej palety, tylko wybiera z istniejącej. */
.flagi-rzad { margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 6px; }
.flagi-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px 18px; }
.flaga { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13.5px; cursor: pointer; }
.flaga input { width: 16px; height: 16px; accent-color: var(--blekit); cursor: pointer; }
.flaga .hint { flex: 1 1 100%; margin-left: 24px; }
.fld-label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px; }

/* --- nazwa zamierzenia budowlanego --------------------------------- */
/* Zdanie z wniosku, nie nazwa robocza - stoi pod nagłówkiem karty, bo
   przy pisaniu pism sięga się po nie kilka razy dziennie. */
.zamierzenie { margin: 6px 0 0; font-size: 13.5px; }

/* --- sekcja „tylko dla mnie” --------------------------------------- */
/* Czerwona ramka jest tu funkcją, a nie ozdobą: to jedyne miejsce na
   karcie, którego treść nie ma prawa wyjść do klienta. Kolor ma o tym
   przypominać w ułamku sekundy, zanim ktoś skopiuje tekst do maila. */
.card-prywatna { border-color: #f0d3d1; }
.card-prywatna .card-head { background: var(--err-bg); border-bottom-color: #f0d3d1; }
.card-prywatna .card-head h2 { color: var(--err); }
.prywatna-tresc { margin: 0; font-size: 14px; }
.note-prywatna { border-left: 3px solid var(--err); background: var(--err-bg); }
.note-prywatna strong { color: var(--err); }
.fld-prywatne textarea { border-color: #f0d3d1; background: #fffafa; }
.fld-prywatne > span { color: var(--err); font-weight: 600; }

/* --- historia zlecenia: nowe elementy wiersza ---------------------- */
.droga-item.is-na { opacity: .55; }
.droga-item.is-na::before { background: var(--line-2); border-color: var(--line); }
.droga-item.is-na .droga-name { text-decoration: line-through; }

.droga-kolejnosc { display: inline-flex; gap: 3px; margin-left: 4px; vertical-align: middle; }

/* Odhaczenie etapu z data, przy wierszu. Pole daty jest waskie, bo ma
   sluzyc do cofniecia o kilka dni, a nie do przegladania kalendarza. */
.etap-zrobione { display: inline-flex; align-items: center; gap: 5px; }
.etap-zrobione input[type="date"] {
  padding: 3px 6px; font-size: 12px; width: auto; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r); background: #fff;
}
.btn-strzalka { padding: 1px 7px; line-height: 1.4; }

.droga-pliki { list-style: none; margin: 8px 0 0; padding: 0 0 0 2px; }
.droga-pliki li { padding: 4px 0; font-size: 13px; border-bottom: 1px dashed var(--line-2); }
.droga-pliki li:last-child { border-bottom: 0; }
.droga-pliki li small { display: block; font-size: 11.5px; }
/* Wersja zastąpiona nowszą zostaje widoczna, ale cichnie - stara decyzja
   bywa potrzebna, tylko nie ona obowiązuje. */
.droga-pliki li.jest-stara { opacity: .6; }
.droga-pliki li.jest-stara a { color: var(--muted); }

.droga-dodaj { margin-top: 8px; }
.droga-dodaj > summary {
  cursor: pointer; font-size: 12.5px; color: var(--blekit-deep);
  list-style: none; padding: 3px 0;
}
.droga-dodaj > summary::-webkit-details-marker { display: none; }
.droga-dodaj > summary::before { content: "+ "; font-weight: 700; }
.droga-dodaj[open] > summary::before { content: "\2212 "; }
.droga-dodaj .form-grid { padding: 10px 0 4px; }

/* --- koszty i podwykonawcy ----------------------------------------- */
/* Wiersz z opisem tego, co przekazaliśmy wykonawcy: pełna szerokość pod
   pozycją, bo to bywa kilka zdań, a nie wartość do kolumny. */
.tbl tr.wiersz-opis td { border-top: 0; padding-top: 0; }

/* --- płótno: szkice i podpisy -------------------------------------- */
/* touch-action wyłącza przewijanie strony palcem nad płótnem - bez tego
   na tablecie rysowanie przewija ekran zamiast zostawiać ślad. */
.plotno-box { border: 1px solid var(--line); border-radius: var(--r); background: #fff; padding: 6px; margin-bottom: 12px; }
.plotno { display: block; width: 100%; height: auto; touch-action: none; cursor: crosshair; background: #fff; border-radius: 2px; }
.plotno-podpis .plotno { max-height: 190px; }

.szkice-lista { list-style: none; margin: 0; padding: 0; }
.szkice-lista li {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 18px; border-bottom: 1px solid var(--line-2); font-size: 13.5px;
}
.szkice-lista li:last-child { border-bottom: 0; }

/* --- listy obecności ----------------------------------------------- */
.lista-osob { list-style: none; margin: 0; padding: 0; }
.lista-osob > li { padding: 12px 18px; border-bottom: 1px solid var(--line-2); }
.lista-osob > li:last-child { border-bottom: 0; }
.osoba-glowa { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; }
.osoba-podpis { text-align: right; }
.podpis-mini { max-height: 46px; max-width: 200px; }
.osoba-akcje { display: flex; align-items: flex-start; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.podpis-box { flex: 1 1 320px; }
.podpis-box > summary {
  cursor: pointer; font-size: 12.5px; color: var(--blekit-deep); list-style: none; padding: 3px 0;
}
.podpis-box > summary::-webkit-details-marker { display: none; }
.podpis-box > summary::before { content: "✎ "; }

/* --- podsumowanie rozmowy ------------------------------------------ */
/* Osobno od szybkiej notatki, bo notatka zostaje u nas, a podsumowanie
   wychodzi do klienta - i ta różnica musi być widoczna przed kliknięciem. */
.podsumowanie { border-bottom: 1px solid var(--line-2); background: #fafbfc; }
.podsumowanie > summary {
  padding: 11px 18px; cursor: pointer; font-size: 13.5px; font-weight: 500;
  color: var(--blekit-deep); list-style: none;
}
.podsumowanie > summary::-webkit-details-marker { display: none; }
.podsumowanie > summary::before { content: "✉ "; }
.podsumowanie > summary:hover { background: var(--papier); }
.podsumowanie textarea { width: 100%; }
.podsumowanie .chk { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; }
.podsumowanie .chk input { width: 16px; height: 16px; accent-color: var(--blekit); }

/* Kolumna widoczności pozycji wyceny - węższa niż reszta pól. */
.poz-hidden { font-size: 13px; }

@media (max-width: 900px) {
  .osoba-glowa { flex-direction: column; align-items: flex-start; }
  .osoba-podpis { text-align: left; }
}

/* Koszt wiszący przy etapie historii - jedna linia pod wierszem, żeby
   termin sprawy i pieniądze na nią były widoczne razem. */
.droga-koszt { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-2); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Krótkie pole „Dodaj kwotę” przy etapie: kwota, wykonawca, stan
   i przycisk w jednym wierszu. Pełny formularz kosztu ma dziesięć pól -
   tutaj chodzi o to, żeby kwota dała się dopisać bez schodzenia
   wzrokiem na dół karty. */
.kwota-row { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; padding-top: 10px; }
.kwota-row .fld { margin: 0; }
.kwota-row .fld-kwota { flex: 0 0 120px; }
.kwota-row .fld-wykonawca { flex: 1 1 200px; min-width: 160px; }
.kwota-row .fld-stan { flex: 0 1 210px; }
.kwota-row button { flex: 0 0 auto; }
.droga-kwota > summary::before { content: "+ "; }
.droga-kwota .hint { padding-top: 2px; }

@media (max-width: 700px) {
  .kwota-row { flex-direction: column; align-items: stretch; }
  .kwota-row .fld { flex: 1 1 auto !important; }
}

/* ---------------------------------------------------------------------
   Tryb prezentacji - dopełnienie zakresu

   Pierwsza wersja rozmywała komórki tabel, kafle i listy, ale poza nią
   zostały miejsca, w których dane klienta stoją w zwykłym akapicie albo
   we własnym kontenerze: cała droga przez urząd (urząd, znak sprawy,
   uwagi), metryka działki, notatki na karcie klienta i kwoty na kaflach
   pieniędzy. Ekran wyglądał na zasłonięty, a najbardziej konkretne dane
   były widoczne - a to gorsze niż brak zasłony, bo usypia czujność.

   Zasada bez zmian: rozmywamy kontener z treścią, zostawiamy ostre
   etykiety, nagłówki i wszystko, w co trzeba kliknąć.
   --------------------------------------------------------------------- */
html.dane-ukryte .money-value,
html.dane-ukryte .money-sub,
html.dane-ukryte .tile-txt em,
html.dane-ukryte .dl dd:not(:has(.jawna)),
html.dane-ukryte .droga-name,
html.dane-ukryte .droga-meta,
html.dane-ukryte .droga-koszt,
html.dane-ukryte .droga-pliki,
html.dane-ukryte .zamierzenie,
html.dane-ukryte .note-box p,
html.dane-ukryte .prywatna-tresc,
html.dane-ukryte .szkice-lista li,
html.dane-ukryte .lista-osob > li,
html.dane-ukryte .podpis-mini,
html.dane-ukryte .podsumowanie textarea,
html.dane-ukryte .fld select,
html.dane-ukryte .lejek-name,
html.dane-ukryte .lejek-val,
html.dane-ukryte .tbl tfoot th,
html.dane-ukryte .tbl tfoot td,
html.dane-ukryte .poz-row input,
html.dane-ukryte .poz-row select,
html.dane-ukryte .poz-sum,
html.dane-ukryte .poz-total,
html.dane-ukryte .inline-select,
html.dane-ukryte .bulk-act select {
  filter: blur(5px);
  user-select: none;
}

/* Sekcja "między nami" to jedyne miejsce, gdzie zasłona ma być
   nieprzezroczysta, a nie rozmyta: przy rozmyciu dłuższy tekst nadal
   zdradza układ zdań, a przy prezentacji chodzi o to, żeby po tej
   sekcji nie dało się nawet poznać, ile jej jest. */
html.dane-ukryte .note-prywatna p,
html.dane-ukryte .card-prywatna .prywatna-tresc {
  filter: blur(9px);
}

/* Etykiety w metryce i nazwy kolumn zostają ostre - bez nich nie widać,
   o czym jest ekran, a same nazwy pól nie są niczyimi danymi. */
html.dane-ukryte .dl dt,
html.dane-ukryte .note-box strong,
html.dane-ukryte .droga-dodaj > summary,
html.dane-ukryte .fld > span,
html.dane-ukryte .card-prywatna .empty {
  filter: none;
}

/* Pole, w którym właśnie stoisz, musi być czytelne - tak samo jak pole
   tekstowe w trakcie pisania. Inaczej nie da się wypełnić wyceny przy
   włączonym trybie, a wtedy ludzie go wyłączają i zapominają włączyć. */
html.dane-ukryte .fld select:focus,
html.dane-ukryte .poz-row input:focus,
html.dane-ukryte .poz-row select:focus,
html.dane-ukryte .inline-select:focus,
html.dane-ukryte .podsumowanie textarea:focus {
  filter: none;
}

/* =====================================================================
   Kreator wniosków
   ===================================================================== */

/* Wybór wzoru: lista kart do klikania, a nie lista rozwijana. Wniosków
   jest kilkanaście i różnią się jednym słowem w nazwie - w rozwijanej
   liście trafia się w zły co jakiś czas, a wniosek idzie do urzędu. */
.wzory { display: grid; gap: 8px; }
.wzory-grupa {
  margin: 12px 0 2px; font-family: var(--sans); font-size: 11px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.wzory-grupa:first-child { margin-top: 0; }
.wzor {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--r);
  cursor: pointer; background: #fff;
}
.wzor:hover { border-color: var(--blekit); background: var(--papier); }
.wzor input { margin-top: 3px; accent-color: var(--blekit); }
.wzor.is-on { border-color: var(--blekit); background: var(--papier); }
.wzor-txt { min-width: 0; }
.wzor-txt strong { font-weight: 600; }

/* Podgląd wniosku wygląda jak kartka, bo to jest kartka - tyle że
   jeszcze na ekranie. Ten sam tekst wychodzi na wydruk i do Worda. */
.wniosek-kartka {
  padding: 26px 30px; background: #fff; font-size: 13.5px; line-height: 1.55;
  max-height: 78vh; overflow-y: auto;
}
.wniosek-kartka h3 {
  font-family: var(--sans); font-size: 12.5px; letter-spacing: .04em;
  text-transform: uppercase; margin: 16px 0 5px;
}
.wniosek-kartka p { margin: 0 0 4px; }
.wniosek-kartka .wn-pusta { margin: 0 0 9px; }
.wniosek-podstawa {
  font-size: 11.5px; color: var(--muted);
  border-bottom: 1px solid var(--line-2); padding-bottom: 9px; margin-bottom: 14px;
}

/* Edytor treści: monospace, bo w piśmie do urzędu liczy się układ
   wierszy, a proporcjonalna czcionka go zaciera. */
.wniosek-edytor {
  width: 100%; font: 13px/1.55 ui-monospace, "SFMono-Regular", Consolas, monospace;
  min-height: 320px;
}

.znaczniki { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 8px; }
.znacznik { font-size: 12px; }
.znacznik code { font-size: 11.5px; }

@media (max-width: 1100px) {
  .wniosek-kartka { max-height: none; }
}

/* Tryb prezentacji: treść wniosku to dane klienta w najczystszej
   postaci - nazwisko, adres, numer działki, znak sprawy. */
html.dane-ukryte .wniosek-kartka p,
html.dane-ukryte .wniosek-edytor,
html.dane-ukryte .wzor-txt {
  filter: blur(5px);
  user-select: none;
}
html.dane-ukryte .wniosek-kartka h3,
html.dane-ukryte .wniosek-edytor:focus {
  filter: none;
}
