/* ============================================
   ABCare — editorial-utility design system
   (paleta AB + mockup-style components)
   ============================================ */

/* ── Reset bazowy — ZASTĘPUJE bootstrap.min.css ────────────────────────────────────────────────
   Bootstrap ważył 227 KB, czyli 29% wszystkiego, co przeglądarka pobiera przy pierwszym wejściu,
   a ABCare używał z niego WYŁĄCZNIE reguł poniżej. Żadna klasa typowa dla Bootstrapa
   (container, d-flex, form-control, navbar, col-*) nie występuje w kodzie ani razu, a
   .btn-primary / .card-body / .modal / .table / .badge / .row ABCare definiuje samo niżej.

   ⚠ Zestaw NIE jest zgadywany — powstał z pomiaru: scenariusz `abcare-bootstrap-probe` porównuje
   położenie i styl KAŻDEGO elementu na 8 ekranach w dwóch szerokościach (~9 600 elementów)
   przed i po usunięciu Bootstrapa. Warunek stopu: ZERO różnic. Zmieniając cokolwiek tutaj,
   przepuść to przez `--compare-baseline`, bo te reguły dotykają każdego ekranu naraz. */
*, *::before, *::after { box-sizing: border-box; }

/* ── Panele podniesione do warstwy nad stroną (top layer) ─────────────────────────────────────
   Rozwijany panel przycięty przodkiem z `overflow` nie da się uratować `z-index`-em: nożyczki
   działają przed układaniem warstw. Jedyne miejsce, którego żaden przodek nie dosięga, to warstwa
   nad stroną — atrybut `popover` nakłada Components/Shared/PodniesDoWarstwy.razor.js.

   ⚠ Przeglądarka dokłada elementom z `popover` własne style, w tym `color: CanvasText` — kolor
   z palety SYSTEMU, który nic nie wie o naszym trybie ciemnym. Zdejmujemy go tutaj RAZ, a nie
   w kilkunastu panelach. Reguła stoi na górze pliku celowo: ma tę samą wagę co `.snooze-list`
   czy `.ms-panel`, więc każdy panel, który sam ustawia kolor, wygrywa kolejnością. */
[popover] { color: inherit; }

body {
    margin: 0;
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    /* ⚠ Było tu zaszyte #212529 — kolor tekstu, który dawał Bootstrap. Zostawiono go „1:1, żeby
       usunięcie Bootstrapa niczego nie przemalowało", z odłożoną na później decyzją o przejściu
       na paletę. Decyzję podjął pomiar (29.08.2026): w motywie ciemnym #212529 na tle karty
       rgb(26,29,35) daje 1,09 : 1 — tekst jest fizycznie nieczytelny, bo motyw ciemny nie ma jak
       podmienić wartości wpisanej na sztywno. Paleta ma obie wersje, hex nie ma żadnej. */
    color: var(--text);
    line-height: 1.5;
}

/* Nagłówki: przeglądarka domyślnie daje im bold i duże marginesy — Bootstrap to normował. */
h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; }
p { margin-top: 0; margin-bottom: 1rem; }
ul, ol { padding-left: 2rem; margin-top: 0; margin-bottom: 1rem; }
ul ul, ol ul, ul ol, ol ol { margin-bottom: 0; }
dl, dd { margin-top: 0; margin-bottom: 0.5rem; }
hr { margin: 1rem 0; color: inherit; border: 0; border-top: 1px solid; opacity: 0.25; }

/* Pola i przyciski dziedziczą typografię — bez tego przeglądarka wraca do własnych 13.3333px
   i formularze robią się mniejsze od reszty interfejsu. */
button, input, optgroup, select, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; }
button, select { text-transform: none; }
button { border-radius: 0; }
button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; }
button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) { cursor: pointer; }
[role="button"] { cursor: pointer; }
textarea { resize: vertical; }
label { display: inline-block; }
legend { float: left; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: 1.5rem; line-height: inherit; }
fieldset { min-width: 0; padding: 0; margin: 0; border: 0; }

table { caption-side: bottom; border-collapse: collapse; }
th { text-align: inherit; text-align: -webkit-match-parent; }
thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; }

img, svg { vertical-align: middle; }
small { font-size: 0.875em; }
strong, b { font-weight: bolder; }
sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; }
sub { bottom: -0.25em; }
sup { top: -0.5em; }
/* Stos DOKLADNIE jak w Bootstrapie — inna kolejnosc daje inna czcionke w blokach `code`. */
code, kbd, samp, pre { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 1em; }
pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; }
/* `code` był stylowany przez Bootstrapa (mniejszy stopień + różowy) i tak wygląda dziś w Ustawieniach. */
/* Kolor przez zmienną, nie hexem: różowy #d63384 (domyślny Bootstrapa) na tle karty motywu
   ciemnego daje 3,72 : 1, a `<code>` stoi na ekranach klienta (np. „Dodaj integrację"). */
code { font-size: 0.875em; color: var(--code-text); word-wrap: break-word; }
a > code { color: inherit; }
pre code { font-size: inherit; color: inherit; word-break: normal; }
kbd { padding: 0.1875rem 0.375rem; font-size: 0.875em; color: var(--text-light); background-color: var(--global-palette3); border-radius: 0.25rem; }
kbd kbd { padding: 0; font-size: 1em; }
a { color: inherit; }
summary { display: list-item; cursor: pointer; }
[hidden] { display: none !important; }

:root, [data-theme="light"] {
    /* AB brand colors — stałe (taki sam zielony i limonkowy w obu motywach) */
    --global-palette1: #009244;
    --global-palette2: #c1d11c;
    --global-palette3: #111317;
    --global-palette4: #022c32;
    --global-palette5: #1e4c53;
    --global-palette6: #4a6a6e;
    --text-light: #ffffff;
    --p1: #009244; --p2: #c1d11c; --p3: #111317; --p4: #022c32; --p5: #1e4c53; --p6: #4a6a6e;

    /* Krój o stałej szerokości znaku — JEDNO miejsce. Stos był przepisany z palca w kilkunastu
       regułach i w sześciu z nich stało `var(--mono, …)`, czyli odwołanie do znacznika, którego
       paleta nie miała: numery zgłoszeń i adresy formularzy szły wtedy zapasowym `monospace`
       przeglądarki, a nie tym samym krojem, co reszta liczb w tabelach. */
    --mono: 'Geist Mono', ui-monospace, 'SF Mono', monospace;

    /* Channel marks — stałe per kanał */
    --ch-allegro: #ff5a00;
    --ch-erli:    #00a78e;
    --ch-amazon:  #232f3e;
    --ch-email:   #6b46c1;
    --ch-ebay:    #e53238;

    /* Sizing — stałe */
    --sidebar-w: 230px;
    --topbar-h:  3.5rem;
    --radius-sm: 6px;
    --radius:    8px;
    --radius-lg: 12px;

    /* === LIGHT MODE PALETA (default) === */
    --cream:       #faf9f5;
    --cream-2:     #f4f2ea;
    --paper:       #ffffff;
    --line:        #e8e5db;
    --line-strong: #d3d0c4;
    /* TRZY POZIOMY TEKSTU — PRZELICZONE 07.09.2026 NA PROG AA (4,5:1).
       Stary `--text-faint` (#8b9099) nie przechodzil NIGDZIE: 3,04:1 na `--cream`,
       2,86:1 na `--cream-2`, 3,21:1 na `--paper`. Samo przyciemnienie go nie
       ratowalo — przy 4,5:1 wchodzil na `--text-soft` (#5e6671) i z trzech
       poziomow robily sie dwa. Dlatego przesunieta jest CALA trojka naraz,
       zeby odstepy w jasnosci (CIE L*) zostaly te same, co dzisiaj:
         przed  L* 5,8 / 42,9 / 59,6   (odstepy 37,0 i 16,8)
         po     L* 5,8 / 29,5 / 45,5   (odstepy 23,6 i 16,1)
       Barwa i nasycenie kazdego poziomu zostaja bez zmian (chlodna szarosc
       H~215-220) — to nie jest przemalowanie, tylko zjazd po jasnosci.
       `--line-faint` to NOWA zmienna dla przygaszonej GRAFIKI (kropki stanu,
       ikony, suwak przewijania, obrys). Tam obowiazuje prog 3:1, nie 4,5:1,
       wiec zostaje jasna — ale i tak musiala drgnac, bo stara wartosc na
       `--cream-2` dawala 2,86:1, czyli nie przechodzila nawet progu dla grafiki.
       NIE UZYWAJ `--line-faint` do tekstu. */
    --text:        #111317;         /* L* 5,8  — 17,65 / 16,59 / 18,59 : 1 */
    --text-soft:   #40464e;         /* L* 29,5 —  9,04 /  8,50 /  9,53 : 1 */
    --text-faint:  #676c76;         /* L* 45,5 —  5,00 /  4,70 /  5,27 : 1 */
    --line-faint:  #80858f;         /* GRAFIKA, nie tekst — 3,52 / 3,30 / 3,70 : 1 */
    --bg-light:    #faf9f5;
    --border-color:#e8e5db;

    --danger:    #c4392f; --danger-bg: #fbe9e6;
    /* TLO OSTRZEZENIA BYLO CIEPLYM KREMEM, CZYLI TYM SAMYM, CO TLO STRONY (02.09.2026).
       Plakietka "Doreczony" na zwrotach znikala, a spokojniejszy "Zwrot zgloszony"
       (niebieski) bylo widac dobrze — stan wymagajacy uwagi czytal sie slabiej niz stan
       neutralny. Pozostale trzy tla odcinaja sie od kremu barwa; ostrzezenie nie mialo
       czym, bo jest z tej samej rodziny.
       `--warn-mocny` to kolor NAPISU na tym tle: sam `--warn` dawal na nim kontrast
       2,6:1, czyli ponizej progu czytelnosci. Grafika (paski SLA, kropki) zostaje przy
       jasniejszym `--warn` — tam kontrast liczy sie inaczej niz dla tekstu. */
    --warn:      #c98a14; --warn-bg:   #f8e5b4; --warn-mocny: #7a5200;
    --info:      #2563eb; --info-bg:   #e2ebff;
    --ok:        var(--p1); --ok-bg:   #e3f4eb;

    --shadow-sm:    0 1px 2px rgba(17,19,23,0.04), 0 1px 3px rgba(17,19,23,0.06);
    --shadow-md:    0 4px 12px rgba(17,19,23,0.06), 0 2px 4px rgba(17,19,23,0.04);
    --shadow-lg:    0 12px 32px rgba(17,19,23,0.08), 0 4px 8px rgba(17,19,23,0.04);
    --shadow-inset: inset 0 0 0 1px var(--line);
    --card-shadow:  0 1px 2px rgba(17,19,23,0.04), 0 1px 3px rgba(17,19,23,0.06);
    --hover-shadow: 0 4px 12px rgba(17,19,23,0.06), 0 2px 4px rgba(17,19,23,0.04);

    --grad-brand: linear-gradient(95deg, #009244 0%, #c1d11c 100%);
    --grad-dark:  linear-gradient(180deg, #022c32 0%, #1e4c53 100%);

    /* Grain overlay opacity — w dark mode wygaszony */
    --grain-opacity: 1;

    /* ── Pozostałości po Bootstrapie ─────────────────────────────────────────────────────────
       Te trzy wartości stały w kodzie wpisane hexem (#f8f9fa, #495057, #d63384 — gray-100,
       gray-700 i różowy `code` Bootstrapa). Motyw ciemny nie ma jak podmienić liczby wpisanej
       na sztywno, więc jasnoszare tło zostawało jasnoszare także w ciemnym: tekst z palety
       (#e8e5db) na #f8f9fa to 1,2 : 1.
       ⚠ W motywie JASNYM zostają CO DO BAJTA — to nie jest przemalowanie, tylko dorobienie
       drugiej wersji tam, gdzie jej nigdy nie było. */
    --surface-muted:      #f8f9fa;
    --surface-muted-text: #495057;
    --code-text:          #d63384;
}

/* === DARK MODE PALETA === */
[data-theme="dark"] {
    --cream:       #0e1014;            /* primary background */
    --cream-2:     #181b22;            /* secondary background (table headers, alt rows) */
    --paper:       #1a1d23;            /* card body */
    --line:        #2a2e35;
    --line-strong: #3a3e45;
    --text:        #e8e5db;         /* L* 90,9 — 15,11 / 13,67 / 13,39 : 1 */
    --text-soft:   #afb3b9;         /* L* 72,8 —  9,04 /  8,18 /  8,02 : 1 */
    --text-faint:  #838892;         /* L* 56,6 —  5,35 /  4,84 /  4,74 : 1 */
    --line-faint:  #6c707a;         /* GRAFIKA, nie tekst — 3,84 / 3,48 / 3,41 : 1 */
    --bg-light:    #0e1014;
    --border-color:#2a2e35;

    --danger:    #ef6055; --danger-bg: #3a1a17;
    --warn:      #e0a13d; --warn-bg:   #4a3813; --warn-mocny: #f0c778;
    --info:      #5a8aff; --info-bg:   #1a2440;
    --ok:        #2eb068; --ok-bg:     #142f1f;

    --shadow-sm:    0 1px 2px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.5);
    --shadow-md:    0 4px 12px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.35);
    --shadow-lg:    0 12px 32px rgba(0,0,0,0.5), 0 4px 8px rgba(0,0,0,0.4);
    --shadow-inset: inset 0 0 0 1px var(--line);
    --card-shadow:  0 1px 2px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.5);
    --hover-shadow: 0 4px 12px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.35);

    /* grain w dark mode rozpraszany — białe szumy na ciemnym tle nie wygladają dobrze */
    --grain-opacity: 0.15;

    /* Ciemne odpowiedniki bootstrapowych resztek — patrz komentarz w bloku jasnym. */
    --surface-muted:      #181b22;
    --surface-muted-text: #a8acb3;
    --code-text:          #f78fb3;
}

/* Auto-prefers (jeśli user NIE wybrał ręcznie, weź system preference) */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]):not([data-theme="dark"]) {
        --cream:       #0e1014;
        --cream-2:     #181b22;
        --paper:       #1a1d23;
        --line:        #2a2e35;
        --line-strong: #3a3e45;
        --text:        #e8e5db;
        --text-soft:   #afb3b9;
        --text-faint:  #838892;
        --line-faint:  #6c707a;     /* GRAFIKA, nie tekst */
        --bg-light:    #0e1014;
        --border-color:#2a2e35;

        --danger:    #ef6055; --danger-bg: #3a1a17;
        --warn:      #e0a13d; --warn-bg:   #4a3813; --warn-mocny: #f0c778;
        --info:      #5a8aff; --info-bg:   #1a2440;
        --ok:        #2eb068; --ok-bg:     #142f1f;

        --shadow-sm:    0 1px 2px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.5);
        --shadow-md:    0 4px 12px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.35);
        --shadow-lg:    0 12px 32px rgba(0,0,0,0.5), 0 4px 8px rgba(0,0,0,0.4);
        --card-shadow:  0 1px 2px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.5);
        --hover-shadow: 0 4px 12px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.35);
        --grain-opacity: 0.15;

        --surface-muted:      #181b22;
        --surface-muted-text: #a8acb3;
        --code-text:          #f78fb3;
    }
}

html, body {
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    background: var(--cream);
    background-image:
        radial-gradient(at 0% 0%, rgba(193,209,28,0.045) 0px, transparent 40%),
        radial-gradient(at 100% 100%, color-mix(in srgb, var(--global-palette1) 4%, transparent) 0px, transparent 50%);
    background-attachment: fixed;
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Subtle grain overlay (mockup vibe) — w dark mode wygaszony przez var(--grain-opacity) */
body::before {
    content: '';
    position: fixed; inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.92' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.06 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    opacity: var(--grain-opacity, 1);
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 9999;
}

/* Editorial / utility typography helpers */
.serif      { font-family: 'Instrument Serif', Georgia, serif; font-weight: 400; }
.mono       { font-family: 'Geist Mono', ui-monospace, 'SF Mono', monospace; font-feature-settings: 'tnum' 1; letter-spacing: -0.01em; }
.italic     { font-style: italic; }
.uppercase  { text-transform: uppercase; letter-spacing: 0.08em; font-size: 11px; font-weight: 500; }

a, .btn-link { color: var(--global-palette1); }

.btn:focus, .btn:active:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem color-mix(in srgb, var(--global-palette1) 50%, transparent);
}

h1:focus { outline: none; }

.valid.modified:not([type=checkbox]) { outline: 1px solid var(--global-palette1); }
.invalid { outline: 1px solid #e50000; }
/* --danger, nie bootstrapowe #dc3545: to drugie na tle karty motywu ciemnego daje 3,70 : 1. */
.validation-message { color: var(--danger); font-size: 0.85rem; }

/* Wiersz, który jeszcze jest, ale już nie obowiązuje — np. cofnięte połączenie zgłoszeń.
   ⚠ Znalezione przy okazji, tą samą sondą co `txt-danger` (09.09.2026): klasa stała
   w `PolaczoneZgloszenia.razor` przy warunku `p.Cofniete` i nie miała definicji w żadnym arkuszu,
   więc cofnięte połączenie wyglądało dokładnie tak samo jak obowiązujące. Napis „połączenie
   cofnięte" był jedyną różnicą i trzeba go było przeczytać. */
.is-muted { opacity: 0.6; }
.is-muted a { color: var(--text-soft); }

/* Liczba, która ma krzyczeć — pojedyncza wartość w tabeli, nie cały wiersz.
   ⚠ Ta klasa BYŁA UŻYWANA, ZANIM POWSTAŁA. Do 09.09.2026 stała w jednym miejscu
   (`ReturnsByProductReport`, kolumna „Zwroty 30d") i nie miała definicji w żadnym ze 180 arkuszy
   projektu — czyli liczba nie robiła się czerwona nigdy, a zdanie pod tabelą tłumaczyło człowiekowi,
   co znaczy jej czerwień. Nieistniejąca klasa wygląda w kodzie dokładnie jak istniejąca. */
.txt-danger { color: var(--danger); }

.blazor-error-boundary {
    background: #b32121;
    padding: 1rem;
    color: white;
}
.blazor-error-boundary::after { content: "Wystąpił błąd."; }

/* Globalny default hide dla Blazor reconnect/error UI.
   Blazor JS wstrzykuje inline `style="display: block"` gdy realny circuit error,
   więc default hidden = bezpieczny stan. Bez tego scoped CSS layout-u nie matchuje
   #blazor-error-ui w innym layoucie (np. EditorialLayout) i UI pokazuje się stale. */
#blazor-error-ui {
    color-scheme: light only;
    background: #fff3cd;
    border-top: 1px solid #ffc107;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    color: #856404;
}
#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}
#blazor-error-ui .reload {
    color: #009244;
    text-decoration: underline;
    margin: 0 0.25rem;
}

