html, body {
    font-family: var(--font-family-brand, 'CircularXX'), sans-serif;
}

/* Decorative dot pattern in upper-right corner */
.pattern-overlay {
    position: fixed;
    top: 0;
    right: 0;
    width: 1360px;
    max-width: calc(100% - 280px);
    height: 184px;
    background-image: url('/images/pattern-final.png');
    background-repeat: no-repeat;
    background-position: top right;
    background-size: cover;
    pointer-events: none;
    z-index: 1;
    opacity: 0.5;
    mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.6) 60%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.6) 60%, transparent 100%);
}

a, .btn-link {
    color: #006bb7;
}

/* Bootstrap .btn-primary uses --bs-primary from bootstrap-antumo.css (#3A3A66) */
/* No override needed - design tokens handle colors */

/* Button focus - inputs now handled by antumo/inputs.css */
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus {
  box-shadow: var(--focus-ring);
}

/* Przycisk wtórny i stan wyłączony brały kolory z kompilacji Bootstrapa, wpisane tam na
   sztywno pod jasny motyw: na ciemnym wychodził z tego jasnoszary przycisk na czarnej
   karcie — najbardziej widoczny element na ekranie, choć akurat ten nic nie robi.

   Kolory idą z tokenów, nie z wyjątku dla ciemnego motywu: para tokenów ma w każdym motywie
   swoją wartość, więc jeden zapis obsługuje oba i nie da się dodać trzeciego motywu
   z pominięciem przycisków. Tło zostaje przezroczyste — przycisk obrysowany ma pokazywać
   to, na czym stoi. */
.btn-outline-secondary {
    --bs-btn-color: var(--color-btn-secondary-text);
    --bs-btn-border-color: var(--color-btn-secondary-border);
    --bs-btn-hover-color: var(--color-btn-secondary-text);
    --bs-btn-hover-bg: var(--color-btn-secondary-bg-hover);
    --bs-btn-hover-border-color: var(--color-btn-secondary-border);
    --bs-btn-active-color: var(--color-btn-secondary-text);
    --bs-btn-active-bg: var(--color-btn-secondary-bg-hover);
    --bs-btn-active-border-color: var(--color-btn-secondary-border);
}

/* Wyłączony przycisk bierze tę samą parę kolorów, co wyłączone pole — na jednym ekranie
   te dwa stany mówią to samo, więc mają wyglądać tak samo. Deklaracje, nie zmienne:
   w kompilacji Bootstrapa stan wyłączony jest wpisany kolorami, a nie przez `--bs-btn-*`. */
.btn:disabled,
.btn.disabled,
fieldset:disabled .btn {
    background-color: var(--color-input-bg-disabled);
    border-color: var(--color-border-secondary);
    color: var(--color-input-text-disabled);
}

/* ---------------------------------------------------------------------------
   Paski przewijania
   ---------------------------------------------------------------------------
   Cienkie i wygaszone: sam suwak, bez ramy i bez tła rynny. Suwak jest węższy od rynny,
   bo rysowany z przezroczystą krawędzią i przycięty do pola treści — tak dostaje odstęp
   od krawędzi panelu bez dokładania sobie marginesu.

   Pseudoelementy WebKita, a nie `scrollbar-width` z `scrollbar-color`: w Chromium te dwa
   wyłączają pseudoelementy, a same nie pozwalają ustawić ani zaokrąglenia, ani odstępu od
   krawędzi. Przeglądarki, które pseudoelementów nie znają (Firefox), dostają wariant
   standardowy — wychodzi z niego cienki pasek w tym samym kolorze, tylko bez zaokrąglenia. */
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background-color: var(--color-scrollbar-thumb, #d5d7da);
    background-clip: content-box;
    border: 2px solid transparent;
    border-radius: var(--radius-full, 999px);
}

::-webkit-scrollbar-thumb:hover {
    background-color: var(--color-scrollbar-thumb-hover, #94979c);
}

@supports not selector(::-webkit-scrollbar) {
    * {
        scrollbar-width: thin;
        scrollbar-color: var(--color-scrollbar-thumb, #d5d7da) transparent;
    }
}

/* Wypełnienie kolumny treści daje układ (32 piksele z każdej strony, jak w UTS) — tutaj
   zostaje samo wyniesienie nad wzór w kropki. */
.content {
    position: relative;
    z-index: 2;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--color-green-500);
}

.invalid {
    outline: 1px solid var(--color-input-border-error);
}

.validation-message {
    color: var(--color-input-error-text);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: var(--color-grey-500);
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}
/* Diff Viewer Styles */
.diff-viewer {
    font-family: 'Courier New', Monaco, monospace;
}

.diff-content {
    background-color: #f8f9fa;
    max-height: 600px;
    overflow: auto;
}

/* One horizontal scrollbar for the whole diff. Sizing the list to its widest line stops each
   long line from growing its own scrollbar, which turned every hunk into a stack of bars. */
.diff-lines {
    width: max-content;
    min-width: 100%;
    padding: 0;
    margin: 0;
}

.diff-line {
    display: flex;
    align-items: center;
    padding: 2px 8px;
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    white-space: pre;
    font-family: 'Courier New', Monaco, monospace;
}

.diff-line.diff-added {
    background-color: #e6ffed;
    border-left: 3px solid #28a745;
}

.diff-line.diff-removed {
    background-color: #ffeef0;
    border-left: 3px solid #dc3545;
}

.diff-line.diff-modified {
    background-color: #fff8c5;
    border-left: 3px solid #ffc107;
}

.diff-line.diff-unchanged {
    background-color: white;
    color: #6c757d;
    border-left: 3px solid transparent;
}

.line-number {
    display: inline-block;
    width: 46px;
    padding-right: 8px;
    color: #999;
    text-align: right;
    user-select: none;
    flex-shrink: 0;
}

.line-number + .line-number {
    border-right: 1px solid var(--color-border-secondary);
    margin-right: 8px;
}

.line-prefix {
    display: inline-block;
    width: 20px;
    font-weight: bold;
    flex-shrink: 0;
}

/* Keeps blank lines at full row height instead of collapsing to padding only */
.line-content:empty::after {
    content: "\00a0";
}

.diff-gap {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    width: 100%;
    padding: 4px 12px;
    border: 0;
    border-top: 1px solid var(--color-border-secondary);
    border-bottom: 1px solid var(--color-border-secondary);
    background-color: var(--color-grey-100);
    color: var(--color-text-tertiary);
    font-family: inherit;
    font-size: 12px;
    text-align: left;
    cursor: pointer;
}

.diff-gap:hover {
    background-color: var(--color-grey-200);
    color: var(--color-text-primary);
}

.diff-line.diff-added .line-prefix {
    color: #28a745;
}

.diff-line.diff-removed .line-prefix {
    color: #dc3545;
}

.diff-line.diff-modified .line-prefix {
    color: #ffc107;
}

.line-content {
    flex: 0 0 auto;
}

.diff-stats .badge {
    font-size: 0.9rem;
}

.page-header {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xl);
    margin-bottom: var(--spacing-3xl);
}

.page-header-content {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--spacing-5xl);
}

.page-header-text {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    flex: 1;
    min-width: 0;
}

.page-header-title {
    font-family: var(--heading-lg-font-family);
    font-weight: var(--heading-lg-font-weight);
    font-size: var(--heading-lg-font-size);
    line-height: var(--heading-lg-line-height);
    letter-spacing: var(--heading-lg-letter-spacing);
    color: var(--color-text-primary);
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.page-header-icon {
    flex-shrink: 0;
}

.page-header-description {
    font-family: var(--body-lg-font-family);
    font-weight: var(--body-lg-font-weight);
    font-size: var(--body-lg-font-size);
    line-height: var(--body-lg-line-height);
    letter-spacing: var(--body-lg-letter-spacing);
    color: var(--color-text-secondary);
    margin: 0;
}

.page-header-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-lg);
    flex-shrink: 0;
}

.breadcrumbs {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-xxs);
}

.breadcrumb-item {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    padding: var(--spacing-xs) var(--spacing-md);
    border-radius: var(--radius-sm);
    font-family: var(--label-md-font-family);
    font-weight: var(--label-md-font-weight);
    font-size: var(--label-md-font-size);
    line-height: var(--label-md-line-height);
    color: var(--color-text-tertiary);
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.breadcrumb-item:hover {
    background-color: var(--color-interactive-secondary);
    color: var(--color-text-primary);
    text-decoration: none;
}

.breadcrumb-home {
    padding: var(--spacing-xs) var(--spacing-md) var(--spacing-xs) 0;
}

.breadcrumb-current {
    color: var(--color-interactive-primary);
    font-weight: var(--font-weight-medium);
    cursor: default;
}

.breadcrumb-current:hover {
    background-color: transparent;
    color: var(--color-interactive-primary);
}

.breadcrumb-separator {
    color: var(--color-text-tertiary);
    flex-shrink: 0;
}

@media (max-width: 768px) {
    .page-header {
        padding: 0 var(--spacing-xl);
    }
    
    .page-header-content {
        flex-direction: column;
        gap: var(--spacing-xl);
    }
    
    .page-header-actions {
        width: 100%;
        justify-content: flex-start;
    }
}

.filter-buttons {
    display: flex;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}

/* ===== Antumo Card Component ===== */
/* Based on Figma: https://www.figma.com/design/aKIP8PcGfbAMKAZNhEbDOZ/?node-id=1308-29401 */

/* Wypełnienie karty jedną zmienną, a nie tokenem wpisanym w każdą część: nagłówek, treść,
   stopka, zakładki i listy sięgające krawędzi muszą mieć zawsze tę samą liczbę, bo te
   ostatnie wychodzą na krawędź ujemnym marginesem. Na mniejszym ekranie zmienna schodzi
   niżej (reguła pod spodem) i wszystko przelicza się razem z nią. */
.antumo-card {
    --card-padding: var(--spacing-3xl, 24px);

    background-color: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xs);
}

/* Ekran laptopa: przy odstępach policzonych na duży monitor karty zabierają na samo
   obramowanie treści tyle wysokości, co dwie pozycje listy. */
@media (max-width: 1700px) {
    .antumo-card {
        --card-padding: var(--spacing-xl, 16px);
    }
}

.antumo-card-header {
    overflow: visible;
}

.antumo-card-header {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-lg);
    padding: var(--card-padding, var(--spacing-3xl));
    padding-bottom: 0;
}

.antumo-card-header-left {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-lg);
    flex: 1;
    min-width: 0;
}

.antumo-card-header-right {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-md);
    flex-shrink: 0;
}

/* Nagłówki kart w kolorze marki — tak samo jak nagłówki kart z liczbami na przeglądzie.
   Wcześniej te pierwsze były ciemne, a te drugie granatowe, więc na jednym ekranie stały
   dwa różne rodzaje nagłówka. */
.antumo-card-title {
    color: var(--color-text-brand, var(--color-navy-500));
    margin: 0;
}

.antumo-card-header-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-md);
    flex-shrink: 0;
}

.antumo-card-body {
    padding: var(--card-padding, var(--spacing-3xl));
}

.antumo-card-footer {
    padding: var(--card-padding, var(--spacing-3xl));
    padding-top: 0;
    border-top: 1px solid var(--color-border-secondary);
}

/* ===== Antumo Tabs (inside a card body, bleeding to the card edges) ===== */

.antumo-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
    margin-left: calc(-1 * var(--card-padding, var(--spacing-3xl)));
    margin-right: calc(-1 * var(--card-padding, var(--spacing-3xl)));
    margin-bottom: var(--card-padding, var(--spacing-3xl));
    padding: 0 var(--card-padding, var(--spacing-3xl));
    border-bottom: 1px solid var(--color-border-secondary);
}

.antumo-tab {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-lg) var(--spacing-xl);
    border: 0;
    background: none;
    color: var(--color-text-tertiary);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
}

.antumo-tab:hover:not(:disabled) {
    color: var(--color-text-primary);
}

.antumo-tab:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Inset shadow rather than a border, so the active tab does not shift the strip by 2px */
.antumo-tab.active {
    color: var(--color-text-primary);
    box-shadow: inset 0 -2px 0 var(--color-brand-primary);
}

.antumo-tab .badge {
    font-weight: 500;
}

/* Licznik zaznaczen na zakladce — jak w UTS przy rolach konta: ile rol jest wybranych
   widac bez wchodzenia na zakladke. */
.antumo-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.375rem;
    height: 1.375rem;
    padding: 0 0.375rem;
    border-radius: 999px;
    background-color: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs, 0.875rem);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.antumo-tab.active .antumo-tab-count {
    background-color: var(--color-btn-primary-bg);
    color: #fff;
}

/* ===== Prompt version history ===== */

.version-row {
    padding-top: var(--spacing-lg);
    padding-bottom: var(--spacing-lg);
}

/* Collapsed: two flowed lines. Newlines fold into spaces here, so the raw changelog can be
   rendered once and the expanded state only has to restore pre-wrap. */
.changelog-text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-width: 95ch;
    margin-top: var(--spacing-sm);
    color: var(--color-text-secondary);
    font-size: 13px;
    line-height: 1.5;
}

.changelog-text.expanded {
    display: block;
    max-width: none;
    max-height: 340px;
    overflow-y: auto;
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background-color: var(--color-grey-50);
    white-space: pre-wrap;
    font-family: 'Courier New', Monaco, monospace;
    font-size: 12px;
}

.antumo-card-body .table-responsive.mx-n4,
.antumo-card-body .list-group.mx-n4 {
    margin-left: calc(-1 * var(--card-padding, var(--spacing-3xl)));
    margin-right: calc(-1 * var(--card-padding, var(--spacing-3xl)));
}

.antumo-card-body .table-responsive.mb-n4,
.antumo-card-body .list-group.mb-n4 {
    margin-bottom: calc(-1 * var(--card-padding, var(--spacing-3xl)));
}

.antumo-card .list-group-item.active {
    background-color: var(--color-grey-100);
    border-color: var(--color-border-secondary);
    color: var(--color-text-primary);
}

.antumo-card .list-group-item.active .text-muted {
    color: var(--color-text-tertiary) !important;
}

/* ===== Ghost Button (icon only, no background) ===== */
.btn-ghost {
    background: transparent;
    border: none;
    color: var(--color-text-tertiary);
    padding: var(--spacing-xs);
    border-radius: var(--radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.btn-ghost:hover {
    background-color: var(--color-grey-100);
    color: var(--color-text-primary);
}

.btn-ghost:focus {
    box-shadow: var(--focus-ring);
}

.btn-ghost:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.dropdown-toggle-icon::after {
    display: none;
}

/* ===== Dropdown Menu Styling ===== */
.dropdown-menu {
    --bs-dropdown-bg: var(--color-bg-secondary);
    --bs-dropdown-border-color: var(--color-grey-200);
    --bs-dropdown-link-color: var(--color-text-primary);
    --bs-dropdown-link-hover-bg: var(--color-grey-50);
    --bs-dropdown-link-hover-color: var(--color-text-primary);
    --bs-dropdown-divider-bg: var(--color-grey-200);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-xs) 0;
    min-width: 160px;
}

.dropdown-item {
    padding: var(--spacing-md) var(--spacing-xl);
    font-family: var(--font-family-brand);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-book);
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.dropdown-item:active {
    background-color: var(--color-grey-100);
    color: var(--color-text-primary);
}

.dropdown-item.text-danger:hover {
    background-color: var(--color-red-50);
    color: var(--color-red-600);
}

.dropdown-divider {
    margin: var(--spacing-xs) 0;
}

/* ===== Antumo Table Styling ===== */
.table {
    --bs-table-bg: var(--color-bg-secondary);
    --bs-table-border-color: var(--color-grey-200);
    border-color: var(--color-grey-200);
    margin-bottom: 0;
}

.table > thead {
    background-color: var(--color-bg-secondary);
}

.table > thead > tr > th {
    background-color: var(--color-bg-secondary);
    border-bottom: 1px solid var(--color-grey-200);
    padding: var(--spacing-lg) var(--spacing-2xl);
    font-family: var(--font-family-brand);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--line-height-2xs);
    color: var(--color-grey-600);
    text-transform: none;
    letter-spacing: normal;
    vertical-align: middle;
}

.table > tbody > tr > td {
    padding: var(--spacing-xl) var(--spacing-2xl);
    font-family: var(--font-family-brand);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-book);
    line-height: var(--line-height-xs);
    color: var(--color-text-primary);
    border-bottom: 1px solid var(--color-grey-200);
    vertical-align: middle;
}

.table > tbody > tr:last-child > td {
    border-bottom: none;
}

.table-hover > tbody > tr:hover > td {
    --bs-table-hover-bg: var(--color-grey-50);
    background-color: var(--color-grey-50);
}

.table-light,
.table > thead.table-light > tr > th {
    --bs-table-bg: var(--color-grey-50);
    background-color: var(--color-grey-50);
}

/* Table inside Card - rounded corners */

/* Poziomy pasek przewijania, nie ucięcie: `overflow: hidden` zdejmowało z `.table-responsive`
   przewijanie Bootstrapa, więc tabela szersza od karty gubiła prawe kolumny bez śladu, że
   tam coś jest. Pion zostaje ucięty, bo tabela nie jest wyższa od swojego opakowania,
   a zaokrąglenie dolnych narożników karty ma nadal obcinać ostatni wiersz. */
.antumo-card .table-responsive {
    border-radius: 0 0 var(--radius-xl) var(--radius-xl);
    overflow-x: auto;
    overflow-y: hidden;
}

.antumo-card .table {
    border-radius: 0;
}

/* Nazwa wyjątku i ścieżka w kodzie to jeden wyraz bez spacji, a tabela nie zwęża się poniżej
   najdłuższego wyrazu w komórce — przy rozwiniętym pasku bocznym wypychało to kolumnę statusu
   za krawędź karty. `anywhere` (nie `break-word`) liczy się do najmniejszej szerokości
   komórki, więc dopiero ono pozwala tabeli zmieścić się w karcie. */
.antumo-card .table > tbody > tr > td {
    overflow-wrap: anywhere;
}

/* Tabele o krotkich wartosciach — konta, role, jezyki — wypisane bez lamania wyrazow.
   Zgoda na lamanie „gdziekolwiek" liczy sie do najmniejszej szerokosci komorki, wiec tabela
   o siedmiu kolumnach zwezala sie do szerokosci karty, ustawiajac kazde slowo po jednej
   literze na wiersz. Tutaj ma byc odwrotnie: tabela zostaje przy swojej szerokosci,
   a karta ja przewija. */
.antumo-card .table.table-plain > tbody > tr > td,
.antumo-card .table.table-plain > thead > tr > th {
    overflow-wrap: normal;
    white-space: nowrap;
}

/* Liczby i odznaki trzymają się w jednym wierszu — łamanie w środku pozycji z kolumny
   wyrównanej do prawej nie ma czego zmieścić, a rozbija linię bazową wiersza. */
.antumo-card .table > tbody > tr > td.text-end {
    overflow-wrap: normal;
    white-space: nowrap;
}

/* Dwa wiersze na tytuł zgłoszenia i dwa na miejsce w kodzie. Zgoda na łamanie w środku
   wyrazu pozwala tabeli się zwężać, ale ślad wyjątku ze stu znaków rozciągał wtedy wiersz
   na kilkanaście linijek i jedno zgłoszenie zajmowało całą kartę. Dalszy ciąg i tak jest
   w szczegółach zgłoszenia, a tu liczy się rozpoznanie wpisu. */
.issue-cell-title,
.issue-cell-culprit {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* First row header in card gets top corners */
.antumo-card .table > thead > tr:first-child > th:first-child {
    border-top-left-radius: 0;
}

.antumo-card .table > thead > tr:first-child > th:last-child {
    border-top-right-radius: 0;
}

/* Last row in card gets bottom corners */
.antumo-card .table > tbody > tr:last-child > td:first-child {
    border-bottom-left-radius: var(--radius-xl);
}

.antumo-card .table > tbody > tr:last-child > td:last-child {
    border-bottom-right-radius: var(--radius-xl);
}

/* ===== Antumo Modal Styling ===== */
.modal-content {
    background-color: var(--color-bg-secondary);
    border: none;
    border-radius: var(--radius-2xl);
    box-shadow: var(--shadow-xl);
}

.modal-header {
    padding: var(--spacing-3xl);
    padding-right: 64px;
    padding-bottom: var(--spacing-2xl);
    border-bottom: 1px solid var(--color-grey-200);
    position: relative;
}

.modal-header .modal-title {
    font-family: var(--font-family-brand);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    line-height: 1.25;
    color: var(--color-text-primary);
    margin: 0;
}

.modal-header .btn-close {
    position: absolute;
    top: var(--spacing-lg);
    right: var(--spacing-lg);
    width: 40px;
    height: 40px;
    padding: 0;
    margin: 0;
    border-radius: var(--radius-md);
    opacity: 1;
    background-size: 12px;
    transition: background-color 0.15s ease;
}

.modal-header .btn-close:hover {
    background-color: var(--color-grey-100);
}

.modal-header .btn-close:focus {
    box-shadow: var(--focus-ring);
}

.modal-body {
    padding: var(--spacing-3xl);
    font-family: var(--font-family-brand);
    font-size: var(--font-size-xs);
    line-height: 1.5;
    color: var(--color-text-primary);
}

.modal-footer {
    padding: var(--spacing-3xl);
    border-top: 1px solid var(--color-grey-200);
    gap: var(--spacing-lg);
    justify-content: flex-end;
}

.modal-footer .btn {
    border-radius: var(--radius-full);
    min-height: 40px;
    padding-left: var(--spacing-xl);
    padding-right: var(--spacing-xl);
}

.modal-backdrop.show {
    opacity: 0.5;
}

.modal-dialog-scrollable .modal-body {
    overflow-y: auto;
}

.modal-lg {
    --bs-modal-width: 640px;
}

.modal-xl {
    --bs-modal-width: 1000px;
}

/* ===== Badge with Icon Fix ===== */
/* Vertically center icons inside badges */
.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs, 4px);
}

.badge svg {
    flex-shrink: 0;
}

.changelog-cell {
    white-space: pre-wrap;
    font-size: var(--font-size-2xs);
    color: var(--color-text-secondary);
    max-width: 400px;
}

/* ===== Antumo Loading Spinner ===== */
/* Based on Figma: https://www.figma.com/design/aKIP8PcGfbAMKAZNhEbDOZ/?node-id=567-60681 */

.loading-spinner {
    display: inline-block;
    vertical-align: middle;
}

/* Track (background circle) - 20% opacity of spinner color */
.loading-spinner__track {
    opacity: 0.2;
}

/* Spinner (animated arc) */
.loading-spinner__spinner {
    transform-origin: center;
    animation: loading-spinner-rotate 1s linear infinite;
}

/* Rotation animation */
@keyframes loading-spinner-rotate {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

/* Color variants */
.loading-spinner--brand {
    color: var(--color-navy-600);
}

.loading-spinner--error {
    color: var(--color-red-700);
}

.loading-spinner--inverted {
    color: var(--color-white);
}

/* ===== Blazor Reconnect Modal ===== */
#components-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10000;
    background-color: rgba(10, 13, 18, 0.6);
    backdrop-filter: blur(4px);
    align-items: center;
    justify-content: center;
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.reconnect-modal-content {
    background-color: var(--color-bg-secondary);
    border-radius: var(--radius-2xl);
    box-shadow: var(--shadow-xl);
    padding: var(--spacing-5xl);
    max-width: 400px;
    width: 90%;
    text-align: center;
    animation: modalFadeIn 0.2s ease-out;
}

@keyframes modalFadeIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

.reconnect-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80px;
    height: 80px;
    margin: 0 auto var(--spacing-3xl);
    background-color: var(--color-yellow-100);
    border-radius: var(--radius-full);
    color: var(--color-yellow-600);
}

#components-reconnect-modal.components-reconnect-show .reconnect-icon svg {
    animation: spin 1.5s linear infinite;
}

@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

#components-reconnect-modal.components-reconnect-failed .reconnect-icon,
#components-reconnect-modal.components-reconnect-rejected .reconnect-icon {
    background-color: var(--color-red-100);
    color: var(--color-red-600);
}

.reconnect-title {
    font-family: var(--heading-md-font-family);
    font-size: var(--heading-md-font-size);
    font-weight: var(--heading-md-font-weight);
    line-height: var(--heading-md-line-height);
    color: var(--color-text-primary);
    margin: 0 0 var(--spacing-md);
}

.reconnect-message {
    font-family: var(--body-md-font-family);
    font-size: var(--body-md-font-size);
    font-weight: var(--body-md-font-weight);
    line-height: var(--body-md-line-height);
    color: var(--color-text-secondary);
    margin: 0 0 var(--spacing-3xl);
}

.btn-reconnect {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    min-width: 160px;
    padding: var(--spacing-lg) var(--spacing-3xl);
    background-color: var(--color-btn-primary-bg);
    color: var(--color-btn-primary-text);
    border: none;
    border-radius: var(--radius-full);
    font-family: var(--button-md-font-family);
    font-size: var(--button-md-font-size);
    font-weight: var(--button-md-font-weight);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.btn-reconnect:hover {
    background-color: var(--color-btn-primary-bg-hover);
}

.btn-reconnect:focus {
    outline: none;
    box-shadow: var(--focus-ring);
}

.reconnect-hint {
    font-family: var(--body-sm-font-family);
    font-size: var(--body-sm-font-size);
    color: var(--color-text-tertiary);
    margin: var(--spacing-xl) 0 0;
}

.reconnect-hint a {
    color: var(--color-interactive-primary);
    text-decoration: none;
}

.reconnect-hint a:hover {
    text-decoration: underline;
}

/* ========================================
   Tooltip (Antumo)
   ======================================== */

.antumo-tooltip-wrap {
    position: relative;
    display: inline-flex;
}

.antumo-tooltip {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 1000;
    min-width: 180px;
    max-width: 320px;
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--color-text-primary, #181D27);
    color: #fff;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    font-size: var(--body-sm-font-size, 0.8125rem);
    line-height: 1.4;
    white-space: normal;
    pointer-events: none;
}

.antumo-tooltip::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--color-text-primary, #181D27);
}

.antumo-tooltip-wrap:hover .antumo-tooltip {
    display: block;
}

.antumo-tooltip-line {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-xs);
    padding: var(--spacing-xxs) 0;
}

.antumo-tooltip-line + .antumo-tooltip-line {
    border-top: 1px solid rgba(255, 255, 255, 0.15);
}

/* ========================================
   Transcript List Cards
   ======================================== */

.transcript-search {
    position: relative;
    flex: 1;
    max-width: 320px;
}

.transcript-search input {
    padding-left: calc(var(--spacing-xl) + 16px);
}

.transcript-search-icon {
    position: absolute;
    left: var(--spacing-lg);
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-tertiary);
    pointer-events: none;
}

.transcript-card-header {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    width: 100%;
}

.transcript-card-top {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-lg);
}

.transcript-card-meta {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-lg);
    flex: 1;
    min-width: 0;
    flex-wrap: wrap;
}

.transcript-card-date {
    white-space: nowrap;
    color: var(--color-text-primary);
    font-size: var(--font-size-xs);
}

.transcript-card-badges {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-xs);
    flex-wrap: wrap;
}

.transcript-card-subline {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-lg);
}

.transcript-card-time {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    font-size: var(--font-size-xs);
    color: var(--color-text-tertiary);
    white-space: nowrap;
}

.transcript-card-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--spacing-xs);
    flex-shrink: 0;
}

.transcript-card-actions .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    white-space: nowrap;
}

@media (max-width: 992px) {
    .transcript-card-top {
        flex-direction: column;
        align-items: flex-start;
    }
}

@media (max-width: 576px) {
    .transcript-card-meta {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--spacing-xs);
    }

    .transcript-card-actions {
        width: 100%;
    }

    .transcript-card-actions .btn {
        flex: 1;
        justify-content: center;
    }

    .transcript-card-subline {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--spacing-xs);
    }
}