/* ---------- Layout helpers ---------- */
.modern-container {
    width: 100%;
    padding: 0.75rem;
    animation: fadeIn 0.4s ease-in;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

.hero-section {
    background: linear-gradient(135deg, var(--global-palette4) 0%, var(--global-palette5) 100%);
    border-radius: 8px;
    padding: 1.25rem 1.5rem;
    margin-bottom: 1rem;
    box-shadow: var(--card-shadow);
    position: relative;
    overflow: hidden;
    color: white;
}
.hero-section::before {
    content: '';
    position: absolute;
    top: -50%; right: -10%;
    width: 400px; height: 400px;
    background: var(--global-palette1);
    opacity: 0.08;
    border-radius: 50%;
}
.hero-section h1 { color: white; margin: 0; }
.hero-section p { color: rgba(255,255,255,0.85); margin: 0.5rem 0 0; }

/* ---------- Cards ---------- */
.modern-card {
    background: var(--paper);
    color: var(--text);
    border-radius: 4px;
    padding: 1rem 1.25rem;
    margin-bottom: 1rem;
    box-shadow: var(--card-shadow);
    border-left: 4px solid var(--global-palette1);
    transition: all 0.3s ease;
}
.modern-card:hover { box-shadow: var(--hover-shadow); }

.card-header-modern {
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 1rem;
    padding-bottom: 0.6rem;
    border-bottom: 2px solid var(--global-palette2);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* ---------- Forms ---------- */
.modern-input, select.modern-input, textarea.modern-input {
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 0.7rem 0.9rem;
    font-size: 0.95rem;
    transition: all 0.3s ease;
    background: var(--paper);
    color: var(--text);
    width: 100%;
    font-family: inherit;
}
.modern-input:focus {
    border-color: var(--global-palette1);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--global-palette1) 10%, transparent);
    outline: none;
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1rem;
}
.form-field {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.form-label-modern {
    font-weight: 600;
    color: var(--text);
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.label-badge {
    background: var(--global-palette1);
    color: white;
    padding: 0.15rem 0.5rem;
    border-radius: 3px;
    font-size: 0.7rem;
    font-weight: 600;
}

.toggle-switch {
    position: relative;
    display: inline-block;
    width: 56px;
    height: 28px;
    flex-shrink: 0;
}
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background: #ccc;
    border-radius: 28px;
    transition: 0.3s;
}
.toggle-slider:before {
    position: absolute;
    content: "";
    height: 22px; width: 22px;
    left: 3px; bottom: 3px;
    background: white;
    border-radius: 50%;
    transition: 0.3s;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
input:checked + .toggle-slider { background: var(--global-palette1); }
input:checked + .toggle-slider:before { transform: translateX(28px); }

.readonly-value {
    padding: 0.6rem 0.85rem;
    background: var(--surface-muted);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--surface-muted-text);
    min-height: 2.4rem;
    display: flex;
    align-items: center;
    word-break: break-word;
}

/* ---------- Buttons ---------- */
.modern-btn {
    padding: 0.7rem 1.25rem;
    border-radius: 4px;
    font-weight: 600;
    font-size: 0.9rem;
    border: none;
    cursor: pointer;
    transition: all 0.3s ease;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    text-decoration: none;
}
.modern-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.modern-btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

.btn-gradient-success { background: var(--global-palette1); color: white; }
.btn-gradient-success:hover { background: #007a38; color: white; }

.btn-gradient-primary { background: var(--global-palette5); color: white; }
.btn-gradient-primary:hover { background: var(--global-palette4); color: white; }

.btn-gradient-info { background: var(--global-palette6); color: white; }
.btn-gradient-info:hover { background: var(--global-palette5); color: white; }

.btn-gradient-warning { background: #dc3545; color: white; }
.btn-gradient-warning:hover { background: #c82333; color: white; }

.btn-gradient-secondary { background: #6c757d; color: white; }
.btn-gradient-secondary:hover { background: #5a6268; color: white; }

/* ---------- Pasek alarmu (alert banner) ----------
   ⚠ Te klasy stały do 29.08.2026 w Dashboard.razor.css, czyli w arkuszu ZAKRESOWYM. Zakresowy
   arkusz działa wyłącznie w swoim komponencie, a `.alert-banner` używają też ekran rozmowy,
   edycja skrzynki i podłączanie skrzynki — i tam pasek renderował się jako goły szary tekst,
   bez ramki i bez kolorowego paska z boku. Najbardziej bolało to przy „Sprawdź połączenie":
   odpowiedź na kliknięcie wyglądała jak przypadkowe zdanie wsunięte w formularz.
   Ten sam błąd i ta sama naprawa co wcześniej przy kafelkach KPI. */
.alert-banner {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--danger);
    background: var(--danger-bg);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    animation: shake-in 0.6s ease-out forwards;
    color: var(--text);
}

@keyframes shake-in {
    0% { transform: translateX(0); opacity: 0; }
    25% { transform: translateX(-3px); opacity: 0.5; }
    50% { transform: translateX(3px); opacity: 0.8; }
    75% { transform: translateX(-1px); }
    100% { transform: translateX(0); opacity: 1; }
}

.alert-bar { width: 5px; background: var(--danger); }
.alert-icon {
    width: 56px;
    display: grid; place-items: center;
    background: rgba(196,57,47,0.08);
    color: var(--danger);
}
.alert-icon svg { width: 24px; height: 24px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.alert-content {
    flex: 1;
    padding: 0.85rem 1.1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.alert-text { color: var(--text); }
.alert-text strong { color: var(--danger); font-weight: 600; }
.alert-text .alert-headline { font-size: 14px; font-weight: 500; margin-bottom: 2px; }
.alert-text .alert-sub { font-size: 12px; color: var(--text-soft); }
.alert-actions { display: flex; gap: 0.5rem; }

/* ---------- Banners ---------- */
.warning-banner, .success-banner, .info-banner, .error-banner {
    border-radius: 4px;
    padding: 0.85rem 1.25rem;
    margin: 0.75rem 0;
    font-weight: 500;
}
.warning-banner { background: #fff3cd; border-left: 4px solid #ffc107; color: #856404; }
.success-banner { background: #d4edda; border-left: 4px solid var(--global-palette1); color: #155724; }
.info-banner    { background: #f1f5f9; border-left: 4px solid #cbd5e1; color: #475569; }
.error-banner   { background: #f8d7da; border-left: 4px solid #dc3545; color: #721c24; }

/* ---------- Toast ---------- */
.toast-notification {
    position: fixed;
    bottom: 2rem;
    right: 2rem;
    padding: 0;
    border-radius: 4px;
    color: white;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 1000;
    animation: slideInRight 0.4s ease-out;
    max-width: 500px;
    min-width: 280px;
}
@keyframes slideInRight {
    from { transform: translateX(400px); opacity: 0; }
    to   { transform: translateX(0); opacity: 1; }
}
.toast-success { background: var(--global-palette1); }
.toast-error   { background: #dc3545; }
.toast-content {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 1rem 1.5rem;
    gap: 1rem;
}
.toast-content span {
    flex: 1;
    word-break: break-word;
    line-height: 1.5;
}
.toast-close-btn {
    background: none;
    border: none;
    color: white;
    font-size: 1.6rem;
    cursor: pointer;
    line-height: 1;
    opacity: 0.85;
}
.toast-close-btn:hover { opacity: 1; }

/* ---------- Spinner ---------- */
.spinner-overlay {
    position: fixed; inset: 0;
    background: rgba(17, 19, 23, 0.85);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    animation: fadeIn 0.3s ease;
}
/* `var(--paper)`, nie `white`: w ciemnym motywie biala plansza na ciemnym tle wyglada jak
   awaria interfejsu. `max-width` liczony z szerokoscia okna — na telefonie (<=768px) zaslona
   z dluzszym zdaniem wychodzila poza ekran i tekst dawalo sie przewijac w bok. */
.spinner-content {
    background: var(--paper);
    color: var(--text);
    padding: 2rem;
    border-radius: 8px;
    text-align: center;
    box-shadow: 0 8px 24px rgba(0,0,0,0.2);
    max-width: min(24rem, calc(100vw - 2.5rem));
}
.spinner {
    width: 50px; height: 50px;
    border: 4px solid #f3f3f3;
    border-top: 4px solid var(--global-palette1);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    margin: 0 auto 1rem;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Tables ---------- */
.modern-table {
    width: 100%;
    border-collapse: collapse;
    background: white;
    border-radius: 4px;
    overflow: hidden;
    box-shadow: var(--card-shadow);
}
.modern-table th {
    background: var(--global-palette4);
    color: white;
    text-align: left;
    padding: 0.75rem 1rem;
    font-weight: 600;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.modern-table td {
    padding: 0.65rem 1rem;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.95rem;
}
.modern-table tr:last-child td { border-bottom: none; }
.modern-table tr:hover td { background: color-mix(in srgb, var(--global-palette1) 5%, transparent); }

.table-wrap { overflow-x: auto; }

/* ---------- Worker checklist (rejestruj czas) ---------- */
.worker-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
}
.worker-row {
    display: flex;
    align-items: center;
    background: var(--surface-muted);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 0.6rem 0.75rem;
    gap: 0.6rem;
    transition: all 0.2s ease;
}
.worker-row.checked {
    background: color-mix(in srgb, var(--global-palette1) 8%, transparent);
    border-color: var(--global-palette1);
}
.worker-row label {
    flex: 1;
    cursor: pointer;
    font-weight: 500;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0;
}
.worker-row input[type=checkbox] {
    width: 22px; height: 22px;
    accent-color: var(--global-palette1);
    cursor: pointer;
    flex-shrink: 0;
}
.worker-row .ot-input {
    width: 80px;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    text-align: right;
    font-size: 0.95rem;
}
.worker-row .ot-input:disabled { background: #f1f1f1; opacity: 0.6; }
.worker-row .ot-suffix { font-size: 0.8rem; color: var(--global-palette6); white-space: nowrap; }

/* ---------- Button row ---------- */
.btn-row {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}
.btn-row .modern-btn { min-width: 160px; }

/* ---------- Mobile tweaks ---------- */
@media (max-width: 640.98px) {
    .modern-container { padding: 0.5rem; }
    .modern-card { padding: 0.85rem; }
    .modern-btn { padding: 0.7rem 1rem; font-size: 0.85rem; }
    .toast-notification { right: 0.5rem; bottom: 0.5rem; left: 0.5rem; max-width: none; }
    .btn-row .modern-btn { flex: 1 1 100%; min-width: 0; }
    .form-grid { grid-template-columns: 1fr; }
}

/* ---------- Responsive toggles ----------
   Bez bazowego `display`, bo wewnętrzne klasy (np. `.data-card-list { display: flex }`)
   ustawiają własny tryb i nie chcemy ich nadpisywać. Toggle wyłącznie w media query
   z !important — kontrola na poziomie bandwidth. */
@media (max-width: 768px) {
    .desktop-only { display: none !important; }
}
@media (min-width: 769px) {
    .mobile-only  { display: none !important; }
}

/* ---------- Reconnect blocked overlay ----------
   `body.abc-disconnected` ustawia JS reconnect handler gdy SignalR circuit jest down.
   Strona w tle przyciemniona + pointer-events: none — user widzi wyraźnie że nie może
   działać, NIE pisze w textarea „w pustkę" przez 30 sekund. Reconnect modal sam ma
   wyższy z-index i pointer-events: auto, więc „Połącz teraz" pozostaje klikalny. */
body.abc-disconnected main,
body.abc-disconnected .sidebar,
body.abc-disconnected .topbar {
    pointer-events: none;
    user-select: none;
    filter: grayscale(0.3) brightness(0.92);
    opacity: 0.65;
    transition: opacity 0.2s, filter 0.2s;
}
body.abc-disconnected input,
body.abc-disconnected textarea,
body.abc-disconnected select,
body.abc-disconnected button:not(.abc-reconnect-btn) {
    pointer-events: none !important;
}

/* ---------- Key-value row (label + value) ----------
   Default layout: label po lewej (uppercase), value po prawej. Value mozemy mieć dlugi
   (subject konwersacji, URL, long token) — musi sie zawijac, nie wystawac z karty. */
.kv-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.4rem 0;
    font-size: 13.5px;
    border-bottom: 1px solid var(--line);
    gap: 0.75rem;
}
.kv-row:last-child { border-bottom: none; }
/* Zdanie pod wierszem „klucz : wartość", gdy sama wartość wprowadzałaby w błąd — np. zero, które
   mówi o tym, czego NIE POBRALIŚMY, a czyta się jak fakt o kliencie (09.09.2026, przegląd UX poz. 9). */
.kv-uwaga {
    margin: 0.15rem 0 0.6rem;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--text-soft);
}
.kv-label {
    color: var(--text-soft);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    /* ⚠ Było `flex: 0 0 auto`, czyli „nigdy się nie kurcz". Etykieta nie mieszcząca się obok
       wartości nie zawijała się, tylko WYCHODZIŁA poza wiersz — złapane 13.08.2026, gdy
       „Konektor" i „External ID" zamieniły się na dłuższe polskie „Rodzaj integracji"
       i „Numer u dostawcy" (9 i 11 px poza kartą). Dłuższe tłumaczenie nie może rozwalać
       układu, więc etykieta ma prawo się zwęzić i złamać. */
    flex: 0 1 auto;
    /* ⚠ Było `min-width: 0` — i TO ONO przecinało wyraz, nie sposób zawijania.
       `min-width: 0` znosi automatyczne minimum elementu elastycznego, czyli pozwala ścisnąć go
       PONIŻEJ jego najdłuższego wyrazu; wtedy przeglądarka nie ma wyjścia i wyraz tnie. Sama
       zmiana `anywhere` → `break-word` tego nie naprawiła: zmierzone po wydaniu, „Załączniki”
       nadal dostawało 46-51 px przy potrzebnych 66. `min-content` mówi dokładnie to, o co chodzi:
       kurcz się, ale nie poniżej jednego wyrazu. Karta i tak nie pęknie — wartość obok ma
       `flex: 1 1 auto` z `min-width: 0`, więc to ona oddaje miejsce. */
    min-width: min-content;
    /* ⚠ Było `anywhere` — a ono dodatkowo obniża szerokość minimalną do JEDNEJ LITERY. Różnica między
       `anywhere` a `break-word` nie dotyczy tego, gdzie wolno złamać wyraz (oba pozwalają),
       tylko SZEROKOŚCI MINIMALNEJ elementu: przy `anywhere` spada ona do jednej litery, więc
       pojemnik elastyczny ma prawo ścisnąć etykietę poniżej jej najdłuższego wyrazu i wtedy go
       przecina. `break-word` zostawia minimum na najdłuższym wyrazie — etykieta nie zejdzie
       poniżej „ZAŁĄCZNIKI”, a intencja z 13.08.2026 (nie wychodzić poza kartę) zostaje.
       Widziane na `/integrations` na WSZYSTKICH czterech szerokościach; sonda tego nie łapała,
       bo reguła „tekst łamany” zaczyna od pominięcia tekstów bez spacji. */
    overflow-wrap: break-word;
}
.kv-val {
    color: var(--text);
    text-align: right;
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;  /* dlugi GUID / subject się zawinie */
    word-break: break-word;
}
.kv-val.mono {
    font-family: 'Geist Mono', monospace;
    font-size: 12px;
}

/* ---------- Form grid responsive (e.g. invite agent) ----------
   Default 3 col na desktop (label-pair-pair-button). Mobile: 1 col stack — button na końcu pełnej szerokości. */
.agents-invite-grid {
    display: grid;
    /* Kolumna roli szersza niż 220 px od 09.09.2026: pozycja listy nie jest już samą nazwą,
       tylko nazwą i tym, co ta rola daje — a zwinięty `select` ucina bez ostrzeżenia. */
    grid-template-columns: 1fr 270px auto;
    gap: 0.75rem;
    align-items: end;
}
@media (max-width: 768px) {
    .agents-invite-grid {
        grid-template-columns: 1fr;
    }
    .agents-invite-grid > button {
        width: 100%;
        justify-content: center;
    }
}

/* Opisy ról pod listą wyboru (09.09.2026, przegląd UX poz. 16). Ekran Agentów jest statyczny,
   więc opis wybranej roli nie ma jak pojawić się „po wybraniu" — stoją wszystkie naraz, drobnym
   drukiem, jako ściąga przy decyzji „Właściciel czy Administrator". */
.agents-role-opisy {
    margin: 0.9rem 0 0;
    display: grid;
    gap: 0.45rem;
    font-size: 12.5px;
    line-height: 1.45;
}
.agents-role-opis {
    display: grid;
    grid-template-columns: 9.5rem 1fr;
    gap: 0.6rem;
    align-items: baseline;
}
.agents-role-opis > dt { font-weight: 600; color: var(--text); margin: 0; }
.agents-role-opis > dd { margin: 0; color: var(--text-soft); min-width: 0; }
@media (max-width: 768px) {
    .agents-role-opis { grid-template-columns: 1fr; gap: 0.1rem; }
}

/* ---------- Outbox detail responsive grid ----------
   Desktop: payload 2/3 + aside 1/3 obok siebie. Mobile (<880px): full-width stack —
   aside (Powiązanie/Timeline) WYŻEJ niż payload, bo „przejdź do dyskusji" + customer chip
   są ważniejsze dla agenta na mobile niż raw JSON payload. */
.outbox-detail-grid {
    display: grid;
    /* ⚠ `minmax(0, …)`, nie gole `2fr 1fr`. Sciezka `fr` ma AUTOMATYCZNE MINIMUM rowne szerokosci
       minimalnej tresci — wiec jedna dluga linia bez spacji (surowy ladunek operacji w bloku
       `<pre>`) rozpycha pierwsza kolumne ponad jej udzial i sciska druga. Zmierzone 18.08.2026:
       CALY prawy panel („Powiazanie", „Przebieg", klient, konto) zostal wypchniety poza ekran,
       a jego wiersze mialy po 26 px szerokosci. Uzytkownik nie widzial, do ktorej rozmowy nalezy
       operacja — czyli tego, po co ten ekran istnieje. `minmax(0, 2fr)` znosi to minimum. */
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: flex-start;
}
@media (max-width: 880px) {
    .outbox-detail-grid {
        grid-template-columns: 1fr;
    }
    .outbox-detail-grid > aside {
        order: -1;  /* aside (powiązanie/timeline) pierwsze na mobile */
    }
}

/* ----------------------------------------------------------------------
   Theme toggle button — CSS-only icon visibility per active mode
   ----------------------------------------------------------------------
   Pokazuje TYLKO ikone aktualnego motywu (nie obu naraz). CSS reaguje na
   <html data-theme="..."> ustawiane przez SSR (App.razor z cookie).
   Gdy brak data-theme → follow prefers-color-scheme (auto effective).
   Zaden JS nie ustawia display - eliminuje race conditions po enhanced nav.
*/
.abc-theme-toggle .abc-theme-icon {
    line-height: 1;
    font-size: 16px;
    display: none;
}
/* Default (brak data-theme, system light) → slonce */
.abc-theme-toggle .abc-theme-icon-light { display: inline; }
/* System dark + brak override → ksiezyc */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .abc-theme-toggle .abc-theme-icon-light { display: none; }
    :root:not([data-theme="light"]) .abc-theme-toggle .abc-theme-icon-dark  { display: inline; }
}
/* Explicit data-theme override */
:root[data-theme="light"] .abc-theme-toggle .abc-theme-icon-light { display: inline; }
:root[data-theme="light"] .abc-theme-toggle .abc-theme-icon-dark  { display: none; }
:root[data-theme="dark"]  .abc-theme-toggle .abc-theme-icon-light { display: none; }
:root[data-theme="dark"]  .abc-theme-toggle .abc-theme-icon-dark  { display: inline; }

/* ---------- Mobile table safety net ----------
   Każda <table> bez explicit `.desktop-only` / `.mobile-only` strategy dostaje horizontal scroll
   na mobile zamiast wypchnięcia treści poza viewport. Strony które już mają card-list mobile
   fallback opakowują table w `.table-wrap.desktop-only` — ten reset ich nie dotyka (są ukryte). */
@media (max-width: 768px) {
    .card > table,
    .content > table,
    table:not(.table-wrap *):not(.no-mobile-scroll) {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
    }
}

/* ---------- Conversation strip collapse (mobile) ----------
   Pasek statusu/agenta/tagów zajmuje dużo miejsca na mobile. Defaultnie chowamy go
   pod button "▼ Więcej", trigger pokazuje mini-podgląd Status + SLA + tag count. */
.conv-strip-toggle {
    /* Visibility kontrolowane przez klasę `mobile-only` na elemencie (display:none na desktop via media query). */
    display: flex;
    align-items: center; gap: 0.4rem;
    width: 100%;
    margin-top: 0.4rem;
    padding: 0.4rem 0.6rem;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    font-size: 12px;
    cursor: pointer;
    color: var(--text);
}
.conv-strip-toggle:hover { background: var(--cream-2); }
.conv-strip-toggle-more { margin-left: auto; color: var(--text-faint); font-weight: 600; }
.conv-strip-tags-count { color: var(--text-soft); font-size: 11px; }
@media (max-width: 768px) {
    .conv-strip { display: none !important; }
    .conv-strip.mobile-open {
        display: flex !important;
        flex-wrap: wrap; gap: 0.4rem 0.5rem;
        margin-top: 0.4rem; padding: 0.6rem; border-radius: 8px;
        background: var(--paper); border: 1px solid var(--line);
    }
}

/* ---------- Data cards (mobile alternative to tables) ---------- */
.data-card-list { display: flex; flex-direction: column; gap: 0.75rem; }
.data-card {
    background: var(--paper);
    color: var(--text);
    border-radius: 6px;
    padding: 0.85rem 1rem;
    box-shadow: var(--card-shadow);
    border-left: 4px solid var(--global-palette1);
}
.data-card-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 0.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.data-card-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.4rem 0;
    font-size: 0.9rem;
    border-bottom: 1px solid var(--line);
    gap: 0.5rem;
}
.data-card-row:last-of-type { border-bottom: none; }
.data-card-row .label {
    color: var(--text-faint);
    font-weight: 500;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex: 0 0 auto;
}
.data-card-row .value {
    font-weight: 600;
    color: var(--text);
    text-align: right;
    word-break: break-word;
    flex: 1 1 auto;
}
.data-card-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
    flex-wrap: wrap;
}
.data-card-actions .modern-btn {
    flex: 1 1 calc(50% - 0.25rem);
    min-width: 0;
    padding: 0.55rem 0.7rem;
    font-size: 0.78rem;
}

.status-badge {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 12px;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.status-badge.on  { background: color-mix(in srgb, var(--global-palette1) 15%, transparent); color: var(--global-palette1); }
.status-badge.off { background: rgba(220,53,69,0.12); color: #b91c1c; }

/* ---------- Modal ---------- */
.modal-overlay {
    position: fixed; inset: 0;
    background: rgba(17, 19, 23, 0.85);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    animation: fadeIn 0.25s ease;
    padding: 1rem;
    /* Overlay bez pointer-events (nie ma close-on-outside-click) — żeby buttony w dialogu
       były klikalne bez problemu „overlay intercepts pointer events". */
    pointer-events: none;
}
.modal-dialog {
    background: var(--paper);
    color: var(--text);
    border-radius: 10px;
    max-width: 640px;
    width: 100%;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 16px 48px rgba(0,0,0,0.4);
    animation: modalSlideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    overflow: hidden;
    /* Włącz interaktywność z powrotem dla samego dialogu i wszystkich jego dzieci. */
    pointer-events: auto;
}
@keyframes modalSlideUp {
    from { transform: translateY(40px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}
.modal-header {
    background: linear-gradient(135deg, var(--global-palette4) 0%, var(--global-palette5) 100%);
    color: white;
    padding: 1rem 1.25rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    border-bottom: 2px solid var(--global-palette1);
}
.modal-header h2 {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 600;
    color: white;
    flex: 1;
    word-break: break-word;
}
.modal-close {
    background: rgba(255,255,255,0.1);
    border: none;
    color: white;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    font-size: 1.4rem;
    cursor: pointer;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s;
    flex-shrink: 0;
}
.modal-close:hover { background: rgba(255,255,255,0.25); }

/* Mały kółkowy "×" do usuwania rzędów w listach (warunki/akcje automation, taski, itp).
   Inny niż .modal-close (który jest w nagłówku, na ciemnym tle) — neutralny, hover czerwony. */
.btn-icon-close {
    width: 26px; height: 26px;
    display: inline-grid; place-items: center;
    background: transparent;
    border: 1px solid var(--line, #e8e5db);
    color: var(--text-faint, #676c76);
    border-radius: 50%;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: all 0.15s;
    flex-shrink: 0;
    padding: 0;
}
.btn-icon-close:hover {
    background: var(--danger-bg, #fbe9e6);
    border-color: var(--danger, #c4392f);
    color: var(--danger, #c4392f);
}
/* ⚠ Ten sam przycisk na CIEMNYM pasku okna. `--text-faint` jest dobrany pod jasne tło i na
   gradiencie nagłówka daje 1,80:1 przy progu 4,5:1 (zmierzone 21.09, wydanie 33) — krzyżyka
   praktycznie nie widać, a używa go 13 okien. Na pasku bierze biel, tak jak napis obok niego. */
.modal-header .btn-icon-close {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.4);
}
.modal-header .btn-icon-close:hover {
    background: rgba(255, 255, 255, 0.18);
    border-color: #fff;
    color: #fff;
}
.modal-body {
    padding: 1.25rem;
    overflow-y: auto;
    flex: 1;
}
.modal-footer {
    padding: 0.85rem 1.25rem;
    background: var(--surface-muted);
    border-top: 1px solid var(--border-color);
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}
.modal-footer .modern-btn { min-width: 110px; }

@media (max-width: 640px) {
    /* Full-screen modal na mobile — nie sheet, lecz cała wysokość ekranu od topu.
       User feedback: bottom-sheet z 70% wysokości zostawia widoczny brzeg tła
       który myli (Image #17). Lepiej pełen ekran + duży obszar treści. */
    .modal-overlay { padding: 0; align-items: stretch; }
    .modal-dialog {
        max-height: 100vh;
        height: 100vh;
        max-width: 100%;
        width: 100%;
        border-radius: 0;
    }
    .modal-footer { padding: 0.75rem 1rem; }
    .modal-footer .modern-btn { flex: 1 1 calc(50% - 0.25rem); min-width: 0; }
}

/* ============================================
   ABCare mockup components (editorial-utility)
   ============================================ */

/* Cards */
.card {
    /* display:flex + kierunek kolumnowy szły dotąd z Bootstrapa — bez nich karty rozjeżdżają się
       na całej aplikacji (pomiar: `abcare-bootstrap-probe`). */
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    /* ⚠ TU SIEDZIAŁA NIEWIDZIALNOŚĆ MOTYWU CIEMNEGO. Bootstrap ustawiał na .card jawny #212529
       i po jego usunięciu wartość została „1:1, żeby nic nie przemalować" — ale hex nie ma wersji
       ciemnej. Pomiar 29.08.2026: #212529 na tle karty rgb(26,29,35) to 1,09 : 1 przy wymaganych
       4,5 : 1, czyli tekst, którego fizycznie nie widać. Ginęły przez to całe akapity na
       /settings/storage (nazwy skrzynek, obie liczby zajętości), karta „Sprawdź, czy są nowe
       wiadomości" i etykiety na ekranie dodawania skrzynki — wszędzie tam, gdzie element nie
       miał własnego koloru i dziedziczył ten z karty.
       ⚠ Reguła ma wagę (0,1,0) i stoi PÓŹNIEJ niż `html, body`, więc bije paletę na całej
       zawartości karty — dlatego nie wystarczyło poprawić samego `body`. */
    color: var(--text);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.card-header {
    padding: 1.1rem 1.25rem 0.6rem;
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1rem;
}
.card-title {
    font-family: 'Instrument Serif', Georgia, serif;
    font-size: 1.45rem;
    line-height: 1;
    letter-spacing: -0.01em;
    color: var(--text);
    margin: 0;
}
.card-title em { font-style: italic; color: var(--p1); }
.card-subtitle {
    color: var(--text-soft);
    font-size: 12.5px;
    margin-top: 0.35rem;
}
.card-body { padding: 0.5rem 1.25rem 1.25rem; }

/* ============================================
   Shared .data-table — globalna tabela ABCare (replace inline <table style="...">)
   Wszystkie strony settings/admin/raporty MUSZA uzywac tej klasy zamiast inline stylow.
   Dark mode dziala automatycznie przez tokens (var(--paper)/var(--line)/var(--text)).
   ============================================ */
.data-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--paper);
    color: var(--text);
}
.data-table thead {
    background: var(--cream-2);
}
.data-table thead tr {
    text-align: left;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 11px;
}
.data-table th {
    padding: 0.65rem 1rem;
    font-weight: 500;
}
.data-table th:first-child { padding-left: 1.25rem; }
.data-table th:last-child  { padding-right: 1.25rem; }
.data-table td {
    padding: 0.85rem 1rem;
    font-size: 13.5px;
    border-bottom: 1px solid var(--line);
    color: var(--text);
}
.data-table td:first-child { padding-left: 1.25rem; }
.data-table td:last-child  { padding-right: 1.25rem; }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--cream-2); transition: background 0.12s; }
.data-table .row-actions { text-align: right; white-space: nowrap; }

/* ──────────────────────────────────────────────────────────────────────
   .data-table.responsive — CSS-only auto-cards na mobile (≤768px)
   ──────────────────────────────────────────────────────────────────────
   Usage:
       <table class="data-table responsive">
           <thead><tr><th>Email</th><th>Rola</th></tr></thead>
           <tbody>
               <tr>
                   <td data-label="Email">anna@firma.pl</td>
                   <td data-label="Rola">Admin</td>
               </tr>
           </tbody>
       </table>

   - Każdy `<td>` MUSI mieć `data-label` (tekst z `<th>`).
   - Pierwszy `<td>` (data-card-title) renderowany jako headline bez labela.
   - Eliminuje konieczność dual markup `desktop-only` + `mobile-only`.
   ────────────────────────────────────────────────────────────────────── */
/* ⚠ SIATKA BEZPIECZEŃSTWA dla tabel BEZ klasy `responsive`.
   Sam `data-label` nic nie daje — reguła kart niżej łapie wyłącznie `.data-table.responsive`.
   Tabela bez tej klasy była na telefonie PRZYCINANA na krawędzi karty razem z ostatnią kolumną,
   czyli zwykle z przyciskami „Edytuj"/„Usuń" — nie dało się ich ani zobaczyć, ani kliknąć
   (sprawdzone na /settings/brands i /settings/email-channels). Poziome przewijanie to nie jest
   docelowy wygląd (dom­yślnie chcemy kart), ale gwarantuje, że nic nie zniknie bezpowrotnie.
   Zamiana konkretnej tabeli na karty = dodanie `responsive` + `data-label` na każdym `<td>`. */
@media (max-width: 768px) {
    .data-table:not(.responsive) {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;

        /* ⚠ Samo przewijanie NIE wystarczy: obcieta kolumna wyglada jak koniec tabeli
           i nikt nie zgaduje, ze cos jest dalej. Cien przy prawej krawedzi pojawia sie
           tylko wtedy, gdy faktycznie jest co przewijac, i znika po dojechaniu do konca
           (`background-attachment: local` na warstwach tla — bez JS-a i bez nasluchow). */
        background:
            linear-gradient(to right, var(--paper) 30%, transparent) left center,
            linear-gradient(to left,  var(--paper) 30%, transparent) right center,
            radial-gradient(farthest-side at 0 50%,   rgba(17,19,23,.16), transparent) left center,
            radial-gradient(farthest-side at 100% 50%, rgba(17,19,23,.16), transparent) right center;
        background-repeat: no-repeat;
        background-size: 28px 100%, 28px 100%, 12px 100%, 12px 100%;
        background-attachment: local, local, scroll, scroll;
    }
}

@media (max-width: 768px) {
    .data-table.responsive {
        display: block;
        background: transparent;
        min-width: 0 !important;
    }
    .data-table.responsive thead { display: none; }
    .data-table.responsive tbody { display: block; }
    .data-table.responsive tr {
        display: block;
        background: var(--paper);
        color: var(--text);
        border: 1px solid var(--line);
        border-left: 4px solid var(--p1);
        border-radius: 6px;
        margin-bottom: 0.75rem;
        padding: 0.85rem 1rem;
        box-shadow: var(--shadow-sm);
    }
    .data-table.responsive tr:hover { background: var(--paper); }
    .data-table.responsive td {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 0.75rem;
        padding: 0.4rem 0;
        border-bottom: 1px solid var(--line);
        font-size: 0.9rem;
        text-align: right;
    }
    .data-table.responsive td:first-child,
    .data-table.responsive td:last-child {
        padding-left: 0;
        padding-right: 0;
    }
    .data-table.responsive td:last-child { border-bottom: none; }

    /* ⚠ PUSTY WIERSZ ZNIKA Z KARTY, ale w tabeli ZOSTAJE (04.09.2026).
       W tabeli myslnik trzyma wyrownanie kolumn i czyta sie jako "nic tu nie ma".
       Na karcie kolumn nie ma, wiec ten sam myslnik kosztuje CALY wiersz z etykieta,
       ktory nie mowi nic. Na stanowisku karta kontrahenta "Delta" miala osiem wierszy,
       z czego CZTERY byly samym myslnikiem — polowa karty milczala, a czerwona
       plakietka zaleglosci u sasiada gubila sie w tym halasie.
       Komorka sama mowi o sobie, ze jest pusta (data-puste="1") — CSS nie umie
       wybierac po tresci, a zgadywanie po dlugosci tekstu bylo by loteria. */
    .data-table.responsive td[data-puste="1"] { display: none; }
    .data-table.responsive td::before {
        content: attr(data-label);
        font-weight: 500;
        color: var(--text-soft);
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        flex: 0 0 auto;
        text-align: left;
    }
    /* Headline row (first td) — bez labela, full width, większy font */
    .data-table.responsive td.cell-title,
    .data-table.responsive td[data-cell-title] {
        font-size: 1.05rem;
        font-weight: 600;
        color: var(--text);
        padding-bottom: 0.5rem;
        border-bottom: 1px solid var(--line);
        justify-content: flex-start;
        text-align: left;
    }
    .data-table.responsive td.cell-title::before,
    .data-table.responsive td[data-cell-title]::before { display: none; }

    /* Komórka z BLOKIEM treści (kilka akapitów, podgląd wiadomości), a nie pojedynczą wartością.
       ⚠ Domyślny wiersz karty to `justify-content: space-between` — etykieta z lewej, wartość
       z prawej. Przy kilku elementach w komórce każdy z nich staje się osobnym elementem flex
       i walczą o tę samą szerokość: teksty nachodzą na siebie i są przycinane. Tutaj etykieta
       idzie NAD treść, a treść dostaje całą szerokość karty. */
    .data-table.responsive td.cell-block {
        flex-direction: column;
        align-items: stretch;
        text-align: left;
        gap: 0.3rem;
    }
    .data-table.responsive td.cell-block::before { text-align: left; }

    /* Komórka z PRZYCISKAMI. `.row-actions` ma na komputerze `white-space: nowrap` (żeby dwa
       przyciski nie łamały się w kolumnie) — w karcie na telefonie ten sam zapis wypycha trzeci
       przycisk poza krawędź. Tu podpis idzie nad przyciski, a przyciski wolno łamać. */
    .data-table.responsive td.row-actions {
        flex-wrap: wrap;
        justify-content: flex-start;
        white-space: normal;
        text-align: left;
        gap: 0.4rem;
        padding-top: 0.65rem;
    }
    .data-table.responsive td.row-actions::before {
        flex: 0 0 100%;
        margin-bottom: 0.15rem;
    }
}

/* Section headings */
.section { margin-top: 1.5rem; }
.section-title-row {
    display: flex; align-items: flex-end; justify-content: space-between;
    margin-bottom: 0.85rem; gap: 1rem;
}
.section-title {
    font-family: 'Instrument Serif', Georgia, serif;
    font-size: 1.55rem;
    line-height: 1;
    letter-spacing: -0.005em;
    margin: 0;
}
.section-title em { font-style: italic; color: var(--p1); }

/* Buttons (mockup style — different namespace than .modern-btn) */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
    /* vertical-align dawal Bootstrap (.btn) — bez tego przyciski osadzone w tekscie siadaja
       na linii bazowej zamiast na srodku (pomiar zlapal to jako przesuniecie o pol piksela). */
    vertical-align: middle;
    height: 36px; padding: 0 0.95rem;
    border-radius: var(--radius);
    font-weight: 500; font-size: 13px;
    font-family: inherit;
    border: none;
    cursor: pointer;
    transition: all 0.15s;
    white-space: nowrap;
    text-decoration: none;
    color: inherit;
}
/* ⚠ WARIANTY GRADIENTOWE MAJĄ BIAŁY NAPIS — I MUSZĄ GO POWTÓRZYĆ TUTAJ.
   `.btn-gradient-success` i spółka deklarują `color: white` znacznie WYŻEJ w tym arkuszu,
   a `.btn { color: inherit }` tuż nad tym komentarzem ma tę samą wagę (0,1,0) i stoi później —
   więc przy równej wadze wygrywało `inherit` i napis brał kolor rodzica. Wewnątrz `.card` był
   to bootstrapowy #212529: ciemny tekst na zielonym, zmierzone 3,82 : 1, podczas gdy wszystkie
   pozostałe zielone przyciski (te bez klasy `.btn`, np. „Pobierz nowe teraz") mają biel i 4,04 : 1.
   Główne wezwanie do działania wyłamywało się przez to ze stylu CAŁEJ aplikacji.
   Waga (0,2,0) zamyka sprawę bez przestawiania bloków — a przestawienie ich byłoby groźniejsze:
   `.btn { color: inherit }` osłania też `a, .btn-link { color: var(--global-palette1) }`,
   więc jego usunięcie zazieleniłoby napisy na odnośnikach udających przyciski. */
.btn.btn-gradient-success,
.btn.btn-gradient-primary,
.btn.btn-gradient-info,
.btn.btn-gradient-warning,
.btn.btn-gradient-secondary { color: var(--text-light); }

.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }
.btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }

.btn-primary {
    background: var(--global-palette1);
    color: #fff;
    box-shadow: 0 1px 2px color-mix(in srgb, var(--global-palette1) 25%, transparent);
}
.btn-primary:hover { background: #007a38; transform: translateY(-1px); box-shadow: 0 4px 10px color-mix(in srgb, var(--global-palette1) 28%, transparent); color: #fff; }

.btn-secondary {
    background: var(--paper);
    color: var(--text);
    border: 1px solid var(--line-strong);
}
.btn-secondary:hover { background: var(--cream-2); border-color: var(--p3); color: var(--text); }

.btn-ghost { background: transparent; color: var(--text-soft); padding: 0 0.7rem; }
.btn-ghost:hover { background: var(--cream-2); color: var(--text); }
/* Skrót ustawiający wartość pola obok (np. progi dni przy automatycznym zamykaniu) — ten,
   który odpowiada bieżącej wartości, musi być widoczny, bo inaczej sześć przycisków wygląda
   identycznie i nie wiadomo, który jest teraz ustawiony. */
.btn-ghost.is-active {
    background: color-mix(in srgb, var(--p1) 14%, transparent);
    color: var(--p1);
    border-color: var(--p1);
}

.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { background: #a3261d; color: #fff; }

/* Soft danger — subtle background z danger text + border (mniej krzyczący niż solid btn-danger).
   Używany dla destructive akcji w drugiej kolejności (np. "Ukryj" obok "Usuń trwale"). */
.btn-soft-danger {
    background: #fbe9e6;
    color: var(--danger);
    border: 1px solid #f1c5be;
}
.btn-soft-danger:hover { background: #f5d4ce; color: var(--danger); border-color: var(--danger); }

/* Kasowanie W WIERSZU LISTY — najcichszy z wariantów destrukcyjnych: wygląda jak przycisk poboczny,
   czerwień pokazuje dopiero pod kursorem i przy ognisku klawiatury.
   ⚠ POWSTAŁO Z POMIARU (obchód ekranów 30.08.2026). Na `/settings/tags` stało trzydzieści pełnych
   czerwonych „Usuń" i to one były pierwszym, co widać na ekranie — czerwień przestała znaczyć
   „uwaga" i zaczęła być tłem. Sama akcja nie znika, zmienia się jej głośność; potwierdzenie
   dostaje pełną czerwień, bo tam ostrzeżenie jest na miejscu.
   Stosuj RAZEM z `.btn-ghost` — ta klasa dokłada wyłącznie kolor. */
.btn-ghost-danger { color: var(--text-faint); }
.btn-ghost-danger:hover,
.btn-ghost-danger:focus-visible { background: var(--danger-bg); color: var(--danger); }
[data-theme="dark"] .btn-soft-danger { background: rgba(196,57,47,0.12); border-color: rgba(196,57,47,0.32); color: #f08a82; }
[data-theme="dark"] .btn-soft-danger:hover { background: rgba(196,57,47,0.22); color: #f5a8a1; }

.btn-sm { height: 28px; padding: 0 0.65rem; font-size: 12px; }
.btn-lg { height: 44px; padding: 0 1.4rem; font-size: 14px; }

/* Ekran dotykowy — 28 px to wysokość dobra pod kursor, nie pod palec. Przy przeglądzie interfejsu
   na telefonie wyszło ponad dwadzieścia ekranów, gdzie „Edytuj", „Usuń" czy „Zapisz" mają 28 px
   i trafienie w nie jest loterią. Podnosimy TYLKO na urządzeniach wskazujących niedokładnie
   (pointer: coarse) — na komputerze gęstość interfejsu zostaje bez zmian.
   Zostaje poniżej zalecanych 44 px, żeby nie rozepchnąć pasków akcji, ale 40 px to już palec,
   a nie szpilka.
   ⚠ 38 → 40 px (21.09.2026, paczka C). Agent J mierzył cele względem czterdziestu i połowa
   przycisków akcji przegrywała o DWA PIKSELE — czyli wynik „za mały" był prawdziwy, a różnica
   niewidoczna dla kogokolwiek poza sondą. Dwa piksele nie rozpychają pasków, a kończą spór
   o to, czy reguła domu jest dotrzymana. */
@media (pointer: coarse) {
    .btn-sm { height: 40px; padding: 0 0.85rem; }
    /* ⚠ Sam padding dawal 31 px — o jeden pod progiem i o siedem pod nasza wlasna regula.
       Chipy filtrow i pozycje list rozwijanych sa NAJCZESCIEJ klikanymi elementami na
       telefonie (kazdy filtr, kazdy status, kazdy tag), wiec `min-height` wprost. */
    .f-chip { padding: 0.55rem 0.85rem; min-height: 40px; display: inline-flex; flex-direction: row; align-items: center; }
    /* Przyciski z sama ikona (strzalki nawigacji, „+") maja dobra wysokosc, ale 28 px szerokosci.
       `min-width` dotyka wylacznie ich — przyciski z tekstem sa i tak szersze. */
    .btn { min-width: 40px; }
    .ms-option, .ms-group-head { min-height: 40px; }
    /* ⚠ `min-height` bez `min-width` zalatwia polowe sprawy. Zmierzone 18.08.2026 na ekranie
       terminow SLA: przycisk "Usun" mial 27x38 px — wysokosc juz naprawiona, szerokosc nie.
       Krotkie slowo zostaje waskie, a to wlasnie w te strone chybia palec, gdy akcje stoja
       w rzedzie obok siebie. */
    .btn-link-sm { display: inline-flex; flex-direction: row; align-items: center; justify-content: center;
                   min-height: 40px; min-width: 40px; padding: 0 0.5rem; }
}

/* Chips / badges */
.chip {
    display: inline-flex; align-items: center; gap: 0.35rem;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11.5px; font-weight: 500;
    line-height: 1.5;
}
.chip-ok      { background: var(--ok-bg);     color: var(--ok); }
.chip-warn    { background: var(--warn-bg);   color: var(--warn-mocny); }
.chip-danger  { background: var(--danger-bg); color: var(--danger); }
.chip-info    { background: var(--info-bg);   color: var(--info); }
.chip-neutral { background: var(--cream-2);   color: var(--text-soft); }
.chip .dot-mini { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Plakietka, ktora jest przyciskiem (np. „239 nieudanych" nad kolejka wysylki).
   Przegladarka daje <button> wlasne tlo, obwodke i kroj — bez tego resetu plakietka
   przestaje wygladac jak plakietka. `cursor` i podkreslenie po najechaniu sa jedynym
   sygnalem, ze to dziala; sama barwa go nie niesie. */
.chip-klikalny {
    border: 0;
    font: inherit;
    font-size: 11.5px;
    font-weight: 500;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.chip-klikalny:hover { text-decoration: underline; }
.chip-klikalny:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }

/* Tags (channel/conversation labels) */
.tag {
    display: inline-flex; align-items: center;
    padding: 1px 7px;
    border-radius: 4px;
    font-size: 11px;
    background: var(--cream-2);
    color: var(--text-soft);
    font-weight: 500;
}
.tag.tone-1 { background: #fdecd9; color: #a4541a; }
.tag.tone-2 { background: #e0f0e8; color: #1e6a3f; }
.tag.tone-3 { background: #ebe5f8; color: #5a36a8; }
.tag.tone-4 { background: #fcdbe0; color: #a72c4b; }

/* Channel pill (Allegro/Erli/Amazon/Email/eBay) */
.channel {
    display: inline-flex; align-items: center; gap: 0.35rem;
    font-size: 12px; font-weight: 500;
}
.channel-icon {
    width: 22px; height: 22px;
    border-radius: 5px;
    display: grid; place-items: center;
    color: #fff;
    font-weight: 700; font-size: 11px;
    box-shadow: var(--shadow-sm);
}
.channel-icon.allegro { background: linear-gradient(135deg, #ff8c42, #ff5a00); }
.channel-icon.erli    { background: linear-gradient(135deg, #00d4b0, #00a78e); }
.channel-icon.amazon  { background: linear-gradient(135deg, #ffae47, #ff9900); color: #232f3e; }
.channel-icon.email   { background: linear-gradient(135deg, #8b62d8, #6b46c1); }
.channel-icon.ebay    { background: linear-gradient(135deg, #ff7b7b, #e53238); }

/* SLA progress bar */
.sla-bar {
    position: relative;
    width: 64px; height: 5px;
    background: var(--cream-2);
    border-radius: 999px;
    overflow: hidden;
}
.sla-bar .fill {
    position: absolute; left: 0; top: 0; bottom: 0;
    border-radius: 999px;
    transition: width 0.3s;
}
.sla-bar.ok     .fill { background: var(--p1); }
.sla-bar.warn   .fill { background: var(--warn); }
.sla-bar.danger .fill { background: var(--danger); }
.sla-bar.breach .fill { background: var(--danger); animation: pulse-bar 1.2s infinite; }
@keyframes pulse-bar { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }

/* Avatars (user/agent/customer) */
.avatar-circle {
    border-radius: 50%;
    display: inline-grid; place-items: center;
    color: #fff;
    font-weight: 600;
    font-size: 11px;
    flex: none;
}
.avatar-circle.sz-22 { width: 22px; height: 22px; font-size: 9.5px; }
.avatar-circle.sz-28 { width: 28px; height: 28px; font-size: 11px; }
.avatar-circle.sz-36 { width: 36px; height: 36px; font-size: 13px; }
.avatar-circle.sz-48 { width: 48px; height: 48px; font-size: 16px; }
.avatar-circle.c-1 { background: linear-gradient(135deg, #ff8a4c, #c4392f); }
.avatar-circle.c-2 { background: linear-gradient(135deg, #6ec3a8, #1e7a5a); }
.avatar-circle.c-3 { background: linear-gradient(135deg, #d8b86a, #7a5a1e); }
.avatar-circle.c-4 { background: linear-gradient(135deg, #b884e8, #6b3ec7); }
.avatar-circle.c-5 { background: linear-gradient(135deg, #5dade2, #2874a6); }
.avatar-circle.c-6 { background: linear-gradient(135deg, #e07a9e, #ad3768); }

/* Agent avatar — solid color (hash z UserId), inicjały białe, kompaktowy. Tło z inline style.
   Mniejsza wersja niż .avatar-circle bo używany w wierszach inboxa (gęsta lista). */
.agent-avatar {
    display: inline-grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    color: #fff;
    font-weight: 700;
    font-size: 10px;
    line-height: 1;
    letter-spacing: 0.02em;
    flex: none;
    cursor: default;
    box-shadow: 0 1px 2px rgba(0,0,0,0.15);
    border: 1.5px solid var(--paper);
}

/* Page-load stagger fade */
@keyframes fade-up {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.stagger > * { opacity: 0; animation: fade-up 0.4s ease-out forwards; }
.stagger > *:nth-child(1) { animation-delay: 0.05s; }
.stagger > *:nth-child(2) { animation-delay: 0.10s; }
.stagger > *:nth-child(3) { animation-delay: 0.15s; }
.stagger > *:nth-child(4) { animation-delay: 0.20s; }
.stagger > *:nth-child(5) { animation-delay: 0.25s; }
.stagger > *:nth-child(6) { animation-delay: 0.30s; }
.stagger > *:nth-child(7) { animation-delay: 0.35s; }
.stagger > *:nth-child(8) { animation-delay: 0.40s; }

/* Generic content wrapper — full width minus padding. Na szerszych monitorach (1600+)
   większy boczny padding żeby tabele/karty nie były rozjechane na 2000px linijek tekstu. */
.content {
    padding: 1.5rem 2.5rem 3rem;
    width: 100%;
    max-width: none;
}
@media (min-width: 1600px) { .content { padding: 1.75rem 3rem 3rem; } }
@media (max-width: 1100px) { .content { padding: 1.25rem 1.25rem 3rem; } }
@media (max-width: 768px)  { .content { padding: 0.85rem 0.85rem 2rem; } }

/* Editorial display heading (hero) */
/* ══════════════════════════════════════════════════════════════════════════════════════════════
   NAGŁÓWEK EKRANU — układ „LINIA STANU" (propozycja 01, wybrana przez właściciela 22.09.2026)
   ══════════════════════════════════════════════════════════════════════════════════════════════
   Zasada: przy narzędziu, przy którym ktoś siedzi osiem godzin, NAZWA EKRANU jest najmniej
   użyteczną rzeczą na górze — on wie, gdzie jest. Największe mają być LICZBY, które się zmieniają.

   Znika stąd wszystko, co właściciel wskazał jako przeszkadzające: szeryfowy krój do tytułów,
   podział „słowo + słowo w kursywie" i zielony akcent na jednym wyrazie. Zostaje jeden krój
   i hierarchia robiona wielkością oraz grubością.

   ⚠ Ekrany jeszcze nieprzerobione używają `.display-heading` i mają wyglądać SPOKOJNIE, a nie
   „na wpół zmienione": dlatego ta klasa dostaje niżej nową typografię zamiast zostać usunięta.
   Nic nie jest zepsute w trakcie przenoszenia. */

.nagl-linia { margin: 0 0 1.1rem; }

.nagl-linia-glowa {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.7rem;
}

/* Nazwa ekranu: drobna, spokojna, bez wersalików. To jest podpis, nie afisz. */
.nagl-linia-nazwa {
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1.3;
    color: var(--text-soft);
    margin: 0;
}
.nagl-linia-kontekst { color: var(--text-faint); font-weight: 400; }

.nagl-linia-narzedzia { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* ── Liczby ─────────────────────────────────────────────────────────────────────────────────
   ⚠ `flex-wrap` i `column-gap` zamiast sztywnej siatki: liczb bywa od jednej do pięciu,
   a na telefonie mają się łamać do dwóch rzędów, nie ściskać do nieczytelnych słupków. */
.nagl-linia-miary {
    display: flex;
    flex-wrap: wrap;
    column-gap: 1.8rem;
    row-gap: 0.7rem;
    align-items: flex-start;
}

.miara-linii b {
    display: block;
    font-family: 'Geist Mono', ui-monospace, monospace;
    /* Cyfry o stałej szerokości — licznik odświeżany w miejscu nie ma skakać w bok. */
    font-variant-numeric: tabular-nums;
    font-size: clamp(1.55rem, 3.2vw, 1.95rem);
    font-weight: 500;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--text);
}
.miara-linii span {
    display: block;
    font-size: 11.5px;
    color: var(--text-soft);
    margin-top: 0.2rem;
}
/* Kolor niesie TYLKO to, co pilne — patrz komentarz w MiaraLinii.razor. */
.miara-linii.pilne b { color: var(--danger); }

.miara-linii-link { text-decoration: none; color: inherit; display: block; }
.miara-linii.klikalna .miara-linii-link:hover b { text-decoration: underline; text-underline-offset: 3px; }
.miara-linii-link:focus-visible { outline: 2px solid var(--p1); outline-offset: 3px; border-radius: 3px; }

.nagl-linia-lede {
    font-size: 13px;
    color: var(--text-soft);
    max-width: 68ch;
    line-height: 1.55;
    margin: 0.75rem 0 0;
}
/* Bez liczb nagłówek jest tylko linią nazwy i zdaniem — wtedy zdanie stoi bliżej. */
.nagl-linia.bez-miar .nagl-linia-glowa { margin-bottom: 0.25rem; }
.nagl-linia.bez-miar .nagl-linia-lede { margin-top: 0.15rem; }

/* ── Ekrany jeszcze nieprzerobione ──────────────────────────────────────────────────────────
   Ta sama decyzja typograficzna, tylko w postaci tytułu: jeden krój, hierarchia z wagi,
   zero koloru na pojedynczym słowie. Do czasu przeniesienia na `NaglowekEkranu`. */
.display-heading {
    font-family: inherit;
    font-size: clamp(1.45rem, 2.6vw, 1.8rem);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--text);
    margin: 0 0 0.5rem;
}
.display-heading em { font-style: normal; font-weight: 600; color: inherit; }

.lede {
    font-size: 1.05rem;
    color: var(--text-soft);
    max-width: 56ch;
    line-height: 1.55;
}

/* Centered single-card page (auth landing, onboarding, accept invitation) */
.page-centered {
    min-height: calc(100vh - var(--topbar-h));
    display: grid;
    place-items: center;
    padding: 2rem 1rem;
}
.page-centered > .card { width: min(540px, 100%); }

/* ============================================
   Wyciągnięte ze scoped razor.css — Blazor scope-attr nie matchuje
   elementów wstawianych dynamicznie / w details > summary popoverach.
   Trzymaj te selektory tutaj — żeby działały wszędzie.
   ============================================ */

/* Form input — używane w wielu miejscach (Tags, Templates, Customers) */
.form-input {
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    padding: 0.5rem 0.7rem;
    font-size: 13px;
    font-family: inherit;
    background: var(--paper);
    color: var(--text);
    transition: border-color 0.15s, box-shadow 0.15s;
    width: 100%;
    box-sizing: border-box;
}
.form-input:focus {
    outline: none;
    border-color: var(--p1);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--global-palette1) 15%, transparent);
}
.form-input::placeholder { color: var(--text-faint); }

/* Filter bar / chips (Inbox, Outbox, Audit, ApiLimits) */
.filter-bar {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    padding: 0.55rem;
    margin-bottom: 1rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    flex-wrap: wrap;
    /* overflow: visible — dropdown panels (.ms-panel) muszą wystawać poza bar.
       Wrap zamiast horizontal scroll wystarczy na wąskich viewportach. */
    overflow: visible;
    position: relative;
    z-index: 20;
}
.f-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.35rem 0.75rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.12s;
    font-family: inherit;
}
.f-chip:hover { background: var(--cream-2); color: var(--text); }
.f-chip.active { background: var(--p1); color: var(--text-light); border-color: var(--p1); }
.f-chip.danger.active { background: var(--danger); border-color: var(--danger); }

/* ── Plakietki filtrów ZE STANEM (N2b, 18.09.2026) ──────────────────────────────────────
   Filtr, który coś znaczy, nosi kolor swojego znaczenia — ten sam, co plakietka na liście:
   po terminie = czerwień, zaraz po terminie = pomarańcz, nieprzeczytane = niebieski, czekają na
   nas / moje = akcent. W spoczynku: kropka w kolorze + obrys; włączony: wypełnienie tym kolorem.
   Do tej pory pasek był rzędem szarych napisów bez stanu („wszystko białe"). */
.f-chip-info, .f-chip-warn, .f-chip-danger, .f-chip-akcent {
    color: var(--chip-kolor);
    border-color: color-mix(in srgb, var(--chip-kolor) 40%, var(--line));
    background: color-mix(in srgb, var(--chip-kolor) 6%, var(--paper));
}
.f-chip-info   { --chip-kolor: var(--info); }
.f-chip-warn   { --chip-kolor: var(--warn-mocny); }
.f-chip-danger { --chip-kolor: var(--danger); }
.f-chip-akcent { --chip-kolor: var(--p1); }
.f-chip-info::before, .f-chip-warn::before, .f-chip-danger::before, .f-chip-akcent::before {
    content: '';
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--chip-kolor);
    flex: none;
}
.f-chip-info:hover, .f-chip-warn:hover, .f-chip-danger:hover, .f-chip-akcent:hover {
    background: color-mix(in srgb, var(--chip-kolor) 14%, var(--paper));
    color: var(--chip-kolor);
}
.f-chip-info.active, .f-chip-warn.active, .f-chip-danger.active, .f-chip-akcent.active {
    background: var(--chip-kolor);
    border-color: var(--chip-kolor);
    color: var(--text-light);
}
.f-chip-info.active::before, .f-chip-warn.active::before, .f-chip-danger.active::before, .f-chip-akcent.active::before {
    background: var(--text-light);
}
/* Licznik w plakietce filtra — ta sama liczba, co w liczniku nad listą. */
.f-chip-licznik {
    font-size: 10.5px;
    font-weight: 600;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--chip-kolor, var(--text-soft)) 14%, transparent);
    line-height: 1.4;
}
.f-chip.active .f-chip-licznik { background: rgba(255, 255, 255, 0.24); }

.f-chip-premium { opacity: 0.45; cursor: not-allowed; background: var(--cream-2); }
.f-chip-premium:hover { background: var(--cream-2); color: var(--text-soft); }
.f-chip-premium:disabled { cursor: not-allowed; }
.f-sep { width: 1px; height: 18px; background: var(--line); margin: 0 0.25rem; }

/* Sort listy (native select) — spójny z paskiem filtrów (editorial-utility). */
.f-sort {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.1rem 0.35rem 0.1rem 0.5rem;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    background: transparent;
    transition: all 0.12s;
}
.f-sort:hover { background: var(--cream-2); color: var(--text); }
.f-sort-ico { flex: none; color: var(--text-faint); }
.f-sort-select {
    border: none;
    background: transparent;
    color: inherit;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    padding: 0.25rem 0.15rem;
}
.f-sort-select:focus { outline: none; }

/* ───────────────────────── Multi-select dropdown (filters) ─────────────────────────
   Editorial-utility style — używany w Inbox + każdej liście z filtrami.
   Markup: <details data-ms-dropdown><summary class="ms-trigger">…</summary><div class="ms-panel">…</div></details>
   Click-outside zamyka przez abc-ms-dropdown.js. */
.ms-dropdown {
    position: relative;
    display: inline-block;
    z-index: 1;
}
.ms-dropdown[open] {
    /* Hard wybicie nad topbar (z-index: 50) — żeby panel nie chował się pod sticky nagłówkiem. */
    z-index: 200;
}
.ms-dropdown > summary {
    list-style: none;
    cursor: pointer;
}
.ms-dropdown > summary::-webkit-details-marker { display: none; }
.ms-dropdown > summary::marker { display: none; }

.ms-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.65rem;
    height: 30px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    font-size: 12.5px;
    font-weight: 500;
    font-family: inherit;
    transition: all 0.12s;
    white-space: nowrap;
    user-select: none;
}
.ms-trigger:hover { background: var(--cream-2); color: var(--text); }
.ms-dropdown.has-selection > .ms-trigger {
    background: color-mix(in srgb, var(--global-palette1) 8%, transparent);
    color: var(--p1);
    border-color: color-mix(in srgb, var(--global-palette1) 18%, transparent);
}
.ms-dropdown[open] > .ms-trigger {
    background: var(--paper);
    color: var(--text);
    border-color: var(--line-strong);
    box-shadow: var(--shadow-sm);
}
.ms-trigger-label { font-weight: 500; }
.ms-trigger-icon {
    display: inline-grid; place-items: center;
    color: var(--text-faint);
}
.ms-trigger-icon svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ms-dropdown.has-selection > .ms-trigger .ms-trigger-icon { color: var(--p1); }
.ms-trigger-count {
    display: inline-grid; place-items: center;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    background: var(--p1);
    color: #fff;
    border-radius: 999px;
    font-size: 10.5px; font-weight: 600;
    font-family: 'Geist Mono', ui-monospace, monospace;
    line-height: 1;
}
.ms-trigger-chevron {
    color: var(--text-faint);
    transition: transform 0.15s;
}
.ms-dropdown[open] > .ms-trigger .ms-trigger-chevron { transform: rotate(180deg); color: var(--text-soft); }

.ms-panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 240px;
    max-width: min(420px, 90vw);
    background: var(--paper);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    z-index: 200;
    overflow: hidden;
    animation: msFadeIn 0.12s ease-out;
}
@keyframes msFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}
.ms-panel-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--line);
    background: var(--cream-2);
}
.ms-panel-title {
    font-family: 'Instrument Serif', serif;
    font-size: 14.5px;
    color: var(--text);
}
.ms-clear-btn {
    background: transparent;
    border: none;
    color: var(--text-soft);
    font-size: 11.5px;
    font-family: inherit;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 4px;
    transition: all 0.1s;
}
.ms-clear-btn:hover { background: var(--paper); color: var(--danger); }

.ms-panel-body {
    overflow-y: auto;
    padding: 0.25rem;
}
.ms-empty {
    padding: 1.5rem 0.75rem;
    text-align: center;
    color: var(--text-faint);
    font-size: 12.5px;
    font-style: italic;
}

.ms-group { padding: 0.15rem 0; }
.ms-group + .ms-group { border-top: 1px solid var(--line); margin-top: 0.25rem; padding-top: 0.4rem; }

.ms-group-head {
    display: flex; align-items: center; gap: 0.5rem;
    width: 100%;
    padding: 0.4rem 0.55rem;
    background: transparent;
    border: none;
    border-radius: 5px;
    color: var(--text);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    text-align: left;
    transition: background 0.1s;
    text-transform: uppercase;
}
.ms-group-head:hover { background: var(--cream-2); }
.ms-group-label { flex: 1; }
.ms-group-hint {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 10px;
    color: var(--text-soft);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}
.ms-group-icon {
    display: inline-grid; place-items: center;
    width: 18px; height: 18px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    background: var(--cream-2);
    color: var(--text-soft);
}

.ms-group-options { display: flex; flex-direction: column; }
.ms-group-options.is-nested { padding-left: 0.3rem; }

/* Wiersz opcji: sama opcja rozpycha się na całą szerokość, akcja (np. „schowaj") stoi z prawej
   i pokazuje się dopiero pod kursorem — na dotyku jest widoczna zawsze, bo hovera tam nie ma. */
.ms-option-row { display: flex; align-items: center; gap: 0.15rem; }
.ms-option-row > .ms-option { flex: 1; min-width: 0; }

.ms-option-act {
    display: inline-grid; place-items: center;
    width: 26px; height: 26px;
    flex: none;
    border: 1px solid transparent;
    border-radius: 5px;
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
    /* Widoczny zawsze, po najechaniu pełny (agent K, 20.09.2026: osiem „Schowaj tag” schowanych do najechania —
       akcja, która zdejmuje tag z list wyboru, nie może być niewidoczna). */
    opacity: 0.45;
    transition: all 0.12s;
}
.ms-option-row:hover .ms-option-act,
.ms-option-act:focus-visible { opacity: 1; }
.ms-option-act:hover { background: var(--cream-2); color: var(--text); border-color: var(--line-strong); }
@media (pointer: coarse) {
    .ms-option-act { opacity: 1; width: 32px; height: 32px; }
}

/* Szukajka nad listą — pokazywana tylko przy Searchable="true". */
.ms-panel-search {
    display: flex; align-items: center; gap: 0.4rem;
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--line);
    color: var(--text-faint);
}
.ms-search-input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    font-family: inherit;
    font-size: 12.5px;
    color: var(--text);
    outline: none;
}
.ms-search-input::placeholder { color: var(--text-faint); }
.ms-search-input::-webkit-search-cancel-button { display: none; }
.ms-search-clear {
    border: none; background: transparent; cursor: pointer;
    color: var(--text-faint); font-size: 15px; line-height: 1;
    padding: 0 2px; border-radius: 4px;
}
.ms-search-clear:hover { color: var(--text); }

/* Stopka panelu — przełączniki dotyczące całej listy (np. „Pokaż ukryte"). */
.ms-panel-foot {
    padding: 0.45rem 0.6rem;
    border-top: 1px solid var(--line);
    background: var(--cream-2);
    font-size: 11.5px;
    color: var(--text-soft);
}

.ms-option {
    display: flex; align-items: center; gap: 0.5rem;
    width: 100%;
    padding: 0.42rem 0.55rem;
    background: transparent;
    border: none;
    border-radius: 5px;
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 400;
    cursor: pointer;
    text-align: left;
    transition: background 0.1s;
}
.ms-option:hover { background: var(--cream-2); }
.ms-option.is-selected { color: var(--text); font-weight: 500; }
.ms-option-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-option-hint {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 10.5px;
    color: var(--text-soft);
}
.ms-option-swatch {
    width: 10px; height: 10px; border-radius: 50%;
    flex: none;
    border: 1px solid rgba(17,19,23,0.12);
}
.ms-option-icon {
    display: inline-grid; place-items: center;
    width: 18px; height: 18px;
    border-radius: 4px;
    background: var(--cream-2);
    color: var(--text-soft);
    font-size: 10px;
    font-weight: 700;
    flex: none;
}

/* Faux checkbox (3 stany: empty, mixed, all) — bez <input> bo browser nie eksponuje indeterminate w pure CSS. */
.ms-cbx {
    display: inline-grid; place-items: center;
    width: 16px; height: 16px;
    flex: none;
    border: 1.4px solid var(--line-strong);
    border-radius: 4px;
    background: var(--paper);
    color: transparent;
    transition: all 0.1s;
}
.ms-cbx .ms-cbx-check, .ms-cbx .ms-cbx-dash { display: none; }
.ms-cbx.is-some {
    background: var(--p1);
    border-color: var(--p1);
    color: #fff;
}
.ms-cbx.is-some .ms-cbx-dash { display: block; }
.ms-cbx.is-all {
    background: var(--p1);
    border-color: var(--p1);
    color: #fff;
}
.ms-cbx.is-all .ms-cbx-check { display: block; }
.ms-option:hover .ms-cbx:not(.is-all):not(.is-some) { border-color: var(--p1); }

/* Smaller variant for compact filter bars */
.ms-dropdown.is-compact .ms-trigger { height: 26px; font-size: 12px; padding: 0.2rem 0.55rem; }

/* Dark mode */
[data-theme="dark"] .ms-trigger:hover { background: rgba(255,255,255,0.05); }
[data-theme="dark"] .ms-dropdown[open] > .ms-trigger { background: var(--paper); border-color: var(--line-strong); }
[data-theme="dark"] .ms-dropdown.has-selection > .ms-trigger {
    background: rgba(193, 209, 28, 0.10);
    color: var(--p2);
    border-color: rgba(193, 209, 28, 0.25);
}
[data-theme="dark"] .ms-trigger-count { background: var(--p2); color: var(--p4); }
[data-theme="dark"] .ms-cbx.is-some, [data-theme="dark"] .ms-cbx.is-all { background: var(--p2); border-color: var(--p2); color: var(--p4); }

/* Responsive: na mobile dropdown rozszerza się do całego viewport */
@media (max-width: 640px) {
    .ms-panel {
        position: fixed;
        left: 1rem;
        right: 1rem;
        top: auto;
        max-width: calc(100vw - 2rem);
        min-width: 0;
    }
}

/* Kind badge — wiadomość/dyskusja/reklamacja na liście konwersacji.
   Default kolory; w Faza B będą nadpisywane per-user. */
.kind-badge {
    display: inline-flex; align-items: center; gap: 4px;
    height: 18px;
    padding: 0 6px;
    border-radius: 4px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    line-height: 1;
    font-family: inherit;
    background: var(--kind-bg, #e2ebff);
    color: var(--kind-fg, #2563eb);
    white-space: nowrap;
}
.kind-badge.kind-message    { --kind-bg: #e2ebff; --kind-fg: #2563eb; }
.kind-badge.kind-discussion { --kind-bg: #fef0d8; --kind-fg: #b66a14; }
.kind-badge.kind-claim      { --kind-bg: #fbe9e6; --kind-fg: #c4392f; }
.kind-badge.kind-return     { --kind-bg: #ebe5f8; --kind-fg: #5a36a8; }

/* EmailChannel chip — kolor z DB, inline w wierszu inboxa obok kind/status badge. */
.email-channel-chip {
    display: inline-flex; align-items: center;
    height: 18px;
    padding: 0 7px;
    border-radius: 4px;
    border: 1px solid;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
}
[data-theme="dark"] .kind-badge.kind-message    { --kind-bg: rgba(37,99,235,0.18);  --kind-fg: #93b4ff; }
[data-theme="dark"] .kind-badge.kind-discussion { --kind-bg: rgba(201,138,20,0.18); --kind-fg: #f5c98f; }
[data-theme="dark"] .kind-badge.kind-claim      { --kind-bg: rgba(196,57,47,0.18);  --kind-fg: #f4a39c; }
[data-theme="dark"] .kind-badge.kind-return     { --kind-bg: rgba(90,54,168,0.22);  --kind-fg: #c2a6ee; }

/* Source-color stripe on conversation row (Faza B per-user override target) */
.t-row.source-tinted::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--row-source-color, transparent);
    border-radius: 3px 0 0 3px;
}

/* Snooze dropdown (Conversation) */
.snooze-dropdown { position: relative; display: inline-block; }
.snooze-dropdown > summary { list-style: none; cursor: pointer; }
.snooze-dropdown > summary::-webkit-details-marker { display: none; }
/* ⚠ Lista rozwija się od LEWEJ krawędzi przycisku (18.09.2026). Z `right: 0` menu o szerokości 200 px
   rosło w lewo od przycisku „Odłóż", który stoi przy lewej krawędzi treści — dwie trzecie pozycji
   lądowały POD menu bocznym (wyższy z-index) i były niewidoczne ani nieklikalne; na pokazie właściciel
   widział pusty biały prostokąt. Szerokość ograniczona do okna, żeby na telefonie nie wystawała. */
.snooze-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: auto;
    max-width: calc(100vw - 2rem);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    padding: 0.35rem;
    z-index: 50;
    min-width: 200px;
}
.snooze-item {
    display: block;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 0.45rem 0.7rem;
    border-radius: 4px;
    font-size: 12.5px;
    cursor: pointer;
    color: var(--text);
    font-family: inherit;
}
.snooze-item:hover { background: var(--cream-2); }
.snooze-item[disabled] { opacity: 0.5; cursor: not-allowed; }
/* Chip "wysłane bezpośrednio z panelu Allegro" — oznacza wiadomości od sprzedawcy zsynchronizowane przez polling,
   żeby agent wiedział że to NIE jego wysyłka z ABCare. */
.chip-source-external {
    background: rgba(255, 102, 0, 0.08);
    color: #c45a00;
    border: 1px solid rgba(255, 102, 0, 0.25);
}
.snooze-item-danger { color: var(--danger, #c0392b); }
.snooze-section {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-soft, #8a8a85);
    padding: 0.45rem 0.7rem 0.2rem;
    border-top: 1px solid var(--line);
    margin-top: 0.2rem;
}
.snooze-section:first-child { border-top: none; margin-top: 0; }
/* Mobile actions menu — popup wjeżdża "od prawej i w dół" zamiast wąskiego dropdownu */
.mobile-actions-menu > .snooze-list {
    max-height: calc(100vh - 120px);
    overflow-y: auto;
}

/* Templates dropdown (composer) */
.tpl-dropdown { position: relative; display: inline-block; }
.tpl-dropdown > summary { list-style: none; cursor: pointer; }
.tpl-dropdown > summary::-webkit-details-marker { display: none; }
.tpl-dropdown-list {
    position: absolute;
    bottom: calc(100% + 4px);
    right: 0;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    padding: 0.35rem;
    z-index: 50;
    min-width: 280px;
    max-height: 320px;
    overflow-y: auto;
}
.tpl-dropdown-item {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 0.5rem 0.7rem;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text);
    line-height: 1.35;
    font-family: inherit;
}
.tpl-dropdown-item:hover { background: var(--cream-2); }
.tpl-dropdown-item strong { font-size: 12.5px; }
.tpl-dropdown-item small { color: var(--text-soft); font-size: 11.5px; }

/* Customer notes (Conversation side panel) */
.cust-notes {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px dashed var(--line);
}
.cust-notes-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.35rem;
}
.cust-notes-body {
    font-size: 12.5px;
    color: var(--text);
    line-height: 1.45;
    white-space: pre-wrap;
    word-wrap: break-word;
    background: var(--cream-2);
    padding: 0.5rem 0.7rem;
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--warn, #c98a14);
}
.cust-notes-empty {
    font-size: 11.5px;
    color: var(--text-soft);
    font-style: italic;
}
.btn-link-sm {
    background: transparent;
    border: none;
    color: var(--p1, #019344);
    font-size: 11.5px;
    cursor: pointer;
    padding: 0;
    text-decoration: underline;
    font-family: inherit;
}
.btn-link-sm:hover { color: var(--text); }

/* Bulk action bar (Inbox) */
.bulk-bar {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    padding: 0.55rem 0.85rem;
    background: var(--info-bg, #e2ebff);
    border: 1px solid var(--info, #2563eb);
    border-radius: 6px;
    margin-bottom: 0.75rem;
    font-size: 13px;
}
/* Zakres zaznaczenia — „zaznaczanie obejmuje tę stronę (25 z 36)". Bez tego zdania liczba
   nad listą i liczba w pasku zbiorczym mówią o dwóch różnych zbiorach, a wygląda to jak
   jeden. Ton stonowany: to doprecyzowanie, nie ostrzeżenie. */
.bulk-zakres { font-size: 11.5px; color: var(--text-soft); }

/* Odnosnik „pomin nawigacje" — pierwszy element, w ktory trafia klawiatura i czytnik ekranu.
   Na dotyku ma byc celem, a nie paskiem 130x34. */
@media (pointer: coarse) { .pomin-nawigacje { min-height: 40px; display: inline-flex; flex-direction: row; align-items: center; } }

/* ⚠ Reszta celów poniżej czterdziestu, wskazana przez przyrząd Q po wydaniu 25 — element
   po elemencie, z jego zmierzonym rozmiarem w komentarzu. Bez takiej listy „poprawiamy
   cele dotykowe" jest hasłem, a nie pracą: pierwsze trzy podejścia poprawiały to, co akurat
   przyszło do głowy, i nie ruszały tego, w co człowiek naprawdę celuje palcem. */
@media (pointer: coarse) {
    .app-burger { min-width: 40px; min-height: 40px; }          /* było 36×36 */
    .app-user-item { min-height: 40px; }                        /* było 156×34 */
    .pager-btn { min-width: 40px; min-height: 40px; }           /* było 32×32 */
    /* ⚠ POLA WYBORU NIE RUSZAM: niżej w tym pliku stoi świadoma reguła dająca polom wyboru
       32 px, z uzasadnieniem, że tyle ma na telefonie normalne pole wyboru. Moja reguła 22 px
       i tak przegrywała (selektor atrybutowy jest bardziej szczegółowy) — była martwa
       i sprzeczna z sąsiadem naraz. */
    /* ⚠ BYLO TU `.view-toggle ::deep button` — a `::deep` to pseudoelement BLAZORA, nie CSS-a.
       W zwyklym arkuszu przegladarka uznaje taki selektor za nieprawidlowy i wyrzuca CALA regule,
       razem z drugim, poprawnym selektorem obok niego. Przycisk przelacznika ma wlasna regule
       w ViewToggle.razor.css, gdzie `::deep` ma sens. */
    .view-toggle button { min-width: 40px; min-height: 40px; }
    .mbox-item { min-height: 40px; }                            /* było 294×32 */
    .fold-item { min-height: 40px; }                            /* było 294×34 — foldery poczty */
    .ms-trigger { min-height: 40px; }                           /* było 92×30 — rozwijak wielokrotnego wyboru */
    /* Nazwa klienta: prawdziwa reguła stoi niżej jako `.cust-row .cr-clickable` i jest
       bardziej szczegółowa — podniesiona tam z 38 na 40 px. */
    /* ⚠ `.btn` ma `min-width: 40px` wyżej, ale NIE ma wysokości: przyciski drugorzędne
       mierzyły 124×36. Wysokość ustawia dopiero `.btn-sm`, a te nie są „sm". */
    .btn { min-height: 40px; }
    /* Pole wyboru w wierszu listy: sama kontrolka 22 px, ale całe pole czułe 40 px.
       Etykieta wokół niej jest celem, nie kwadracik. */
    label.bulk-cb-wrap, .cr-cb, .ch-cb { min-width: 40px; min-height: 40px; display: inline-flex; flex-direction: row; align-items: center; justify-content: center; }
}

.bulk-cb {
    cursor: pointer;
    width: 14px;
    height: 14px;
    margin: 0;
    accent-color: var(--p1, #019344);
}
.bulk-tag-dropdown { position: relative; }
.bulk-tag-dropdown > summary { list-style: none; cursor: pointer; }
.bulk-tag-dropdown > summary::-webkit-details-marker { display: none; }
.bulk-tag-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    padding: 0.35rem;
    z-index: 50;
    min-width: 200px;
    max-height: 240px;
    overflow-y: auto;
}
.bulk-tag-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 0.35rem 0.5rem;
    border-radius: 4px;
    font-size: 12.5px;
    cursor: pointer;
    color: var(--text);
    font-family: inherit;
}
.bulk-tag-item:hover { background: var(--cream-2); }

/* Inbox search input */
.inbox-search {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.85rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 6px;
    margin-bottom: 0.6rem;
    color: var(--text-soft);
}
.inbox-search input[type="search"] {
    flex: 1;
    border: none;
    background: transparent;
    padding: 0;
    font-size: 13.5px;
    outline: none;
    color: var(--text);
    font-family: inherit;
}
.inbox-search input[type="search"]::-webkit-search-cancel-button { display: none; }
.btn-icon-clear {
    background: transparent;
    border: none;
    color: var(--text-faint);
    font-size: 18px;
    cursor: pointer;
    padding: 0 0.4rem;
    line-height: 1;
}
.btn-icon-clear:hover { color: var(--text); }
/* ⚠ Cel dotykowy krzyżyka „wyczyść" (agent J). Sam znak ma 18 px, a pole czułe było jeszcze
   mniejsze — kasowanie frazy palcem było loterią. Na myszy zostaje jak było: tam 18 px to dużo. */
@media (pointer: coarse) {
    .btn-icon-clear { min-width: 40px; min-height: 40px; display: inline-grid; place-items: center; padding: 0; }
}

/* Response templates editor (Settings) */
.tpl-edit {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
    padding: 0.85rem;
    background: var(--cream-2);
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
}
.tpl-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.tpl-item {
    padding: 0.85rem 1rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
}
.tpl-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.4rem;
    gap: 0.5rem;
}
.tpl-body {
    background: var(--cream-2);
    padding: 0.65rem 0.85rem;
    border-radius: 6px;
    font-size: 12.5px;
    font-family: 'Geist', sans-serif;
    color: var(--text);
    white-space: pre-wrap;
    word-wrap: break-word;
    max-height: 200px;
    overflow-y: auto;
    margin: 0;
}

/* Tone-swatch dot for color-coded tags */
.tone-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
}
.tone-swatch.tone-neutral { background: #aaa; }
.tone-swatch.tone-success { background: var(--p1, #019344); }
.tone-swatch.tone-warning { background: var(--warn, #c98a14); }
.tone-swatch.tone-danger { background: var(--danger, #c4392f); }
.tone-swatch.tone-info { background: var(--info, #2563eb); }
.form-input-sm { padding: 4px 8px; font-size: 13px; }

/* Native color picker — zachowuje mockup styling (mała kafelka + cienka ramka) */
.color-input {
    width: 56px;
    height: 32px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--paper);
    cursor: pointer;
    padding: 2px;
}
.color-input::-webkit-color-swatch-wrapper { padding: 0; }
.color-input::-webkit-color-swatch { border: none; border-radius: 4px; }

.color-swatch {
    display: inline-block;
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 1px solid var(--line);
    vertical-align: middle;
    margin-right: 0.4rem;
}

/* Sync spinner — w chipie info na karcie integracji gdy poller pracuje */
.sync-spinner {
    display: inline-block;
    width: 10px;
    height: 10px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    vertical-align: middle;
    margin-right: 4px;
}
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* Tags-management table (Settings) */
.tags-table { width: 100%; border-collapse: collapse; }
.tags-table thead { background: var(--cream-2); }
.tags-table th {
    text-align: left;
    padding: 0.65rem 1rem;
    font-weight: 500;
    color: var(--text-soft);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.tags-table td {
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--line);
    font-size: 13px;
}

/* Audit log timeline + table (used in /audit) */
.audit-table { width: 100%; border-collapse: collapse; }
.audit-table thead { background: var(--cream-2); }
.audit-table th {
    text-align: left;
    padding: 0.65rem 1rem;
    font-weight: 500;
    color: var(--text-soft);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 1px solid var(--line);
}
.audit-table td {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--line);
    font-size: 13px;
    vertical-align: top;
}
.audit-table tr:last-child td { border-bottom: none; }
.audit-table td.col-time { white-space: nowrap; color: var(--text-soft); font-size: 12px; font-family: 'Geist Mono', monospace; }
.audit-table td.col-actor { font-size: 12px; color: var(--text-soft); font-family: 'Geist Mono', monospace; white-space: nowrap; }
.audit-table td.col-payload { max-width: 480px; }

/* Kolumna „Zgłoszenie" na /audit — numer, temat i klient wpisu historii (09.09.2026, przegląd UX
   poz. 10). Trzy linijki, nie jedna: numer jest tym, po czym się szuka, temat tym, po czym się
   rozpoznaje, a klient rozstrzyga między dwoma zgłoszeniami o tym samym temacie.
   ⚠ `min-width: 0` na komórce — bez tego `text-overflow` na dzieciach nie ma czego przycinać
   i długi temat rozpycha tabelę zamiast się skrócić. */
.audit-table td.col-zgloszenie { max-width: 280px; min-width: 0; }
.audyt-zgloszenie {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    text-decoration: none;
    color: inherit;
}
.audyt-zgloszenie:hover .audyt-zgloszenie-temat { text-decoration: underline; }
.audyt-zgloszenie-nr {
    font-size: 11.5px;
    color: var(--p1);
    font-family: 'Geist Mono', monospace;
}
.audyt-zgloszenie-temat {
    font-size: 12.5px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.audyt-zgloszenie-klient {
    font-size: 11px;
    color: var(--text-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Rozmowy już nie ma — mówimy to wprost zamiast rysować odnośnik, który kończy się „nie znaleziono". */
.audyt-zgloszenie-brak { font-size: 12px; color: var(--text-faint); font-style: italic; }
.audit-payload-pre {
    background: var(--cream-2);
    border-radius: 4px;
    padding: 0.4rem 0.55rem;
    font-size: 11.5px;
    font-family: 'Geist Mono', monospace;
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
    max-height: 140px;
    overflow-y: auto;
}
.audit-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
    margin-right: 0.5rem;
    background: var(--line-faint);
    vertical-align: middle;
}
.audit-dot.tone-ok { background: var(--p1); }
.audit-dot.tone-warn { background: var(--warn); }
.audit-dot.tone-danger { background: var(--danger); }
.audit-dot.tone-info { background: var(--info); }

/* Composer internal-note variant (yellow background) */
.composer-area.composer-internal {
    background: var(--warn-bg, #fbf2dc);
    border-color: rgba(201,138,20,0.35);
}
.composer-area.composer-internal:focus {
    border-color: var(--warn, #c98a14);
    box-shadow: 0 0 0 2px rgba(201,138,20,0.15);
}

/* Snippet autocomplete (#71 phase 2) — float pickera nad composerem.
   composer-area-wrap musi byc position:relative zeby picker dropowal sie tylko nad textareą,
   nie nad calym composerem. */
.composer-area-wrap { position: relative; }
.snippet-picker {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + 4px);
    background: var(--cream);
    border: 1px solid var(--line);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    max-height: 280px;
    overflow-y: auto;
    z-index: 30;
    display: flex;
    flex-direction: column;
    padding: 0.3rem 0;
}
.snippet-picker-hint {
    font-size: 10.5px;
    color: var(--text-soft);
    padding: 0.25rem 0.75rem 0.4rem;
    border-bottom: 1px solid var(--line);
    margin-bottom: 0.2rem;
    font-family: 'Geist Mono', monospace;
    letter-spacing: 0.02em;
}
.snippet-picker-item {
    background: transparent;
    border: 0;
    text-align: left;
    padding: 0.45rem 0.75rem;
    display: grid;
    grid-template-columns: minmax(auto, max-content) 1fr;
    grid-template-rows: auto auto;
    column-gap: 0.6rem;
    row-gap: 0.15rem;
    cursor: pointer;
    border-left: 3px solid transparent;
    transition: background 0.06s ease;
}
.snippet-picker-item:hover,
.snippet-picker-item.selected {
    background: var(--cream-2, #f8f3e8);
    border-left-color: var(--global-palette1, #009244);
}
.snippet-picker-trigger {
    grid-column: 1;
    grid-row: 1;
    font-size: 12px;
    font-weight: 600;
    color: var(--global-palette1, #009244);
    min-width: 0;
}
.snippet-picker-desc {
    grid-column: 2;
    grid-row: 1;
    font-size: 12px;
    color: var(--text);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.snippet-picker-preview {
    grid-column: 1 / -1;
    grid-row: 2;
    font-size: 11px;
    color: var(--text-soft);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: 'Geist Mono', monospace;
}

/* Dashboard — connector health card grid */
.health-row {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.health-row .health-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.55rem 0.75rem;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--danger);
}
.health-row .health-line.warn { border-left-color: var(--warn); }
.health-row .health-line .h-name {
    font-weight: 500;
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
}
.health-row .health-line .h-name .channel-icon { width: 22px; height: 22px; font-size: 10.5px; }
.health-row .health-line .h-msg {
    color: var(--danger);
    font-size: 11.5px;
    font-family: 'Geist Mono', monospace;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    margin: 0 0.4rem;
}
.health-row .health-line.warn .h-msg { color: var(--warn); }

/* Karta „Kontakt" w szczegółach klienta hostuje picker tagów (dropdown absolutny).
   .card ma overflow:hidden → picker byłby przycięty przez kartę i chowałby się pod sekcją
   „Statystyki". Tu przywracamy overflow:visible, żeby dropdown wychodził poza kartę. */
.cdetail-contact-card { overflow: visible; }

/* Customer-level tagi (cross-conv kontekst — wspólna pula z conv tags) */
.cust-tags {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px dashed var(--line);
}
.cust-tags-head {
    margin-bottom: 0.4rem;
}
.cust-tags-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: center;
}

/* Tag picker + add button + remove × — wspólne dla Conversation modal i CustomerDetail.
   Wcześniej żyły tylko w Conversation.razor.css (scoped) → CustomerDetail wyglądał jak rozjazd. */
.tag-add-btn {
    display: inline-flex;
    align-items: center;
    padding: 0.2rem 0.65rem;
    background: transparent;
    border: 1px dashed var(--line-strong);
    border-radius: 12px;
    font-size: 11.5px;
    color: var(--text-soft);
    cursor: pointer;
    font-family: inherit;
    line-height: 1.4;
    transition: all 0.12s;
}
.tag-add-btn:hover { border-style: solid; color: var(--text); background: var(--cream-2); }
.tag-remove {
    background: transparent;
    border: none;
    color: inherit;
    cursor: pointer;
    padding: 0 0.15rem;
    margin-left: 0.25rem;
    font-size: 14px;
    line-height: 1;
    opacity: 0.55;
    border-radius: 50%;
}
.tag-remove:hover { opacity: 1; background: rgba(0,0,0,0.08); }

.tag-picker-anchor { position: relative; display: inline-flex; }
.tag-picker-pop {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 200;
    background: var(--paper);
    border: 1px solid var(--line-strong);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    padding: 0.5rem;
    min-width: 240px;
    max-width: 320px;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.tag-picker-input {
    font-size: 12px;
    padding: 0.35rem 0.55rem;
    border: 1px solid var(--line-strong);
    border-radius: 7px;
    background: var(--paper);
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
}
.tag-picker-list {
    max-height: 240px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.tag-picker-item {
    display: block;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 0.35rem 0.5rem;
    cursor: pointer;
    border-radius: 6px;
    font-family: inherit;
    font-size: 12px;
}
.tag-picker-item:hover { background: var(--cream-2); }
.tag-picker-new {
    color: var(--p1);
    border-top: 1px solid var(--line);
    margin-top: 0.25rem;
    padding-top: 0.5rem;
}
@media (max-width: 600px) {
    .tag-picker-pop {
        position: fixed;
        top: auto;
        bottom: 1rem;
        left: 1rem;
        right: 1rem;
        max-width: none;
    }
}

/* Lista innych otwartych spraw klienta (side panel Conversation) */
.other-convs {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.other-conv {
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--cream-2);
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.08s ease;
}
.other-conv:hover {
    background: var(--cream);
    border-color: var(--line-faint);
}
.other-conv-link {
    display: block;
    padding: 0.55rem 0.7rem;
    color: var(--text);
    text-decoration: none;
}
.other-conv-link:hover { text-decoration: none; }
.other-conv-head {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    margin-bottom: 0.3rem;
    flex-wrap: wrap;
    min-width: 0;
}
.other-conv-head .chip { flex-shrink: 0; }
.other-conv-subj {
    font-size: 13px;
    color: var(--text);
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
}
.other-conv-meta {
    color: var(--text-soft);
    font-size: 11px;
    margin-top: 0.25rem;
}
.avatar-circle.sz-18 {
    width: 18px;
    height: 18px;
    line-height: 18px;
}

/* Customers list table (domyślnie 7 kolumn z 36px checkboxem).
   Modyfikator `--6col` dla list bez checkbox (Returns, SLA settings).
   `min-width: 0` na komórkach jest KRYTYCZNE — bez tego flex/grid items mają
   automatyczny minimum-size równy content-size i text-overflow:ellipsis nie działa
   (długie login Allegro np. "Client:111182502" wylewają się poza komórkę zachodząc
   na sąsiednie kolumny — efekt widoczny na screenshocie /returns iter 87). */
.cust-table {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--cream-2);
    overflow: hidden;
}
.cust-head {
    display: grid;
    grid-template-columns: 36px minmax(180px,1.4fr) minmax(160px,1.2fr) minmax(160px,1.2fr) 90px 90px 130px;
    gap: 0.75rem;
    align-items: center;
    padding: 0.7rem 1rem;
    font-size: 11.5px;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--cream);
    border-bottom: 1px solid var(--line);
}
.cust-head .sortable {
    cursor: pointer;
    user-select: none;
}
.cust-head .sortable:hover {
    color: var(--text);
}
.cust-row {
    display: grid;
    grid-template-columns: 36px minmax(180px,1.4fr) minmax(160px,1.2fr) minmax(160px,1.2fr) 90px 90px 130px;
    gap: 0.75rem;
    align-items: center;
    padding: 0.7rem 1rem;
    border-bottom: 1px solid var(--line);
    text-decoration: none;
    color: var(--text);
    transition: background 0.1s ease;
}
.cust-row:last-child { border-bottom: none; }
.cust-row:hover { background: var(--cream); text-decoration: none; }
.cust-row.selected { background: color-mix(in srgb, var(--global-palette1) 6%, transparent); }
.cust-row .cr-clickable { color: inherit; text-decoration: none; cursor: pointer; }
.cust-row .cr-clickable:hover { text-decoration: none; }
.cust-row .cr-cb, .cust-head .ch-cb { display: flex; align-items: center; justify-content: center; }

/* 6-kolumnowy wariant — Returns list, SLA settings. Layout: name 1.6fr | contact 1.3fr | tags 1.1fr | num 80 | num 90 | last 130 */
.cust-table--6col .cust-head,
.cust-table--6col .cust-row {
    grid-template-columns: minmax(180px,1.6fr) minmax(160px,1.3fr) minmax(140px,1.1fr) 80px 90px 130px;
}
.cust-table--6col .cust-row > div,
.cust-table--6col .cust-head > div { min-width: 0; }
.cust-table--6col .cr-name strong { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cust-table--6col .cr-name span,
.cust-table--6col .cr-contact div {
    display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cust-table--6col .cr-tags { overflow: hidden; }

.cr-name strong { font-size: 13.5px; display: block; }
.cr-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}
.cust-pager {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    justify-content: flex-end;
    margin-top: 0.75rem;
}

/* Returns list — barcode-friendly search input z ikoną skanera */
.returns-search-wrap { position: relative; flex: 1 1 280px; max-width: 360px; }
.returns-search-icon {
    position: absolute;
    left: 0.6rem;
    top: 50%;
    transform: translateY(-50%);
    width: 14px; height: 14px;
    color: var(--text-faint);
    pointer-events: none;
}
.returns-search-input { padding-left: 2rem; width: 100%; }
.returns-search-input:focus { border-color: var(--p1); outline: none; }

/* ─────────── Return Detail Page (rd-*) ───────────
   Editorial-utility layout. Hero header + status timeline + 2-col grid (main items + sticky sidebar).
   Naming convention: `rd-` prefix dla wszystkiego, scope contained. */

/* Fit available width — z .content (100% width parent). 1440 jest dobry breakpoint:
   shorter screens się fit'ują naturalnie, big ultrawide nie rozjeżdżają items na 4 monitora. */
.rd-shell { max-width: 1480px; margin: 0 auto; padding-bottom: 2rem; }

.rd-crumbs { display: flex; align-items: center; gap: 0.4rem; font-size: 12px; color: var(--text-faint); margin-bottom: 0.5rem; }
.rd-back { color: var(--text-faint); text-decoration: none; }
.rd-back:hover { color: var(--p1); text-decoration: underline; }
.rd-crumb-sep { color: var(--line-strong); }
.rd-crumb-id { font-size: 11.5px; }

.rd-hero {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 1rem;
    padding: 1.25rem 1.5rem 1.5rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius, 8px);
    margin-bottom: 1rem;
    border-left: 4px solid var(--p1);
}
.rd-hero-label { font-size: 11px; color: var(--text-soft); letter-spacing: 0.06em; margin: 0 0 0.25rem; }
.rd-hero-title {
    font-family: 'Instrument Serif', 'Geist', serif;
    font-size: clamp(1.9rem, 4vw, 2.5rem);
    font-weight: 400;
    line-height: 1.1;
    color: var(--text);
    margin: 0;
}
.rd-hero-title em { font-style: italic; color: var(--p1); }
.rd-hero-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.6rem; font-size: 12.5px; color: var(--text-soft); }
.rd-meta-sep { color: var(--line-strong); }
.rd-meta-stat strong { color: var(--text); font-weight: 600; }
.rd-hero-actions { display: flex; gap: 0.5rem; align-items: center; }

.rd-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem 0.2rem 0.5rem;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.rd-status-chip .rd-status-dot {
    width: 6px; height: 6px; border-radius: 50%; display: inline-block;
}
.rd-chip-info { background: var(--info-bg, #e2ebff); color: var(--info, #1d4ed8); }
.rd-chip-info .rd-status-dot { background: var(--info, #2563eb); }
.rd-chip-warn { background: var(--warn-bg, #fbf2dc); color: #92590e; }
.rd-chip-warn .rd-status-dot { background: var(--warn, #c98a14); }
.rd-chip-ok { background: var(--ok-bg, #e3f4eb); color: #14653a; }
.rd-chip-ok .rd-status-dot { background: var(--ok, var(--p1)); }
.rd-chip-danger { background: var(--danger-bg, #fbe9e6); color: #921e16; }
.rd-chip-danger .rd-status-dot { background: var(--danger, #c4392f); }
.rd-chip-neutral { background: #eee; color: #555; }
.rd-chip-neutral .rd-status-dot { background: #888; }

.rd-completed {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.85rem;
    background: var(--ok-bg);
    color: #14653a;
    border-radius: var(--radius, 8px);
    font-weight: 600;
    font-size: 13px;
}
.rd-completed--rejected { background: var(--danger-bg); color: #921e16; }

/* Status timeline (stepper) */
.rd-timeline {
    display: flex;
    align-items: center;
    padding: 0.75rem 1.25rem;
    background: var(--cream-2);
    border-radius: var(--radius, 8px);
    border: 1px solid var(--line);
    margin-bottom: 1.25rem;
    overflow-x: auto;
}
.rd-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    min-width: 80px;
    flex: 0 0 auto;
}
.rd-step-dot {
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--line-strong);
    border: 3px solid var(--cream-2);
    box-shadow: 0 0 0 1px var(--line-strong);
    transition: all 0.2s ease;
}
.rd-step.active .rd-step-dot {
    background: var(--p1);
    box-shadow: 0 0 0 1px var(--p1), 0 0 0 5px color-mix(in srgb, var(--global-palette1) 18%, transparent);
    transform: scale(1.1);
}
.rd-step.done .rd-step-dot {
    background: var(--p1);
    box-shadow: 0 0 0 1px var(--p1);
}
.rd-step-label {
    font-size: 11px;
    color: var(--text-soft);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.rd-step.active .rd-step-label { color: var(--p1); font-weight: 600; }
.rd-step.done .rd-step-label { color: var(--text-soft); }
.rd-step-line {
    flex: 1 1 auto;
    height: 2px;
    background: var(--line-strong);
    min-width: 24px;
    margin: 0 -4px;
    align-self: flex-start;
    margin-top: 6px;
}
.rd-step-line.done { background: var(--p1); }

/* Flash banner */
.rd-flash {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.65rem 0.95rem;
    border-radius: var(--radius-sm, 6px);
    margin-bottom: 1rem;
    font-size: 13px;
    font-weight: 500;
}
.rd-flash.ok { background: var(--ok-bg); color: #14653a; border-left: 3px solid var(--ok); }
.rd-flash.err { background: var(--danger-bg); color: #921e16; border-left: 3px solid var(--danger); }
.rd-flash-icon { font-size: 14px; font-weight: 700; }
.rd-flash-x { margin-left: auto; opacity: 0.5; font-size: 18px; line-height: 1; padding: 0 0.4rem; }
.rd-flash-x:hover { opacity: 1; }

/* Grid layout — sidebar wider na ultra wide screens dla customer activity widget */
.rd-grid {
    display: grid;
    grid-template-columns: 1fr 360px;
    gap: 1.5rem;
}
@media (max-width: 1024px) {
    .rd-grid { grid-template-columns: 1fr; }
}

/* Main column sections */
.rd-main { display: flex; flex-direction: column; gap: 1rem; }
.rd-section {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius, 8px);
    overflow: hidden;
}
.rd-section--alt { border-color: color-mix(in srgb, var(--global-palette1) 25%, transparent); border-left: 3px solid var(--p1); }
.rd-section-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.9rem 1.1rem 0.7rem;
    border-bottom: 1px solid var(--line);
    background: var(--cream-2);
}
.rd-section-title { font-size: 13px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text); margin: 0; }
.rd-section-meta { font-size: 12px; color: var(--text-faint); font-family: 'Geist Mono', monospace; }

/* Items list */
.rd-items { display: flex; flex-direction: column; }
.rd-item {
    padding: 0.95rem 1.1rem;
    border-bottom: 1px solid var(--line);
}
.rd-item:last-child { border-bottom: none; }
.rd-item-row {
    display: grid;
    grid-template-columns: 1fr 80px 120px;
    gap: 1rem;
    align-items: start;
}
.rd-item-main { min-width: 0; }
.rd-item-name {
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    line-height: 1.4;
    word-wrap: break-word;
}
.rd-item-offer {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.3rem;
    font-size: 11.5px;
    color: var(--text-soft);
    text-decoration: none;
}
.rd-item-offer:hover { color: var(--p1); }
.rd-item-offer svg { width: 11px; height: 11px; stroke: currentColor; fill: none; stroke-width: 2; }
.rd-item-qty { text-align: center; }
.rd-item-qty-num { display: block; font-size: 18px; font-weight: 600; color: var(--text); }
.rd-item-qty-lbl { font-size: 10.5px; color: var(--text-soft); text-transform: uppercase; letter-spacing: 0.05em; }
.rd-item-price { text-align: right; }
.rd-item-price-amt { display: block; font-size: 14px; font-weight: 600; color: var(--text); }
.rd-item-price-lbl { font-size: 10.5px; color: var(--text-soft); text-transform: uppercase; letter-spacing: 0.05em; }
.rd-item-reason {
    margin-top: 0.65rem;
    padding-top: 0.6rem;
    border-top: 1px dashed var(--line);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 12px;
}
.rd-item-reason-lbl { color: var(--text-faint); }
.rd-reason-chip {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    background: var(--warn-bg);
    color: #92590e;
    border-radius: 4px;
    font-size: 11.5px;
    font-weight: 500;
}

/* Parcels */
.rd-parcels { display: flex; flex-direction: column; }
.rd-parcel {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1.1rem;
    border-bottom: 1px solid var(--line);
}
.rd-parcel:last-child { border-bottom: none; }
.rd-parcel-icon {
    width: 36px; height: 36px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--cream-2);
    display: flex; align-items: center; justify-content: center;
}
.rd-parcel-icon svg { width: 18px; height: 18px; stroke: var(--text-soft); fill: none; stroke-width: 1.5; }
.rd-parcel-waybill { font-size: 13px; font-weight: 600; color: var(--text); }
.rd-parcel-meta { font-size: 11.5px; color: var(--text-soft); margin-top: 0.15rem; }

/* Rejection / Refund sections */
.rd-rejection, .rd-refund { padding: 1rem 1.1rem; }
.rd-rejection-row { display: flex; gap: 0.5rem; align-items: baseline; }
.rd-rejection-lbl { font-size: 12px; color: var(--text-faint); }
.rd-rejection-val { font-size: 13px; color: var(--text); }
.rd-rejection-desc {
    margin-top: 0.6rem;
    padding: 0.6rem 0.85rem;
    background: var(--cream-2);
    border-left: 2px solid var(--line-strong);
    font-style: italic;
    color: var(--text-soft);
    font-size: 13px;
}
.rd-rejection-by, .rd-refund-meta { margin-top: 0.6rem; font-size: 11.5px; color: var(--text-soft); }
.rd-refund-amt { font-size: 22px; font-weight: 700; color: var(--p1); letter-spacing: -0.02em; }
.rd-refund-meta { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.rd-refund-meta code { background: var(--cream-2); padding: 0.1rem 0.35rem; border-radius: 3px; font-size: 11px; }

/* Sidebar */
.rd-side {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    align-self: start;
    position: sticky;
    top: 1rem;
}
.rd-side-card {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius, 8px);
    padding: 0.95rem 1rem 1rem;
}
.rd-side-card--accent { border-color: color-mix(in srgb, var(--global-palette1) 30%, transparent); border-top: 2px solid var(--p1); }
.rd-side-title {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-soft);
    margin: 0 0 0.7rem 0;
}
.rd-side-customer { display: flex; gap: 0.75rem; align-items: center; }
.rd-side-avatar {
    width: 38px; height: 38px;
    flex-shrink: 0;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--p4), var(--p5));
    color: white;
    font-weight: 600;
    font-size: 13px;
    display: flex; align-items: center; justify-content: center;
}
.rd-side-customer-info { min-width: 0; }
.rd-side-name { font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rd-side-login { font-size: 11.5px; color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rd-side-email {
    display: block;
    font-size: 12px;
    color: var(--p1);
    margin-top: 0.15rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rd-customer-tags {
    display: flex; flex-wrap: wrap; gap: 0.3rem;
    margin-top: 0.65rem; padding-top: 0.65rem;
    border-top: 1px dashed var(--line);
}
.rd-customer-notes {
    display: flex; gap: 0.4rem;
    margin-top: 0.65rem; padding: 0.6rem 0.7rem;
    background: var(--cream-2);
    border-left: 2px solid var(--p1);
    border-radius: 0 4px 4px 0;
    font-size: 12px;
    color: var(--text);
    font-style: italic;
    line-height: 1.4;
}
.rd-customer-notes-icon { flex-shrink: 0; opacity: 0.7; }
.rd-customer-notes-text { word-break: break-word; }
.rd-customer-link {
    display: inline-block;
    margin-top: 0.65rem;
    font-size: 11.5px;
    color: var(--p1);
    text-decoration: none;
}
.rd-customer-link:hover { text-decoration: underline; }
.rd-side-empty { font-size: 12.5px; color: var(--text-faint); margin: 0; }

.rd-side-kv { display: flex; flex-direction: column; gap: 0.4rem; }
.rd-side-kv-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 12px;
}
.rd-side-kv-lbl { color: var(--text-faint); flex-shrink: 0; }
.rd-side-kv-val { color: var(--text); text-align: right; word-break: break-all; min-width: 0; }

.rd-side-bank .rd-bank-iban-row {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    padding: 0.5rem 0.65rem;
    background: var(--cream-2);
    border-radius: var(--radius-sm, 6px);
    margin-bottom: 0.6rem;
}
.rd-bank-iban {
    flex: 1 1 auto;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text);
    word-break: break-all;
    font-feature-settings: 'tnum' 1;
    letter-spacing: 0.02em;
}
.rd-bank-copy {
    flex-shrink: 0;
    width: 28px; height: 28px;
    border-radius: 4px;
    background: var(--paper);
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: all 0.15s ease;
}
.rd-bank-copy:hover { background: var(--p1); border-color: var(--p1); }
.rd-bank-copy:hover svg { stroke: white; }
.rd-bank-copy svg { width: 14px; height: 14px; stroke: var(--text-soft); fill: none; stroke-width: 2; }
.rd-bank-holder { font-size: 12px; color: var(--text-soft); }

/* Customer history widget (sidebar) — quick win z Responso */
.rd-history { display: flex; flex-direction: column; gap: 0.5rem; }
.rd-history-counts { display: flex; gap: 0.85rem; padding: 0.4rem 0 0.5rem; border-bottom: 1px solid var(--line); }
.rd-history-count { flex: 1; text-align: center; }
.rd-history-count-num { display: block; font-size: 18px; font-weight: 600; color: var(--text); }
.rd-history-count-num.danger { color: var(--danger); }
.rd-history-count-lbl { font-size: 10.5px; color: var(--text-soft); text-transform: uppercase; letter-spacing: 0.04em; }
.rd-history-flag {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.65rem;
    margin-top: 0.5rem;
    background: var(--danger-bg);
    color: #921e16;
    border-radius: 4px;
    font-size: 11.5px;
    font-weight: 500;
}
.rd-history-list { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.4rem; }
.rd-history-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.4rem 0.55rem;
    border-radius: 4px;
    font-size: 11.5px;
    color: var(--text);
    text-decoration: none;
    transition: background 0.1s ease;
}
.rd-history-item:hover { background: var(--cream-2); }
.rd-history-item-meta { font-size: 10.5px; color: var(--text-soft); flex-shrink: 0; }

/* Activity widget — kind icon + subject + relative time */
.rd-activity-kind { font-size: 13px; flex-shrink: 0; opacity: 0.8; }
.rd-activity-subject { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* Inline chat w return detail sidebar (#75) — kompaktowy thread + reply */
.rd-side-title-link {
    font-size: 11px;
    font-weight: 400;
    color: var(--global-palette1, #009244);
    margin-left: auto;
    text-decoration: none;
}
.rd-side-title-link:hover { text-decoration: underline; }
.rd-side-title { display: flex; align-items: baseline; gap: 0.4rem; }
.rd-inline-thread {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin: 0.4rem 0 0.6rem;
    max-height: 320px;
    overflow-y: auto;
}
.rd-inline-msg {
    padding: 0.4rem 0.6rem;
    border-radius: 6px;
    background: var(--cream-2, #f8f3e8);
    border-left: 3px solid transparent;
    font-size: 11.5px;
    min-width: 0;
}
.rd-inline-msg.out { border-left-color: var(--global-palette1, #009244); background: color-mix(in srgb, var(--global-palette1) 5%, transparent); }
.rd-inline-msg.in { border-left-color: var(--line-faint); }
.rd-inline-msg-head {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.2rem;
    align-items: baseline;
    min-width: 0;
}
.rd-inline-msg-head strong { font-size: 11px; color: var(--text); }
.rd-inline-msg-head .mono { font-size: 10px; color: var(--text-soft); flex-shrink: 0; }
.rd-inline-msg-body { color: var(--text); white-space: pre-wrap; word-break: break-word; }
.rd-inline-reply { margin-top: 0.5rem; }

/* External link button (Allegro) */
.rd-link-ext {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.rd-link-ext svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2; }

/* Zdanie wprowadzajace w naglowku zwrotu. `.lede` niesie krój i szerokość — tutaj tylko odstęp. */
.rd-hero-lede { margin: 0.7rem 0 0; }

/* Podpis pod paskiem stanu: „ETAP 2 Z 5 · W drodze". Na komputerze schowany przez `.mobile-only`
   (pasek ma tam wszystkie pięć podpisów), na telefonie NIESIE całą treść etapu.
   Rysuje się jak dolna połowa panelu paska — to samo tło, ta sama ramka bez górnej krawędzi —
   więc kropki i zdanie czytają się jako jeden element, a nie dwa. */
.rd-timeline-now {
    margin: 0 0 1.25rem;
    padding: 0 1rem 0.75rem;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-top: none;
    border-radius: 0 0 var(--radius, 8px) var(--radius, 8px);
    font-size: 12.5px;
    color: var(--text-soft);
    text-align: center;
}
.rd-timeline-now strong { color: var(--p1); font-weight: 600; }
.rd-timeline-now .rd-timeline-licznik {
    font-family: 'Geist Mono', monospace;
    font-size: 11px;
    color: var(--text-soft);
    letter-spacing: 0.04em;
}

/* ─────────── Karta zwrotu na telefonie (≤768 px) ───────────
   Obchód UX 01.09.2026, znalezisko nr 2: JEDYNY ekran w aplikacji, który przewijał się w bok.
   Zmierzone przy 390 px: `main.scrollLeft` = 260 px, w kadrze 1 przycisk z 4 — poza ekranem
   zostawały „Odrzuć" i „Zwróć pieniądze →", czyli to, po co człowiek tu wchodzi.

   ⚠ DLACZEGO STOS, A NIE `overflow`. Obcięcie (`hidden`) chowa przyciski za niewidzialną
   krawędzią, a `overflow-x:auto` chowa je za gestem, którego nikt nie wykonuje — oba zabierają
   akcję dokładnie tak samo skutecznie jak przewijanie całej strony. Nagłówek przestaje więc być
   układem dwukolumnowym i staje się stosem, a przyciski układają się w hierarchię: dwa ciche
   odnośniki obok siebie, potem każda DECYZJA na własnym wierszu.

   ⚠ DLACZEGO ZAWIJANY FLEX, A NIE SIATKA. Przyciski renderują się warunkowo (uprawnienie do
   odpowiedzi, uprawnienie do zwrotu pieniędzy, zwrot już odrzucony/rozliczony) — jest osiem
   kombinacji. Siatka o stałej liczbie kolumn zostawia w części z nich dziurę po nieobecnym
   przycisku; zawijany flex nie zostawia jej w żadnej, bo elementy rosną do końca wiersza.

   ⚠ Ten blok MUSI stać PO regułach bazowych `.rd-*` — `@media` nie dodaje specyficzności,
   więc przy równej wadze (0,1,0) rozstrzyga kolejność w pliku. */
@media (max-width: 768px) {
    .rd-hero {
        grid-template-columns: 1fr;
        align-items: start;
        padding: 1rem 1.1rem 1.15rem;
    }

    .rd-hero-actions {
        flex-wrap: wrap;
        width: 100%;
        gap: 0.5rem;
    }

    /* ⚠ `min-width: 0` jest tu obowiązkowe: element flexa ma domyślnie `min-width: auto`,
       czyli szerokość swojej najdłuższej niepodzielnej treści. Przy `white-space: nowrap`
       z `.btn` oznaczałoby to CAŁY napis — i przycisk rozpychałby wiersz dokładnie tak,
       jak rozpychał stronę przed tą poprawką.
       `white-space: normal` + `height: auto` domykają sprawę na najwęższych telefonach:
       napis zawija się w drugą linijkę, zamiast wyjść przyciskowi za krawędź.
       Przy okazji 44 px zamiast 36 px — cztery cele w tym nagłówku były poniżej progu,
       którego ten sam plik pilnuje niżej dla reszty ekranu zwrotu (`pointer: coarse`). */
    .rd-hero-actions > .btn {
        flex: 1 1 8.5rem;
        min-width: 0;
        height: auto;
        min-height: 44px;
        padding-block: 0.45rem;
        white-space: normal;
        line-height: 1.25;
        text-align: center;
    }

    /* Decyzja — „Odrzuć" i „Zwróć pieniądze →" — bierze cały wiersz. Nie dlatego, że jest
       szeroka, tylko dlatego, że jest decyzją: nie ma stać w rzędzie z odnośnikiem. */
    .rd-hero-actions > .rd-act-decyzja { flex-basis: 100%; }

    /* „Odrzuć" na komputerze stoi w rzędzie cichych przycisków i przezroczyste tło mu wystarcza.
       Samo na całym wierszu czytało się jako wyśrodkowany podpis, nie jako przycisk — więc na
       telefonie bierze traktowanie drugorzędne (te same wartości co `.btn-secondary`).
       Wtedy obie decyzje widać jako parę: cichą i zieloną. */
    .rd-hero-actions > .btn-ghost.rd-act-decyzja {
        background: var(--paper);
        border: 1px solid var(--line-strong);
        color: var(--text);
    }

    .rd-completed { width: 100%; justify-content: center; }

    /* ── Pasek stanu ──
       Pięć podpisów („Zwrot zgłoszony / W drodze / Doręczony / Weryfikacja w magazynie /
       Zwrot wpłaty") potrzebuje 587 px. Przy 390 px zmierzyłem 197 px paska schowane za
       własnym przewijakiem i 3 etapy z 5 widoczne w całości. Zamiast zostawiać je za
       niewidzialną krawędzią, na telefonie zdejmujemy podpisy z kropek — kropki niosą
       POŁOŻENIE, a zdanie pod nimi niesie ZNACZENIE („Etap 2 z 5 — W drodze"). Nic nie ginie:
       treść jest przeniesiona, nie obcięta. */
    .rd-timeline {
        overflow-x: visible;
        padding: 0.85rem 1rem 0.7rem;
        /* Odstęp przejmuje podpis pod spodem — inaczej kropki i zdanie rozjechałyby się
           na dwa osobne panele zamiast czytać się jako jeden. */
        margin-bottom: 0;
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
    }
    .rd-timeline .rd-step { min-width: 0; }
    .rd-timeline .rd-step-label { display: none; }
    .rd-timeline .rd-step-line { min-width: 0; margin-top: 6px; }

    /* ── Zwracane pozycje ──
       Na komputerze wiersz pozycji to trzy kolumny: nazwa / ilość / cena (`1fr 80px 120px`).
       Przy 390 px na nazwę zostaje jakieś 108 px i „Słuchawki bezprzewodowe QX-200" łamie się
       w ŚRODKU słowa („bezprzewodow / e QX-200"). To jedyne miejsce na tej karcie, gdzie stosuje
       się repowa zasada „≤768 px lista zamienia się w kartę": nazwa dostaje całą szerokość,
       a ilość i cena schodzą pod nią w jeden rząd — po przeciwnych stronach, żeby dało się je
       porównać wzrokiem. Reszta karty (panel klienta, zamówienie, konto bankowe, rozmowa)
       układa się w jedną kolumnę już przy 1024 px i przy 390 px nie ma czego poprawiać. */
    .rd-item-row {
        grid-template-columns: 1fr auto;
        gap: 0.55rem 1rem;
    }
    .rd-item-main { grid-column: 1 / -1; }
    .rd-item-qty { text-align: left; }
}

/* Customer detail page (cross-conv) */
.cdetail-grid {
    display: grid;
    grid-template-columns: minmax(280px, 360px) 1fr;
    gap: 1.25rem;
    margin-top: 1rem;
}
.cdetail-side, .cdetail-main {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
@media (max-width: 900px) {
    .cdetail-grid { grid-template-columns: 1fr; }

    /* ⚠ Wariant 6-kolumnowy MUSI być wymieniony osobno, inaczej ta reguła go NIE dotyczy.
       Zapytanie o szerokość ekranu nie dodaje wagi selektorowi: `.cust-row` to waga 0,1,0,
       a `.cust-table--6col .cust-row` wyżej w pliku to 0,2,0 — i wygrywa NIEZALEŻNIE od
       tego, że jest w bloku dla szerokiego ekranu.
       Skutek na telefonie (znaleziony 12.08.2026 przez przegląd wszystkich ekranów): listy
       „Zwroty" i „Ustawienia SLA" zostawały przy sześciu kolumnach z komputera, więc wartość,
       liczba pozycji i data lądowały 240–470 px POZA wierszem i były ucinane. Na telefonie
       tego nie widać — nie ma poziomego paska, treść po prostu znika. */
    .cust-head, .cust-row,
    .cust-table--6col .cust-head,
    .cust-table--6col .cust-row {
        grid-template-columns: 1fr;
        gap: 0.4rem;
    }
    .cust-head { display: none; }
    .cust-row { padding: 1rem; }

    /* Nagłówek kolumn znika na telefonie, więc wartości liczbowe zostawały bez żadnego opisu —
       pod nazwiskiem szła kolumna „0 / 0 / —" i nie dało się zgadnąć, co znaczy która.
       Komórka z atrybutem data-label dokleja sobie podpis; komórki bez atrybutu (nazwa, kontakt,
       tagi) mówią same za siebie i zostają bez zmian. */
    .cust-row > [data-label] {
        display: flex;
        gap: 0.4rem;
        align-items: baseline;
    }
    .cust-row > [data-label]::before {
        content: attr(data-label);
        flex: none;
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--text-soft);
    }
    /* Zaznaczenie wiersza ląduje wtedy nad nazwą, wyśrodkowane — wygląda jak zgubiony kwadrat.
       Na telefonie dosuwamy je do lewej, do jednej linii z resztą. */
    .cust-row .cr-cb { justify-content: flex-start; }
}

/* Customer merge modal */
.cust-merge-overlay {
    position: fixed;
    inset: 0;
    background: rgba(20, 22, 26, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    backdrop-filter: blur(2px);
}
.cust-merge-modal {
    background: var(--cream);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1.5rem 1.75rem;
    max-width: 640px;
    width: calc(100% - 2rem);
    box-shadow: 0 20px 60px rgba(0,0,0,0.25);
}
.cust-merge-modal h3 {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
    font-size: 1.4rem;
    margin-bottom: 0.4rem;
}
.merge-choice-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
    margin-top: 1rem;
}
.merge-choice-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    padding: 0.85rem 1rem;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease;
    text-align: left;
}
.merge-choice-card:hover:not(:disabled) {
    border-color: var(--p1);
    background: var(--cream);
}
.merge-choice-card:disabled {
    opacity: 0.5;
    cursor: wait;
}
.merge-choice-card strong {
    font-size: 14px;
}
@media (max-width: 600px) {
    .merge-choice-grid { grid-template-columns: 1fr; }
}

/* Keyword highlight w wiadomościach (Quick-reply suggestion P9.3) */
.msg-text mark.kw-hit {
    background: rgba(193, 209, 28, 0.35);
    border-radius: 3px;
    padding: 0 0.15em;
    color: inherit;
}

/* Dashboard volumes 24h chart */
.vol-chart {
    width: 100%;
    padding: 0.5rem 0;
}
.vol-chart rect:hover {
    opacity: 1 !important;
    cursor: pointer;
}
.vol-chart-labels {
    display: flex;
    justify-content: space-between;
    font-size: 10px;
    color: var(--text-soft);
    padding: 0.3rem 0 0;
}

/* Reports — per-agent FRT bar chart */
.agent-frt-bars {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    container-type: inline-size;
}
.agent-frt-row {
    display: grid;
    grid-template-columns: 32px minmax(110px, 1.2fr) minmax(120px, 3fr) 70px;
    align-items: center;
    gap: 0.6rem;
}
.agent-frt-text { min-width: 0; }
.agent-frt-name { font-size: 13px; color: var(--text); }
.agent-frt-sub { color: var(--text-soft); font-size: 10.5px; }
.agent-frt-bar-wrap {
    width: 100%;
    height: 12px;
    background: var(--cream-2);
    border-radius: 6px;
    overflow: hidden;
}
.agent-frt-bar {
    height: 100%;
    border-radius: 6px;
    transition: width 0.4s ease;
    min-width: 4px;
}
.agent-frt-label {
    font-size: 11.5px;
    color: var(--text-soft);
    text-align: right;
}
/* Wąska karta: pasek znika, zostaje czas.
   Cztery kolumny mają razem minimum ~360 px, a na telefonie karta ma ~300 px — nadmiar wychodził
   poza kartę i UCINAŁ ostatnią kolumnę, czyli jedyną liczbę, po którą ktoś tu przychodzi.
   Pasek jest ilustracją tej liczby, więc to on ustępuje.
   ⚠ @container, a NIE @media: szerokość karty wynika z tego, czy siatka raportu stoi w jednej
   czy w dwóch kolumnach — przy szerokim oknie karta i tak bywa wąska. */
@container (max-width: 380px) {
    .agent-frt-row { grid-template-columns: 32px minmax(0, 1fr) auto; }
    .agent-frt-bar-wrap { display: none; }
}

/* Dashboard day×hour 2D heatmap (P17.5) */
.dayhour-heatmap {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0.5rem 0;
    width: 100%;
    overflow-x: auto;
}
.dh-header, .dh-row {
    display: grid;
    grid-template-columns: 30px repeat(24, 1fr);
    gap: 2px;
    align-items: center;
}
.dh-day-label, .dh-hour-label {
    font-size: 10px;
    color: var(--text-soft);
}
.dh-day-label { text-align: right; padding-right: 0.3rem; }
.dh-hour-label { text-align: center; height: 14px; }
.dh-cell {
    height: 18px;
    border-radius: 3px;
    background: var(--p1);
    transition: opacity 0.15s ease, transform 0.08s ease;
    cursor: default;
}
.dh-cell:hover {
    transform: scale(1.2);
    opacity: 1 !important;
    z-index: 2;
}

/* Powiadomienia wstrzykiwane przez abc-realtime.js po SignalR push.
   Auto-dismiss po 8 s, ręczne zamknięcie krzyżykiem.

   ⚠ STOS PRZENIESIONY Z GÓRY-PRAWO NA DÓŁ-PRAWO (02.09.2026). `top: 1rem` przy pasku
     górnym wysokim na `--topbar-h` (3,5rem) znaczyło, że powiadomienie ZAWSZE lądowało
     na pasku aplikacji: zasłaniało wyszukiwarkę, dzwonek, znak zapytania i menu konta —
     czyli sterowanie, które ma być dostępne przez cały czas. Drugie powiadomienie w stosie
     schodziło na rząd przycisków ekranu; na zrzucie z raportów obsługi „Pokaż →" z kartki
     powiadomienia wchodziło w połowę słowa „Pobierz" pod spodem i całość była nie do
     odczytania.
     Dół-prawo to zarazem miejsce, w którym ABCare pokazuje potwierdzenia zapisu
     (`.toast-notification`) — czyli róg, którego żaden ekran nie używa na swoje przyciski.
     `column-reverse`: najnowsze na dole, stos rośnie w górę i nigdy nie dosięga paska. */
#abc-toast-container {
    position: fixed; bottom: 1rem; right: 1rem; z-index: 9999;
    display: flex; flex-direction: column-reverse; gap: 0.5rem;
    pointer-events: none;
}
.abc-toast {
    pointer-events: auto;
    display: flex; align-items: flex-start; gap: 0.6rem;
    min-width: 280px; max-width: 380px;
    padding: 0.8rem 1rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-left: 4px solid var(--warn);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    font-size: 13px;
    animation: abc-toast-in 250ms ease-out;
}
.abc-toast-danger { border-left-color: #d04030; }
.abc-toast-ok { border-left-color: var(--global-palette1, #009244); }
.abc-toast-ok .abc-toast-icon { color: var(--global-palette1, #009244); }
.abc-toast-icon { font-size: 18px; line-height: 1; padding-top: 1px; }
.abc-toast-content { flex: 1; }
.abc-toast-content strong { display: block; color: var(--text, #1a1a1a); margin-bottom: 0.2rem; }
.abc-toast-body { color: var(--text-soft, #555); font-size: 12px; line-height: 1.4; }
.abc-toast-link {
    display: inline-block; margin-top: 0.4rem;
    color: var(--p1, #009244); font-weight: 500; text-decoration: none;
}
.abc-toast-link:hover { text-decoration: underline; }
.abc-toast-close {
    background: none; border: none; cursor: pointer;
    font-size: 18px; line-height: 1; color: var(--text-faint, #676c76);
    padding: 0 0.2rem;
}
.abc-toast-close:hover { color: var(--text, #1a1a1a); }
.abc-toast-leaving { opacity: 0; transition: opacity 250ms; }
@keyframes abc-toast-in {
    from { transform: translateX(20px); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}
@media print { #abc-toast-container { display: none; } }

/* Presence chip pulse (collision detection — agent typing reply) */
@keyframes presencePulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.3; transform: scale(0.7); }
}

/* EditorialLayout — minimalistyczny layout dla landing/auth/onboarding pages bez sidebar.
   Styles trzymane w app.css (nie scoped razor.css) bo dynamic @layout w Blazor czasem gubi
   scope attribute b-XXX, przez co scoped CSS nie matchuje. */
.editorial-shell { min-height: 100vh; display: flex; flex-direction: column; }
.editorial-topbar {
    height: var(--topbar-h, 3.5rem);
    padding: 0 1.5rem;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    border-bottom: 1px solid var(--line, #e8e5db);
    background: color-mix(in srgb, var(--paper, #fff) 80%, transparent);
    backdrop-filter: blur(8px);
    position: sticky; top: 0; z-index: 50;
}
.editorial-brand { display: flex; align-items: center; gap: 0.55rem; text-decoration: none; color: inherit; }
.editorial-logo {
    width: 30px; height: 30px; border-radius: 7px;
    background: #ffffff;
    display: grid; place-items: center;
    border: 1px solid var(--line, #e5e7eb);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.2);
    flex: none;
}
.editorial-logo svg { width: 18px; height: 18px; }
.editorial-brandname { font-family: 'Instrument Serif', Georgia, serif; font-size: 1.4rem; line-height: 1; letter-spacing: -0.01em; color: var(--text, #111317); }
.editorial-brandname em { font-style: italic; color: var(--p1, #019344); }
.editorial-nav { display: flex; align-items: center; gap: 0.4rem; }
/* Chip konta w pasku stron bez menu bocznego (licencja, regulamin, potwierdzenia).
   Wygląda tak samo jak chip w pasku aplikacji — ten sam człowiek, ten sam awatar. */
.editorial-user {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.3rem 0.65rem 0.3rem 0.3rem;
    border-radius: 999px;
    color: var(--text, #111317);
    text-decoration: none;
    transition: background 0.15s;
}
.editorial-user:hover { background: var(--cream-2, #f5f2e9); color: var(--text, #111317); }
.editorial-user-name {
    font-size: 13px; font-weight: 500;
    max-width: 160px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 600px) { .editorial-user-name { display: none; } }
.editorial-main { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 2rem 1rem; }
.editorial-main > .page-centered { padding: 0; }
.editorial-footer {
    padding: 1rem 1.5rem; border-top: 1px solid var(--line, #e8e5db);
    display: flex; align-items: center; gap: 0.5rem; font-size: 12px; color: var(--text-soft, #5e6671);
}
.editorial-footer a { text-decoration: none; }
.editorial-footer a:hover { color: var(--p1, #019344); }
/* Stopka stron publicznych to NAWIGACJA (Dokumentacja / Polityka / Regulamin), a nie tekst
   w zdaniu — na dotyku odnosniki dostaja pelna wysokosc celu. ⚠ NIE dotyczy adresow e-mail
   i odnosnikow WEWNATRZ akapitow regulaminu: tam 38 px rozwalilby interlinie, a to nie sa
   przyciski, tylko fragmenty zdania. */
@media (pointer: coarse) {
    .editorial-footer a { display: inline-flex; align-items: center; min-height: 40px; flex-direction: row; }
}
@media (max-width: 600px) {
    .editorial-topbar { padding: 0 0.85rem; }
    .editorial-brandname { font-size: 1.2rem; }
    .editorial-footer { padding: 0.85rem 1rem; flex-wrap: wrap; }
}

/* OAuth re-auth banner — pokazywany gdy ConnectorAccount.Status = Unauthorized.
   Sticky pod topbar; kliknięcie linku przenosi do /integrations gdzie agent re-auth. */
.reauth-banner {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 1rem;
    background: var(--warn-bg, #fff8e6);
    color: var(--warn-mocny);
    border-bottom: 1px solid var(--warn);
    font-size: 13px;
    line-height: 1.4;
}
.reauth-banner svg { flex-shrink: 0; color: #c08000; }
.reauth-banner span { flex: 1; }
.reauth-banner-btn {
    color: var(--warn-mocny);
    text-decoration: underline;
    font-weight: 500;
    white-space: nowrap;
}
.reauth-banner-btn:hover { color: #5a3500; }
/* Baner siedzi w layoucie, czyli na KAZDEJ stronie — a jego odnosnik mial na telefonie
   18 px wysokosci, czyli polowe minimalnego celu dotykowego. Powiekszamy pole klikania
   (nie sam tekst) i tylko na dotyku, zeby gestosc interfejsu na komputerze zostala. */
@media (pointer: coarse) {
    .reauth-banner-btn {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 0.25rem;
        flex-direction: row;
    }
}
@media print { .reauth-banner { display: none; } }

/* ── Pasek wersji pokazowej — jeden wiersz nad trescia, na KAZDYM ekranie (oba uklady).
   Celowo skromniejszy od `.reauth-banner`: to nie jest ostrzezenie o awarii, tylko staly
   znacznik „to nie sa prawdziwe dane". Bez ikony, bez przycisku, bez wlasnego tla o mocnym
   kolorze — pokaz jest o tym, co jest POD paskiem. ── */
.demo-banner {
    padding: 0.4rem 1rem;
    background: var(--cream-2);
    color: var(--text-soft);
    border-bottom: 1px solid var(--line);
    font-size: 12.5px;
    line-height: 1.4;
    letter-spacing: 0.01em;
    text-align: center;
}
/* Zrzuty ekranu do dokumentacji robimy na danych demo — pasek w nich tylko przeszkadza. */
@media print { .demo-banner { display: none; } }

/* ── Karta „mowi do Ciebie instancja pokazowa" — WYLACZNIE na instancji demo.
   W odroznieniu od `.demo-banner` (staly, dyskretny znacznik) ta karta MA byc widoczna:
   to jedyne miejsce, w ktorym czlowiek dowiaduje sie, czym ma sie zalogowac. Bez niej
   pokaz konczyl sie na formularzu, do ktorego nie bylo czego wpisac.

   Od 06.09.2026 tych samych klas uzywaja jeszcze dwa miejsca (swiadomie, bo to ta sama
   rodzina komunikatow): kartka odmowy `OdmowaDemo` na ekranach integracji i jawne haslo
   do sejfu na ekranie `/vault`. Zmiana wygladu dotyka wiec calej trojki naraz. ── */
.karta-demo {
    margin-bottom: 1.25rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--p1);
    border-left-width: 3px;
    border-radius: var(--radius-sm, 6px);
    background: var(--cream-2);
}
.karta-demo-tytul {
    margin: 0 0 0.35rem;
    font-weight: 700;
    font-size: 13.5px;
    color: var(--p1);
}
.karta-demo-opis {
    margin: 0 0 0.75rem;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-soft);
}
/* Siatka dwukolumnowa: podpis nie ucieka od wartosci przy dlugim loginie.
   `min-width: 0` na wartosci — bez tego dlugi adres rozpycha karte poza formularz. */
.karta-demo-dane {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem 0.75rem;
    margin: 0 0 0.7rem;
    align-items: baseline;
}
.karta-demo-dane dt {
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-soft);
}
.karta-demo-dane dd {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
    font-size: 13px;
    color: var(--text);
    -webkit-user-select: all;
    user-select: all;      /* jedno klikniecie zaznacza calosc do skopiowania */
}
.karta-demo-stopka {
    margin: 0;
    font-size: 12px;
    color: var(--text-soft);
}

/* ── Presety kont na ekranie logowania pokazu (06.09.2026) ──────────────────────────────────
   Po jednym koncie na rolę, każde ze zdaniem o tym, komu tę rolę nadać. Handlowiec przełącza
   się między nimi, zamiast opowiadać o uprawnieniach.
   Lista jest DRUGORZĘDNA wobec konta głównego wyżej — stąd cieńsza kreska u góry zamiast
   własnej ramki: to dalej jedna karta, a nie dwie. */
.karta-demo-presety {
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    /* `--border-color`, nie `--border` — tej drugiej paleta nie zna, a nieistniejąca zmienna
       kasuje CAŁĄ deklarację, więc kreski po prostu by nie było. Złapała to zapadka
       ZmiennaWygladuKtorejPaletaNieMa, trzeci raz tego dnia. */
    border-top: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.karta-demo-presety-tytul {
    margin: 0;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-soft);
}

.karta-demo-preset-glowa {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 13px;
}

.karta-demo-preset-osoba {
    font-size: 12px;
    color: var(--text-soft);
}

.karta-demo-preset-login {
    font-size: 12px;
    /* Adres bywa dłuższy niż karta — łamiemy go zamiast rozpychać ją w bok. */
    overflow-wrap: anywhere;
}

.karta-demo-preset-opis {
    margin-top: 0.15rem;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--text-soft);
}

/* ── Metrics help — rozwijany panel „Co oznaczają te wskaźniki?" na raportach.
   Native <details> (dostępny, działa bez JS). Editorial-utility: subtelna karta,
   niebieski akcent info na ikonie. Reużywalny na /reports/*. ── */
.metrics-help {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--paper);
    margin-bottom: 1.25rem;
    overflow: hidden;
}
.metrics-help > summary {
    list-style: none;
    cursor: pointer;
    display: flex; align-items: center; gap: 0.55rem;
    padding: 0.7rem 1rem;
    font-size: 13px; font-weight: 500;
    color: var(--text);
    user-select: none;
}
.metrics-help > summary::-webkit-details-marker { display: none; }
.metrics-help > summary::marker { content: ""; }
.metrics-help > summary:hover { background: var(--cream-2); }
.metrics-help > summary:focus-visible { outline: 2px solid var(--info); outline-offset: -2px; }
.metrics-help .mh-icon {
    width: 22px; height: 22px; flex: none;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--info-bg); color: var(--info);
    font-weight: 700; font-size: 13px; line-height: 1;
}
.metrics-help .mh-chevron {
    margin-left: auto; flex: none;
    width: 16px; height: 16px;
    stroke: currentColor; fill: none; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-faint);
    transition: transform 0.18s ease;
}
.metrics-help[open] > summary .mh-chevron { transform: rotate(180deg); }
.metrics-help-body {
    padding: 0.25rem 1rem 1rem;
    border-top: 1px solid var(--line);
}
.metrics-help-body dl { margin: 0; }
.metrics-help-body dl > div {
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--cream-2);
}
.metrics-help-body dl > div:last-of-type { border-bottom: none; }
.metrics-help-body dt {
    font-weight: 600; font-size: 13px; color: var(--text);
    margin-bottom: 0.2rem;
}
.metrics-help-body dd {
    margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--text-soft);
}
.metrics-help-body dd .mh-ex {
    display: block; margin-top: 0.25rem;
    color: var(--text-faint); font-style: italic;
}
.metrics-help-more {
    display: inline-block; margin-top: 0.85rem;
    font-size: 12.5px; color: var(--p1); text-decoration: none; font-weight: 500;
}
.metrics-help-more:hover { text-decoration: underline; }

/* Inline „?" przy etykiecie wskaźnika — tooltip przez title=, znaczenie przez aria-label. */
.info-dot {
    display: inline-grid; place-items: center;
    width: 15px; height: 15px;
    margin-left: 0.25rem;
    border-radius: 50%;
    background: var(--info-bg); color: var(--info);
    font-size: 10px; font-weight: 700; line-height: 1;
    cursor: help; vertical-align: middle;
    text-decoration: none; user-select: none;
}
.info-dot:hover { filter: brightness(0.96); }
.info-dot:focus-visible { outline: 2px solid var(--info); outline-offset: 1px; }

/* Print stylesheet — przy "Drukuj / PDF" ukrywamy nav/menu/topbar i drukujemy
   sam content raportu. Białe tło.
   WAŻNE (fix pustych stron): layout ma `main { height: 100vh; overflow-y: auto }`,
   czyli kontener przewijania o stałej wysokości. Przy druku taki kontener przycina
   treść do jednego ekranu, a przeglądarka rezerwuje kolejne strony jako PUSTE.
   Dlatego w druku zdejmujemy stałe wysokości i overflow z całego łańcucha layoutu
   (html → body → .page → main → .content-wrapper → .content), żeby raport płynął
   naturalnie przez wszystkie strony. */
@media print {
    /* App chrome do ukrycia: sidebar, topbar (uwaga: to KLASA .app-topbar, nie #id),
       banery, kontrolki filtrów oraz przyciski akcji raportu (.no-print). */
    #page-sidebar, #app-topbar, .app-topbar, .app-burger, .alert-actions, .filter-bar,
    .conv-side-toggle, .conv-side-toggle-mobile, .conv-side-backdrop,
    .snooze-dropdown, .composer-area-wrap, .composer-actions, .composer-tabs,
    .tenant-switcher-wrap, .nav-section, .sidebar-brand, .nav-account,
    .reauth-banner, .sidebar-backdrop, .no-print {
        display: none !important;
    }
    /* Zdejmij stałą wysokość + scroll z łańcucha layoutu — inaczej puste strony. */
    html, body {
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
        background: white !important;
        color: black !important;
    }
    .page, #page-shell {
        display: block !important;
        min-height: 0 !important;
        height: auto !important;
        overflow: visible !important;
    }
    main {
        display: block !important;
        height: auto !important;
        max-height: none !important;
        max-width: 100% !important;
        overflow: visible !important;
    }
    .content-wrapper {
        display: block !important;
        min-height: 0 !important;
        overflow: visible !important;
    }
    .content {
        max-width: 100% !important;
        padding: 0 !important;
        overflow: visible !important;
    }
    /* Stagger fade-in startuje z opacity:0 — gdyby animacja nie dobiegła przed drukiem,
       treść byłaby niewidoczna. Wymuszamy pełną widoczność. */
    .stagger > * {
        opacity: 1 !important;
        animation: none !important;
        transform: none !important;
    }
    .card, .kpi {
        page-break-inside: avoid;
        break-inside: avoid;
        box-shadow: none !important;
        border: 1px solid #ccc !important;
    }
    /* Wykresy/heatmapa/paski są rysowane tłem (background) — domyślnie druk pomija tła.
       Wymuszamy dokładne kolory na całej stronie, żeby wizualizacje faktycznie się wydrukowały. */
    * {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
    }
}

/* Email — external images blocked placeholder + show button bar */
.email-images-blocked-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.5rem 0.8rem;
    margin: 0.4rem 0;
    background: var(--cream-2, #f5f3ed);
    border: 1px dashed var(--line, #d8d3c4);
    border-radius: 6px;
    font-size: 12.5px;
}
img.external-image-blocked {
    display: inline-block;
    min-width: 80px;
    min-height: 80px;
    background: #f1f5f9 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'><rect width='80' height='80' fill='%23f1f5f9'/><circle cx='40' cy='35' r='10' fill='%23cbd5e1'/><path d='M28 60h24l-6-12-6 8-3-4z' fill='%23cbd5e1'/><text x='40' y='75' text-anchor='middle' fill='%2364748b' font-size='9' font-family='sans-serif'>obrazek</text></svg>") no-repeat center;
    border: 1px dashed #94a3b8;
    border-radius: 4px;
    color: transparent;
}
img.external-image-loaded {
    border: 1px solid #e2e8f0;
    border-radius: 4px;
}

/* ── Natywna powloka mobilna (Android): chowa elementy topbara zdublowane przez natywny dolny pasek.
   Klasa `abcare-native` dokladana na <html> przez WebView (MainPage.OnNavigated). Desktop nigdy jej
   nie ma -> zero wplywu. Dzwonek -> zakladka Alerty; user chip -> zakladka Konto. ── */
html.abcare-native .notif-dropdown,
html.abcare-native .app-user-chip {
    display: none;
}

/* Pusty pas pod paskiem akcji watku — TYLKO w apce, na mobilnym webie go nie ma.
   Powod: .reader-actionbar rezerwuje miejsce na dolny obszar bezpieczny
   (env(safe-area-inset-bottom)), ale w natywnej powloce to miejsce zajmuje juz natywny
   dolny pasek (Poczta/Zadania/Alerty/Konto) — rezerwacja liczyla sie DRUGI raz.
   W przegladarce nie ma natywnego paska, wiec tam zapas zostaje.
   Specyficznosc: html.abcare-native .reader-actionbar (0,2,1) bije scoped
   .reader-actionbar[b-xxx] (0,2,0), wiec nadpisanie zadziala mimo scoped CSS. */
html.abcare-native .reader-actionbar {
    padding-bottom: 0.55rem;
}

/* ══════════════════════════════════════════════════════════════════════
   Pull-to-refresh (mobile) — wskaznik gestu "przeciagnij od gory, by odswiezyc".
   Element .abc-ptr tworzony w abc-pull-refresh.js => styl MUSI byc globalny (scoped
   .razor.css nie obejmuje elementow spoza markupu komponentu). Wskaznik = kolko ze
   strzalka; po przekroczeniu progu strzalka sie obraca (.ready), podczas odswiezania
   spinner (.spin). Pozycja/opacity sterowane inline z JS (transform translateY).
   ══════════════════════════════════════════════════════════════════════ */
.abc-ptr {
    position: absolute;
    top: 0;
    left: 50%;
    margin-top: 6px;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--paper, #fff);
    border: 1px solid var(--line, #e4e7eb);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16);
    color: var(--p1, #009244);
    opacity: 0;
    transform: translateX(-50%) translateY(-46px);
    pointer-events: none;
    z-index: 6;
}
.abc-ptr.anim { transition: transform 0.24s ease, opacity 0.24s ease; }
.abc-ptr svg {
    width: 16px; height: 16px;
    stroke: currentColor; fill: none; stroke-width: 2.2;
    stroke-linecap: round; stroke-linejoin: round;
    transition: transform 0.18s ease;
}
.abc-ptr.ready svg { transform: rotate(180deg); }
.abc-ptr.spin svg { display: none; }
.abc-ptr.spin::after {
    content: '';
    width: 15px; height: 15px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--p1, #009244) 25%, transparent);
    border-top-color: var(--p1, #009244);
    animation: abc-ptr-spin 0.7s linear infinite;
}
@keyframes abc-ptr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .abc-ptr svg { transition: none; }
    .abc-ptr.spin::after { animation-duration: 1.4s; }
}

/* ── K3-2 — dropdown podpowiadania adresów e-mail (abc-address-suggest.js, montowany w body → global) ── */
.abc-addr-suggest {
    position: fixed;
    z-index: 100000;
    max-height: 240px;
    overflow-y: auto;
    background: var(--paper, #fff);
    border: 1px solid var(--line-strong, #d3d0c4);
    border-radius: 8px;
    box-shadow: 0 12px 32px rgba(17, 19, 23, 0.16);
    padding: 4px;
    font-size: 13px;
}
.abc-addr-opt {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.4rem 0.55rem;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
}
.abc-addr-opt.on,
.abc-addr-opt:hover { background: var(--cream-2, #f4f2ea); }
.abc-addr-opt .aao-email { color: var(--text, #111317); font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.abc-addr-opt .aao-name { color: var(--text-soft, #8b9099); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; }

/* ── K3-3 — podświetlenie edytora przy przeciąganiu pliku (drag&drop załącznika) ── */
.abc-drag-over {
    outline: 2px dashed var(--p1, #019344);
    outline-offset: -4px;
    background: var(--ok-bg, #e3f4eb) !important;
}

/* ── Paski przewijania — jeden wygląd w całej apce ───────────────────────────────────────────
   Menu boczne dostało cienki, wtopiony pasek już dawno (MainLayout.razor.css), ale reszta apki
   została z systemowym: szerokim, szarym, z kwadratowymi strzałkami. Widać go wszędzie tam, gdzie
   coś się przewija — listy, tabele, panele — i to on rzucał się w oczy jako „brzydki".

   Reguła jest GLOBALNA i celowo o najniższej sile: własne paski (sidebar, czytnik wiadomości,
   mini-audyt) mają wyższą specyficzność i zostają nietknięte.

   Thumb rysujemy przez border + background-clip: content-box — daje wrażenie wąskiego paska
   z odstępem od krawędzi, zamiast przyklejonego do niej prostokąta. */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(17, 19, 23, 0.18) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: rgba(17, 19, 23, 0.16);
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: content-box;
}

::-webkit-scrollbar-thumb:hover {
    background: rgba(17, 19, 23, 0.32);
    background-clip: content-box;
}

/* Bez tego róg między poziomym a pionowym paskiem zostaje systemowo szary. */
::-webkit-scrollbar-corner {
    background: transparent;
}

/* ── Baner komunikatu (alert-banner) ───────────────────────────────────────────
   Uzywa go OSIEMNASCIE ekranow — pulpit, rozmowa, zwroty, obie skrzynki e-mail
   i dwanascie ekranow ustawien. Reguly siedzialy WYLACZNIE w Dashboard.razor.css,
   czyli w scoped CSS, ktory dziala tylko w swoim komponencie. Na pozostalych
   siedemnastu ekranach baner renderowal sie jako GOLY TEKST: bez ramki, bez tla,
   bez paska koloru — czyli bez jedynej rzeczy, ktora odrozniala „udalo sie" od
   „nie udalo sie".

   ⚠ Znalezione 28.08.2026 przy poprawianiu przycisku „Sprawdz polaczenie": ekran
   ustawia kolor ramki i paska wprost (var(--ok) albo var(--danger)) w zaleznosci
   od wyniku — ale skoro sama ramka nie istniala, werdykt przyrzadu byl nie do
   odroznienia od zwyklego akapitu strony. Ten sam blad co z kafelkiem KPI nizej. */
.alert-banner {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--danger);
    background: var(--danger-bg);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    animation: shake-in 0.6s ease-out forwards;
    color: var(--text);
}

@keyframes shake-in {
    0% { transform: translateX(0); opacity: 0; }
    25% { transform: translateX(-3px); opacity: 0.5; }
    50% { transform: translateX(3px); opacity: 0.8; }
    75% { transform: translateX(-1px); }
    100% { transform: translateX(0); opacity: 1; }
}

.alert-bar { width: 5px; background: var(--danger); }

/* Ten sam baner, gdy niesie DOBRA wiadomosc („Polaczenie udane"). Bez tego ekrany
   podmienialy w stylu tylko kolor ramki, a tlo zostawalo czerwone — zielona kreska
   na czerwonym tle to nie jest werdykt, ktory ktokolwiek odczyta jako „udalo sie". */
.alert-banner.ok { border-color: var(--ok); background: var(--ok-bg); }
.alert-banner.ok .alert-bar { background: var(--ok); }
.alert-banner.ok .alert-text strong { color: var(--ok); }

.alert-icon {
    width: 56px;
    display: grid; place-items: center;
    background: rgba(196,57,47,0.08);
    color: var(--danger);
}
.alert-icon svg { width: 24px; height: 24px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.alert-content {
    flex: 1;
    padding: 0.85rem 1.1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.alert-text { color: var(--text); }
.alert-text strong { color: var(--danger); font-weight: 600; }
.alert-text .alert-headline { font-size: 14px; font-weight: 500; margin-bottom: 2px; }
.alert-text .alert-sub { font-size: 12px; color: var(--text-soft); }
.alert-actions { display: flex; gap: 0.5rem; }

/* ── Kafelek wskaznika (KPI) ────────────────────────────────────────────────────
   Uzywany na /dashboard ORAZ w raportach (/reports/sla, /reports/messages).
   ⚠ Te reguly siedzialy wczesniej WYLACZNIE w Dashboard.razor.css, czyli w scoped CSS —
   a ten dziala tylko w swoim komponencie. Skutek: w raportach kafelki byly golym tekstem
   na tle strony, bez ramki i bez tla, i nikt tego nie zauwazyl, bo sonda ukladu mierzy
   przepelnienie i lamanie tekstu, a nie „brak stylu". Uklad kolumn zostal w Dashboardzie
   (jest jego wlasny); tutaj jest sam wyglad kafelka. */
/* Kafelek wskaznika.
   ⚠ GRZBIET DOMYSLNY JEST NEUTRALNY, nie zielony (03.09.2026). Do tej pory kazdy kafelek
   dostawal firmowa zielen z automatu — takze taki, ktorego liczby aplikacja z niczym nie
   porownala. Na raporcie "Dotrzymywanie terminow" wygladalo to tak: "ZGODNOSC Z SLA 7%"
   na czerwono, a obok "MEDIANA TTR 4 d" na zielono. Ten sam kolor znaczyl w jednym rzedzie
   dwie rozne rzeczy: "sprawdzilismy i jest dobrze" oraz "nie mamy zdania". Czlowiek czyta
   rzad jako jedno zdanie i wychodzi mu, ze czasy sa w porzadku — czego nikt nie stwierdzil.
   Zielen dostaje sie teraz WYLACZNIE za werdykt (.tone-ok). */
.kpi {
    background: var(--paper);
    border: 1px solid var(--line);
    border-left: 4px solid var(--line);
    border-radius: var(--radius-lg);
    padding: 1.05rem 1.1rem;
    box-shadow: var(--shadow-sm);
    transition: transform 0.15s, box-shadow 0.15s;
    position: relative;
}

.kpi:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.kpi.tone-ok { border-left-color: var(--p1); }
.kpi.tone-danger { border-left-color: var(--danger); }
.kpi.tone-warn { border-left-color: var(--warn); }

.kpi-label {
    font-size: 11.5px;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-weight: 500;
    margin-bottom: 0.5rem;
}

.kpi-value {
    font-family: 'Instrument Serif', Georgia, serif;
    font-size: 2.6rem;
    line-height: 1;
    color: var(--text);
    letter-spacing: -0.02em;
}

.kpi-sub {
    font-size: 11px;
    color: var(--text-soft);
    margin-top: 0.4rem;
}

@media (max-width: 640px) {
    .kpi-value { font-size: 2rem; }
}

/* ── Karta zwijana TYLKO na telefonie (.collapse-mobile) ────────────────────────
   Dluga sciagawka (np. lista zmiennych w szybkich odpowiedziach) zjada na waskim
   ekranie pol strony, a jest potrzebna dopiero przy pisaniu. Na telefonie zwijamy
   ja do jednego wiersza, na komputerze pokazujemy jak zwykla karte — bez naglowka
   do klikania, tak jak bylo.

   ⚠ NIE uzywamy <details>: przegladarka chowa jego tresc wewnetrznym slotem, ktorego
   nie da sie odslonic autorskim CSS-em. Proba "na telefonie zwiniete, na komputerze
   rozwiniete" konczyla sie tym, ze na komputerze karta znikala w calosci.
   Stan trzyma komponent (klasa `is-open`), tutaj jest sama widocznosc. */
.collapse-mobile-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    width: 100%;
    padding: .9rem 1.15rem;
    background: transparent;
    border: none;
    font-family: inherit;
    font-size: 14px;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}
.collapse-mobile-hint { color: var(--text-soft); font-size: 11.5px; margin-left: .45rem; }
.collapse-mobile-chevron { color: var(--text-faint); transition: transform .15s; flex: none; }
.collapse-mobile.is-open .collapse-mobile-chevron { transform: rotate(180deg); }

/* Telefon: tresc widoczna dopiero po rozwinieciu. */
@media (max-width: 768px) {
    .collapse-mobile:not(.is-open) > .collapse-mobile-body { display: none; }
    .collapse-mobile-summary { min-height: 44px; }
}

/* Komputer: karta jak przedtem — naglowek zwijania znika, tresc zawsze widoczna. */
@media (min-width: 769px) {
    .collapse-mobile > .collapse-mobile-summary { display: none; }
}

/* ── Pola wyboru na telefonie ──────────────────────────────────────────────────
   Domyslny checkbox ma 13x13 px (a `.bulk-cb` 14x14) — jedna czwarta tego, w co
   da sie trafic palcem. Zaznaczanie watkow na liscie bylo w praktyce loteria.
   Powiekszamy sam kontrolkę do 20 px i dokladamy niewidoczne pole dotyku do 40 px
   przez ::after — bez ruszania ukladu wiersza (element zajmuje dalej tyle samo). */
@media (pointer: coarse) {
    /* ⚠ NIE probuj powiekszac pola dotyku pseudoelementem (::after) — pola formularza sa
       elementami zastepowanymi i pseudoelementow NIE renderuja. Taka regula wyglada w kodzie
       jak zabezpieczenie, a nie robi zupelnie nic. Jedyne, co dziala bez zmiany znacznikow,
       to powiekszenie samej kontrolki. 32 px to na telefonie normalny rozmiar pola wyboru. */
    input[type="checkbox"] { width: 32px; height: 32px; }
}

/* Nazwa klienta na liscie to GLOWNA akcja wiersza (otwiera karte), a ma 20 px wysokosci —
   miedzy dwoma innymi liniami tekstu palec trafia obok. Powiekszamy pole klikania,
   nie czcionke; wiersz i tak ma zapas w pionie. */
@media (pointer: coarse) {
    /* ⚠ KOLUMNA, NIE RZAD (04.09.2026). Ten odnosnik niesie DWIE linie — nazwisko i login
       kupujacego. Bez podanego kierunku pojemnik elastyczny uklada je w rzad i na kazdym
       ekranie dotykowym wychodzilo "Marta Zielinskakupujacy05". Na komputerze nigdy tego nie
       widac, bo tam wskaznik jest precyzyjny i ta regula w ogole nie dziala — szukalem tego
       pol godziny wsrod regul szerokosci, a to nie jest regula szerokosci. */
    .cust-row .cr-clickable {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
        min-height: 40px;
    }
}

/* Odnosnik w wierszu karty (np. temat wiadomosci w kolejce wysylki) to glowna akcja
   tego wiersza, a mial 19 px wysokosci. Powiekszamy pole klikania, nie czcionke.
   ⚠ Dotyczy TYLKO odnosnikow — zwykla wartosc tekstowa nie jest celem dotyku. */
@media (pointer: coarse) {
    .data-card-row a.value {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        min-height: 40px;
        flex-direction: row;
    }
    /* Logo w naglowku stron publicznych (30 px) — jedyny odnosnik nawigacyjny na tych ekranach. */
    .editorial-brand { min-height: 40px; }
}

/* ── Osłona przed błędem ekranu ─────────────────────────────────────────────
   Karta pokazywana, gdy jeden ekran się wywali. Reszta aplikacji żyje dalej,
   więc karta ma wyglądać jak część aplikacji, a nie jak komunikat systemowy. */
.oslona-bledu {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    padding: 2rem 1rem;
}

.oslona-bledu .card {
    max-width: 34rem;
    width: 100%;
}

.oslona-nadtytul {
    color: var(--text-faint);
    margin-bottom: 0.4rem;
    font-size: 0.78rem;
    letter-spacing: 0.12em;
}

.oslona-tytul {
    font-size: clamp(1.5rem, 3vw, 2rem);
    margin: 0 0 0.6rem;
}

.oslona-tresc {
    font-size: 14.5px;
    margin-bottom: 1.2rem;
}

.oslona-numer {
    font-size: 13px;
    color: var(--text-soft);
    background: var(--cream-2);
    padding: 0.6rem 0.8rem;
    border-radius: 6px;
    margin-bottom: 1.3rem;
    /* Numer musi dać się zaznaczyć i skopiować — po to istnieje. */
    user-select: all;
}

.oslona-akcje {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
}

/* ─── Odnośnik do poradnika („?" przy nagłówku albo przy opcji) ──────────────────────────────
   Ma być widoczny, gdy ktoś go szuka, i niewidoczny, gdy nie szuka — stąd przygaszony domyślnie
   i wyraźny po najechaniu. Nie jest przyciskiem akcji i nie może wyglądać jak przycisk akcji:
   agent klikający „?" zamiast „Zapisz" to koszt, którego ta ozdoba nie jest warta.

   ⚠ OBWÓDKI TU NIE BYŁO — mimo że stała w kodzie. `border: 1px solid var(--line)` odwoływało
     się do zmiennej, której ta aplikacja NIE MA (paleta zna `--line`, `--line-strong`
     i `--border-color`). Skrót `border` z nieznaną zmienną jest dla przeglądarki nieprawidłowy
     w całości, więc kasował się razem ze STYLEM obwódki — element wychodził bez ramki, jako goły
     szary znak zapytania. Stąd zgłoszenie „bardzo źle widoczny". Zmienne bez fallbacku wolno tu
     wpisywać tylko takie, które naprawdę są w palecie na górze tego pliku.

   Element jest `inline-flex` i `flex: 0 0 auto` — nie zajmuje własnego wiersza i nie rozpycha
   nagłówka, w którym stoi. Jeśli mimo to ląduje pod nagłówkiem, to znaczy, że kontener nagłówka
   nie jest flexem (tak było w railu poczty — dziś ten odnośnik stoi w `.email-nameplate`). */
/* ⚠ KRÓJ PISMA MUSI BYĆ TU WPISANY — I TO JEST CAŁE ZGŁOSZENIE „napisy praktycznie niewidoczne"
     (07.09.2026, nagłówek „Do rozliczenia"). Wbrew pierwszemu podejrzeniu NIE był to problem
     koloru. Zmierzone przed poprawką, wzorem WCAG na luminancję względną:
         motyw jasny:  --text-soft #5e6671 na --cream-2 #f4f2ea = 5,18 : 1
         motyw ciemny: --text-soft #a8acb3 na --cream-2 #181b22 = 7,56 : 1
     Oba PRZECHODZĄ próg 4,5 : 1 — czyli kolor był w porządku, a napis i tak znikał.

     Powód prawdziwy: ten odnośnik stoi w `<h1 class="display-heading">`, a `.display-heading`
     ustawia `font-family: 'Instrument Serif'`. Element dziedziczył ten krój, bo sam żadnego nie
     podawał. Instrument Serif to szeryfowy krój PLAKATOWY — ma włoskowate cienkie kreski
     policzone na 40 px. Zjechany do 11,5 px renderuje się kreską cieńszą niż piksel, więc
     wygładzanie rozmywa go do jasnej szarości: zmierzony kontrast zostaje 5,18 : 1, a widziany
     jest kilkakrotnie niższy, bo do oka dociera ułamek pełnego krycia glifu. Dodatkowo z Google
     Fonts ciągniemy `Instrument+Serif:ital@0;1`, czyli TYLKO grubość 400 — `font-weight: 500`
     poniżej nie miał się na czym oprzeć i przeglądarka pogrubiała syntetycznie albo wcale.

     Stąd `font-family` na sztywno (ten sam stos, co reszta interfejsu), `font-style: normal`
     (żeby kursywa z `.display-heading em` nie wciekła, gdy ktoś wstawi odnośnik wewnątrz `<em>`)
     i `letter-spacing: normal` (nagłówek ma -0,015em policzone na duży stopień, w plakietce
     zlepiało to litery). Skutek widać na siedmiu ekranach — tyle jest `<PomocLink>` w nagłówkach.

     Rozmiar 11,5 → 12 px: pół piksela, świadomie ostrożnie. Historia kilkaset linii niżej
     (ok. 6018) opisuje, jak powiększenie tego elementu do 40 px WYSOKOŚCI zostało cofnięte, bo
     rozjeżdżało nagłówki i rozciągało wariant bez podpisu w owal. Tu nie ruszamy ani wysokości,
     ani `::after` — 12 px zmienia sam stopień pisma i nie dokłada elementowi ani jednego piksela
     wysokości ponad to, co wynikało z `line-height: 1`.

     Koloru NIE ciemnimy do `--text`: ten odnośnik ma być dyskretny (patrz akapit wyżej — nie może
     wyglądać jak przycisk akcji), a `--text-soft` i tak przechodzi AA z zapasem. */
.pomoc-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex: 0 0 auto;
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 12px;
    font-style: normal;
    letter-spacing: normal;
    line-height: 1;
    color: var(--text-soft);
    text-decoration: none;
    border: 1px solid var(--line-strong);
    background: var(--cream-2);
    border-radius: 999px;
    padding: 0.25rem 0.6rem;
    transition: color 0.12s, border-color 0.12s, background 0.12s;
    vertical-align: middle;
}

/* Rysowany znak zapytania — stały rozmiar niezależny od kroju i wielkości pisma wokół. */
.pomoc-link-ikona {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Kropka pod haczykiem — wypełnienie, nie kreska (kreska o zerowej długości bywa niewidoczna). */
.pomoc-link-ikona .pomoc-link-kropka {
    fill: currentColor;
    stroke: none;
}

/* Sam znak, bez podpisu — kółko przy nagłówku sekcji. */
.pomoc-link.sam-znak {
    padding: 0;
    width: 1.6rem;
    height: 1.6rem;
    justify-content: center;
    border-radius: 50%;
}

.pomoc-link:hover,
.pomoc-link:focus-visible {
    color: var(--global-palette1);
    border-color: var(--global-palette1);
    background: var(--ok-bg);
}

.pomoc-link-tekst { font-weight: 500; }

/* ⚠ POLE DOTYKU ZNAKU ZAPYTANIA — powiekszone BEZ zmiany wygladu.
   Odnosnik do poradnika ma 1,15 rem (~18 px) i taki ma zostac: to dyskretny znak przy naglowku,
   a nie przycisk. Powiekszenie go wizualnie do 44 px przecialoby kazdy naglowek w aplikacji.
   Zamiast tego rozciagamy sam obszar klikalny warstwa `::after` — element zajmuje w ukladzie
   tyle samo, a palec dostaje 44 px.

   Dlaczego to wazne: ten sam komponent siedzi na kilkunastu ekranach, wiec jedno chybienie
   powtarza sie wszedzie. W przejezdzie 18.08.2026 wychodzil jako "za maly cel dotykowy"
   na tablicy, kalendarzu, kanalach poczty, terminach SLA i ekranie rozmowy — pieciokrotnie
   ta sama usterka. */
@media (pointer: coarse) {
    .pomoc-link { position: relative; }

    /* Warstwa przezroczysta rozciaga OBSZAR KLIKALNY bez zmiany wygladu: element zajmuje
       w ukladzie tyle samo, a palec dostaje 44 px.
       ⚠ Ta sztuczka dziala tylko tam, gdzie nic jej nie przycina. W komorce tabeli warstwa
         bywa ucinana i wtedy trzeba dac realna wysokosc (patrz WorkTaskStatusesSettings.razor.css).
         Tutaj odnosnik stoi przy naglowku, wiec przycinania nie ma — sprawdzone pomiarem:
         ekran tablicy i terminow SLA przestal zglaszac za maly cel. */
    .pomoc-link::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 44px;
        height: 44px;
        transform: translate(-50%, -50%);
        pointer-events: auto;
    }
}

/* ─── Poradnik wewnętrzny w panelu obsługi („Co to robi") ────────────────────────────────────
   ⚠ Treść WYŁĄCZNIE dla obsługi — inny odbiorca niż „?" wyżej, więc i inny wygląd: nie chip
   przy nagłówku, tylko zwijany blok pod paskiem tytułowym ekranu.

   ZWINIĘTY domyślnie. Rozwinięty na stałe zabrałby pół ekranu każdemu, kto już wie — a wtedy
   po tygodniu przewija się go odruchowo i przestaje czytać także wtedy, gdy jest potrzebny. */
.poradnik-wew {
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--cream-2);
    margin-bottom: 1.25rem;
    font-size: 13px;
}

.poradnik-wew > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.85rem;
    cursor: pointer;
    color: var(--text-soft);
    list-style: none;
}

/* Domyślny trójkąt przeglądarki różni się między nimi na tyle, że psuje wyrównanie. */
.poradnik-wew > summary::-webkit-details-marker { display: none; }

.poradnik-wew > summary:hover { color: var(--text); }

.poradnik-wew-znak {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: 50%;
    border: 1px solid var(--line);
    font-size: 11px;
    font-weight: 600;
    font-style: italic;
    flex: none;
}

.poradnik-wew-tresc { padding: 0 0.85rem 0.85rem; }

.poradnik-wew-po-co {
    margin: 0 0 0.85rem;
    color: var(--text);
    font-size: 13.5px;
    line-height: 1.6;
}

.poradnik-wew-sekcja { margin-bottom: 0.85rem; }

.poradnik-wew-sekcja h4 {
    margin: 0 0 0.3rem;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-soft);
}

.poradnik-wew-uwaga h4 { color: var(--warn); }

/* Ostrzeżenie przy ustawieniu, które klient może sobie obrócić przeciwko sobie.
   ⚠ Nie „info" i nie zwykły szary tekst pod polem: to jest WARUNEK oddania tego suwaka
   klientowi, więc ma być widoczne tak samo jak samo pole. */
.uwaga-limit {
    display: block;
    padding: 0.6rem 0.75rem;
    border-left: 3px solid var(--warn);
    border-radius: 0 6px 6px 0;
    background: color-mix(in srgb, var(--warn) 9%, transparent);
    font-size: 12px;
    line-height: 1.55;
    color: var(--text-soft);
}
.uwaga-limit strong { color: var(--warn); }

.poradnik-wew-sekcja ul {
    margin: 0;
    padding-left: 1.1rem;
    line-height: 1.65;
    color: var(--text-soft);
}

.poradnik-wew-stopka {
    margin: 0;
    padding-top: 0.6rem;
    border-top: 1px solid var(--line);
    font-size: 12px;
    color: var(--text-faint);
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.poradnik-wew-kropka { opacity: 0.5; }

/* ─── Kłódka „nie masz do tego uprawnienia" (komponent BrakUprawnienia) ──────────────────────
   ⚠ Ta klasa istnieje po to, żeby brak uprawnienia NIE wyglądał jak zero. Myślnik w kolumnie
   liczbowej człowiek czyta jako „zero" i idzie z tym dalej — kłódka nie daje się tak przeczytać.
   Ma być czytelna, ale nie krzykliwa: to nie jest błąd ani ostrzeżenie, tylko informacja, że
   ktoś inny ma tu więcej widoku. Kolor z palety marki, nigdy hex w znaczniku. */
.brak-uprawnienia {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    vertical-align: middle;
    line-height: 1;
    font-size: 11.5px;
    color: var(--global-palette6);
    cursor: help;
}

.brak-uprawnienia-ikona {
    width: 13px;
    height: 13px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.brak-uprawnienia-tekst { font-weight: 500; }

.brak-uprawnienia:hover { color: var(--global-palette5); }

/* Kłódka „wersja pokazowa” stojąca PRZY wygaszonym przycisku zapisu (ZapisZablokowanyPokazem.razor).
   Własnego wyglądu nie ma — świadomie: to ta sama rodzina komunikatów co brak uprawnienia
   („program wie, czemu nie wolno; człowiek ma się dowiedzieć”), więc dziedziczy kłódkę i kolor.
   Tu zostaje wyłącznie odstęp, żeby nie kleiła się do przycisku. */
.zapis-zablokowany-pokazem {
    display: inline-flex;
    align-items: center;
    margin-left: 0.55rem;
    vertical-align: middle;
}

/* Tekst wyłącznie dla czytników ekranu — nie „display: none", bo to by go schowało także przed nimi. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}


/* ── Ekran „Miejsce": dwa liczniki obok siebie (dane / pliki) ───────────────────
   Od 11.08.2026 limity są dwa i muszą być widoczne jako dwie osobne rzeczy —
   jeden wspólny pasek kłamałby, bo pliki i dane nie zabierają sobie miejsca. */
.miejsce-dwa {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
    margin: 0.6rem 0 0.2rem;
}
.miejsce-blok {
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 0.75rem 0.9rem;
    background: var(--cream-2);
}
.miejsce-naglowek { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.miejsce-etykieta {
    font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
    color: var(--text-soft); font-weight: 600;
}
.miejsce-procent { font-size: 26px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.miejsce-wartosc { font-size: 14px; font-weight: 600; color: var(--text-soft); margin-top: 0.15rem; }
.miejsce-tor { height: 8px; background: rgba(128,128,128,.15); border-radius: 5px; overflow: hidden; margin: 0.55rem 0 0.4rem; }
.miejsce-wypelnienie { height: 100%; transition: width .2s; }
.miejsce-skladniki {
    display: flex; flex-direction: column; gap: 0.15rem;
    font-size: 11.5px; color: var(--text-soft);
}

/* ── Załączniki pod wiadomością: miniaturki + kafelki plików ────────────────────
   GLOBALNIE, nie w scoped CSS — i to jest cała nauka z 11.08.2026. Te klasy istniały
   wcześniej wyłącznie w `Conversation.razor.css`, czyli w stylach ZAKRESOWYCH jednego
   komponentu. Czat i dyskusja zadania używały tych samych nazw klas i nie dostawały
   ANI JEDNEJ reguły: `<a>` zostawał `display:inline`, a ikonka `<svg>` bez wymiarów
   rozdymała się do 834×446 px czarnej plamy. W powiększarce ta plama prześwitywała
   przez półprzezroczyste tło i wyglądała jak „wielki czarny kwadrat w tle".

   Dlatego niżej jest też twarda reguła na `svg` wewnątrz kafelka: brak wymiarów na
   ikonie nigdy więcej nie ma prawa zamienić się w plamę na pół ekranu. */
.abc-zal-lista {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin-top: 0.45rem;
    /* Bez tego pojedyncza długa nazwa pliku rozpycha całą kolumnę wiadomości. */
    min-width: 0;
}

/* Opakowanie pojedynczego załącznika — po to, żeby kosz miał się względem czego ustawić.
   ⚠ W app.css, nie w .razor.css: to komponent WSPÓŁDZIELONY przez czat, zadania i zgłoszenia,
   a styl zakresowy działałby wyłącznie w jednym z nich. Ta sama blizna co 11.08.2026. */
.abc-zal-poz { position: relative; display: inline-flex; min-width: 0; max-width: 100%; }

/* Kasowanie pojedynczego pliku. Chowa się, dopóki nikt nie patrzy — kosz przy każdym
   załączniku na stałe wygląda jak zaproszenie do pomyłki. */
.abc-zal-kosz {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    border: 1px solid var(--line, #e4e7eb);
    border-radius: 6px;
    background: var(--paper);
    color: var(--text-soft);
    cursor: pointer;
    /* Widoczny ZAWSZE, po najechaniu pełny (W-14, 19.09.2026): kosz „widoczny dopiero po najechaniu" to dla
       nowego pracownika kosz, którego nie ma — a akcja jest nieodwracalna, więc tym bardziej ma być jawna. */
    opacity: 0.55;
    transition: opacity 0.12s, color 0.12s, border-color 0.12s;
}
.abc-zal-poz:hover .abc-zal-kosz,
.abc-zal-kosz:focus-visible { opacity: 1; }
.abc-zal-kosz:hover { color: var(--danger); border-color: var(--danger); }
.abc-zal-kosz svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2; }

/* Na dotyku nie ma najechania — bez tego kosza nie da się dosięgnąć na telefonie. */
@media (hover: none) {
    .abc-zal-kosz { opacity: 1; }
}

/* ── Odpowiedź, reakcje, przypinanie ─────────────────────────────────── */

.msg-reakcja {
    display: inline-flex;
    align-items: center;
    gap: 0.22rem;
    border: 1px solid var(--line, #e4e7eb);
    background: var(--paper);
    border-radius: 999px;
    padding: 0.08rem 0.42rem;
    font-size: 12px;
    cursor: pointer;
    line-height: 1.5;
}

.msg-reakcja:hover { border-color: var(--line-strong, #c9d1cd); }

/* „Moja" reakcja musi być rozpoznawalna — od tego zależy, czy kliknięcie doda, czy zdejmie. */
.msg-reakcja.moja {
    border-color: var(--global-palette1, #009244);
    background: color-mix(in srgb, var(--global-palette1, #009244) 12%, transparent);
}

.msg-akcja-emoji { font-size: 13px; padding: 0.1rem 0.28rem; }

.composer-odpowiedz {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    border-left: 2px solid var(--global-palette1, #009244);
    padding: 0.3rem 0.5rem;
    margin-bottom: 0.4rem;
    background: var(--cream-2);
    border-radius: 0 5px 5px 0;
    font-size: 12px;
    min-width: 0;
}

.composer-odpowiedz-etyk { font-weight: 600; color: var(--text-soft); flex: none; }
.composer-odpowiedz-tresc {
    color: var(--text-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}

/* ── Poprawianie i kasowanie własnej wiadomości w czacie ────────────────────────
   ⚠ W app.css, nie w .razor.css — z tego samego powodu co reszta wspólnych klas czatu. */
/* Przyciski akcji pod wiadomoscia czatu. IKONY, nie napisy: piec napisow ("Odpowiedz",
   "Przypnij", "Popraw", "Usun") nad kazdym dymkiem zajmowalo wiecej miejsca niz sama tresc. */
.msg-akcja {
    border: 0;
    background: transparent;
    color: var(--text-soft);
    font-size: 11.5px;
    min-width: 24px;
    height: 24px;
    display: inline-grid;
    place-items: center;
    padding: 0 0.3rem;
    border-radius: 5px;
    cursor: pointer;
}

.msg-akcja:hover { background: var(--cream-2); color: var(--text); }
.msg-akcja-zla:hover { color: var(--danger); background: var(--danger-bg, #fdecec); }
/* Stan "przypieta" musi byc widoczny BEZ najechania - mowi o wiadomosci, nie o przycisku. */
.msg-akcja.wl { color: var(--global-palette1, #009244); }

.msg-edycja { display: flex; flex-direction: column; gap: 0.35rem; }

.msg-edycja textarea {
    width: 100%;
    min-width: 0;
    resize: vertical;
    font: inherit;
    padding: 0.4rem 0.55rem;
    border: 1px solid var(--line-strong, #c9d1cd);
    border-radius: 5px;
    background: var(--paper);
    color: inherit;
}

.msg-edycja-akcje { display: flex; gap: 0.35rem; }

/* Usunięta wiadomość ZOSTAJE w wątku — twarde usunięcie zrobiłoby dziurę w rozmowie. */
.txt-usunieta { color: var(--text-faint); font-style: italic; }

.txt-poprawiona {
    margin-left: 0.35rem;
    font-size: 10.5px;
    color: var(--text-soft);
}

/* ── Strona wyników szukania ──────────────────────────────────────────── */
.szukaj-pole {
    display: flex;
    gap: 0.5rem;
    max-width: 40rem;
    margin-bottom: 1.6rem;
}

.szukaj-pole input { flex: 1; min-width: 0; }

.szukaj-sekcja { margin-bottom: 2rem; }

.szukaj-naglowek {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin: 0 0 0.55rem;
}

.szukaj-licznik {
    font-size: 11px;
    color: var(--text-soft);
    border: 1px solid var(--line, #e4e7eb);
    border-radius: 3px;
    padding: 0 0.32rem;
}

.szukaj-trafienie {
    display: block;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--line, #e4e7eb);
    border-radius: 6px;
    margin-bottom: 0.45rem;
    text-decoration: none;
    color: inherit;
    max-width: 52rem;
    /* Bez tego długi fragment bez spacji rozpycha całą stronę w bok. */
    min-width: 0;
}

.szukaj-trafienie:hover { border-color: var(--line-strong, #c9d1cd); background: var(--cream-2); }

.szukaj-tytul {
    font-size: 13.5px;
    font-weight: 600;
    margin-bottom: 0.18rem;
    overflow-wrap: anywhere;
}

.szukaj-fragment {
    font-size: 12.5px;
    color: var(--text-soft);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

/* Zaznaczenie trafienia. ⚠ To jedyne <mark>, jakie wpuszczamy z treści — i jest wstawiane
   PO zakodowaniu całego fragmentu, patrz `Wartownik` w wyszukiwarce. */
.szukaj-fragment mark {
    background: color-mix(in srgb, var(--global-palette1, #009244) 22%, transparent);
    color: inherit;
    padding: 0 0.1em;
    border-radius: 2px;
}

.szukaj-data {
    font-size: 11px;
    color: var(--text-soft);
    margin-top: 0.28rem;
}

/* Kto i które zgłoszenie — krytyk (20.09.2026): „wyszukiwarka «Borowska» daje 6 zgłoszeń bez
   nazwiska klienta i bez karty". Szukanie po nazwisku działało, tylko wynik go nie pokazywał,
   więc sześć wierszy „Re: zamówienie" wyglądało jak sześć przypadkowych trafień. */
.szukaj-poz { max-width: 52rem; margin-bottom: 0.45rem; }
.szukaj-poz .szukaj-trafienie { margin-bottom: 0; }
.szukaj-kto {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem;
    font-size: 12px; color: var(--text-soft); margin-bottom: 0.2rem;
}
.szukaj-numer { color: var(--text-faint); }
.szukaj-klient { font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
/* ⚠ Poza kafelkiem trafienia, nie w środku: odnośnik w odnośniku jest w HTML-u niedozwolony. */
.szukaj-karta {
    display: inline-block; margin: 0.15rem 0 0 0.9rem;
    font-size: 12px; color: var(--p1, #009244); text-decoration: none; font-weight: 600;
}
.szukaj-karta:hover { text-decoration: underline; }


/* ── Przeciąganie plików na całe okno ─────────────────────────────────────────────────────
   ⚠ TU, W app.css, A NIE W .razor.css. Ta nakładka służy trzem ekranom naraz (czat, dyskusja
   zadania, panel rozmowy) i wstawia ją JavaScript prosto do <body> — a styl zakresowy nie
   dotyczy ani cudzego komponentu, ani elementu spoza drzewa Blazora. Dokładnie na tym poległy
   klasy `.composer-att-*` 11.08.2026: mieszkały w Conversation.razor.css, więc czat i zadania
   nie dostawały ani jednej reguły i pokazywały czarny prostokąt zamiast kafelka. */
.abc-drop-nakladka {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--global-palette1, #009244) 12%, rgba(15, 23, 20, 0.55));
    backdrop-filter: blur(2px);
    /* ⚠ Nakładka NIE MOŻE łapać zdarzeń myszy. Gdyby łapała, `dragleave` sypnęłoby natychmiast
       po jej pokazaniu (kursor „wszedłby" na nowy element), nakładka zniknęłaby, zdarzenie
       poleciałoby znowu — i tak w kółko, przez całe przeciąganie. */
    pointer-events: none;
    animation: abc-drop-wejscie 120ms ease-out;
}

@keyframes abc-drop-wejscie { from { opacity: 0; } to { opacity: 1; } }

.abc-drop-ramka {
    border: 2px dashed rgba(255, 255, 255, 0.9);
    border-radius: 14px;
    padding: 2.2rem 3.2rem;
    text-align: center;
    background: rgba(15, 23, 20, 0.35);
}

.abc-drop-tekst {
    font-size: 1.35rem;
    font-weight: 650;
    color: #fff;
    letter-spacing: 0.01em;
}

.abc-drop-podpis {
    margin-top: 0.35rem;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.82);
}

@media (prefers-reduced-motion: reduce) {
    .abc-drop-nakladka { animation: none; }
}

/* Zdjęcie — kafelek z podglądem.
   ⚠ STAŁA WYSOKOŚĆ, szerokość z proporcji — a nie kwadrat z kadrowaniem. Kwadrat wygląda równo
   na zdjęciach z aparatu i fatalnie na tym, co ludzie wklejają najczęściej: na zrzucie ekranu.
   Zrzut jest szeroki i płaski, więc kadrowanie do kwadratu pokazuje środkowy pasek bez początku
   i końca zdania — czyli dokładnie to, po czym zrzut się rozpoznaje. Wspólna wysokość wystarcza,
   żeby rząd był równy. */
.abc-zal-foto {
    position: relative;
    display: inline-block;
    height: 8.5rem;
    max-width: 20rem;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--line);
    background: var(--cream-2, rgba(128,128,128,.08));
    cursor: zoom-in;
    flex: none;
    text-decoration: none;
    transition: border-color .12s, transform .12s;
}
.abc-zal-foto:hover { border-color: var(--line-strong); transform: translateY(-1px); }
/* ⚠ SZEROKOŚĆ MINIMALNA I MIGOTANIE — agent A: „załączniki jako puste ramki po wejściu".
   Kafelek bierze szerokość ze zdjęcia, więc DOPÓKI zdjęcie nie dojdzie, jest szerokości zera
   albo pustym prostokątem. Nic w tym widoku nie mówiło, że coś się wczytuje. Migotanie znika
   po `onload`, więc kafelek, który się wczytał, nie miga w nieskończoność. */
.abc-zal-foto { min-width: 7rem; }
.abc-zal-foto:not(.wczytane):not(.bez-podgladu) {
    background-image: linear-gradient(90deg,
        rgba(128,128,128,.05) 25%, rgba(128,128,128,.13) 37%, rgba(128,128,128,.05) 63%);
    background-size: 400% 100%;
    animation: abc-zal-migot 1.3s ease-in-out infinite;
}
@keyframes abc-zal-migot { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .abc-zal-foto:not(.wczytane) { animation: none; } }

/* Miniatury, której nie da się pokazać (plik uszkodzony albo nie jest obrazkiem), NIE udajemy.
   Kafelek zamienia się w podpis z nazwą pliku i przestaje być powiększarką. */
.abc-zal-foto.bez-podgladu { cursor: pointer; display: inline-flex; align-items: center; justify-content: center; height: auto; padding: 0.55rem 0.7rem; }
.abc-zal-foto.bez-podgladu img { display: none; }
.abc-zal-foto.bez-podgladu::after {
    content: 'Podglądu nie da się pokazać — otwórz plik';
    font-size: 11.5px;
    color: var(--text-soft);
}
.abc-zal-foto.bez-podgladu .abc-zal-podpis { position: static; opacity: 1; color: var(--text); background: none; padding: 0 0 0 0.4rem; }
.abc-zal-foto:focus-visible { outline: 2px solid var(--global-palette1); outline-offset: 2px; }
.abc-zal-foto img {
    height: 100%;
    width: auto;
    max-width: 20rem;
    /* `cover` łapie dopiero panoramę szerszą niż max-width — wtedy i tak trzeba coś uciąć. */
    object-fit: cover;
    display: block;
}
/* Nazwa pliku wjeżdża na zdjęcie dopiero pod kursorem — kafelek ma pokazywać zdjęcie,
   nie napis, ale nazwa musi być osiągalna bez otwierania. */
.abc-zal-podpis {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 0.7rem 0.4rem 0.25rem;
    font-size: 10.5px;
    color: #fff;
    background: linear-gradient(to top, rgba(0,0,0,.72), rgba(0,0,0,0));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0;
    transition: opacity .12s;
}
.abc-zal-foto:hover .abc-zal-podpis,
.abc-zal-foto:focus-visible .abc-zal-podpis { opacity: 1; }

/* Plik, który nie jest obrazkiem — pasek z ikoną, nazwą i rozmiarem. */
.abc-zal-plik {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    max-width: 100%;
    padding: 0.3rem 0.55rem 0.3rem 0.4rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 11.5px;
    color: var(--text);
    text-decoration: none;
    line-height: 1.35;
}
.abc-zal-plik:hover { background: var(--cream-2); border-color: var(--line-strong); }
.abc-zal-nazwa { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 16rem; }
.abc-zal-rozmiar { color: var(--text-soft); font-size: 10.5px; flex: none; }

/* ⚠ Ikona BEZ wymiarów to domyślnie 300×150 px czarnego wypełnienia. Ta reguła jest
   bezpiecznikiem, nie kosmetyką. */
.abc-zal-plik svg,
.abc-zal-lista svg {
    width: 12px; height: 12px; flex: none;
    stroke: currentColor; fill: none;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-soft);
}

/* Plik skasowany przez retencję albo limit miejsca — nie jest odnośnikiem, bo nie ma
   dokąd prowadzić. */
.abc-zal-usuniety {
    cursor: help;
    opacity: .62;
    border-style: dashed;
    text-decoration: line-through;
}
.abc-zal-usuniety:hover { background: var(--paper); border-color: var(--line); opacity: .85; }
.abc-zal-usuniety .abc-zal-rozmiar { text-decoration: none; font-style: italic; }

/* Ostrzeżenie przy pliku wykonywalnym — ta sama treść co w widoku zgłoszenia. */
.abc-zal-grozny { color: var(--danger); font-weight: 700; margin-left: 2px; }

@media (max-width: 768px) {
    .abc-zal-foto { height: 6.5rem; max-width: 13rem; }
    .abc-zal-foto img { max-width: 13rem; }
    .abc-zal-nazwa { max-width: 9rem; }
}

/* ── Kompozytor: pliki dopięte przed wysłaniem ───────────────────────────
   Przeniesione z Conversation.razor.css — tych samych klas używa czat i dyskusja zadania,
   a styl zakresowy dawał im pusto. */
/* ─── Composer attachments preview (before send) ─────────────────────── */
.composer-attachments {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.5rem 0 0;
}
.composer-att-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.55rem 0.3rem 0.4rem;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    font-size: 11.5px;
    color: var(--text);
    max-width: 260px;
}
.composer-att-chip svg {
    width: 12px; height: 12px;
    stroke: currentColor; fill: none;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-soft);
    flex: none;
}
.composer-att-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 160px;
}
.composer-att-size { color: var(--text-soft); font-size: 10.5px; }
.composer-att-remove {
    background: transparent;
    border: none;
    color: var(--text-faint);
    cursor: pointer;
    padding: 0 0.2rem;
    font-size: 14px;
    line-height: 1;
    border-radius: 4px;
}
.composer-att-remove:hover { background: rgba(0,0,0,0.06); color: var(--text); }

/* ── Małe ikony czatu: pinezka i kłódka ─────────────────────────────────────────
   GLOBALNIE, i to nie jest kwestia gustu. Te dwie ikony żyły w `ChatPage.razor.css`,
   czyli w stylach ZAKRESOWYCH, a wstawiane były przez `AddMarkupContent` — z pominięciem
   kompilatora Razora. Element bez atrybutu zakresu nie dostaje ANI JEDNEJ reguły z pliku
   zakresowego, a `<svg>` bez wymiarów nie ma własnego rozmiaru: rozdyma się do rozmiaru
   kontenera. Panel przypiętych wyglądał przez to jak czarna plama 834×446 px, a test
   liczący pozycje na liście przechodził — bo pozycje BYŁY, tylko nie dało się ich zobaczyć.

   Reguła globalna to druga warstwa: nadaje wymiar niezależnie od tego, kto i jak
   wstawi ikonę w przyszłości. */
.ikona-pinezka {
    width: 13px;
    height: 13px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
    flex: none;
}
.ikona-klodka {
    width: 12px;
    height: 12px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    flex: none;
}

/* ── Okno potwierdzenia (OknoPotwierdzenia.razor) ───────────────────────────────
   Nasze pytanie „na pewno?" zamiast przeglądarkowego `confirm()`. Style MUSZĄ być tutaj:
   komponent jest współdzielony (czat, załączniki, cokolwiek dalej), a styl zakresowy
   działałby wyłącznie w komponencie, w którym powstał. */
.abc-potw {
    max-width: 430px;
    /* Okno pytania nie ma czego przewijać — ma jedno zdanie i dwa przyciski. */
    max-height: none;
}
.abc-potw-head {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 1.1rem 1.25rem 0.35rem;
}
.abc-potw-ikona {
    width: 34px;
    height: 34px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: var(--cream-2, #f2f4f3);
    color: var(--text-soft);
}
.abc-potw-ikona svg {
    width: 17px;
    height: 17px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.abc-potw.grozne .abc-potw-ikona {
    background: var(--danger-bg, #fbe9e6);
    color: var(--danger, #c4392f);
}
.abc-potw-tytul {
    margin: 0;
    font-family: 'Instrument Serif', serif;
    font-size: 1.3rem;
    font-weight: 400;
    line-height: 1.15;
    color: var(--text);
}
.abc-potw-tresc {
    margin: 0;
    padding: 0.15rem 1.25rem 0;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-soft);
    overflow-wrap: anywhere;
}
.abc-potw-stopka {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 1.1rem 1.25rem 1.1rem;
}

/* Na telefonie okno-pytanie NIE jest pełnoekranowe (globalna reguła `.modal-dialog` robi
   z okien pełny ekran ≤640 px). Pytanie o jedno kliknięcie rozciągnięte na cały ekran
   wygląda jak awaria, a nie jak pytanie. */
@media (max-width: 640px) {
    /* ⚠ `:has()` celowo — reguła ma dotyczyć WYŁĄCZNIE zasłony, pod którą stoi okno pytania.
       Zwykłe `.modal-overlay` przerobiłoby na małe okienka wszystkie okna w aplikacji,
       a te mają na telefonie być pełnoekranowe. Gdzie `:has()` nie zadziała, pytanie
       wyświetli się na pełnym ekranie — brzydziej, ale poprawnie. */
    .modal-overlay:has(.abc-potw) { padding: 1rem; align-items: center; }
    .abc-potw {
        max-width: 100%;
        height: auto;
        max-height: 90vh;
        border-radius: 12px;
    }
    .abc-potw-stopka .btn { flex: 1; }
}

/* ── Panel „Pliki i media" (abc-pliki-*) — wspólny dla czatu, dyskusji zadania i zgłoszenia ──
   ⚠ Klasy MUSZĄ być tutaj, a nie w `PanelPlikow.razor.css`. Panel sąsiaduje z powiększarką
   (`abc-lightbox.js`), która dokłada własne znaczniki poza zakresem komponentu — reguła zakresowa
   nie objęłaby ich wcale. Repo ma po tym bliznę: nieostylowana ikona rozdęła się do 834×446 px. */
.abc-pliki-panel {
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--paper);
    padding: 0.6rem 0.7rem 0.7rem;
    margin-bottom: 0.7rem;
}

.abc-pliki-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

.abc-pliki-head strong { font-size: 13px; }
.abc-pliki-spacer { flex: 1 1 auto; }

.abc-pliki-ikona {
    width: 15px; height: 15px; flex: none;
    stroke: currentColor; fill: none;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-soft);
}

.abc-pliki-licznik { color: var(--text-soft); font-size: 11px; }

.abc-pliki-info {
    color: var(--text-faint);
    font-size: 12.5px;
    padding: 0.5rem 0.1rem;
}

/* ── Zakładki: Media / Pliki ─────────────────────────────────────────── */
.abc-pliki-zakladki {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--line);
    margin-bottom: 0.55rem;
}

.abc-pliki-zakladka {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--text-soft);
    font-size: 12.5px;
    padding: 0.32rem 0.55rem;
    cursor: pointer;
    border-radius: 6px 6px 0 0;
}

.abc-pliki-zakladka:hover { background: rgba(0,0,0,0.04); color: var(--text); }

.abc-pliki-zakladka.aktywna {
    color: var(--text);
    border-bottom-color: var(--global-palette1);
    font-weight: 600;
}

/* ── Zakładka „Media": kafelki z datą ────────────────────────────────── */
.abc-pliki-kafelki {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 0.5rem;
}

.abc-pliki-kafelek { position: relative; min-width: 0; }

.abc-pliki-foto {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--line);
    border-radius: 8px;
    overflow: hidden;
    background: var(--cream-2);
}

.abc-pliki-foto img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.abc-pliki-kafelek-brak {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px dashed var(--line);
    border-radius: 8px;
    color: var(--text-faint);
    padding: 0.3rem;
    text-align: center;
}

/* ⚠ Wymiary ikony PODANE WPROST. Bez nich svg bez atrybutów width/height rozciąga się do
   rozmiaru kontenera — właśnie tak powstała czarna plama 834×446 px. */
.abc-pliki-kafelek-brak svg,
.abc-pliki-wiersz svg {
    width: 13px; height: 13px; flex: none;
    stroke: currentColor; fill: none;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

.abc-pliki-podpis {
    font-size: 10.5px;
    color: var(--text-soft);
    margin-top: 0.18rem;
    text-align: center;
}

.abc-pliki-kosz {
    position: absolute;
    top: 3px; right: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px; height: 22px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: rgba(0,0,0,0.45);
    color: #fff;
    cursor: pointer;
    /* Widoczny zawsze, po najechaniu pełny — patrz uwaga przy .abc-zal-kosz (W-14). */
    opacity: 0.6;
    transition: opacity 0.12s ease;
}

.abc-pliki-kafelek:hover .abc-pliki-kosz,
.abc-pliki-kosz:focus-visible { opacity: 1; }

.abc-pliki-kosz svg {
    width: 13px; height: 13px;
    stroke: currentColor; fill: none;
    stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* Na dotyku nie ma najechania — kosz musi być widoczny od razu, inaczej nie istnieje. */
@media (hover: none) {
    .abc-pliki-kosz { opacity: 1; }
}

/* ── Zakładka „Pliki": lista z datą, nazwą i rozmiarem ───────────────── */
.abc-pliki-lista { display: flex; flex-direction: column; }

.abc-pliki-wiersz {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.32rem 0.15rem;
    border-bottom: 1px solid var(--line);
    /* ⚠ min-width: 0 na elemencie flex — bez tego długa nazwa pliku rozpycha wiersz
       zamiast się przyciąć. */
    min-width: 0;
}

.abc-pliki-wiersz:last-child { border-bottom: none; }

.abc-pliki-data {
    color: var(--text-soft);
    font-size: 11px;
    flex: none;
    width: 72px;
}

.abc-pliki-nazwa {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12.5px;
    color: var(--text);
}

a.abc-pliki-nazwa:hover { text-decoration: underline; }

.abc-pliki-usuniety {
    color: var(--text-faint);
    text-decoration: line-through;
}

.abc-pliki-rozmiar {
    color: var(--text-soft);
    font-size: 11px;
    flex: none;
}

.abc-pliki-grozny { color: var(--warn); flex: none; }

.abc-pliki-kosz-lista {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 22px; height: 22px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
}

.abc-pliki-kosz-lista:hover { background: rgba(0,0,0,0.06); color: var(--danger); }

.abc-pliki-kosz-lista svg {
    width: 13px; height: 13px;
    stroke: currentColor; fill: none;
    stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* ─────────────────────────────────────────────────────────────────────────────
   PODEJRZANY NADAWCA (podszywanie / spoofing) — tor S2b.
   Dodane na końcu świadomie: klasa wspólna dla listy skrzynki (Inbox/Poczta)
   i czytnika rozmowy, więc nie może być zakresowa (.razor.css w jednym komponencie
   nie zadziała w drugim). Kolor ostrzegawczy, ale nie „awaria” — wiadomość zostaje,
   ma być zauważona, nie ukryta. */
.spoof-badge {
    display: inline-flex; align-items: center; gap: 3px;
    height: 18px; padding: 0 7px;
    border-radius: 9px;
    font-size: 10.5px; font-weight: 700; line-height: 1;
    white-space: nowrap;
    background: #fbe4e0; color: #b5271b; border: 1px solid #f0b8b0;
}
[data-theme="dark"] .spoof-badge {
    background: rgba(196,57,47,0.20); color: #f4a39c; border-color: rgba(196,57,47,0.45);
}

/* Pasek wyjaśnienia w czytniku rozmowy: „dlaczego uznaliśmy nadawcę za podejrzanego”. */
.spoof-warning {
    display: flex; gap: 10px; align-items: flex-start;
    margin: 8px 0 4px;
    padding: 10px 12px;
    border-radius: 8px;
    background: #fbe4e0; color: #7a1c13;
    border: 1px solid #f0b8b0;
    font-size: 12.5px; line-height: 1.5;
}
[data-theme="dark"] .spoof-warning {
    background: rgba(196,57,47,0.14); color: #f4b7b0; border-color: rgba(196,57,47,0.40);
}
.spoof-warning .spoof-warning-icon { flex: 0 0 auto; font-size: 15px; line-height: 1.3; }
.spoof-warning strong { display: block; margin-bottom: 3px; }
.spoof-warning ul { margin: 4px 0 0; padding-left: 18px; }
.spoof-warning li { margin: 2px 0; }

/* ── Cele dotykowe na ekranach szczegółu (zwrot, zadanie) ──────────────────────
   Przejazd 18.08.2026 zgłosił po kilkanaście za małych celów na `/returns/{id}`
   i `/tasks/{id}`: odnośnik powrotu 51×18, adres e-mail klienta 136×18, kosz przy
   załączniku 22×22, „+ tag" 47×24. Wszystko poniżej progu, w który da się trafić palcem.

   ⚠ DLACZEGO REALNY ROZMIAR, A NIE WARSTWA `::after`.
   Sonda liczy cel za dobry, gdy element ma ≥32×32 px ALBO gdy cztery punkty szesnaście
   pikseli od środka trafiają w niego (`elementFromPoint`). Druga droga działa TYLKO dla
   elementów w widocznym kadrze — punkt poza oknem jest pomijany, ale licznik trafień
   i tak go wymaga, więc wszystko poniżej zgięcia strony przepada bez względu na warstwę.
   Ekran szczegółu zwrotu i zadania to długie strony: większość tych celów leży pod
   zgięciem. Dlatego dajemy im PRAWDZIWĄ wysokość — i wyłącznie na dotyku, więc gęstość
   interfejsu na komputerze zostaje bez zmian.

   ⚠ Druga pułapka: warstwa `::after` sąsiada. W liście (np. „Inne sprawy klienta")
   pozycje stoją co ~29 px, więc warstwa 44 px jednej pozycji wchodziłaby na sąsiednią
   i kradła jej kliknięcia. Realna wysokość 40 px rozsuwa je zamiast nakładać. */
@media (pointer: coarse) {
    /* ── Zwrot: `/returns/{id}` ── */

    /* Okruszek powrotu nad kartą zwrotu — 51×18 px. */
    .rd-back { display: inline-flex; align-items: center; min-height: 40px; min-width: 44px; flex-direction: row; }

    /* Numer oferty pod nazwą pozycji (odnośnik do Allegro) — 97×17 px. */
    .rd-item-offer { min-height: 40px; }

    /* Adres e-mail klienta w panelu bocznym — 136×18 px.
       ⚠ NIE zamieniać na `inline-flex`: element ma skracać długi adres wielokropkiem,
         a `text-overflow` działa w bloku, nie na elemencie zgiętym. `line-height` daje
         wysokość i wyśrodkowanie bez ruszania sposobu wyświetlania. */
    .rd-side-email { min-height: 40px; line-height: 40px; }

    /* „Pełen profil →" pod danymi klienta. */
    .rd-customer-link {
        display: inline-flex; align-items: center;
        min-height: 40px; min-width: 44px;
        flex-direction: row;
    }

    /* „otwórz pełną →" w nagłówku karty rozmowy.
       Nagłówek trzyma dzieci na linii bazowej — przy celu 40 px musi trzymać je na środku,
       inaczej odnośnik zwisa pod tytułem. */
    .rd-side-title { align-items: center; }
    .rd-side-title-link {
        display: inline-flex; align-items: center; justify-content: center;
        min-height: 40px; min-width: 44px;
        flex-direction: row;
    }

    /* Pozycje list „Inne sprawy klienta" i „Historia tego klienta" — po ~29 px każda. */
    .rd-history-item { min-height: 40px; }

    /* Kopiowanie numeru konta — 28×28 px. */
    .rd-bank-copy { width: 40px; height: 40px; }

    /* Zamknięcie paska z komunikatem po akcji. */
    .rd-flash-x {
        display: inline-flex; align-items: center; justify-content: center;
        min-width: 40px; min-height: 40px;
        flex-direction: row;
    }

    /* ── Zadanie: `/tasks/{id}` — klasy WSPÓŁDZIELONE, więc siedzą tutaj, nie w stylach
         zakresowych strony (te same przyciski są w oknie tagów rozmowy i na karcie klienta). ── */

    /* „+ tag" (47×24 px) i „+ zgłoszenie". */
    .tag-add-btn {
        justify-content: center;
        min-height: 40px; min-width: 44px;
        padding: 0.2rem 0.85rem;
    }

    /* Krzyżyk zdejmujący tag z plakietki. */
    .tag-remove {
        display: inline-flex; align-items: center; justify-content: center;
        min-width: 36px; min-height: 36px;
        padding: 0; margin-left: 0.15rem;
        flex-direction: row;
    }

    /* ── Załączniki pod wpisem (komponent wspólny dla zadania, czatu i zgłoszenia) ── */

    /* Kosz przy załączniku — 22×22 px, i to on wychodził jako „22x22 bez etykiety".
       ⚠ 36, nie 40: kosz stoi w rogu kafelka, a przy pasku z nazwą pliku (~27 px wysokości)
         większy wystawałby pod kafelek i wchodził na następny rząd załączników. Pasek
         dostaje więc własną wysokość, żeby kosz miał gdzie się zmieścić. */
    .abc-zal-plik { min-height: 40px; }
    .abc-zal-kosz { width: 36px; height: 36px; top: 3px; right: 3px; }
    .abc-zal-kosz svg { width: 15px; height: 15px; }

    /* Krzyżyk odpinający plik JESZCZE NIEWYSŁANY (plakietka nad polem komentarza) — 15×14 px.
       W przejeździe go nie było, bo w chwili pomiaru nikt nic nie dopinał, ale to ten sam
       kompozytor zadania i ta sama ręka. Znalazł go dopiero pomiar na stanowisku. */
    .composer-att-chip { min-height: 40px; }
    .composer-att-remove {
        display: inline-flex; align-items: center; justify-content: center;
        flex: none;
        min-width: 36px; min-height: 36px;
        padding: 0;
        flex-direction: row;
    }
}

@media (pointer: coarse) {
    /* ── Odnośnik w pierwszej kolumnie tabeli (nazwa klienta, kontrahenta, agenta) ──
       Zmierzone 18.08.2026 na `/clients` i `/service-reports`: 38×22, 128×22, 117×22 px —
       wysokość samego wiersza tekstu. Wcześniej te ekrany były na stanowisku PUSTE, więc
       sonda nie miała czego zmierzyć i wyglądały na czyste.

       ⚠ Realna wysokość, nie warstwa `::after`: wewnątrz komórki tabeli warstwa bywa przycięta
       przez `overflow` rodzica i wtedy `elementFromPoint` jej nie widzi — poprawka wygląda
       w kodzie na zrobioną, a pomiar dalej pokazuje ten sam rozmiar. Ta sama lekcja, co przy
       `.ts-link` na ekranie statusów zadań.

       Reguła obejmuje WSZYSTKIE tabele z `cell-title` (klienci, raporty serwisowe, agenci,
       role, rozliczenia, tłumaczenia błędów) — celowo, bo tylko powiększa cel. */
    .data-table td.cell-title a,
    td.cell-title a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        flex-direction: row;
    }
}

/* ── Kafelek zdjęcia w wiadomości na wąskim ekranie ──────────────────────────────
   ⚠ Kafelek miał `flex: none` i `max-width: 20rem` (320 px). Na telefonie 390 px dymek
   komentarza jest węższy niż to, więc kafelek NIE MIEŚCIŁ SIĘ i nie miał prawa się zwęzić —
   `flex: none` znaczy „nigdy się nie kurcz". Zdjęcie wyjeżdżało poza dymek, a użytkownik
   telefonu widział zielone pudełko bez treści: komentarz, którego CAŁA zawartość to zrzut
   ekranu, wyglądał jak pusty. Na komputerze ten sam komentarz pokazuje podgląd poprawnie,
   więc przegląd wzrokowy na dużym ekranie nie miał tego jak zobaczyć.

   Zmierzone 18.08.2026 na `/tasks/{id}`: sonda zgłosiła nazwę pliku o rozmiarze 2×91 px —
   pasek nazwy ściśnięty do dwóch pikseli szerokości i rozciągnięty na dziewięćdziesiąt
   w pionie, czyli litera pod literą. */
@media (max-width: 768px) {
    /* ⚠ POPRAWKA MUSI DAC ROZMIAR ODNIESIENIA, nie tylko zdjac ograniczenia. Pierwsza proba
       (`flex: 0 1 auto` + `height: auto` + `aspect-ratio`) zostawila kafelek BEZ podstawy:
       szerokosc mialaby wyjsc z tresci, tresc ma `width: 100%`, wiec wyszlo bledne kolo
       i kafelek zapadl sie do 3x2 px. Poprzednio mial 2x91 — czyli poprawilem jedna liczbe
       na inna rownie bezuzyteczna. Zobaczylem to WYLACZNIE dlatego, ze pomiar powtorzylem
       po wydaniu; sam zapis w stylach wygladal sensownie.
       Teraz jest jawna podstawa 220 px, ktora wolno sciskac do szerokosci dymka. */
    .abc-zal-foto {
        flex: 0 1 220px;
        width: 220px;
        max-width: 100%;
        height: auto;
        aspect-ratio: 16 / 10;
    }
    .abc-zal-foto img {
        width: 100%;
        height: 100%;
        max-width: 100%;
        object-fit: cover;
    }
    /* Pasek z nazwą pliku (nie-zdjęcia) też ma prawo się zwęzić zamiast łamać po literze. */
    .abc-zal-plik { min-width: 0; }
    .abc-zal-nazwa { max-width: 100%; }
}

/* ── Licznik nad listą (LicznikWidoku.razor) ────────────────────────────────────
   ⚠ Klasa MUSI stać tutaj, a nie w pliku zakresowym — komponent woła cztery ekrany
   (`/returns`, `/clients`, `/inbox`, `/feedback`), a reguła zakresowa dostaje atrybut
   `b-xxxxxxxxxx` wyłącznie w pliku, w którym powstała. Ta sama blizna, co przy stanie
   pustym niżej. Wygląd jest jeden dla wszystkich czterech świadomie: to ma być ten sam
   przyrząd na każdym ekranie, a nie cztery podobne. */
/* Licznik nad listą jako kafelki-liczniki w kolorze stanu (N2b, 18.09.2026) — separator „·" zostaje
   w tekście (sondy czytają tę linijkę), tylko blednie. */
.licznik-widoku {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15rem;
    color: var(--text-faint);
    margin-left: 0.5rem;
}
.licznik-widoku .lw-glowna { color: var(--text-soft); }
.licznik-widoku .lw-sep { color: var(--line-strong); }
.licznik-widoku .lw-miara {
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    background: var(--cream-2);
    color: var(--text-soft);
    font-size: 12px;
}
.licznik-widoku .lw-info   { background: var(--info-bg);   color: var(--info); }
.licznik-widoku .lw-warn   { background: var(--warn-bg);   color: var(--warn-mocny); }
.licznik-widoku .lw-danger { background: var(--danger-bg); color: var(--danger); }

/* ── Stan pusty (PustoTutaj.razor) ──────────────────────────────────────────────
   ⚠ Klasy MUSZĄ stać tutaj, a nie w `PustoTutaj.razor.css`. Komponent woła kilkanaście
   ekranów, a reguła zakresowa dostaje atrybut `b-xxxxxxxxxx` wyłącznie w pliku, w którym
   powstała — wszędzie indziej zostałoby nieostylowane pudełko. Ta sama blizna, co przy
   oknie potwierdzenia (`abc-potw-*`) i panelu plików (`abc-pliki-*`).

   ⚠ CZEGO TU NIE MA: `font-family` maszynowej. Obchód ekranów 30.08.2026 policzył 313 użyć
   klasy `mono` w 69 plikach ekranów i pokazał, że zdania do człowieka („Nie ma jeszcze żadnego
   kontrahenta.") czytają się przez nią jak wydruk z terminala. Krój maszynowy zostaje przy
   liczbach w kolumnach, identyfikatorach i kluczach — nie przy zdaniach. */
.pusto {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.55rem;
    padding: 2.6rem 1.25rem;
}
.pusto-znak {
    width: 42px;
    height: 42px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: var(--cream-2);
    color: var(--text-faint);
    margin-bottom: 0.15rem;
}
.pusto-znak svg {
    width: 20px;
    height: 20px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.pusto-tytul {
    margin: 0;
    font-family: 'Instrument Serif', Georgia, serif;
    font-size: 1.3rem;
    font-weight: 400;
    line-height: 1.15;
    color: var(--text);
}
.pusto-opis {
    margin: 0;
    max-width: 48ch;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-soft);
}
.pusto-opis a { color: var(--p1); }
.pusto-akcja { margin-top: 0.6rem; }

/* Wariant do sekcji WEWNĄTRZ karty (kilka stanów pustych obok siebie, np. karta kontrahenta):
   ta sama typografia, mniej powietrza. Pełny wariant zjadałby tam pół ekranu. */
.pusto-male { padding: 1.35rem 0.5rem; gap: 0.4rem; }
.pusto-male .pusto-znak { width: 32px; height: 32px; margin-bottom: 0; }
.pusto-male .pusto-znak svg { width: 16px; height: 16px; }
.pusto-male .pusto-tytul { font-size: 1.05rem; }
.pusto-male .pusto-opis { font-size: 12.5px; }
.pusto-male .pusto-akcja { margin-top: 0.35rem; }

@media (max-width: 640px) {
    .pusto { padding: 2rem 0.75rem; }
    .pusto-akcja { width: 100%; }
}

/* Wiersz „Wczytuję…" — ten sam powód co wyżej: to zdanie do człowieka, nie liczba w kolumnie.
   Osobna klasa, żeby ekran nie musiał powtarzać stylu w atrybucie `style` po raz trzydziesty. */
.stan-ladowania {
    margin: 0;
    padding: 1.25rem 0;
    color: var(--text-soft);
    font-size: 13.5px;
}
.stan-ladowania-srodek {
    padding: 2.5rem 1rem;
    text-align: center;
}

/* ── Czat na karcie klienta (klczat-*) ───────────────────────────────────
   W app.css, nie w pliku zakresowym: karta klienta nie ma własnego `.razor.css`,
   a styl zakresowy dorobiony pod jedną sekcję rozjeżdżałby się z resztą ekranu. */
.klczat-lista {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    /* Rozmowa rośnie bez końca — sekcja na karcie ma zostać sekcją, nie stać się stroną. */
    max-height: 22rem;
    overflow-y: auto;
}
.klczat-wpis { display: flex; gap: 0.55rem; align-items: flex-start; min-width: 0; }
.klczat-awatar {
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 600;
    color: #fff;
    background: var(--global-palette1, #009244);
}
/* min-width: 0 — bez tego jedno długie słowo rozpycha całą kolumnę zamiast się złamać. */
.klczat-tresc { min-width: 0; flex: 1; }
.klczat-naglowek { display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }
.klczat-kto { font-size: 12.5px; font-weight: 600; color: var(--text); }
.klczat-kiedy { font-size: 10.5px; color: var(--text-soft); }
.klczat-body {
    font-size: 13px;
    color: var(--text);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
.klczat-usunieta { font-style: italic; color: var(--text-faint); }
.klczat-pusto { color: var(--text-faint); font-size: 12.5px; margin: 0 0 0.75rem; }
.klczat-pole { display: flex; gap: 0.5rem; align-items: flex-end; }
.klczat-input {
    flex: 1;
    min-width: 0;
    resize: vertical;
    font: inherit;
    font-size: 13px;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--line, #e4e7eb);
    border-radius: 8px;
    background: var(--paper);
    color: var(--text);
}
.klczat-blad { color: var(--danger, #c62828); font-size: 12px; margin: 0.5rem 0 0; }

/* ── Przejdź do treści (pominięcie menu) ──────────────────────────────────────
   Pierwszy przystanek klawiatury na każdym ekranie. Schowany poza kadrem, dopóki nie
   dostanie skupienia — wtedy wjeżdża w lewy górny róg jako zwykły przycisk.

   ⚠ Nie `display:none` ani `visibility:hidden`: element schowany tymi sposobami NIE
   przyjmuje skupienia, więc odnośnik byłby dekoracją, której nikt nie dosięgnie.

   Powód (zmierzone 01.09.2026): bez tego dojście Tabem do treści kosztowało 27 naciśnięć
   na KAŻDYM ekranie — menu boczne powtarza się wszędzie. WCAG 2.4.1 „Bypass Blocks". */
.pomin-nawigacje {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 2000;
    transform: translateY(-120%);
    padding: 0.55rem 1rem;
    background: var(--global-palette1, #009244);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    border-bottom-right-radius: 6px;
    transition: transform 120ms ease-out;
}

.pomin-nawigacje:focus,
.pomin-nawigacje:focus-visible {
    transform: translateY(0);
    outline: 2px solid #fff;
    outline-offset: -4px;
}

@media (prefers-reduced-motion: reduce) {
    .pomin-nawigacje { transition: none; }
}

/* Skupienie postawione odnośnikiem na obszarze treści nie ma rysować ramki wokół
   całego ekranu — samo przeniesienie skupienia wystarcza, resztę widać po tym, że
   następny Tab jest już w treści. */
.content-wrapper:focus { outline: none; }

/* ── Cele dotykowe na telefonie ───────────────────────────────────────────────
   Zmierzone 01.09.2026 obchodem `abcare-ui-sweep` przy 390 px: odnośnik „Poradnik"
   w nagłówku ma 71×23 px, a krzyżyk zamykający komunikat 15×18 px. Palec to nie
   kursor — trafienie w 18 px wymaga celowania, a komunikat znika sam, więc kto
   spudłuje, klika już w to, co jest pod spodem.

   ⚠ Podnosimy WYSOKOŚĆ DOTYKU, nie rozmiar rysunku: powiększenie plakietki
   zepsułoby nagłówki, w których stoi obok tytułu. Robi to `min-height` plus
   pionowe wyrównanie — plakietka wygląda tak samo, a obszar kliknięcia rośnie.
   Tylko dla wskaźnika gruboziarnistego (palec); myszy to nie dotyczy. */
/* ⚠ TU STALA REGULA POWIEKSZAJACA `.pomoc-link` DO 40 px WYSOKOSCI (01.09.2026) — USUNIETA 02.09.
   Powod usuniecia jest wart zapamietania, bo to wzorcowy przyklad naprawiania PRZYRZADU zamiast
   aplikacji:

   1. Obchod ekranow zmierzyl znak zapytania jako 71x23 px i zglosil "za maly cel dotykowy".
   2. Dolozono `min-height: 40px` z komentarzem "plakietka wyglada tak samo". Nie wygladala:
      wariant bez podpisu jest KOLKIEM 1,6 rem, wiec podniesienie samej wysokosci rozciagnelo je
      w waski owal. Widac to bylo na telefonie w naglowku Poczty i rozmowy (02.09.2026).
   3. A powiekszenie w ogole nie bylo potrzebne: kilkaset linii wyzej stoi od 18.08.2026 warstwa
      `.pomoc-link::after` (44x44 px, `pointer-events: auto`), ktora daje palcowi caly cel BEZ
      zmiany wygladu — i sonda ta juz to widzi, bo mierzy `elementFromPoint`, nie prostokat
      elementu ("MIERZYMY TO, CO DOSTAJE PALEC, A NIE PROSTOKAT ELEMENTU" w UiSweep.cs).

   Czyli: usterki nie bylo, byla przestarzala miara — a poprawka pod te miare popsula ekran.
   Nie dokladaj tu wysokosci. Jesli obchod znowu zglosi ten element, popraw MIARE. */
@media (pointer: coarse) {
    .abc-toast-close {
        min-width: 40px;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0;
        flex-direction: row;
    }
}

/* ── Znacznik „to nasze słowa" w zajawce wiersza ──────────────────────────────
   Wiersz skrzynki, wiersz poczty i karta na tablicy są podpisane nazwą KLIENTA,
   a linijka pod spodem to ostatnia wiadomość wątku — czyli po odpisaniu NASZE
   zdanie. Bez tego znacznika ekran przypisuje klientowi słowa naszego zespołu
   (02.09.2026, zrzuty ze stanowiska: dotyczyło każdego odpisanego zgłoszenia).

   ⚠ Klasa GLOBALNA, nie zakresowa: używają jej trzy komponenty, a zakresowy CSS
   działa tylko w swoim. */
.zajawka-od-nas {
    font-weight: 600;
    opacity: 0.7;
    margin-right: 0.3em;
    white-space: nowrap;
}

/* -- Zajawka przycieta do CALYCH linii -------------------------------------------
   Ekran "Szybkie odpowiedzi" przycinal tresc przez `max-height: 4em; overflow: hidden`.
   4em to nie jest wielokrotnosc wysokosci wiersza (12px x 1.5 = 18px, wiec 4em = 48px
   miesci dwie linie i dwie trzecie), przez co trzecia linia byla przecieta w POLOWIE
   WYSOKOSCI LITER — na zrzucie z 02.09.2026 widac dolne polowki gloskow bez gornych.
   Wyglada to jak uszkodzony render, a nie jak skrot.
   Zaciecie po LINIACH tnie zawsze na granicy wiersza i samo dokleja wielokropek. */
.zajawka-3-linie {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* -- Naglowek strony i lista priorytetow: KLASY WSPOLNE, wiec GLOBALNE ------------
   Az szesnascie ekranow uzywalo tych klas, a mieszkaly one w stylu ZAKRESOWYM
   dwoch innych komponentow (Inbox.razor.css, Dashboard.razor.css) — czyli u siebie
   dzialaly, a wszedzie indziej nie robily NIC. Widac to bylo na zrzutach z 02.09.2026:
   na ekranie klientow przycisk "Scaleni" spadal pod tekst zamiast stanac po prawej,
   a na raporcie SLA lista tagow rozsypywala sie na trzy linijki z kropkami listy.
   Styl zakresowy nie siega poza swoj komponent — klasa uzywana przez wiecej niz jeden
   ekran musi stac tutaj. */
.inbox-head,
.greet-row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.inbox-head { margin-bottom: 1.25rem; }
.greet-row  { margin-bottom: 1.5rem; }

.prio-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.prio-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--line);
    color: var(--text);
    text-decoration: none;
    transition: background 0.12s;
}

.prio-list li:last-child .prio-row { border-bottom: none; }
.prio-row:hover { background: var(--cream); margin: 0 -0.5rem; padding-left: 0.5rem; padding-right: 0.5rem; border-radius: var(--radius-sm); }

.prio-name {
    font-weight: 500;
    font-size: 13.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prio-snippet {
    font-size: 12px;
    color: var(--text-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prio-sla { flex: none; }

/* Publiczna odpowiedź pod opinią Allegro — schowana pod rozwijakiem, bo jest nieodwracalna. */
.opinia-odpowiedz { margin-top: 0.4rem; }
.opinia-odpowiedz > summary { cursor: pointer; display: inline-block; }
.opinia-odpowiedz > summary::-webkit-details-marker { display: none; }
.opinia-odpowiedz-uwaga { font-size: 11.5px; color: var(--text-soft); margin: 0.35rem 0; }
.opinia-odpowiedz textarea { width: 100%; font-size: 12.5px; }

/* ══ Raporty modułu Obsługa (rp-*) — WSPÓLNE dla ServiceReportsPage i ZestawieniePracPage ══
   ⚠ Stały w ServiceReportsPage.razor.css — arkuszu z zakresem, który działa WYŁĄCZNIE na swoją stronę.
   Zestawienie prac używało tych samych klas i dostawało gołe pola dat na całą szerokość, a „Razem”
   i „Wartość referencyjna” bez kafelków (przegląd zrzutów 25.09.2026, zestawienie-01).
   Pilnuje ZestawieniePracMaStylRaportuTests. .no-print na wydruku — reguła wydruku wyżej w tym pliku. */
.rp-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.1rem;
}

.rp-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }

.rp-range {
    display: flex;
    align-items: flex-end;
    gap: 0.8rem;
    flex-wrap: wrap;
    margin-bottom: 0.8rem;
}

.rp-field { display: flex; flex-direction: column; gap: 0.2rem; }
.rp-field label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-soft); }
.rp-presets { display: flex; gap: 0.3rem; flex-wrap: wrap; }

.rp-period { font-size: 12.5px; color: var(--text-soft); margin: 0 0 1rem; }

/* ── Kafelki podsumowania ── */

.rp-summary {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.8rem;
    margin-bottom: 1.1rem;
}

.rp-tile {
    background: var(--paper);
    border: 1px solid var(--line);
    border-left: 3px solid var(--line-strong, var(--line));
    border-radius: 8px;
    padding: 0.7rem 0.85rem;
    min-width: 0;
}

.rp-tile-accent { border-left-color: var(--p1); }

.rp-tile-l {
    display: block;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-soft);
    margin-bottom: 0.3rem;
}

.rp-tile-v {
    display: block;
    font-size: 17px;
    font-variant-numeric: tabular-nums;
}

.rp-tile-v small { font-size: 11px; color: var(--text-soft); margin-left: 0.3rem; }

/* ── Pasek udziału ── */

.rp-bar {
    display: inline-block;
    width: 4.5rem;
    height: 6px;
    background: var(--cream);
    border-radius: 999px;
    overflow: hidden;
    vertical-align: middle;
    margin-right: 0.4rem;
}

.rp-bar-fill {
    display: block;
    height: 100%;
    background: var(--p1);
}

.rp-bar-label { font-size: 11px; color: var(--text-soft); }

@media (max-width: 900px) {
    .rp-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── Wydruk ──
   Natywny: @media print + window.print(), bez html2canvas/jsPDF. Przeglądarka drukuje lepiej
   niż jakakolwiek biblioteka i sama robi z tego PDF. */
@media print {
    .rp-summary { grid-template-columns: repeat(4, 1fr); }

    .rp-tile,
    .card {
        border: 1px solid #ccc;
        box-shadow: none;
        break-inside: avoid;
    }

    /* Pasek udziału na papierze bywa niewidoczny — zostaje liczba obok niego. */
    .rp-bar { border: 1px solid #999; }
    .rp-bar-fill { background: #666; }
}

/* ═════════════════════════════════════════════════════════════════════════════════════════
   OPROWADZENIE PO APLIKACJI (26.09.2026) — karta-zaproszenie i dymki trasy (Driver.js 1.8.0)
   Specyfikacja: docs/SubAgent/oprowadzenie-spec.md. Kod: Components/Layout/OprowadzenieHost.razor,
   ZaproszenieDoOprowadzenia.razor, wwwroot/js/abc-oprowadzenie.js. Biblioteka: wwwroot/lib/driverjs.

   Znak rozpoznawczy: LINIA PRZYSTANKÓW. Jedna kropka = jeden krok trasy TEJ osoby — w karcie
   zaproszenia widać, jak krótka jest trasa, w dymku — gdzie na niej jestem. Ostatni przystanek
   (pasek u góry) ma kolor limonki z logo. Tytuły krojem znaku ABCare (Instrument Serif, jak „Care”
   w logo), reszta zwykłym krojem aplikacji.

   WARSTWY — jawnie (§7.12): karta 940 < przyciemnienie 960 < dymek 970 < pasek błędu obwodu 1000
   < dymki powiadomień i ponowne łączenie 9999 < okna 10000. Awaria obwodu przykrywa trasę, nie odwrotnie.
   Motyw ciemny: wyłącznie tokeny palety — mają obie wersje, więc dymek przełącza się sam.
   ⚠ Arkusz biblioteki ładuje się PRZED tym plikiem (abc-oprowadzenie.js), więc przy równej wadze
   wygrywa ten; tam, gdzie biblioteka pisze styl wprost w element (położenie, warstwa
   przyciemnienia), potrzebne jest !important.
   ═════════════════════════════════════════════════════════════════════════════════════════ */

/* ── Linia przystanków (karta i dymek) ── */
.opr-trasa {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.opr-trasa::before {
    content: '';
    position: absolute;
    left: 5px;
    right: 5px;
    top: 50%;
    height: 2px;
    transform: translateY(-50%);
    border-radius: 1px;
    background: color-mix(in srgb, var(--global-palette1) 35%, var(--line));
}
.opr-trasa-kropka {
    position: relative;
    box-sizing: border-box;
    flex: none;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--paper);
    border: 2px solid var(--global-palette1);
}
.opr-trasa-kropka:last-child {
    background: var(--global-palette2);
    border-color: var(--global-palette2);
}
.opr-trasa-kropka.is-za {
    background: var(--global-palette1);
}
.opr-trasa-kropka.is-teraz {
    width: 14px;
    height: 14px;
    background: var(--global-palette1);
    border-color: var(--global-palette1);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--global-palette1) 22%, transparent);
}

/* Kropki kroków, o których rozstrzyga przeglądarka — liczba kropek = liczba kroków, które człowiek zobaczy. */
@media (min-width: 1300px) {
    .opr-zaproszenie .opr-trasa-kropka[data-urzadzenie="waskie"] { display: none; }
}
html:not(.abcare-native) .opr-zaproszenie .opr-trasa-kropka[data-urzadzenie="aplikacja"] { display: none; }
html.abcare-native .opr-zaproszenie .opr-trasa-kropka[data-urzadzenie="waskie"] { display: none; }
body:not(:has([data-oprowadzenie="menu-poczta"])) .opr-zaproszenie .opr-trasa-kropka[data-cel="menu-poczta"] { display: none; }

/* ── Karta-zaproszenie: róg obszaru treści, nie okno. Prawy dolny róg należy do dymków powiadomień. ── */
.opr-zaproszenie {
    position: fixed;
    left: calc(var(--sidebar-w) + 1rem);
    bottom: 1rem;
    z-index: 940;
    box-sizing: border-box;
    width: min(22rem, calc(100vw - 2rem));
    padding: 1rem 1.15rem 0.85rem;
    color: var(--text);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    animation: fadeIn 0.3s ease-out both;
}
.page.sidebar-collapsed .opr-zaproszenie { left: 1rem; }
.opr-zaproszenie-tytul {
    margin: 0.8rem 0 0.3rem;
    font-family: 'Instrument Serif', Georgia, serif;
    font-weight: 400;
    font-size: 1.55rem;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--text);
}
.opr-zaproszenie-opis {
    margin: 0 0 0.9rem;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--text-soft);
}
.opr-zaproszenie-akcje {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}
.opr-zaproszenie-nigdy {
    margin-left: auto;
    padding: 0.35rem 0.2rem;
    background: none;
    border: none;
    font: inherit;
    font-size: 12px;
    color: var(--text-faint);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.opr-zaproszenie-nigdy:hover { color: var(--text); }
.opr-zaproszenie button:focus-visible {
    outline: 2px solid var(--global-palette1);
    outline-offset: 2px;
}
@media (max-width: 1299.98px) {
    .opr-zaproszenie { left: 1rem; }
}
/* Telefon: arkusz na całą szerokość przy dolnej krawędzi. */
@media (max-width: 640px) {
    .opr-zaproszenie {
        left: 8px;
        right: 8px;
        width: auto;
        bottom: calc(8px + env(safe-area-inset-bottom));
    }
    .opr-zaproszenie-akcje .btn { flex: 1 1 auto; }
    .opr-zaproszenie-nigdy { flex-basis: 100%; margin-left: 0; text-align: center; }
}
@media (pointer: coarse) {
    .opr-zaproszenie-akcje .btn,
    .opr-zaproszenie-nigdy { min-height: 40px; }
}
@media (prefers-reduced-motion: reduce) {
    .opr-zaproszenie { animation: none; }
}

/* ── Przyciemnienie i podświetlenie ── */
svg.driver-overlay { z-index: 960 !important; }
svg.driver-overlay path { fill: var(--global-palette3) !important; }
.driver-active .driver-active-element {
    outline: 2px solid var(--global-palette1);
    outline-offset: 2px;
}
/* Na czas przesuwania szuflady dymek znika — wisiałby nad pozycją, która odjeżdża. */
body.abc-opr-przejscie .driver-popover { visibility: hidden; }
/* Biblioteka wyłącza klikanie WSZYSTKIEGO poza dymkiem. Ponowne łączenie, pasek błędu obwodu
   i dymki powiadomień mają zostać klikalne także w trakcie trasy. */
.driver-active #components-reconnect-modal,
.driver-active #components-reconnect-modal *,
.driver-active #blazor-error-ui,
.driver-active #blazor-error-ui *,
.driver-active #abc-toast-container * { pointer-events: auto; }

/* ── Dymek ── */
.driver-popover.abc-opr-dymek {
    z-index: 970;
    box-sizing: border-box;
    min-width: 17rem;
    max-width: 21rem;
    padding: 1rem 1.1rem 0.9rem;
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    color: var(--text);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}
.driver-popover.abc-opr-dymek .driver-popover-title {
    padding-right: 2.25rem;
    font-family: 'Instrument Serif', Georgia, serif;
    font-weight: 400;
    font-size: 1.4rem;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--text);
}
.driver-popover.abc-opr-dymek .driver-popover-description {
    margin-top: 0.35rem;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--text-soft);
}
.driver-popover.abc-opr-dymek .driver-popover-close-btn {
    top: 0.45rem;
    right: 0.45rem;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius);
    font-size: 1.3rem;
    line-height: 2.25rem;
    color: var(--text-faint);
}
.driver-popover.abc-opr-dymek .driver-popover-close-btn:hover,
.driver-popover.abc-opr-dymek .driver-popover-close-btn:focus-visible {
    color: var(--text);
    background: var(--cream-2);
}
.driver-popover.abc-opr-dymek .abc-opr-wiersz {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 0.75rem;
    margin-top: 0.9rem;
}
/* Napis w kolorze tekstu, zielone jest tylko podkreślenie: zieleń marki na tle karty ma mniej niż 4,5:1. */
.driver-popover.abc-opr-dymek .abc-opr-pomoc {
    font-size: 12px;
    color: var(--text);
    text-decoration: underline;
    text-decoration-color: var(--global-palette1);
    text-underline-offset: 3px;
    white-space: nowrap;
}
.driver-popover.abc-opr-dymek .driver-popover-footer {
    margin-top: 0.75rem;
    gap: 0.5rem;
}
.driver-popover.abc-opr-dymek .driver-popover-progress-text {
    font-size: 12px;
    color: var(--text-faint);
}
.driver-popover.abc-opr-dymek .driver-popover-navigation-btns { gap: 0.4rem; }
.driver-popover.abc-opr-dymek .driver-popover-navigation-btns button + button { margin-left: 0; }
.driver-popover.abc-opr-dymek .driver-popover-footer-btn {
    box-sizing: border-box;
    height: 2.25rem;
    padding: 0 0.95rem;
    font-family: inherit;
    font-weight: 500;
    font-size: 13px;
    line-height: calc(2.25rem - 2px);
    color: var(--text);
    background: var(--paper);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    text-shadow: none;
    cursor: pointer;
}
.driver-popover.abc-opr-dymek .driver-popover-footer-btn:hover { background: var(--cream-2); }
.driver-popover.abc-opr-dymek .driver-popover-next-btn {
    color: var(--text-light);
    background: var(--global-palette1);
    border-color: var(--global-palette1);
}
.driver-popover.abc-opr-dymek .driver-popover-next-btn:hover {
    background: color-mix(in srgb, var(--global-palette1) 84%, var(--global-palette3));
}
.driver-popover.abc-opr-dymek .driver-popover-footer-btn:focus-visible,
.driver-popover.abc-opr-dymek .driver-popover-close-btn:focus-visible,
.driver-popover.abc-opr-dymek .abc-opr-pomoc:focus-visible {
    outline: 2px solid var(--global-palette1);
    outline-offset: 2px;
}
/* Strzałka w kolorze karty — biblioteka maluje ją na biało, co w trybie ciemnym świeci. */
.driver-popover.abc-opr-dymek .driver-popover-arrow-side-left { border-left-color: var(--paper); }
.driver-popover.abc-opr-dymek .driver-popover-arrow-side-right { border-right-color: var(--paper); }
.driver-popover.abc-opr-dymek .driver-popover-arrow-side-top { border-top-color: var(--paper); }
.driver-popover.abc-opr-dymek .driver-popover-arrow-side-bottom { border-bottom-color: var(--paper); }

@media (pointer: coarse) {
    .driver-popover.abc-opr-dymek .driver-popover-footer-btn { height: 2.5rem; line-height: calc(2.5rem - 2px); }
    .driver-popover.abc-opr-dymek .driver-popover-close-btn { width: 2.5rem; height: 2.5rem; line-height: 2.5rem; }
}
/* Telefon: dymek jako arkusz przy dolnej krawędzi. Położenie biblioteka pisze wprost w element,
   stąd !important. Nakładka dba, żeby arkusz nie przykrył tego, o czym mówi (przewija cel). */
@media (max-width: 640px) {
    .driver-popover.abc-opr-dymek {
        left: 8px !important;
        right: 8px !important;
        top: auto !important;
        bottom: calc(8px + env(safe-area-inset-bottom)) !important;
        width: auto;
        min-width: 0;
        max-width: none;
    }
    .driver-popover.abc-opr-dymek .driver-popover-arrow { display: none; }
    /* Cel przy samej dolnej krawędzi (pole pisania na ekranie zgłoszenia) — arkusz idzie na górę,
       żeby nie przykryć tego, o czym mówi. Klasę dokłada nakładka tylko w tym jednym kroku. */
    .driver-popover.abc-opr-dymek.abc-opr-arkusz-gora {
        top: calc(8px + env(safe-area-inset-top)) !important;
        bottom: auto !important;
    }
}