.transcript-callid {
    font-size: var(--body-sm-font-size);
    color: var(--color-text-tertiary);
    background: var(--color-bg-tertiary, rgba(0, 0, 0, 0.04));
    padding: 1px var(--spacing-xs);
    border-radius: var(--radius-sm);
    word-break: break-all;
    cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.transcript-callid:hover {
    color: var(--color-interactive-primary);
    background: var(--color-blue-50, rgba(46, 144, 250, 0.08));
}

.transcript-callid-copy {
    opacity: 0;
    transition: opacity 0.15s ease;
    vertical-align: middle;
}

.transcript-callid:hover .transcript-callid-copy {
    opacity: 1;
}

.transcript-preview {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    cursor: pointer;
    opacity: 0.8;
    transition: opacity 0.15s ease;
}

.transcript-preview:hover {
    opacity: 1;
}

.preview-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.preview-row.ai {
    flex-direction: row-reverse;
    justify-content: flex-start;
    margin-left: auto;
}

.preview-avatar {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: var(--radius-full, 9999px);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
}

.preview-row.caller .preview-avatar {
    background: var(--color-blue-500, #2E90FA);
}

.preview-row.ai .preview-avatar {
    background: var(--color-navy-500, #3A3A66);
}

.preview-bubble {
    font-size: var(--body-sm-font-size, 0.8125rem);
    line-height: 1.4;
    padding: var(--spacing-xs) var(--spacing-md);
    border-radius: var(--radius-md, 8px);
    max-width: 90%;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.preview-bubble p {
    margin: 0;
}

.preview-bubble p + p {
    margin-top: 0.2em;
}

.preview-bubble h1,
.preview-bubble h2,
.preview-bubble h3,
.preview-bubble h4,
.preview-bubble h5,
.preview-bubble h6 {
    font-size: inherit;
    font-weight: 600;
    margin: 0;
    line-height: inherit;
}

.preview-bubble ul,
.preview-bubble ol {
    margin: 0;
    padding-left: 1em;
}

.preview-bubble pre,
.preview-bubble code {
    font-size: inherit;
}

.preview-row.caller .preview-bubble {
    background-color: var(--color-blue-50);
    border: 1px solid var(--color-blue-200);
    color: var(--color-text-primary);
}

.preview-row.ai .preview-bubble {
    background-color: var(--color-navy-50);
    border: 1px solid var(--color-navy-200);
    color: var(--color-text-primary);
}

.transcript-preview-more {
    font-size: var(--body-sm-font-size);
    font-style: italic;
    padding-left: calc(18px + var(--spacing-sm));
    color: var(--color-text-tertiary);
}


/* ---------------------------------------------------------------------------
   Kafle liczbowe na przeglądzie
   --------------------------------------------------------------------------- */

/* Nagłówek karty z liczbą, 1:1 z kartami przeglądu w UTS (Figma „_Card progress"):
   16 na 20, grubo, w kolorze marki — granat na jasnym tle, jaśniejszy granat w ciemnym.
   Bez kapitalików: wersalikami czytało się jak podpis techniczny, a to jest nazwa. */
.metric-label {
    font-family: var(--font-family-brand);
    font-size: var(--font-size-sm, 1rem);
    font-weight: var(--font-weight-bold, 700);
    line-height: var(--line-height-xs, 1.25rem);
    letter-spacing: -0.01em;
    color: var(--color-text-brand, var(--color-navy-500));
}

.metric-value {
    font-family: var(--font-family-brand);
    font-size: var(--font-size-display-xs, 1.75rem);
    font-weight: var(--font-weight-bold, 700);
    line-height: 1.2;
    color: var(--color-text-primary, var(--color-grey-900));
    font-variant-numeric: tabular-nums;
}

.metric-hint {
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, var(--color-grey-500));
}

/* Kreska udziału pod liczbą, 1:1 z kartami przeglądu w UTS: osiem pikseli wysokości,
   zaokrąglona, tor w odcieniu warstwy podniesionej. Wypełnienia leżą obok siebie, więc
   jeden kafel może pokazać podział całości na dwie części. */
.metric-bar {
    display: flex;
    height: 8px;
    overflow: hidden;
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary, #f5f5f5);
}

.metric-bar-fill {
    height: 100%;
}

/* Kolor marki w wersji „solid", nie tło paska bocznego: to drugie w ciemnym motywie jest
   prawie czarne, więc kreska ginęła na karcie. */
.metric-bar-fill.is-brand {
    background: var(--color-interactive-primary, #3a3a66);
}

.metric-bar-fill.is-danger {
    background: var(--color-red-500, #d14c4c);
}

.metric-bar-fill.is-success {
    background: var(--color-green-500, #2fa46f);
}

/* Kreska ląduje na dole kafla, żeby wszystkie cztery miały ją w jednej linii niezależnie
   od tego, ile wierszy zajął nagłówek. Odstęp nad kreską trzyma ją przy dnie także wtedy,
   gdy kafel jest wyższy od swojej treści. */
.antumo-card-body:has(.metric-bar) {
    display: flex;
    height: 100%;
    flex-direction: column;
}

.antumo-card-body:has(.metric-bar) .metric-bar {
    margin-top: auto;
    padding-top: 0;
}

.antumo-card-body:has(.metric-bar) .metric-hint {
    margin-bottom: var(--spacing-xl, 1rem);
}

/* ---------------------------------------------------------------------------
   Zgłoszenia — układ master–detail
   --------------------------------------------------------------------------- */

.issue-workspace {
    display: grid;
    grid-template-columns: 380px minmax(0, 1fr) 300px;
    gap: var(--spacing-lg, 1rem);
    align-items: start;
}

/* Każda kolumna przewija się u siebie, nie razem z całą stroną. Wspólny pasek strony
   znaczył, że szukanie czegoś w środku zgłoszenia zabierało z widoku listę, po której się
   do tego zgłoszenia doszło, a stronicowanie pod listą dało się zobaczyć tylko po
   wyprowadzeniu kursora poza treść i przewinięciu całości — wtedy z kolei znikał nagłówek
   zgłoszenia, które się właśnie czyta.

   Pasek jest widoczny, ale cienki i wygaszony (reguły na górze arkusza) — po tym, że
   kolumna ma dalszą część, widać samą kreską przy jej krawędzi. Przy paskach ukrytych
   w ogóle nie było tego widać, a przy paskach systemowych trzy kolumny obok siebie
   wyglądały jak okno w oknie w oknie.

   Zatrzymanie na końcu kolumny jest tu istotne: bez niego dojechanie do dna logów
   pociąga za sobą stronę. */
.issue-workspace > * {
    overflow-y: auto;
    overscroll-behavior: contain;

    /* Miejsce na pasek zajęte na stałe: bez tego treść kolumny przeskakuje o dziesięć
       pikseli w bok za każdym razem, gdy pasek dochodzi albo znika — a znika przy każdym
       krótszym zgłoszeniu i po każdym zawężeniu listy filtrem. */
    scrollbar-gutter: stable;
}

/* Układ na całą wysokość okna tylko wtedy, gdy trzy kolumny stoją w jednym rzędzie.
   Poniżej tej szerokości trzecia kolumna schodzi do drugiego rzędu (patrz zapytanie
   kontenera niżej), a rzędy dzieliłyby wysokość okna na pół — lista miałaby wtedy dwie
   pozycje i własny pasek. Progu nie da się wyrazić zapytaniem kontenera, bo warunek
   dotyczy `main`, czyli przodka kontenera: 1200 pikseli kolumny treści to okno szersze
   o pasek boczny i marginesy, w zaokrągleniu w górę 1560.

   Selektor patrzy na zawartość, nie na adres: układ jest wspólny dla wszystkich stron,
   a tylko ta jedna ma się zachowywać jak okno z panelami. Wyższa waga przez `.page`,
   bo arkusz układu wchodzi po tym i ustawia `main` na przewijanie. */
@media (min-width: 1560px) {
    .page main:has(.issue-workspace) {
        overflow: hidden;
    }

    .page main:has(.issue-workspace) > .content {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    .content:has(.issue-workspace) .issue-workspace {
        flex: 1 1 auto;
        min-height: 0;
    }

    .issue-workspace > * {
        height: 100%;
        min-height: 0;
    }
}

/* Węższe okno: strona przewija się jak zwykle, a kolumny pinują się pod filtrami, żeby
   nie uciekały z widoku przy dłuższym zgłoszeniu. */
@media (max-width: 1559.98px) {
    .issue-workspace > * {
        position: sticky;
        top: var(--spacing-lg, 1rem);
        max-height: calc(100dvh - 2 * var(--spacing-lg, 1rem));
    }
}

/* Kolumna z listą: karta trzyma wysokość, przewija się sama lista, a pasek stron zostaje
   na dole w zasięgu wzroku — po to jest, żeby było widać, że lista ma dalszą część. */
.issue-workspace > .antumo-card {
    display: flex;
    flex-direction: column;
    overflow: hidden;

    /* Bez zapasu na pasek: karta się nie przewija, przewija się lista w środku. Zapas
       z reguły wspólnej dla kolumn zabierałby jej dziesięć pikseli szerokości dodatkowo
       do tych, które lista rezerwuje u siebie — pozycje kończyłyby się dwa paski przed
       krawędzią karty. */
    scrollbar-gutter: auto;
}

.issue-workspace > .antumo-card > .antumo-card-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.issue-workspace > .antumo-card .issue-rail {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

.issue-rail-pager {
    flex: 0 0 auto;
}

/* Zapowiedź nowych zgłoszeń nad listą — jak pasek „nowa wiadomość" w skrzynce.
   Kliknięcie wraca na pierwszą stronę i pokazuje je; do tego czasu nic się nie rusza,
   bo czytający stoi na dalszej stronie i podmiana wierszy byłaby dla niego zaskoczeniem. */
.issue-rail-new {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm, 6px);
    width: 100%;
    margin-bottom: var(--spacing-md, 8px);
    padding: var(--spacing-sm, 6px) var(--spacing-lg, 12px);
    border: 1px solid var(--color-border-brand, var(--color-navy-500));
    border-radius: var(--radius-md, 8px);
    background-color: color-mix(in srgb, var(--color-bg-brand, #3A3A66) 8%, transparent);
    color: var(--color-text-brand, var(--color-navy-500));
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.15s ease-in-out;
}

.issue-rail-new:hover {
    background-color: color-mix(in srgb, var(--color-bg-brand, #3A3A66) 16%, transparent);
}

@container content (max-width: 1200px) {
    .issue-workspace {
        grid-template-columns: 360px minmax(0, 1fr);
    }

    .issue-workspace > .issue-actions {
        grid-column: 1 / -1;
    }

    /* Tu układ przestaje być rzędem paneli obok siebie: akcje schodzą do drugiego rzędu na
       całą szerokość. Przypięcie i własne przewijanie mają sens tylko wtedy, gdy panele stoją
       obok siebie i każdy zajmuje całą wysokość okna. W dwóch rzędach panele przypięte do
       górnej krawędzi zostają w miejscu, a rząd pod nimi wjeżdża na nie przy przewijaniu —
       widać to jako akcje i scalanie malowane na liście i na szczegółach zgłoszenia.

       Właśnie w to wpada powiększenie strony powyżej 100%: kolumna treści schodzi wtedy
       poniżej 1200 pikseli. Poniżej tej szerokości przewija się cała strona, a panele mają
       wysokość swojej treści. */
    .issue-workspace > * {
        position: static;
        max-height: none;
        overflow-y: visible;
    }
}

@container content (max-width: 740px) {
    .issue-workspace {
        grid-template-columns: minmax(0, 1fr);
    }
}

.issue-rail {

    /* Na boki lista sięga krawędzi karty — inaczej tło zaznaczonej pozycji kończyłoby się
       w powietrzu. W pionie już nie: u góry ma zostać odstęp od liczby zgłoszeń, u dołu od
       paska stron. Ujemny margines dolny wciągał pasek na listę i „Na stronie" stało na
       ostatniej pozycji; górny sklejał pierwszą pozycję z nagłówkiem karty. */
    margin: 0 calc(-1 * var(--card-padding, var(--spacing-3xl, 1.5rem)));
    overflow: hidden auto;
    border-bottom-left-radius: var(--radius-lg, 12px);
    border-bottom-right-radius: var(--radius-lg, 12px);
}













.issue-rail-title {
    font-weight: var(--font-weight-bold, 700);
    font-size: var(--font-size-sm, 0.875rem);
    line-height: 1.35;
    overflow-wrap: anywhere;

    /* Najwyżej trzy wiersze, dalej wielokropek: nazwa klasy z pełną ścieżką pakietu
       zajęłaby na liście tyle miejsca, że zmieściłoby się na niej kilka pozycji mniej.
       Pełny tytuł zostaje w podpowiedzi i w panelu szczegółów. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

.issue-rail-culprit {
    font-family: var(--font-family-mono, ui-monospace, monospace);
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.issue-rail-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.5rem;
    align-items: center;
    margin-top: 0.375rem;
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
}

/* „1 urz." złamane na dwa wiersze wygląda jak błąd — członów nie dzielimy,
   łamie się dopiero cały wiersz metryczki. */
.issue-rail-meta > * {
    white-space: nowrap;
}

/* Metryczka zdarzenia: ikona plus para etykieta/wartość, dwie kolumny. */
.issue-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.875rem 1.5rem;
}

@media (max-width: 576px) {
    .issue-facts {
        grid-template-columns: minmax(0, 1fr);
    }
}

.issue-fact {
    display: flex;
    gap: 0.625rem;
    align-items: flex-start;
    min-width: 0;
}

.issue-fact-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-md, 8px);
    border: 1px solid var(--color-border-secondary, #E9EAEB);
    color: var(--color-text-tertiary, #717680);
}

.issue-fact-label {
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
}

.issue-fact-value {
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: var(--font-weight-medium, 500);
    overflow-wrap: anywhere;
}

/* Ślad kroków: pionowa linia z kropkami, żeby kolejność czytała się od razu. */
.issue-timeline {
    list-style: none;
    margin: 0;
    padding: 0 0 0 1rem;
    border-left: 1px solid var(--color-border-secondary, #E9EAEB);

    /* Bufor w SDK trzyma sto kroków — tyle wpisów nie ma rozciągać karty. Przewija ten,
       kto listę osadza; sama lista rośnie tyle, ile ma wpisów. Własne ograniczenie zostawało
       też w oknie pełnowymiarowym i ucinało listę w połowie jego wysokości. */
}

.issue-timeline li {
    position: relative;
    padding-bottom: 0.625rem;
    font-size: var(--font-size-sm, 0.875rem);

    /* Ścieżki ekranów i adresy żądań idą bez spacji — bez tego rozpychają kartę. */
    overflow-wrap: anywhere;
}

.issue-timeline li:last-child {
    padding-bottom: 0;
}

.issue-timeline li::before {
    content: "";
    position: absolute;
    left: -1.3125rem;
    top: 0.4375rem;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--color-grey-300, #D5D7DA);
}

.issue-timeline .issue-timeline-at {
    font-family: var(--font-family-mono, ui-monospace, monospace);
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
    margin-right: 0.5rem;
}

.issue-timeline .issue-timeline-type {
    font-size: var(--font-size-xs, 0.75rem);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-tertiary, #717680);
    margin-right: 0.5rem;
}

/* ---------------------------------------------------------------------------
   Logi zdarzenia
   --------------------------------------------------------------------------- */

.logs-tools {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 0.625rem);
}

.logs-search {
    width: 15rem;
    min-width: 8rem;
}

/* Stała wysokość, nie „maksymalna": zrzut z warstwy natywnej ma i tysiąc wierszy, a bez
   ograniczenia rozpycha stronę tak, że wszystko pod nim — kroki, rozmowa, komentarze —
   przestaje być osiągalne bez bezmyślnego przewijania. Wewnątrz przewija się w obu
   osiach, bo wiersze zrzutu bywają dłuższe niż karta. */
.logs-viewport {
    height: 26rem;
    overflow: auto;

    /* Odcień z palety, nie `--color-bg-secondary`: ten w jasnym motywie jest biały, więc
       blok logu zlewał się z kartą i przestawał czytać się jak wydruk. Kolor tekstu też
       z tokenu — blok ma swoje tło, więc musi też mieć swój kolor pisma. */
    background: var(--color-bg-tertiary, #FAFAFA);
    color: var(--color-text-primary, #181D27);
    border: 1px solid var(--color-border-secondary, #E9EAEB);
    border-radius: var(--radius-md, 8px);
}

/* Warunki zawężania nad wydrukiem w oknie: zawijają się na wąskim ekranie, a licznik
   i kopiowanie odchodzą na prawo. */
.logs-dialog-tools {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 12px);
    flex-wrap: wrap;
    flex: 0 0 auto;
}

.logs-dialog-search {
    width: 20rem;
    min-width: 10rem;
}

.logs-dialog-tools .text-secondary {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

/* Wydruk bierze całą wysokość, jaka zostaje w oknie, i przewija się w obu osiach —
   wiersze stosu bywają dłuższe niż okno. */
.logs-dialog-viewport {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    background: var(--color-bg-tertiary, #FAFAFA);
    color: var(--color-text-primary, #181D27);
    border: 1px solid var(--color-border-secondary, #E9EAEB);
    border-radius: var(--radius-md, 8px);
}

/* Wiersz z trafieniem: znacznik przy krawędzi i ledwie widoczne tło.
   Wcześniej cały wiersz dostawał kolor marki na szesnastu procentach — przy jasnym piśmie
   wydruku wychodziła z tego płachta, na której gorzej się czytało niż bez podświetlenia,
   a przy wierszu na kilkaset znaków i tak nie było widać, gdzie jest szukana fraza. */
.logs .logs-hit > td {
    background-color: color-mix(in srgb, var(--color-btn-primary-bg) 8%, transparent);
}

.logs .logs-hit > .logs-number {
    box-shadow: inset 3px 0 0 var(--color-btn-primary-bg);
}

/* Samo dopasowanie: pełny kolor marki i pismo na nim białe w obu motywach — to jedyne
   miejsce w wydruku, które ma ciągnąć wzrok. */
.logs-mark {
    padding: 0;
    border-radius: 2px;
    background-color: var(--color-btn-primary-bg);
    color: #fff;
    font-weight: 600;
}

/* Zawijanie na życzenie: domyślnie wiersz zostaje jednym wierszem, żeby numeracja
   po lewej odpowiadała temu, co widać. */
.logs.logs-wrap .logs-text {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.logs {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    font-family: 'Courier New', Monaco, monospace;
    font-size: var(--font-size-xs, 0.75rem);
    line-height: 1.6;
}

.logs td {
    padding: 0 0.5rem;
    vertical-align: top;
}

/* Numer wiersza zostaje przy krawędzi przy przewijaniu w poziomie i nie daje się zaznaczyć,
   żeby skopiowany fragment logu nie niósł numeracji panelu. */
.logs-number {
    position: sticky;
    left: 0;
    width: 1%;
    text-align: right;
    user-select: none;
    color: var(--color-text-quaternary, #717680);
    background: var(--color-bg-tertiary, #FAFAFA);
    border-right: 1px solid var(--color-border-secondary, #E9EAEB);
    font-variant-numeric: tabular-nums;
}

.logs-text {
    white-space: pre;
}

@container content (max-width: 900px) {
    .logs-search {
        width: 10rem;
    }
}

/* ---------------------------------------------------------------------------
   Rozmowa ze zgłaszającym
   --------------------------------------------------------------------------- */

.chat-thread {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    max-height: 26rem;
    overflow-y: auto;
    padding: 0.25rem;
}

.chat-message {
    max-width: 82%;
    flex: 0 1 auto;
    padding: 0.625rem 0.875rem;
    border-radius: var(--radius-lg, 12px);
    font-size: var(--font-size-sm, 0.875rem);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.chat-message-from-user {
    background: var(--color-bg-secondary, #FAFAFA);
    border: 1px solid var(--color-border-secondary, #E9EAEB);
    border-bottom-left-radius: var(--radius-xs, 4px);
}

.chat-message-from-support {
    background: var(--color-navy-500, #32355A);
    color: #FFFFFF;
    border-bottom-right-radius: var(--radius-xs, 4px);
}

.chat-message-meta {
    font-size: var(--font-size-xs, 0.75rem);
    opacity: 0.7;
    margin-top: 0.25rem;
}

/* Ostrzeżenie, że to nie notatka wewnętrzna — pomyłka tutaj idzie prosto na kasę. */
.chat-notice {
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
}

.chat-unread {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.125rem;
    height: 1.125rem;
    /* Piksel u góry: przy `line-height: 1` cyfry stoją minimalnie nad środkiem pigułki. */
    padding: 0.0625rem 0.25rem 0;
    border-radius: 9999px;
    background: #923434;
    color: #FFFFFF;
    font-size: 0.625rem;
    font-weight: var(--font-weight-bold, 700);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.issue-rail-meta .chat-unread {
    min-width: 1rem;
    height: 1rem;
    font-size: 0.5625rem;
}

/* ---------------------------------------------------------------------------
   Lista zgłoszeń — zaznaczenie
   --------------------------------------------------------------------------- */

/* Lista jest gęsta: pozycje stykają się i rozdziela je włoskowa kreska, a kolorowa
   kreska statusu idzie przez całą wysokość przy lewej krawędzi. Zaznaczona pozycja bierze
   całe tło w kolorze nawigacji — odstępy między pozycjami rozrzedzały listę, a delikatne
   podświetlenie ginęło. Kreska statusu przechodzi wtedy w jaśniejszy odcień, bo w bazowym
   zniknęłaby w granacie. */

.issue-rail-item {
    position: relative;
    display: block;
    padding: 0.75rem 0.875rem 0.75rem 1.125rem;
    border-bottom: 1px solid var(--color-border-secondary, #E9EAEB);
    text-decoration: none;
    color: inherit;
    transition: background-color 120ms ease, color 120ms ease;
}

.issue-rail-item:last-child {
    border-bottom: 0;
}

.issue-rail-item:hover {
    background: var(--color-bg-secondary, #FAFAFA);
}

.issue-rail-item.is-selected {
    background: var(--color-navy-500, #32355A);
    color: #FFFFFF;

    /* Miejsce na grot, żeby nie wchodził na tekst. */
    padding-right: 1.5rem;
}

.issue-rail-item.is-selected .issue-rail-culprit,
.issue-rail-item.is-selected .issue-rail-meta {
    color: rgba(255, 255, 255, 0.72);
}

.issue-rail-item.is-selected .badge {
    background-color: rgba(255, 255, 255, 0.16) !important;
    border-color: rgba(255, 255, 255, 0.24);
    color: #FFFFFF !important;
}

/* Grot przy prawej krawędzi: pokazuje, do której pozycji należy panel obok. W środku
   pozycji, nie za jej krawędzią — lista jest kontenerem przewijanym, więc wystający
   element dokładałby jej poziomy pasek przewijania. */
.issue-rail-item.is-selected::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 0.5rem;
    width: 0.4375rem;
    height: 0.4375rem;
    transform: translateY(-50%) rotate(45deg);
    border-top: 2px solid rgba(255, 255, 255, 0.85);
    border-right: 2px solid rgba(255, 255, 255, 0.85);
}

@container content (max-width: 1200px) {
    .issue-rail-item.is-selected::after {
        display: none;
    }
}

/* Tekst plakietki stał przy górnej krawędzi pigułki: metryka CircularXX z
   `line-height: 1` Bootstrapa zostawia cały luz pod literami. Wysokość liczona
   z wiersza tekstu, żeby pigułka nie była wyższa od tego, co w niej stoi. */
.badge {
    justify-content: center;
    align-items: center;
    line-height: 1;
    padding: 0.3125rem 0.5rem 0.25rem;
    white-space: nowrap;
}

/* Kreska statusu. Pseudoelement, nie `border-left`: przy zaokrąglonym narożniku
   obramowanie oblewa cały róg, a kreska ma stać pionowo i nie dotykać krawędzi. */
.issue-rail-item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: var(--issue-stripe, transparent);
}

.issue-rail-item.is-selected::before {
    background: var(--issue-stripe-inverted, rgba(255, 255, 255, 0.8));
}

.issue-rail-item[data-status="New"] {
    --issue-stripe: #6E70A8;
    --issue-stripe-inverted: #C9CAE8;
}

.issue-rail-item[data-status="InProgress"] {
    --issue-stripe: #4A90B8;
    --issue-stripe-inverted: #9FD0E8;
}

.issue-rail-item[data-status="Regressed"] {
    --issue-stripe: #923434;
    --issue-stripe-inverted: #E39B9B;
}

.issue-rail-item[data-status="Resolved"] {
    --issue-stripe: #3E7C4A;
    --issue-stripe-inverted: #A5D3AE;
}

.issue-rail-item[data-status="Ignored"] {
    --issue-stripe: #98A2B3;
    --issue-stripe-inverted: #D5D7DA;
}

/* ---------------------------------------------------------------------------
   Długie nazwy bez spacji
   --------------------------------------------------------------------------- */

/* Nazwa klasy, ścieżka pakietu Darta albo adres HTTP nie mają miejsca, w którym
   przeglądarka może złamać wiersz. Bez tego tytuł zgłoszenia rozpycha kartę
   i cała kolumna szczegółów wychodzi poza układ. */
.antumo-card-title,
.page-header-title,
.issue-culprit,
.issue-comment-body {
    overflow-wrap: anywhere;
    min-width: 0;
}

/* Nagłówek karty ma dwie części: lewa może się skracać, prawa trzyma znaczniki i odnośniki. */
.antumo-card-header-right {
    min-width: 0;
}

/* Rzędy kart w kolumnie szczegółów.
   Siatka, nie bootstrapowy `row`: ten ma ujemne marginesy na rynny, więc wystaje o 6 px
   poza karty nad i pod sobą i nic w tej kolumnie nie trzyma jednej linii. */
.issue-panels {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--spacing-lg, 1rem);
}

/* Odcisk łamie się w dowolnym miejscu, zamiast dokładać panelowi paska przewijania
   dla trzydziestu dwóch znaków. */
.issue-fingerprint {
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   Awatary
   --------------------------------------------------------------------------- */

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 9999px;
    font-family: var(--font-family-brand);
    font-size: 0.6875rem;
    font-weight: var(--font-weight-bold, 700);
    letter-spacing: 0.02em;
    user-select: none;
}

.avatar-sm {
    width: 1.5rem;
    height: 1.5rem;
    font-size: 0.5625rem;
}

/* Zdjęcie profilowe w miejscu inicjałów. Przycięte do kółka i wypełniające je bez
   rozciągania, bo wgrywają się zdjęcia w dowolnych proporcjach. */
.avatar-photo {
    object-fit: cover;
    background: var(--color-bg-tertiary);
}

/* Duży awatar na ekranie zdjęcia profilowego — tam chodzi o to, żeby zobaczyć, co się wgrało. */
.avatar-xl {
    width: 5rem;
    height: 5rem;
    font-size: 1.75rem;
}

/* ---------------------------------------------------------------------------
   Uprawnienia w formularzu roli
   ---------------------------------------------------------------------------
   Grupy jedna pod drugą, w środku pozycje z opisem: opis jest tu potrzebny, bo z samej
   nazwy uprawnienia nie wynika, co dokładnie odblokowuje — a rola nadana na oko jest
   gorsza od jej braku. */
.permission-group {
    padding: var(--spacing-lg, 12px) 0;
    border-top: 1px solid var(--color-border-secondary);
}

.permission-group:first-of-type {
    border-top: none;
    padding-top: 0;
}

.permission-group-name {
    font-family: var(--font-family-brand);
    font-size: var(--font-size-2xs, 0.75rem);
    font-weight: var(--font-weight-medium, 500);
    color: var(--color-text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: var(--spacing-md, 8px);
}

/* Wypełnienie z lewej zostaje bootstrapowe (1,5 em): kwadrat zaznaczenia jest w tym układzie
   przesunięty ujemnym marginesem w lewo i bez tego miejsca wychodził poza pozycję — a lista
   uprawnień przewija się u siebie, więc przycinała go zupełnie. Nie było widać, że jest co
   zaznaczyć. */
.permission-item {
    padding: var(--spacing-xs, 4px) 0 var(--spacing-xs, 4px) 1.75em;
}

.permission-item .form-check-label {
    cursor: pointer;
}

/* Odcienie z palety Antumo, przygaszone: awatar ma pomagać odróżnić autorów,
   a nie przeciągać wzroku z treści komentarza. */
.avatar-tone-0 { background: #E5E5F0; color: #32355A; }
.avatar-tone-1 { background: #DCEAF3; color: #2C5A73; }
.avatar-tone-2 { background: #E7F0E4; color: #3E7C4A; }
.avatar-tone-3 { background: #F5E6E6; color: #923434; }
.avatar-tone-4 { background: #F3EDE0; color: #7A6320; }
.avatar-tone-5 { background: #EAE4F2; color: #574378; }

.issue-comment {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
}

.issue-comment-author {
    font-weight: var(--font-weight-medium, 500);
}

/* Wiadomość w rozmowie razem z awatarem: strona urządzenia po lewej, panelu po prawej. */
.chat-row {
    display: flex;
    gap: 0.5rem;
    align-items: flex-end;
    max-width: 92%;
}

.chat-row-from-user {
    align-self: flex-start;
}

.chat-row-from-support {
    align-self: flex-end;
    flex-direction: row-reverse;
}

.chat-row .chat-message {
    max-width: none;
}

/* ---------------------------------------------------------------------------
   Alerty na przeglądzie
   --------------------------------------------------------------------------- */

/* Wiersze alertów w tabeli, tak jak dwie sekcje obok: rodzaj, treść i czas zapalenia.
   Kolumna rodzaju i czasu bierze tylko swoją szerokość, treść zajmuje resztę — inaczej
   czas nie stanąłby przy krawędzi karty. */
.alert-row-kind,
.alert-row-when {
    width: 1%;
    white-space: nowrap;
}

.alert-row-message {
    font-size: var(--font-size-sm, 0.875rem);
    overflow-wrap: anywhere;
}

.alert-row-when {
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-tertiary, #717680);
    font-variant-numeric: tabular-nums;
}

/* Karta alertów na całą szerokość kolumny treści, jak wiersze kart nad nią. Ograniczenie
   do 64 rem zostawiało po prawej pustą kolumnę i dół przeglądu wyglądał na rozjechany. */
.alert-card {
    width: 100%;
}

/* Plakietka z tagiem, w odróżnieniu od statusu, niesie dowolny tekst — bywa nim jedno
   długie słowo z myślnikami. Bez łamania wyjeżdżało poza panel i dokładało całej stronie
   poziomy pasek przewijania. */
.badge-tag {
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: left;
    justify-content: flex-start;
}

/* ---------------------------------------------------------------------------
   Ekran alertów
   --------------------------------------------------------------------------- */

/* Alert to karta, nie wiersz tabeli: niesie treść, warunek, który go zapalił, i to,
   czego dotyczy — w wierszu tabeli te trzy rzeczy nie miały gdzie stanąć, a między
   treścią a datą zostawała pustka na pół ekranu. */
.alert-feed {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg, 1rem);
}

.alert-entry-title {
    overflow-wrap: anywhere;
}

/* Etykieta i wartość w dwóch kolumnach: kolumna etykiet bierze szerokość najszerszej,
   więc wartości stoją w jednej linii w każdej karcie. Kropka rozdziela je bez kreski. */
.alert-facts {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.375rem 0;
    margin: 0;
    font-size: var(--font-size-sm, 0.875rem);
}

.alert-facts dt {
    padding-right: 1.25rem;
    font-weight: var(--font-weight-regular, 400);
    color: var(--color-text-tertiary, #717680);
}

.alert-facts dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.alert-facts dd::before {
    content: "";
    display: inline-block;
    width: 0.25rem;
    height: 0.25rem;
    margin: 0 0.625rem 0.125rem 0;
    border-radius: 50%;
    background: var(--color-grey-300, #D5D7DA);
    vertical-align: middle;
}

/* Plakietka rodzaju przed tytułem: mówi, o jaki warunek chodzi, jeszcze przed
   przeczytaniem treści. Po prawej zostaje sama akcja. */
.alert-entry-heading {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

/* Plakietka alarmowa: ciemniejsza czerwień z palety i biały napis.
   Bootstrap dobiera do #D14C4C czarny tekst, bo wychodzi mu z niego wyższy współczynnik
   kontrastu, ale przy jedenastu pikselach i tej barwie napis po prostu ginie. Na #923434
   biały tekst daje 7,6:1 i jest to ten sam odcień, którym oznaczamy regresje i liczniki. */
.badge.text-bg-danger {
    background-color: #923434 !important;
    color: #FFFFFF !important;
}

/* ---------------------------------------------------------------------------
   Plakietki stanu i środowiska
   --------------------------------------------------------------------------- */

/* Stan klucza czyta się z odległości ręki, a nie z nosem w ekranie — dlatego większa
   od zwykłej plakietki. */
.badge-state {
    font-size: var(--font-size-xs, 0.75rem);
    padding: 0.4375rem 0.75rem;
}

/* Zielony z palety Bootstrapa (#2FA46F) daje z białym napisem 3,2:1, czyli za mało.
   Ciemniejsza zieleń z palety Antumo — 5,0:1. */
.badge.text-bg-success {
    background-color: #3E7C4A !important;
    color: #FFFFFF !important;
}


/* Komunikat zdarzenia i opis od użytkownika: bywa w nich wklejony kod biletu albo
   zrzut base64 bez ani jednej spacji, a taki ciąg rozpycha kartę i całą stronę. */
.issue-message {
    overflow-wrap: anywhere;
}


/* Oznaczenie środowiska: ikona z biblioteki i nazwa, tym samym wzorem, którym opisujemy
   metryczkę zdarzenia. Ikona zostaje drugoplanowa, nazwa niesie treść. */
.env-mark {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}

.env-mark svg {
    flex: 0 0 auto;
    color: var(--color-text-tertiary, #717680);
}

.env-mark-prod {
    font-weight: var(--font-weight-bold, 700);
}

.env-mark-other {
    font-weight: var(--font-weight-medium, 500);
    color: var(--color-text-secondary, #414651);
}

/* Historia zgłoszenia: czas i sprawca po bokach, treść zmiany w środku — czyta się
   pionem po godzinach, a nie po nazwach czynności. */
/* Panel dziennika: pole zawężania nad tabelą, strony pod nią. */
.history-panel {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg, 12px);
    flex: 1 1 auto;
    min-height: 0;
}

.history-panel-tools {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 12px);
    flex: 0 0 auto;
}

.history-panel-search {
    width: 20rem;
    min-width: 10rem;
}

.history-panel-tools .text-secondary {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

/* W karcie dziennik przewija się u siebie, żeby nie rozpychał kolumny szczegółów;
   w oknie bierze całą wysokość, jaka zostaje po polu zawężania i stronach. */
.history-panel-viewport {
    max-height: 26rem;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

.history-panel-fill {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    scrollbar-gutter: stable;
}

/* Dziennik jako tabela: data i osoba trzymają się swoich kolumn, opis czynności bierze
   resztę. Kolumny skrajne bez łamania — to daty i nazwy kont, nie zdania. */
.history-table .history-when,
.history-table .history-who {
    white-space: nowrap;
    width: 1%;
}

.history-table .history-when {
    font-variant-numeric: tabular-nums;
}

.history-table .history-what {
    overflow-wrap: anywhere;
}

.issue-history {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Dziennik i dyskusja przewijają się u siebie, tak jak logi.

   Wysokość jest górną granicą, nie stałą: zgłoszenie sprzed chwili ma dwa wpisy historii
   i żaden komentarz, a pusta przestrzeń na pół ekranu wyglądałaby na błąd wczytywania.
   Chodzi o to, żeby długi dziennik nie rozpychał kolumny szczegółów — i to daje
   max-height. */
.issue-history-viewport,
.issue-comments-viewport {
    max-height: 26rem;
    overflow-y: auto;

    /* Miejsce na pasek przewijania zarezerwowane na stałe: bez tego wpis, który dokłada
       trzynasty wiersz, przesuwał całą treść o dziesięć pikseli w lewo. */
    scrollbar-gutter: stable;
}

/* Odstęp od paska przewijania, żeby tekst go nie dotykał. */
.issue-history-viewport {
    padding-right: var(--spacing-md, 8px);
}

.issue-comments-viewport {
    padding-right: var(--spacing-md, 8px);
}

/* ===== Okno na całą wysokość: rozmowa i dyskusja ===== */

/* Rozmowa i dyskusja to nie formularz, a miejsce pracy: wątek zajmuje w oknie tyle, ile
   zostaje po nagłówku, wybieraku i polu do pisania, i przewija się u siebie. Wysokości
   nie liczymy w procentach ekranu — układ pionowy robi to sam. */
.modal-own.modal-own-full {
    padding: var(--spacing-xl, 16px);
    align-items: center;

    /* Bez przewijania warstwy: okno ma dokładnie wysokość ekranu, a przewija się jego
       treść — dwa paski przewijania jeden w drugim gubią miejsce, w którym się jest. */
    overflow: hidden;
}

.modal-own .modal-dialog.modal-full {
    width: 100%;

    /* Szerzej niż zwykłe okno, ale nie na całą szerokość monitora: wątek rozmowy czyta się
       źle, gdy wiersz ma pół metra. */
    max-width: min(76rem, 96vw);

    /* Wysokość całego okna minus wypełnienie warstwy — okno kończy się tam, gdzie ekran. */
    height: calc(100vh - 2 * var(--spacing-xl, 16px));
    margin: 0 auto;
}

.modal-own .modal-dialog.modal-full > .modal-content {
    height: 100%;
    display: flex;
    flex-direction: column;

    /* Zaokrąglone narożniki obcinają to, co w środku — inaczej przewijany wątek wychodził
       poza obwódkę okna. */
    overflow: hidden;
}

.modal-own .modal-dialog.modal-full > .modal-content > .modal-header,
.modal-own .modal-dialog.modal-full > .modal-content > .modal-footer {
    flex: 0 0 auto;
}

/* Treść okna przewija się w środku, nie razem z całym oknem: pole do pisania i przyciski
   zostają na swoim miejscu przy każdej długości wątku. min-height: 0 jest tu konieczne —
   bez niego element w układzie pionowym nie zmniejszy się poniżej swojej treści i wątek
   wypchnąłby stopkę za dół ekranu. */
.modal-own .modal-dialog.modal-full > .modal-content > .modal-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Zawartość okna pełnowymiarowego: wybierak i pole trzymają swoją wysokość, wątek bierze
   resztę. */
.dialog-fill {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg, 12px);
    flex: 1 1 auto;
    min-height: 0;
}

/* Pole do pisania w oknie pełnowymiarowym trzyma swoją wysokość na dole. */
.dialog-compose {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 8px);
    flex: 0 0 auto;
}

.dialog-fill > .dialog-thread,
.dialog-fill > .chat-thread-tall {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

/* Poza oknem pełnowymiarowym (podglądy, starsze użycia) zostaje ograniczenie wysokości. */
.dialog-thread,
.chat-thread-tall {
    max-height: min(52vh, 32rem);
    overflow-y: auto;
    scrollbar-gutter: stable;
}

/* Wycinek kodu do przepisania: własne tło z palety, nie bootstrapowe.

   Bootstrapowe `bg-body-tertiary` bierze kolor z własnych tokenów, a te nie znają
   przełącznika motywu panelu — blok zostawał biały także w ciemnym motywie i jasne pismo
   robiło się na nim niewidoczne. */
.code-snippet {
    overflow: auto;
    background: var(--color-bg-tertiary);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
}

/* Opis od zgłaszającego. `alert-light` z Bootstrapa jest biały z ciemnym pismem —
   w ciemnym motywie wychodził jasną płachtą w środku karty. */
.alert-light {
    background-color: var(--color-bg-tertiary);
    border-color: var(--color-border-secondary);
    color: var(--color-text-primary);
}

/* Jasne plakietki (warstwa zgłoszenia, tagi) w ciemnym motywie: tło z warstwy podniesionej,
   nie biel. Biała plakietka na prawie czarnej karcie ciągnęła wzrok mocniej niż tytuł. */
[data-theme="dark"] .text-bg-light {
    background-color: var(--color-bg-tertiary) !important;
    color: var(--color-text-primary) !important;
    border: 1px solid var(--color-border-primary);
}

/* ===== Załączniki w rozmowie ===== */

/* Pliki pod treścią wiadomości, w tym samym dymku: zrzut ekranu należy do zdania, przy
   którym został przysłany, a nie do rozmowy w ogóle. */
.chat-attachments {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 8px);
    margin-top: var(--spacing-md, 8px);
}

/* Miniatura obrazu: przycisk, nie odnośnik — kliknięcie otwiera okno z podglądem, a nie
   nową kartę przeglądarki z samym plikiem. */
.chat-attachment-image {
    display: block;
    max-width: 18rem;
    padding: 0;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: transparent;
    cursor: zoom-in;
    overflow: hidden;
}

.chat-attachment-image img {
    display: block;
    width: 100%;

    /* Wysoki zrzut z kasy obcięty do rozsądnej miniatury: całość jest w oknie podglądu. */
    max-height: 16rem;
    object-fit: cover;
}

.chat-attachment-image:hover {
    border-color: var(--color-btn-primary-bg);
}

.chat-attachment-video {
    max-width: 22rem;
    border-radius: var(--radius-md, 8px);
    border: 1px solid var(--color-border-secondary);
}

/* Kafelek pliku do pobrania: nazwa i rozmiar, bo po nich nadawca rozpoznaje, co przysłał. */
.chat-attachment-file {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-md, 8px);
    max-width: 22rem;
    padding: var(--spacing-md, 8px) var(--spacing-lg, 12px);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary);
    color: var(--color-text-primary);
    text-decoration: none;
}

.chat-attachment-file:hover {
    border-color: var(--color-btn-primary-bg);
    color: var(--color-text-primary);
}

.chat-attachment-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.chat-attachment-size {
    flex: 0 0 auto;
    color: var(--color-text-tertiary);
    font-size: var(--font-size-2xs, 12px);
    font-variant-numeric: tabular-nums;
}

/* Obraz w oknie podglądu: cały, z przewijaniem, bo zrzuty z kas są wyższe niż szersze. */
.image-preview {
    max-height: min(70vh, 44rem);
    overflow: auto;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary);
}

.image-preview img {
    display: block;
    width: 100%;
    height: auto;
}

/* ===== Pole odpowiedzi w rozmowie ===== */

.chat-composer {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 8px);
}

/* Wybrane pliki przed wysłaniem: widać, co poleci, i da się zdjąć pomyłkę bez czyszczenia
   całej wiadomości. */
.chat-composer-files {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-md, 8px);
}

.chat-composer-file {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-md, 8px);
    max-width: 20rem;
    padding: 4px var(--spacing-md, 8px);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-full, 9999px);
    background: var(--color-bg-tertiary);
    font-size: var(--font-size-2xs, 12px);
}

.chat-composer-remove {
    display: inline-flex;
    align-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--color-text-tertiary);
    cursor: pointer;
}

.chat-composer-remove:hover {
    color: var(--color-text-primary);
}

.chat-composer-tools {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 12px);
    flex-wrap: wrap;
}

/* Spinacz jako etykieta pola wyboru plików: własne pole wyboru w przeglądarce wygląda
   inaczej w każdej z nich i nie da się go dopasować do reszty panelu. */
.chat-composer-attach {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-md, 8px);
    padding: var(--control-padding-y, 6px) var(--control-padding-x, 12px);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-full, 9999px);
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs, 14px);
    cursor: pointer;
    white-space: nowrap;
}

.chat-composer-attach:hover {
    border-color: var(--color-border-primary);
    background-color: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

/* Zdanie o tym, kto to zobaczy, rozpycha się między spinaczem a przyciskiem. Bez zdania
   to samo miejsce zajmuje puste rozpięcie, więc przycisk zostaje przy prawej krawędzi. */
.chat-composer-tools .chat-notice,
.chat-composer-spacer {
    flex: 1 1 auto;
    min-width: 0;
}

.chat-composer-tools .btn {
    flex: 0 0 auto;
}

/* Przycisk-ikona w nagłówku karty: „otwórz w oknie" przy dyskusji i rozmowie. Wygląd
   jak przy odnośnikach w nagłówkach, nie jak przycisk główny — to nie czynność na
   zgłoszeniu, a zmiana sposobu patrzenia na to samo. */
.card-tool {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: transparent;
    color: var(--color-text-tertiary);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.card-tool:hover {
    border-color: var(--color-border-primary);
    background-color: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

.card-tool:focus-visible {
    outline: none;
    border-color: var(--color-input-border-focus);
    box-shadow: 0 0 0 4px var(--color-input-focus-glow);
}

.issue-history li {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.75rem;
    align-items: baseline;
}

.issue-history-when {
    color: var(--color-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.issue-history-what {
    overflow-wrap: anywhere;
}

.issue-history-who {
    color: var(--color-text-secondary);
    white-space: nowrap;
}

/* Lista wystąpień: kolumna z zaznaczeniem wąska, godziny w jednej linii i w tabelarycznych
   cyfrach, żeby daty stały w kolumnie. */
.occurrence-pick {
    width: 2.5rem;
}

.occurrence-when {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.occurrence-split {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}

.occurrence-split .form-control {
    flex: 1 1 12rem;
}

/* Ostrzeżenie o danych osobowych: ikona i tekst w jednej linii bazowej, ton ostrzeżenia
   bez krzyku — to nie awaria, tylko rzecz, o której trzeba pamiętać przy integracji. */
.pii-notice {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--color-border-secondary, #e9eaeb);
    border-left: 3px solid var(--color-yellow-500, #eaaa08);
    border-radius: 0.5rem;
    background: var(--color-bg-secondary, #fafafa);
    color: var(--color-text-secondary, #414651);
    font-size: 0.8125rem;
    line-height: 1.45;
}

.pii-notice svg {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    color: var(--color-yellow-600, #ca8504);
}

/* ---------------------------------------------------------------------------
   Stronicowanie
   ---------------------------------------------------------------------------
   Klasy i wymiary z komponentu `pagination` w systemie designu (wariant z listą
   rozmiarów strony). Stałe szerokości sekcji z biblioteki zamienione na elastyczne:
   pasek stoi w stopce karty, a nie na całej szerokości strony, i musi się zawijać. */
.pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-lg, 0.625rem);
    width: 100%;
    box-sizing: border-box;
}

.pagination-section {
    display: flex;
    align-items: center;
    gap: var(--spacing-md, 0.5rem);
}

.pagination-section-right {
    justify-content: flex-end;
}

.pagination-numbers {
    display: flex;
    align-items: center;
    gap: var(--spacing-xxs, 0.125rem);
    list-style: none;
    margin: 0;
    padding: 0;
}

.pagination-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    color: var(--color-grey-500, #717680);
    font-weight: var(--font-weight-medium, 500);
    font-size: var(--font-size-sm, 0.875rem);
    user-select: none;
}

.pagination-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border: none;
    border-radius: var(--radius-full, 999px);
    background-color: transparent;
    color: var(--color-grey-500, #717680);
    font-family: inherit;
    font-weight: var(--font-weight-medium, 500);
    font-size: var(--font-size-sm, 0.875rem);
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.pagination-button:hover:not(.pagination-button-active) {
    background-color: var(--color-grey-50, #fafafa);
}

/* Bieżąca strona z biblioteki różni się od pozostałych samym tłem, a to przy sześciu
   szarych kółkach obok siebie ginie. Zaznaczenie bierzemy takie jak w pozycji listy
   zgłoszeń — kolorem marki. */
.pagination-button-active {
    background-color: var(--color-bg-brand, #3a3a66);
    color: #ffffff;
}

.pagination-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: var(--spacing-md, 0.5rem);
    border: none;
    border-radius: var(--radius-full, 999px);
    background-color: transparent;
    color: var(--color-grey-500, #717680);
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.pagination-nav-btn:hover:not(.pagination-nav-btn-disabled) {
    color: var(--color-text-primary, #181d27);
    background-color: var(--color-grey-50, #fafafa);
}

.pagination-nav-btn-disabled {
    color: var(--color-grey-300, #d5d7da);
    cursor: not-allowed;
}

.pagination-select {
    padding: 0.375rem var(--spacing-xl, 0.75rem);
    border: 1px solid var(--color-border-primary, #d5d7da);
    border-radius: var(--radius-md, 0.5rem);
    background-color: var(--color-bg-primary, #fff);
    color: var(--color-text-primary, #181d27);
    font-family: inherit;
    font-size: var(--font-size-sm, 0.875rem);
    box-shadow: var(--shadow-xs);
    cursor: pointer;
}

.pagination-info {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-xs, 0.25rem);
    font-variant-numeric: tabular-nums;
}

.pagination-label {
    margin: 0;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: var(--font-weight-medium, 500);
    color: var(--color-text-secondary, #414651);
    white-space: nowrap;
}

.pagination-value {
    font-size: var(--font-size-sm, 0.875rem);
    color: var(--color-text-primary, #181d27);
    white-space: nowrap;
}

/* Pasek stoi pod tabelą w karcie, więc oddziela go od niej kreska, nie odstęp —
   inaczej zlewa się z ostatnim wierszem. */
.pagination-sonar {
    margin-top: var(--spacing-xl, 0.75rem);
    padding-top: var(--spacing-xl, 0.75rem);
    border-top: 1px solid var(--color-border-secondary, #e9eaeb);
}

/* Pasek stron pod listą zgłoszeń stoi w karcie bez odstępów (`p-0`), więc odstęp
   dokładamy tutaj. Węższa kolumna niż tabela wystąpień, więc numery zawijają się
   pod resztę zamiast rozpychać kartę.

   Wariant oszczędny: w tej kolumnie liczy się lista, a nie pasek pod nią. Na ekranie
   laptopa pasek w wymiarach z systemu designu schodził na trzy wiersze i zabierał listę
   na wysokość dwóch pozycji. Kółka i lista rozmiarów są tu mniejsze, odstępy krótsze,
   a układ ustawiony tak, żeby wychodziły z tego najwyżej dwa wiersze. */
.issue-rail-pager {
    padding: 0;
}

.issue-rail-pager .pagination {
    gap: var(--spacing-xs, 0.25rem) var(--spacing-md, 0.5rem);
}

.issue-rail-pager .pagination-sonar {
    margin-top: var(--spacing-md, 0.5rem);
    padding-top: var(--spacing-md, 0.5rem);
}

/* Kolejność wymuszona, a nie zdana na zawijanie: rozmiar strony i zakres w pierwszym
   wierszu (skrajne krawędzie), numery w drugim, wyśrodkowane. Samo zawijanie stawiało
   zakres w osobnym, trzecim wierszu. */
.issue-rail-pager .pagination-section-left {
    order: 1;
}

.issue-rail-pager .pagination-section-right {
    order: 2;
    flex-basis: auto;
    justify-content: flex-end;
}

.issue-rail-pager .pagination > .pagination-section:nth-child(2) {
    order: 3;
    flex-basis: 100%;
    justify-content: center;
}

.issue-rail-pager .pagination-button,
.issue-rail-pager .pagination-nav-btn,
.issue-rail-pager .pagination-ellipsis {
    width: 1.75rem;
    height: 1.75rem;
    font-size: var(--font-size-xs, 0.75rem);
}

.issue-rail-pager .pagination-nav-btn {
    padding: 0;
}

.issue-rail-pager .pagination-select {
    padding: 0.125rem var(--spacing-md, 0.5rem);
    font-size: var(--font-size-xs, 0.75rem);
}

.issue-rail-pager .pagination-value {
    font-size: var(--font-size-xs, 0.75rem);
}

/* ---------------------------------------------------------------------------
   Sortowanie kolumn
   ---------------------------------------------------------------------------
   Klasy i wskaźnik z komponentu tabeli w systemie designu. Kolumna, po której da się
   sortować, ma to pokazywać zawsze — wskaźnik pojawiający się dopiero pod kursorem
   nie mówi nic osobie, która nie zgadnie, że warto tam najechać. */
.table-header-cell-sortable {
    cursor: pointer;
    user-select: none;
    transition: background-color 150ms ease, color 150ms ease;
}

.table-header-cell-sortable:hover {
    background: var(--color-bg-tertiary, #f5f5f5);
    color: var(--color-text-tertiary, #535862);
}

.table-header-content {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs, 0.25rem);
}

.table-sort-indicator {
    flex: 0 0 auto;
    color: var(--color-text-quaternary, #717680);
    transition: transform 200ms ease, color 200ms ease;
}

.table-header-cell-sortable:hover .table-sort-indicator {
    color: var(--color-text-tertiary, #535862);
}

/* Kolumna, po której lista stoi, dostaje strzałkę w kolorze tekstu — wskaźnik w szarości
   pozostałych kolumn nie odróżniałby jej od nich. */
.table-sort-indicator-asc,
.table-sort-indicator-desc {
    color: var(--color-text-primary, #181d27);
}

.table-sort-indicator-desc {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .table-header-cell-sortable,
    .table-sort-indicator {
        transition: none;
    }
}

/* Narzędzia w nagłówku karty wystąpień: pole szukania i licznik. Pole nie rozpycha
   nagłówka — przy węższej karcie kurczy się do połowy zamiast łamać wiersz. */
/* Ikona przy tytule sekcji: ta sama, którą prowadzi do niej skrót. Wielkość i kolor
   podrzędne wobec tytułu — ma pomagać rozpoznać sekcję, nie ciągnąć wzrok. */
.antumo-card-title .card-title-icon {
    color: var(--color-text-tertiary);
    vertical-align: -0.15em;
    margin-right: var(--spacing-md, 8px);
}

/* Stronicowanie bez zakresu (lista zgłoszeń): numery idą w prawo, żeby stanęły w jednym
   rzędzie z wyborem rozmiaru strony, a nie pod nim. */
.pagination-sonar-compact {
    flex-wrap: nowrap;
}

/* Same numery bez rozmiaru strony: stoją w środku kolumny. Dosunięcie do prawej miało
   sens, dopóki po lewej stał wybór rozmiaru — bez niego rząd wyglądał, jakby coś z niego
   wypadło. */
.pagination-sonar-compact:not(:has(.pagination-section-left)) {
    justify-content: center;
}

.pagination-sonar-compact:has(.pagination-section-left) .pagination-section:not(.pagination-section-left) {
    margin-left: auto;
}

/* ===== Skróty ===== */

/* Ikony w rzędach po tyle, ile się zmieści: kolumna czynności ma szerokość jednej karty,
   a sekcji jest osiem. */
.quick-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-md, 8px);
}

.quick-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: transparent;
    color: var(--color-text-tertiary);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.quick-link {
    text-decoration: none;
}

.quick-link:hover {
    border-color: var(--color-btn-primary-bg);
    background-color: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

.quick-link:focus-visible {
    outline: none;
    border-color: var(--color-input-border-focus);
    box-shadow: 0 0 0 4px var(--color-input-focus-glow);
}

/* Sekcja, do której właśnie skoczyliśmy, na moment się zaznacza: karty wyglądają podobnie
   i bez tego nie widać, czy trafiło się w tę, o którą chodziło. */
.antumo-card.is-flashed,
.issue-panels.is-flashed {
    animation: sonar-flash 1.2s ease-out;
}

@keyframes sonar-flash {
    0% {
        box-shadow: 0 0 0 3px var(--color-btn-primary-bg);
    }

    100% {
        box-shadow: 0 0 0 3px rgba(0, 0, 0, 0);
    }
}

/* ===== Kroki odtworzenia ===== */

/* Taśma ekranów: przewija się w poziomie, bo bufor ma piętnaście zrzutów, a karta
   szerokość jednej kolumny. Kolejność od najwcześniejszego do chwili awarii. */
.repro-strip {
    display: flex;
    gap: var(--spacing-lg, 12px);
    overflow-x: auto;
    padding-bottom: var(--spacing-md, 8px);
    scrollbar-gutter: stable;
}

.repro-step {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 0 0 auto;
    width: 9.5rem;
    padding: 0;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
    cursor: zoom-in;
    overflow: hidden;
}

.repro-step:hover,
.repro-step.is-current {
    border-color: var(--color-btn-primary-bg);
    color: var(--color-text-primary);
}

.repro-step img {
    display: block;
    width: 100%;

    /* Kadr o stałej wysokości: zrzuty z kas mają różne proporcje, a taśma ma się czytać
       jak jeden pasek, nie jak schodki. */
    height: 7rem;
    object-fit: cover;
    object-position: top;
}

.repro-step-label {
    padding: 0 6px 6px;
    font-size: var(--font-size-2xs, 12px);
    text-align: center;
}

.repro-others {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-md, 8px);
    margin-top: var(--spacing-lg, 12px);
}

/* Przeglądanie w oknie: strzałki po bokach, ekran w środku, taśma pod nim. */
.repro-viewer {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 12px);
    flex: 1 1 auto;
    min-height: 0;
}

.repro-stage {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: auto;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary);
}

.repro-stage img {
    max-width: 100%;

    /* Cały ekran kasy w kadrze okna: wyższy zrzut zmniejsza się, zamiast wymuszać
       przewijanie w obu osiach. */
    max-height: 100%;
    object-fit: contain;
}

.repro-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-full, 9999px);
    background: transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
}

.repro-nav:hover:not(:disabled) {
    border-color: var(--color-btn-primary-bg);
    color: var(--color-text-primary);
}

.repro-nav:disabled {
    opacity: 0.4;
    cursor: default;
}

.repro-viewer-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-lg, 12px);
    flex: 0 0 auto;
}

/* Taśma w oknie jest tylko do przeskakiwania, więc bez podpisów i niższa. */
.repro-strip-compact {
    flex: 0 0 auto;
}

.repro-strip-compact .repro-step {
    width: 6rem;
}

.repro-strip-compact .repro-step img {
    height: 4.5rem;
}

/* Panel wystąpień: narzędzia, tabela i strony jedno pod drugim; w oknie tabela bierze
   całą wysokość, jaka zostaje. */
.occurrence-panel {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg, 12px);
    flex: 1 1 auto;
    min-height: 0;
}

.occurrence-fill {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    scrollbar-gutter: stable;
}

.occurrence-tools {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 0.625rem);
}

.occurrence-search {
    width: 15rem;
    min-width: 8rem;
}

@container content (max-width: 900px) {
    .occurrence-search {
        width: 10rem;
    }
}

/* ---------------------------------------------------------------------------
   Wyjaśnienia pod znakiem zapytania
   ---------------------------------------------------------------------------
   Klasy i wymiary z komponentu tooltipa w systemie designu. Tam widoczność przełącza
   JavaScript klasą `show` — tutaj robi to kursor i skupienie klawiaturą, bo dymek
   z jednym zdaniem nie potrzebuje własnego skryptu. */
.tooltip-trigger {
    position: relative;
    display: inline-flex;
    cursor: help;
}

.tooltip-trigger:focus-visible {
    outline: 2px solid var(--color-focus, #5b6ef2);
    outline-offset: 2px;
    border-radius: var(--radius-sm, 0.25rem);
}

.tooltip-help-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-quaternary, #a4a7ae);
    transition: color 150ms ease;
}

.tooltip-trigger:hover .tooltip-help-icon,
.tooltip-trigger:focus .tooltip-help-icon {
    color: var(--color-text-tertiary, #717680);
}

.tooltip {
    position: absolute;
    z-index: 9999;
    width: max-content;
    max-width: 20rem;

    /* Dymek przypięty do okna leży nad treścią, a nie ma na czym stać kursorem: bez tego
       przykrywałby to, co pod nim, i klikało się w niego zamiast w przycisk. */
    pointer-events: none;
    padding: 0.5rem 0.75rem;
    background-color: var(--color-grey-900, #181d27);
    color: #ffffff;
    border-radius: var(--radius-sm, 0.25rem);
    box-shadow: var(--shadow-lg);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: var(--font-weight-medium, 500);
    line-height: 1.45;
    text-align: left;
    white-space: normal;
    opacity: 0;
    visibility: hidden;
    transition: opacity 150ms ease, visibility 150ms ease;
}

/* Na każde skupienie, nie tylko klawiaturowe: dymek ma się pokazać także wtedy, gdy
   ognisko przyszło z czytnika ekranu albo z kodu — obwódkę zostawiamy `:focus-visible`. */
.tooltip-trigger:hover .tooltip,
.tooltip-trigger:focus .tooltip {
    opacity: 1;
    visibility: visible;
}

/* Dymek wychodzi w dół i w prawo od ikony: w panelu akcji ikona stoi przy prawej krawędzi
   karty, a dymek wypuszczony do góry chowałby się pod nagłówkiem strony. */
.tooltip-bottom {
    top: calc(100% + 0.5rem);
    left: 50%;
    transform: translateX(-50%);
}

.tooltip-top {
    bottom: calc(100% + 0.5rem);
    left: 50%;
    transform: translateX(-50%);
}

.tooltip-arrow {
    position: absolute;
    width: 0;
    height: 0;
    border-style: solid;
}

/* Strona, z której dymek wyszedł, po przeliczeniu przez `js/tooltip.js` — tam dymek
   przechodzi na `position: fixed`, żeby nie ucinały go przewijane kolumny, i przy braku
   miejsca idzie na drugą stronę, niż mówi klasa z komponentu. Grot musi wtedy pójść
   za nim. */
.tooltip.tooltip-below .tooltip-arrow {
    top: -0.375rem;
    bottom: auto;
    border-width: 0 0.5rem 0.375rem;
    border-color: transparent transparent var(--color-grey-900, #181d27);
}

.tooltip.tooltip-above .tooltip-arrow {
    top: auto;
    bottom: -0.375rem;
    border-width: 0.375rem 0.5rem 0;
    border-color: var(--color-grey-900, #181d27) transparent transparent;
}

.tooltip-bottom .tooltip-arrow {
    top: -0.375rem;
    left: 50%;
    transform: translateX(-50%);
    border-width: 0 0.5rem 0.375rem;
    border-color: transparent transparent var(--color-grey-900, #181d27);
}

.tooltip-top .tooltip-arrow {
    bottom: -0.375rem;
    left: 50%;
    transform: translateX(-50%);
    border-width: 0.375rem 0.5rem 0;
    border-color: var(--color-grey-900, #181d27) transparent transparent;
}

/* Nagłówek karty ma tytuł i wyjaśnienie w jednej linii bazowej. */
.card-title-with-hint {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-md, 0.5rem);
}

@media (prefers-reduced-motion: reduce) {
    .tooltip,
    .tooltip-help-icon {
        transition: none;
    }
}

/* Krzyżyk zdejmujący tag. Mały i drugoplanowy, bo tag ma się czytać treścią, nie
   przyciskiem — ale pole kliknięcia zostaje pełnowymiarowe, żeby dało się w nie trafić
   palcem na kasie. */
.badge-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

.badge-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.125rem;
    height: 1.125rem;
    margin: -0.125rem -0.25rem -0.125rem 0;
    padding: 0;
    border: none;
    border-radius: var(--radius-full, 999px);
    background: transparent;
    color: var(--color-text-quaternary, #717680);
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.badge-remove svg {
    width: 0.75rem;
    height: 0.75rem;
}

.badge-remove:hover {
    background: var(--color-grey-200, #e9eaeb);
    color: var(--color-text-primary, #181d27);
}

.badge-remove:focus-visible {
    outline: 2px solid var(--color-focus, #5b6ef2);
    outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .badge-remove {
        transition: none;
    }
}

/* ---------------------------------------------------------------------------
   Nieotwarte zgłoszenia na liście
   ---------------------------------------------------------------------------
   Tak jak nieprzeczytana wiadomość w skrzynce. Wyróżnienie musiało pójść przez osłabienie
   otwartych — tytuły na tej liście były wszystkie pogrubione, więc samo pogrubienie
   niczego nie odróżniało. Sama grubość zresztą nie wystarczyła: przy trzynastu pikselach
   i tytule złamanym na trzy wiersze różnicy 500 do 700 nie widać z odległości, w której
   się tę listę przegląda. Otwarte blakną więc też kolorem. */
.issue-rail-item .issue-rail-title {
    font-weight: var(--font-weight-medium, 500);
    color: var(--color-text-tertiary, #535862);
}

.issue-rail-item.is-unopened .issue-rail-title {
    font-weight: var(--font-weight-bold, 700);
    color: var(--color-text-primary, #181d27);
}

/* Zaznaczona pozycja ma własne tło w kolorze marki — tam tytuł i kropka muszą być białe,
   inaczej kropka znika w tle, a tytuł traci czytelność. */
.issue-rail-item.is-selected .issue-rail-title {
    color: inherit;
}

.issue-rail-item.is-selected .issue-rail-dot {
    background: currentColor;
}

.issue-rail-dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    margin-right: 0.375rem;
    vertical-align: 0.0625rem;
    border-radius: var(--radius-full, 999px);
    background: var(--color-bg-brand, #3a3a66);
}

/* ---------------------------------------------------------------------------
   Ekran logowania
   ---------------------------------------------------------------------------
   Bez paska bocznego i stopki: nawigacja po panelu, do którego nikt jeszcze nie wszedł,
   prowadziłaby wyłącznie z powrotem tutaj. */
.login-page {
    min-height: 100dvh;
    background: var(--color-bg-secondary, #ffffff);
}

/* Dwie połowy: po lewej formularz, po prawej podgląd panelu. Tak samo jak w UTS —
   ekran wejścia do dwóch narzędzi Antumo ma być rozpoznawalny jako jedno miejsce.

   Połowa z formularzem to powierzchnia karty (biel, w ciemnym prawie czerń), a druga
   połowa tło strony — o stopień dalej w obu motywach. */
.login-container {
    display: flex;
    min-height: 100dvh;
    background: var(--color-bg-secondary, #ffffff);
}

.login-content-area {
    display: flex;
    flex: 1 1 50%;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 0;
    padding: var(--spacing-6xl, 2.5rem) var(--spacing-3xl, 1.5rem);
}

.login-main {
    display: flex;
    width: 100%;
    max-width: 23rem;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-7xl, 4rem);
}

.login-logo {
    display: inline-flex;
}

/* Znak firmowy: firmowy granat na jasnym tle, biel w ciemnym motywie. Kolor podajemy
   wprost, nie tokenem tła paska — ten w ciemnym motywie jest prawie czarny. */
.login-logo-mark {
    height: 2.5rem;
    color: var(--color-navy-500, #3a3a66);
}

[data-theme="dark"] .login-logo-mark {
    color: var(--color-white, #ffffff);
}

.login-panel {
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: var(--spacing-3xl, 1.25rem);
}

.login-header {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 0.5rem);
}

.login-title {
    margin: 0;
    font-family: var(--font-family-brand);
    font-size: var(--font-size-2xl, 2rem);
    font-weight: var(--font-weight-bold, 700);
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--color-text-primary, #181d27);
}

.login-subtitle {
    margin: 0;
    font-size: var(--font-size-md, 1rem);
    line-height: 1.5;
    color: var(--color-text-secondary, #535862);
}

.login-form {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-3xl, 1.25rem);
}

.login-field {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm, 0.375rem);
}

.login-field .form-label {
    margin-bottom: 0;
}

.login-required {
    color: var(--color-red-500, #d14c4c);
}

/* Rozdzielenie dwóch dróg wejścia: hasło i katalog. Kreska po bokach mówi, że to
   alternatywa, a nie kolejny krok tego samego formularza. */
.login-divider {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 0.625rem);
}

.login-divider-line {
    flex: 1 1 auto;
    height: 1px;
    background: var(--color-border-secondary, #e9eaeb);
}

.login-divider-text {
    font-size: var(--font-size-xs, 0.75rem);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-tertiary, #717680);
}

/* Prawa połowa: makieta panelu w ramce okna, na jednolitym tle jak w UTS. Makieta
   wychodzi za prawą krawędź — to ma wyglądać na zajrzenie do środka, a nie na obrazek
   wklejony na środku. */
.login-aside {
    position: relative;
    flex: 1 1 50%;
    min-width: 0;
    overflow: hidden;
    background-color: var(--color-navy-50, #f6f7fa);
}

[data-theme="dark"] .login-aside {
    background-color: var(--color-bg-primary, #181d27);
}

.login-mockup {
    position: absolute;
    top: 50%;
    left: 4rem;
    display: flex;
    width: 46rem;
    height: 30rem;
    transform: translateY(-50%);
    gap: 0;
    padding: 0.25rem;
    border: 1px solid var(--color-border-secondary, rgba(0, 0, 0, 0.08));
    border-radius: 2rem;
    background: var(--color-card-bg, #ffffff);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

.login-mockup-rail {
    display: flex;
    width: 9rem;
    flex: 0 0 auto;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1.25rem 1rem;
    border-radius: 1.75rem 0 0 1.75rem;
    background: var(--color-bg-brand, #3a3a66);
}

.login-mockup-brand {
    height: 0.875rem;
    width: 4.5rem;
    border-radius: var(--radius-full, 999px);
    background: rgba(255, 255, 255, 0.85);
}

.login-mockup-nav {
    height: 0.75rem;
    border-radius: var(--radius-sm, 0.25rem);
    background: rgba(255, 255, 255, 0.16);
}

.login-mockup-nav.is-active {
    margin-top: 1rem;
    background: rgba(255, 255, 255, 0.42);
}

.login-mockup-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 1rem;
    padding: 1.5rem;
}

.login-mockup-heading {
    height: 1rem;
    width: 7rem;
    border-radius: var(--radius-sm, 0.25rem);
    background: var(--color-border-primary, #d5d7da);
}

.login-mockup-tiles {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

.login-mockup-tile {
    display: flex;
    height: 4rem;
    align-items: flex-end;
    padding: 0.75rem;
    border: 1px solid var(--color-card-border, #e9eaeb);
    border-radius: var(--radius-lg, 0.5rem);
}

.login-mockup-bar {
    height: 0.25rem;
    width: 100%;
    border-radius: var(--radius-full, 999px);
}

.login-mockup-bar.is-brand {
    background: var(--color-bg-brand, #3a3a66);
}

.login-mockup-bar.is-danger {
    background: var(--color-red-500, #d14c4c);
}

.login-mockup-bar.is-warning {
    background: var(--color-yellow-500, #f1c846);
}

.login-mockup-chart {
    display: flex;
    flex: 1 1 auto;
    align-items: flex-end;
    gap: 0.5rem;
    padding: 0.75rem;
    border: 1px solid var(--color-card-border, #e9eaeb);
    border-radius: var(--radius-lg, 0.5rem);
}

.login-mockup-chart span {
    flex: 1 1 auto;
    border-radius: var(--radius-xs, 0.125rem) var(--radius-xs, 0.125rem) 0 0;
    background: var(--color-navy-200, #c7cad9);
}

.login-mockup-rows {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.login-mockup-rows span {
    height: 0.5rem;
    border-radius: var(--radius-full, 999px);
    background: var(--color-border-secondary, #e9eaeb);
}

.login-mockup-rows span:nth-child(2) {
    width: 80%;
}

.login-mockup-rows span:nth-child(3) {
    width: 60%;
}

/* Na węższych ekranach zostaje sam formularz: makieta zmniejszona do pasa nad
   formularzem byłaby nieczytelna i tylko zabierałaby miejsce temu, po co ktoś tu
   przyszedł. */
@media (max-width: 62rem) {
    .login-aside {
        display: none;
    }
}

/* Kto pracuje, w pasku bocznym pod nawigacją — razem z wyjściem. */
.user-box {
    margin-top: auto;
    padding: var(--spacing-3xl, 1.5rem);
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.92);
    font-size: var(--font-size-xs, 0.75rem);
}

.user-box-name {
    font-weight: var(--font-weight-bold, 700);
    overflow-wrap: anywhere;
}

.user-box-role {
    color: rgba(255, 255, 255, 0.6);
}

.user-box form {
    margin-top: var(--spacing-lg, 0.625rem);
}

.user-box button {
    padding: 0;
    border: 0;
    background: none;
    color: rgba(255, 255, 255, 0.75);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.user-box button:hover {
    color: #ffffff;
}

/* ---------------------------------------------------------------------------
   Ciemny motyw a Bootstrap
   ---------------------------------------------------------------------------
   Bootstrap trzyma swoje kolory w zmiennych `--bs-*` z jasnymi wartościami wpisanymi
   w arkusz budowany z scss. Zamiast przepisywać reguły komponentów, przestawiamy same
   zmienne na tokeny systemu — wtedy tabele, pola wyboru i klasy pomocnicze w rodzaju
   `.text-secondary` idą za motywem bez dublowania stylów.

   Bez tego w ciemnym motywie tekst tabel i podpisy zostawały prawie czarne na prawie
   czarnym tle, a listy rozwijane były białymi prostokątami w środku ciemnej karty. */
[data-theme="dark"] {
    --bs-body-color: var(--color-text-primary);
    --bs-body-color-rgb: 247, 247, 247;
    --bs-body-bg: var(--color-bg-secondary);
    --bs-body-bg-rgb: 12, 14, 18;

    --bs-emphasis-color: var(--color-text-primary);
    --bs-emphasis-color-rgb: 247, 247, 247;

    /* Podpisy i drugorzędny tekst: jaśniejszy szary z palety ciemnej, nie ten sam co
       w jasnym motywie — na czarnym tle znikał. */
    --bs-secondary-color: var(--color-text-secondary);
    --bs-secondary-rgb: 206, 207, 210;
    --bs-secondary-bg: var(--color-bg-tertiary);
    --bs-tertiary-color: var(--color-text-tertiary);
    --bs-tertiary-bg: var(--color-bg-tertiary);

    --bs-border-color: var(--color-border-primary);
    --bs-heading-color: var(--color-text-primary);
}

/* Przycisk główny w ciemnym motywie bierze granat z palety ciemnej (#757DD0), a nie ten
   z jasnej (#3A3A66) wpisany w kompilację Bootstrapa — tamten na czarnym tle jest ciemniejszy
   od karty, na której stoi, więc przycisk „zrób to" był najmniej widocznym elementem ekranu.
   W UTS ten sam przycisk ma dokładnie ten odcień. */
[data-theme="dark"] .btn-primary {
    --bs-btn-bg: var(--color-btn-primary-bg);
    --bs-btn-border-color: var(--color-btn-primary-bg);
    --bs-btn-color: var(--color-btn-primary-text);
    --bs-btn-hover-bg: var(--color-btn-primary-bg-hover);
    --bs-btn-hover-border-color: var(--color-btn-primary-bg-hover);
    --bs-btn-hover-color: var(--color-btn-primary-text);
    --bs-btn-active-bg: var(--color-btn-primary-bg-hover);
    --bs-btn-active-border-color: var(--color-btn-primary-bg-hover);
    --bs-btn-active-color: var(--color-btn-primary-text);
}

/* Strzałka listy rozwijanej jest obrazkiem z wpisanym kolorem, więc w ciemnym motywie
   trzeba ją podmienić na jaśniejszą. Podmiana samego obrazka, nie zmiennej Bootstrapa:
   listę maluje własna reguła z `antumo/inputs.css`, która wpisuje `background-image`
   wprost — przez zmienną ta reguła w ogóle nie działała. */
[data-theme="dark"] .form-select,
[data-theme="dark"] select.form-control,
[data-theme="dark"] select.antumo-input {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23CECFD2' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* Znak firmowy wpisany w stronę (komponent `AntumoBrand`). Wysokość zadaje miejsce
   użycia, szerokość liczy się sama z proporcji rysunku; napis nazwy produktu składa się
   firmowym krojem, bo znak jest częścią dokumentu, a nie osobnym obrazkiem. */
.antumo-brand {
    display: block;
    height: 2rem;
    width: auto;
}

/* Nazwa produktu w kroju tekstu, nie nagłówków: CircularXX nie ma odmiany średniej, więc
   przeglądarka brała najbliższą — grubą, i napis wychodził cięższy niż „MDM" w UTS. */
.antumo-brand text {
    font-family: var(--font-family-body);
}

/* ---------------------------------------------------------------------------
   Kroje pisma
   ---------------------------------------------------------------------------
   Treść, podpisy i etykiety idą Circular LL, nagłówki i przyciski CircularXX —
   tak samo jak w UTS i jak mówi system designu. Bootstrap ma tu swoją zmienną
   z CircularXX wpisanym w arkusz budowany z scss, więc przestawiamy ją, a nie
   przepisujemy reguły komponentów. */
:root {
    --bs-body-font-family: var(--font-family-body);
}

body {
    font-family: var(--font-family-body);
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-family-brand);
}

/* Przycisk odświeżania w nagłówku karty, jak w kartach pulpitu UTS: sama ikona, bez tła,
   podświetlana pod kursorem. Karta stoi otwarta godzinami, więc musi dać się przeładować
   bez przeładowania całej strony. */
.card-refresh {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    /* 36 na 36 i okrągły, tak jak przyciski odświeżania zmierzone na pulpicie UTS. */
    width: 36px;
    height: 36px;
    padding: 0;
    border: none;
    border-radius: var(--radius-full, 9999px);
    background: transparent;
    color: var(--color-text-quaternary, #a4a7ae);
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.card-refresh:hover {
    background: var(--color-bg-tertiary, #fafafa);
    color: var(--color-text-secondary, #414651);
}

/* Miejsce, które pasek boczny zabiera kolumnie treści. Odmierza je margines samej kolumny,
   bo pasek i nawigacja stoją poza układem strony — dokładnie jak w UTS, gdzie ich pasek jest
   `position: fixed`, a animowany jest margines opakowania treści (273 i 80 pikseli).

   Nie szerokość paska: przeglądarka nie animuje `width` na elemencie, od którego zależy
   układ — przeskakuje od razu na nową wartość (sprawdzone: `width` nie rusza się w żadną
   stronę, `margin-left` w obie). Stąd brało się to, że po zwinięciu treść robiła się szeroka
   w jednej klatce, a rozwijanie wyglądało dobrze: tam rozjeżdżała się jeszcze nawigacja,
   która stała wtedy w układzie.

   Reguły stoją w arkuszu globalnym, nie w izolowanym: kolumna treści należy do układu strony,
   a klasa `collapsed` do komponentu nawigacji — w izolowanym arkuszu każdej z tych stron
   selektor dostałby własny znacznik zakresu i nie trafiłby w drugą.

   Tylko od szerokości okna, przy której pasek stoi z lewej. Niżej jest belką u góry
   i wysokość bierze z zawartości, więc nawigacja musi zostać w układzie. */
@media (min-width: 641px) {
    .page > main {
        margin-left: 265px;
        transition: margin-left 0.25s ease-in-out;
    }

    /* Zwijanie z tym samym opóźnieniem, co nawigacja (u nich 100 milisekund w `setTimeout`),
       żeby krawędź treści nie wyprzedziła krawędzi panelu. */
    .page:has(.nav-menu.collapsed) > main {
        margin-left: 72px;
        transition-delay: 0.1s;
    }
}

/* Zwinięta nawigacja przycina to, co wystaje poza jej szerokość (patrz NavMenu.razor.css),
   ale otwarte menu konta i menu języków są szersze od paska i wychodzą w prawo — na czas
   ich otwarcia przycięcie trzeba zdjąć. Oba istnieją w drzewie tylko wtedy, gdy są otwarte,
   więc `:has` wystarczy za stan. UTS ma u siebie dokładnie ten sam wyjątek.

   Reguła w arkuszu globalnym, bo łączy element z dwóch komponentów: nawigacji i menu
   konta — w izolowanym każdy dostałby własny znacznik zakresu i selektor nie trafiłby. */
/* Selektor z `.sidebar` z przodu, żeby wygrać z regułą przycinania z arkusza izolowanego
   nawigacji — ten wchodzi po arkuszu globalnym, więc przy równej wadze brałby górę. */
.sidebar .nav-menu.collapsed:has(.user-menu),
.sidebar .nav-menu.collapsed:has(.language-menu) {
    overflow: visible;
}

/* ---------------------------------------------------------------------------
   Okno modalne
   ---------------------------------------------------------------------------
   Własne, bez JavaScriptu Bootstrapa (panel go nie wciąga). Warstwa i okno osobno, bo
   kliknięcie w warstwę zamyka okno, a kliknięcie w okno nie ma go zamykać. */
/* Warstwa prawie czarna, nie przygaszenie: w UTS okno stoi na wyraźnie odciętym tle,
   inaczej na ciemnym motywie zlewa się z treścią pod sobą. */
.modal-backdrop-own {
    position: fixed;
    inset: 0;
    z-index: 1050;
    background: rgba(0, 0, 0, 0.72);
}

.modal-own {
    position: fixed;
    inset: 0;
    z-index: 1051;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    /* Okno nie przy samej krawędzi: w UTS stoi z wyraźnym odstępem od góry, a nie doklejone
       pod pasek. `min` zamiast samego `vh`, żeby na niskim ekranie odstęp nie zjadł treści. */
    padding: min(10vh, 96px) var(--spacing-6xl, 24px) var(--spacing-7xl, 32px);

    /* Okno wyższe od okna przeglądarki przewija się razem z tłem warstwy — inaczej stopka
       z „Zapisz" wypadałaby pod krawędź i nie dałoby się jej kliknąć. */
    overflow-y: auto;
}

/* Szerokość jak w UTS: 608 pikseli na formularz i 768 na okno z tabelą albo z listą
   uprawnień. Wyśrodkowane w poziomie, u góry z odstępem — okno przyklejone do środka
   w pionie skacze przy każdej zmianie wysokości treści. */
.modal-own .modal-dialog {
    width: 100%;
    max-width: 38rem;
    margin: 0;
}

.modal-own .modal-dialog.modal-lg {
    max-width: 48rem;
}

/* Krzyżyk zamykający: własny, bo bootstrapowy `.btn-close` maluje się czarnym rysunkiem
   wpisanym w tło i na ciemnym motywie jest niewidoczny. */
.modal-own .modal-close {
    position: absolute;
    top: var(--spacing-3xl, 24px);
    right: var(--spacing-3xl, 24px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: none;
    border-radius: var(--radius-md, 8px);
    background: transparent;

    /* Krzyżyk w kolorze marki i wyraźnie większy, tak jak w UTS. W oknie rozmowy nie ma
       stopki z „Zamknij", więc to jedyna droga wyjścia — ma być widoczny bez szukania. */
    color: var(--color-btn-primary-bg);
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.modal-own .modal-close:hover {
    background-color: var(--color-bg-tertiary);
    color: var(--color-btn-primary-bg);
}

/* Powierzchnia okna o stopień jaśniejsza od karty i z własną krawędzią — tak jak w UTS.
   Bez krawędzi okno na prawie czarnej warstwie nie miało kształtu: kończyło się tam, gdzie
   kończyła się treść. Kolor i krawędź z tokenów, więc każdy motyw bierze swoje. */
.modal-own .modal-content {
    background-color: var(--color-modal-bg);
    border: 1px solid var(--color-modal-border);
    border-radius: var(--radius-2xl, 16px);
}

/* Nagłówek, treść i stopka rozdzielone kreskami, tak jak w UTS. Kreski w kolorze krawędzi
   okna, a nie z szarości jasnej palety wpisanej w reguły Bootstrapa — te na czarnym tle
   rysowały jasną linię przez całe okno. */
.modal-own .modal-header {
    padding: var(--spacing-3xl, 24px) 64px var(--spacing-3xl, 24px) var(--spacing-3xl, 24px);
    border-bottom: 1px solid var(--color-modal-border);
}

/* Skala napisów w oknie o stopień większa niż w tabelach panelu, tak jak w UTS: okno
   przykrywa ekran i niesie jedną rzecz do zrobienia, więc czyta się je z bliska i wprost,
   a nie skanuje wzrokiem jak wiersze listy. */
/* Tytuł o stopień mniejszy niż nagłówek strony: okno niesie jedną czynność, a nie całą
   stronę — 24 piksele przy etykietach po 16 wyglądały jak nagłówek sekcji w środku okna. */
.modal-own .modal-header .modal-title {
    font-size: var(--font-size-md, 1.25rem);
    font-weight: var(--font-weight-bold, 700);
    line-height: 1.3;
}

.modal-own .modal-body {
    padding: var(--spacing-3xl, 24px);
    font-size: var(--font-size-sm, 1rem);
}

.modal-own .modal-tabs .antumo-tab {
    font-size: var(--font-size-sm, 1rem);
}

/* Podpisy pod polem i pod pozycją zaznaczenia: o stopień mniejsze od napisu, do którego
   należą — mają go objaśniać, nie z nim konkurować. */
.modal-own .modal-body .form-text,
.modal-own .modal-body .small,
.modal-own .modal-body .field-error {
    font-size: var(--font-size-xs, 0.875rem);
}

.modal-own .modal-body .alert {
    font-size: var(--font-size-xs, 0.875rem);
}

.modal-own .modal-footer .btn {
    font-size: var(--font-size-sm, 1rem);
}

/* Odstęp między polami większy niż domyślny bootstrapowy: w UTS pola stoją luźno, a etykieta
   należy wzrokowo do pola pod sobą, nie do pola nad. */
.modal-own .modal-body > .mb-3 {
    margin-bottom: var(--spacing-3xl, 24px) !important;
}

.modal-own .modal-body .form-label,
.modal-own .modal-body .form-check-label {
    font-size: var(--font-size-sm, 1rem);
    margin-bottom: var(--spacing-md, 8px);
}

.modal-own .modal-footer {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg, 12px);
    padding: var(--spacing-xl, 16px) var(--spacing-3xl, 24px);
    border-top: 1px solid var(--color-border-secondary);
}

/* „Anuluj" bez wypełnienia: w oknie jest jedna czynność główna, a wyjście bez zmian nie ma
   z nią konkurować wagą. Pod kursorem dostaje ciemną pigułkę — tak samo jak w UTS, gdzie
   dopiero hover pokazuje, że to też jest przycisk. */
.modal-own .modal-footer .btn-link {
    color: var(--color-btn-primary-bg);
    text-decoration: none;
    font-weight: var(--font-weight-medium, 500);
    border-radius: var(--radius-full, 999px);
    padding-left: var(--spacing-2xl, 20px);
    padding-right: var(--spacing-2xl, 20px);
    transition: background-color 150ms ease, color 150ms ease;
}

.modal-own .modal-footer .btn-link:hover,
.modal-own .modal-footer .btn-link:focus-visible {
    background-color: var(--color-bg-tertiary);
    color: var(--color-btn-primary-bg-hover);
    text-decoration: none;
}

.modal-own .modal-footer .btn-primary {
    border-radius: var(--radius-full, 999px);
    padding-left: var(--spacing-2xl, 20px);
    padding-right: var(--spacing-2xl, 20px);
}

/* Komunikat pod polem wymaganym — pokazywany dopiero po dotknięciu pola, nie od razu przy
   otwarciu okna: czerwony formularz przed pierwszym znakiem czyta się jak lista błędów,
   które ktoś już popełnił. */
.field-error {
    margin-top: var(--spacing-sm, 6px);
    font-size: var(--font-size-2xs, 0.75rem);
    color: var(--color-text-secondary);
}

/* Zakładki w oknie: kreska pod nimi na całą szerokość treści, tak jak w UTS. */
.modal-tabs {
    margin-bottom: var(--spacing-3xl, 24px);
}

.modal-tabs .antumo-tab {
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
}

/* Lista uprawnień w oknie przewija się u siebie: przy ośmiu pozycjach z opisami okno byłoby
   wyższe od ekranu, a wtedy stopka z „Zapisz" ucieka poniżej krawędzi. */
.permission-list {
    max-height: 22rem;
    overflow-y: auto;
}

/* ---------------------------------------------------------------------------
   Czynności wiersza tabeli
   --------------------------------------------------------------------------- */
.row-actions {
    position: relative;
    display: inline-flex;
}

.row-actions-backdrop {
    position: fixed;
    inset: 0;
    z-index: 30;
}

/* Lista czynności jest przypięta do okna przeglądarki i ustawiana przez `js/rowactions.js`:
   tabela przewija się w poprzek, a przewijanie w jednej osi przycina zawartość w obu — lista
   rozwinięta w wierszu była przez to ucinana. Ukryta do czasu ustawienia, żeby nie mrugnęła
   w lewym górnym narożniku. */
.row-actions-menu {
    position: fixed;
    top: 0;
    left: 0;
    visibility: hidden;
    z-index: 1040;
    min-width: 12rem;
    padding: var(--spacing-xs, 4px);
    background-color: var(--color-bg-secondary);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-lg, 12px);
    box-shadow: var(--shadow-lg);
}

.row-actions-item {
    display: block;
    width: 100%;
    padding: var(--spacing-md, 8px) var(--spacing-lg, 12px);
    border: none;
    border-radius: var(--radius-md, 8px);
    background: none;
    text-align: left;

    /* Pozycja listy bywa odnośnikiem, nie przyciskiem — a odnośnik przychodzi
       z podkreśleniem i wygląda w liście jak jedyna klikalna pozycja z czterech. */
    text-decoration: none;
    font-family: var(--font-family-brand);
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background-color 150ms ease;
}

.row-actions-item:hover {
    background-color: var(--color-bg-tertiary);
}

.row-actions-item.is-danger {
    color: var(--color-red-500, #d14c4c);
}

/* Kolumna z czynnościami jest tak szeroka, jak jej przycisk — reszta miejsca należy do
   danych. */
.col-actions {
    width: 1%;
    white-space: nowrap;
}

/* Odznaka obrysowana, bez wypełnienia: przy nazwie roli („Statyczna", „Domyślna") mówi o niej
   coś dodatkowego, a nie stanowi o niej samej — wypełniona odznaka przeciągałaby wzrok
   z nazwy. Tak samo wyglądają te odznaki w UTS. */
.badge-outline {
    background: transparent;
    border: 1px solid var(--color-border-primary);
    color: var(--color-text-secondary);
    font-weight: var(--font-weight-medium, 500);
}

/* Zakładka wybrana: kolor i kreska w barwie przycisku głównego, czyli granat z palety
   bieżącego motywu — `--color-brand-primary` jest jedną wartością dla obu i na ciemnym tle
   kreska w nim była niewidoczna. Tak samo wygląda zakładka w UTS. */
.antumo-tab.active {
    color: var(--color-btn-primary-bg);
    box-shadow: inset 0 -2px 0 var(--color-btn-primary-bg);
}

/* Uwaga w oknie: karta z ikoną po lewej, nie jasnoniebieski pasek z Bootstrapa —
   tamten na ciemnym motywie świeci mocniej niż treść, o której mówi. */
.alert-info {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-lg, 12px);
    background-color: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-primary);
    color: var(--color-text-secondary);
    border-radius: var(--radius-lg, 12px);
    padding: var(--spacing-xl, 16px);
    font-size: var(--font-size-2xs, 0.75rem);
}

.alert-icon {
    flex: 0 0 auto;
    margin-top: 2px;
    color: var(--color-btn-primary-bg);
}

/* ---------------------------------------------------------------------------
   Okno konta
   ---------------------------------------------------------------------------
   Awatar po lewej, pola po prawej — jak w UTS. Awatar nie zwęża pól przy wąskim oknie:
   przy braku miejsca schodzi nad nie. */
.user-dialog-body {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-3xl, 24px);
    flex-wrap: wrap;
}

.user-dialog-fields {
    flex: 1 1 20rem;
    min-width: 0;
}

/* Wybór roli: cały wiersz jest polem kliknięcia, nie sam kółeczek — przy jednej roli na
   konto trafienie w 20 pikseli byłoby jedyną drogą jej zmiany. */
.role-choice-list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 8px);
    max-height: 22rem;
    overflow-y: auto;
}

.role-choice {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-lg, 12px);
    padding: var(--spacing-lg, 12px) var(--spacing-xl, 16px);
    border: 1px solid var(--color-border-secondary);
    border-radius: var(--radius-lg, 12px);
    cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease;
}

.role-choice:hover {
    border-color: var(--color-border-primary);
}

.role-choice.is-chosen {
    border-color: var(--color-btn-primary-bg);
    background-color: var(--color-bg-tertiary);
}

.role-choice .form-check-input {
    margin: 2px 0 0;
    float: none;
}

.role-choice-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.role-choice-name {
    display: flex;
    align-items: center;
    gap: var(--spacing-md, 8px);
    font-weight: var(--font-weight-medium, 500);
}

.role-choice-permissions {
    font-size: var(--font-size-xs, 0.875rem);
    color: var(--color-text-secondary);
}

/* Hasło wylosowane przy zakładaniu konta: do przeczytania i przepisania, więc czcionka
   o stałej szerokości i wyraźne tło — to jedyny moment, w którym da się je zobaczyć. */
.created-password {
    display: inline-block;
    padding: var(--spacing-md, 8px) var(--spacing-lg, 12px);
    background-color: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-primary);
    border-radius: var(--radius-md, 8px);
    font-family: var(--font-family-mono, ui-monospace, monospace);
    font-size: var(--font-size-sm, 1rem);
    letter-spacing: 0.04em;
    color: var(--color-text-primary);
    user-select: all;
}

/* Wybór okna czasu na przeglądzie: etykieta i przyciski w jednym wierszu, a na wąskim
   ekranie zawijają się zamiast wypychać kartę. */
.overview-window {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* Paski ostrzeżeń w ciemnym motywie: Bootstrap daje im kremowe i różowe tła rodem z jasnego
   układu, a na prawie czarnej stronie taki pasek świeci mocniej niż treść, o którą chodzi.
   Zostaje kolor jako obwódka i ślad w tle, czytelny tekst bierzemy z palety. */
[data-theme="dark"] .alert {
    background-color: var(--color-bg-tertiary);
    border-color: var(--color-border-primary);
    color: var(--color-text-primary);
}

[data-theme="dark"] .alert-warning {
    background-color: rgba(var(--bs-warning-rgb), 0.12);
    border-color: rgba(var(--bs-warning-rgb), 0.35);
}

[data-theme="dark"] .alert-danger {
    background-color: rgba(var(--bs-danger-rgb), 0.12);
    border-color: rgba(var(--bs-danger-rgb), 0.35);
}

[data-theme="dark"] .alert-info {
    background-color: rgba(var(--bs-info-rgb), 0.12);
    border-color: rgba(var(--bs-info-rgb), 0.35);
}

[data-theme="dark"] .alert-success {
    background-color: rgba(var(--bs-success-rgb), 0.12);
    border-color: rgba(var(--bs-success-rgb), 0.35);
}

/* Polecenie w treści ostrzeżenia: na ciemnym tle różowy Bootstrapa gryzie się z paskiem,
   a to jest rzecz do przepisania do terminala, nie ozdoba. */
[data-theme="dark"] .alert code {
    background-color: var(--color-bg-secondary);
    color: var(--color-text-primary);
    padding: 0.1rem 0.35rem;
    border-radius: var(--radius-sm, 4px);
}

/* Ślad z urządzenia w karcie: SDK trzyma sto ostatnich wpisów, a karta bez ograniczenia
   bywa dłuższa niż wszystko, co pod nią stoi. Całość otwiera się w oknie. */
.issue-timeline-viewport {
    max-height: 18rem;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

/* Ślad kroków w oknie: oprawa jak przy wydruku stosu, ale wpisy to zdania, nie wiersze
   wydruku — zostaje odstęp od krawędzi, żeby nie kleiły się do obramowania. */
.timeline-dialog-viewport {
    padding: var(--spacing-lg, 12px);
}

/* Sekcja szczegółów z chwytem do przestawiania.

   Chwyt stoi obok karty, nie w niej: karty są różne (jedna jest kartą, druga trójką kart
   obok siebie), a chwyt ma być w tym samym miejscu przy każdej. Widać go dopiero pod
   kursorem — na co dzień nie ma po co dokładać kolejnego znaczka do i tak gęstej strony. */
/* Chwyty stoją w odstępie między listą a treścią, a nie obok niej: kolumna cofa się prawie
   o szerokość chwytu, więc nie dokłada do układu własnego marginesu.

   Prawie, bo po prawej stronie kolumny 10 px zjada jej pasek przewijania. Bez tej poprawki
   odstęp od listy wychodzi o tyle węższy niż odstęp od skrótów po drugiej stronie. */
.issue-sections {
    margin-left: calc(-1rem + 10px);
}

.issue-section {
    position: relative;
    padding-left: 1rem;
}

.issue-section-grip {
    position: absolute;
    top: 0.85rem;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 2rem;
    color: var(--color-text-quaternary, #717680);
    cursor: grab;

    /* Widoczny zawsze, choć blado: chwyt, który pokazuje się dopiero pod kursorem, jest
       funkcją, o której nikt się nie dowie. Pod kursorem nabiera pełnego koloru. */
    opacity: 0.4;
    transition: opacity 0.15s ease, color 0.15s ease;
}

.issue-section:hover .issue-section-grip,
.issue-section-grip:focus-visible {
    opacity: 1;
    color: var(--color-text-secondary, #535862);
}

.issue-section-grip:active {
    cursor: grabbing;
}

/* Przeciągana sekcja blednie, a ta pod kursorem dostaje kreskę u góry — widać, dokąd
   trafi upuszczenie, bez podnoszenia całej karty. */
.issue-section.is-dragging {
    opacity: 0.5;
}

.issue-section.is-over::before {
    content: "";
    position: absolute;
    top: -0.5rem;
    left: 0;
    right: 0;
    height: 2px;
    border-radius: 2px;
    background: var(--color-brand-solid, #7F56D9);
}


/* ---------------------------------------------------------------------------
   Powiadomienia o nowych zgłoszeniach
   --------------------------------------------------------------------------- */

.issue-toasts {
    position: fixed;
    right: var(--spacing-xl, 16px);
    bottom: var(--spacing-xl, 16px);
    z-index: 1080;

    display: flex;
    flex-direction: column;
    gap: var(--spacing-md, 8px);

    /* Wąska kolumna przy krawędzi: powiadomienie ma być widoczne kątem oka, a nie
       zasłaniać tabelę, nad którą ktoś właśnie pracuje. */
    width: min(26rem, calc(100vw - 2 * var(--spacing-xl, 16px)));
}

.issue-toast {
    display: flex;
    align-items: stretch;

    background-color: var(--color-card-bg);
    border: 1px solid var(--color-card-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg, 0 12px 16px -4px rgba(10, 13, 18, 0.08));

    /* Wjazd od strony, przy której stoi — ruch mówi „to właśnie przyszło" wyraźniej
       niż samo pojawienie się w rogu. */
    animation: issue-toast-in 0.18s ease-out;
}

@keyframes issue-toast-in {
    from {
        opacity: 0;
        transform: translateX(1rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .issue-toast {
        animation: none;
    }
}

.issue-toast-body {
    flex: 1;
    display: flex;
    gap: var(--spacing-lg, 12px);
    align-items: flex-start;

    padding: var(--spacing-lg, 12px) var(--spacing-md, 8px) var(--spacing-lg, 12px) var(--spacing-lg, 12px);
    background: none;
    border: 0;
    border-radius: var(--radius-xl) 0 0 var(--radius-xl);
    text-align: left;
    cursor: pointer;
}

.issue-toast-body:hover {
    background-color: var(--color-bg-primary-hover, rgba(127, 86, 217, 0.06));
}

.issue-toast-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;

    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-full, 999px);

    color: var(--color-fg-brand-primary, #7f56d9);
    background-color: var(--color-bg-brand-primary, rgba(127, 86, 217, 0.12));
}

.issue-toast-text {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.issue-toast-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--color-text-tertiary, #717680);
}

.issue-toast-title {
    color: var(--color-text-primary, #181d27);

    /* Tytuł zgłoszenia z kasy bywa akapitem, a powiadomienie ma zostać kartą, nie ścianą. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.issue-toast-close {
    display: flex;
    align-items: flex-start;

    padding: var(--spacing-lg, 12px) var(--spacing-lg, 12px) var(--spacing-lg, 12px) var(--spacing-sm, 6px);
    background: none;
    border: 0;
    border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
    color: var(--color-text-quaternary, #717680);
    cursor: pointer;
}

.issue-toast-close:hover {
    color: var(--color-text-secondary, #535862);
}
