/* ============================================================
   Docuflair Core Design System
   Modern UI with optional Dark Mode
   ============================================================ */

/* --- Design Tokens (Light) --- */
:root {
    /* Layout */
    --vk-sidebar-width: 260px;
    --vk-sidebar-rail: 64px;
    --vk-topbar-height: 56px;

    /* Radius */
    --vk-radius-sm: 6px;
    --vk-radius: 10px;
    --vk-radius-lg: 14px;

    /* Transition */
    --vk-transition: 0.2s ease;

    /* Colors - Accent (Docuflair CI Red) */
    --vk-accent: #C0341D;
    --vk-accent-hover: #a02c18;
    --vk-accent-subtle: rgba(192, 52, 29, 0.08);
    --vk-accent-border: rgba(192, 52, 29, 0.25);

    /* Colors - Surfaces */
    --vk-bg-body: #f4f6fa;
    --vk-bg-card: #ffffff;
    --vk-bg-card-hover: #fafbfd;
    --vk-bg-elevated: #ffffff;
    --vk-bg-inset: #f0f2f5;
    --vk-bg-sidebar: #101827;
    --vk-bg-sidebar-hover: rgba(255, 255, 255, 0.06);
    --vk-bg-sidebar-active: var(--vk-accent);
    --vk-bg-topbar: #ffffff;
    --vk-bg-viewer: #4b5563;

    /* Colors - Borders */
    --vk-border: #e3e6ec;
    --vk-border-light: #eef0f4;
    /* Input borders need >= 3:1 against the field surface (WCAG 1.4.11) — the
       decorative card border above is far too light for that. */
    --vk-border-input: #8a92a0;
    --vk-border-sidebar: rgba(255, 255, 255, 0.08);

    /* Folder icons — Windows-like amber so the tree/tiles read as familiar folders.
       Outline icons (tree, list) need a deeper tone than the solid tile fill. */
    --vk-folder: #e0a132;
    --vk-folder-solid: #ffc85c;

    /* Colors - Text */
    --vk-text: #1a1d23;
    --vk-text-secondary: #5f6672;
    /* Muted must still reach 4.5:1 on card AND inset surfaces (WCAG 1.4.3);
       the former #8b919d measured 3.17:1 on white. */
    --vk-text-muted: #626c7e;
    --vk-text-sidebar: rgba(255, 255, 255, 0.65);
    --vk-text-sidebar-active: #ffffff;
    /* 0.55 alpha = 6.1:1 on the sidebar surface; 0.35 measured only 3.2:1. */
    --vk-text-sidebar-section: rgba(255, 255, 255, 0.55);

    /* Colors - Semantic */
    --vk-success: #16a34a;
    --vk-success-bg: #dcfce7;
    --vk-success-text: #166534;
    --vk-warning: #d97706;
    --vk-warning-bg: #fef3c7;
    --vk-warning-subtle: rgba(217, 119, 6, 0.10);
    --vk-warning-text: #92400e;
    --vk-danger: #dc2626;
    --vk-danger-bg: #fee2e2;
    --vk-danger-text: #991b1b;
    --vk-info-bg: #eff6ff;
    --vk-info-text: #1d4ed8;

    /* Shadows */
    --vk-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);
    --vk-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
    --vk-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04);
    --vk-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.08), 0 2px 6px rgba(0, 0, 0, 0.04);

    /* Search highlight */
    --vk-highlight-bg: rgba(254, 240, 138, 0.5);
    --vk-highlight-border: rgba(202, 138, 4, 0.5);
    --vk-highlight-active-bg: rgba(251, 146, 60, 0.55);
    --vk-highlight-active-border: rgba(234, 88, 12, 0.8);

    /* Light-mode link color: Bootstrap's stock #0d6efd is 4.16:1 on --vk-bg-body
       (below AA) — remap to the CI accent like the dark block already does. */
    --bs-link-color: var(--vk-accent);
    --bs-link-color-rgb: 192, 52, 29;
    --bs-link-hover-color: var(--vk-accent-hover);
    --bs-link-hover-color-rgb: 160, 44, 24;
}

/* --- Design Tokens (Dark) --- */
[data-theme="dark"] {
    --vk-bg-body: #0f1117;
    --vk-bg-card: #191c24;
    --vk-bg-card-hover: #1e2130;
    --vk-bg-elevated: #1e2130;
    --vk-bg-inset: #14161e;
    --vk-bg-sidebar: #0d0f15;
    --vk-bg-sidebar-hover: rgba(255, 255, 255, 0.05);
    --vk-bg-topbar: #191c24;
    --vk-bg-viewer: #1a1c24;

    --vk-border: #2a2d38;
    --vk-border-light: #22252e;
    --vk-border-input: #6a7180;
    --vk-border-sidebar: rgba(255, 255, 255, 0.06);

    /* Lifted a little on dark so the amber does not sink into the background. */
    --vk-folder: #e9b661;
    --vk-folder-solid: #e9b44c;

    --vk-text: #e4e6eb;
    --vk-text-secondary: #9ca0ab;
    /* 5.9:1 on the dark card surface; the former #6b7080 measured 3.45:1. */
    --vk-text-muted: #9298a5;
    --vk-text-sidebar: rgba(255, 255, 255, 0.55);

    /* White on the dark accent (#3b82f6) is only 3.68:1 — the active sidebar
       entry gets a darker blue of its own so its white label passes 4.5:1. */
    --vk-bg-sidebar-active: #2563eb;

    --vk-accent: #3b82f6;
    --vk-accent-hover: #60a5fa;
    --vk-accent-subtle: rgba(59, 130, 246, 0.12);
    --vk-accent-border: rgba(59, 130, 246, 0.3);

    --vk-success-bg: rgba(22, 163, 74, 0.15);
    --vk-success-text: #4ade80;
    --vk-warning-bg: rgba(217, 119, 6, 0.15);
    --vk-warning-subtle: rgba(217, 119, 6, 0.18);
    --vk-warning-text: #fbbf24;
    --vk-danger-bg: rgba(220, 38, 38, 0.15);
    --vk-danger-text: #f87171;
    --vk-info-bg: rgba(37, 99, 235, 0.12);
    --vk-info-text: #60a5fa;

    --vk-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.2);
    --vk-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
    --vk-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), 0 1px 3px rgba(0, 0, 0, 0.2);
    --vk-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.2);

    --vk-highlight-bg: rgba(250, 204, 21, 0.2);
    --vk-highlight-border: rgba(234, 179, 8, 0.5);
    --vk-highlight-active-bg: rgba(249, 115, 22, 0.35);
    --vk-highlight-active-border: rgba(234, 88, 12, 0.7);

    /* Map Bootstrap 5.3 CSS custom properties to dark tokens so utilities like
       .form-text, .text-secondary, .text-body-secondary, .pagination, .nav-tabs
       and link colors inherit dark contrast automatically — avoids per-selector
       overrides. */
    --bs-body-bg: var(--vk-bg-body);
    --bs-body-color: var(--vk-text);
    --bs-emphasis-color: var(--vk-text);
    --bs-secondary-color: var(--vk-text-secondary);
    --bs-secondary-bg: var(--vk-bg-inset);
    --bs-secondary-rgb: 156, 160, 171;
    --bs-tertiary-color: var(--vk-text-muted);
    --bs-tertiary-bg: var(--vk-bg-card);
    --bs-border-color: var(--vk-border);
    --bs-border-color-translucent: var(--vk-border);
    --bs-link-color: var(--vk-accent);
    --bs-link-color-rgb: 59, 130, 246;
    --bs-link-hover-color: var(--vk-accent-hover);
    --bs-link-hover-color-rgb: 96, 165, 250;

    --bs-pagination-color: var(--vk-text-secondary);
    --bs-pagination-bg: var(--vk-bg-card);
    --bs-pagination-border-color: var(--vk-border);
    --bs-pagination-hover-color: var(--vk-text);
    --bs-pagination-hover-bg: var(--vk-bg-card-hover);
    --bs-pagination-hover-border-color: var(--vk-border);
    --bs-pagination-focus-color: var(--vk-text);
    --bs-pagination-focus-bg: var(--vk-bg-card-hover);
    --bs-pagination-active-bg: var(--vk-accent);
    --bs-pagination-active-border-color: var(--vk-accent);
    --bs-pagination-disabled-color: var(--vk-text-muted);
    --bs-pagination-disabled-bg: var(--vk-bg-inset);
    --bs-pagination-disabled-border-color: var(--vk-border);

    /* RGB triplets for utilities that use rgba() with --bs-*-rgb variables:
       .text-body, .bg-body-secondary, .bg-body-tertiary. Must match the
       corresponding non-rgb token values above. */
    --bs-body-color-rgb: 228, 230, 235;
    --bs-secondary-bg-rgb: 20, 22, 30;
    --bs-tertiary-bg-rgb: 25, 28, 36;

    /* Alert + subtle/emphasis tokens — Bootstrap's .alert-{variant}, .text-*-emphasis
       and .bg-*-subtle utilities read these. Mirrors Bootstrap's own data-bs-theme=dark
       defaults but reuses our --vk-* palette for visual consistency. */
    --bs-primary-bg-subtle: var(--vk-accent-subtle);
    --bs-primary-text-emphasis: var(--vk-accent-hover);
    --bs-primary-border-subtle: var(--vk-accent-border);
    --bs-secondary-bg-subtle: var(--vk-bg-inset);
    --bs-secondary-text-emphasis: var(--vk-text-secondary);
    --bs-secondary-border-subtle: var(--vk-border);
    --bs-success-bg-subtle: var(--vk-success-bg);
    --bs-success-text-emphasis: var(--vk-success-text);
    --bs-success-border-subtle: rgba(22, 163, 74, 0.3);
    --bs-info-bg-subtle: var(--vk-info-bg);
    --bs-info-text-emphasis: var(--vk-info-text);
    --bs-info-border-subtle: rgba(37, 99, 235, 0.3);
    --bs-warning-bg-subtle: var(--vk-warning-bg);
    --bs-warning-text-emphasis: var(--vk-warning-text);
    --bs-warning-border-subtle: rgba(217, 119, 6, 0.3);
    --bs-danger-bg-subtle: var(--vk-danger-bg);
    --bs-danger-text-emphasis: var(--vk-danger-text);
    --bs-danger-border-subtle: rgba(220, 38, 38, 0.3);
    --bs-light-bg-subtle: var(--vk-bg-inset);
    --bs-light-text-emphasis: var(--vk-text);
    --bs-light-border-subtle: var(--vk-border);
    --bs-dark-bg-subtle: var(--vk-bg-card);
    --bs-dark-text-emphasis: var(--vk-text);
    --bs-dark-border-subtle: var(--vk-border);

    color-scheme: dark;
}

/* .bg-light reads --bs-light-rgb directly (not a remappable variable in the
   sense that other components consume it), so we override the utility itself
   to use an inset surface in dark mode. */
[data-theme="dark"] .bg-light {
    background-color: var(--vk-bg-inset) !important;
}

/* The global .text-dark override above flips dark text to light, which is right
   on the page background but breaks contrast on light-bg badges
   (.badge.bg-warning, .bg-info, .bg-light — those need to stay dark). */
[data-theme="dark"] .badge.text-dark {
    color: #1a1a1a !important;
}

/* Bootstrap's default .nav-tabs active-tab background is --bs-body-bg, which
   in dark mode equals the page background — the active tab visually disappears.
   Lift it onto card surface so it reads as elevated. */
[data-theme="dark"] .nav-tabs {
    --bs-nav-tabs-link-active-bg: var(--vk-bg-card);
    --bs-nav-tabs-link-active-border-color: var(--vk-border) var(--vk-border) var(--vk-bg-card);
}

/* --- Global Reset & Base --- */
*, *::before, *::after {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background: var(--vk-bg-body);
    color: var(--vk-text);
}

/* Bootstrap-Extension: Icon-only Button. Kombiniert Flex-Centering mit
   min-height passend zur Text-Button-Höhe (line-height × font-size + padding + border)
   damit gemischte Icon/Text-Toolbars konsistent ausgerichtet sind. Nutzt Bootstraps
   CSS-Custom-Properties — passt sich automatisch an btn-sm / btn / btn-lg an. */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: calc(var(--bs-btn-line-height) * 1em + var(--bs-btn-padding-y) * 2 + var(--bs-btn-border-width) * 2);
}

/* Bootstrap-Extension: noch kleinere Variante als btn-sm — für inline "Manage"-Aktionen
   in Listen-Headern. Bootstrap hat seit 5.0 kein btn-xs mehr. */
.btn-xs {
    --bs-btn-padding-y: 0.125rem;
    --bs-btn-padding-x: 0.4rem;
    --bs-btn-font-size: 0.7rem;
    --bs-btn-border-radius: var(--bs-border-radius-sm);
    /* WCAG 2.5.8: interactive targets need >= 24x24 CSS px. */
    min-height: 24px;
    min-width: 24px;
}

/* Review row (InfoTab): keep a stable layout when toggling the review state so the
   panel doesn't reflow. The icon slot is always reserved, and the status label and
   toggle button reserve enough width for the longest localized text in either state. */
.velkaris-review-icon {
    flex: 0 0 14px;
    width: 14px;
}

.velkaris-review-status {
    min-width: 6.5rem;
}

.velkaris-review-btn {
    min-width: 9.5rem;
    text-align: center;
}

/* Toggleable Chevron-Icon mit Animation. Klasse .expanded statt
   inline transform für Inline-CSS-Verbot bei statischen Rotation-Werten. */
.chevron-toggle {
    transition: transform 0.2s;
}

.chevron-toggle.expanded {
    transform: rotate(90deg);
}

/* Stat-Card-Variante: Filename als value statt big-number — kompaktere
   Schrift + Truncation für lange Dateinamen. */
.velkaris-stat-card .stat-value-filename {
    font-size: 1.1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Bootstrap-Extension: extra-small Font-Size 0.75rem. Bootstrap-Utilities
   gehen nur bis fs-6 (1rem); für Mikro-Badges in Headings wird .fs-xs nötig. */
.fs-xs {
    font-size: 0.75rem;
}

/* Override Bootstrap for dark mode */
[data-theme="dark"] .card {
    background-color: var(--vk-bg-card);
    border-color: var(--vk-border);
    color: var(--vk-text);
}

[data-theme="dark"] .card-header {
    background-color: var(--vk-bg-inset);
    border-color: var(--vk-border);
    color: var(--vk-text);
}

[data-theme="dark"] .card-body {
    color: var(--vk-text);
}

[data-theme="dark"] .table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--vk-text);
    --bs-table-border-color: var(--vk-border);
    --bs-table-hover-bg: var(--vk-bg-card-hover);
    color: var(--vk-text);
}

[data-theme="dark"] .table th {
    color: var(--vk-text-muted);
}

[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select {
    background-color: var(--vk-bg-inset);
    border-color: var(--vk-border);
    color: var(--vk-text);
}

[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus {
    background-color: var(--vk-bg-inset);
    border-color: var(--vk-accent);
    color: var(--vk-text);
    box-shadow: 0 0 0 3px var(--vk-accent-subtle);
}

[data-theme="dark"] .form-control::placeholder {
    color: var(--vk-text-muted);
}

/* Floating labels: the floated label is the visible caption, so the placeholder
   must stay invisible — the dark-mode ::placeholder recolor above would win the
   cascade against Bootstrap's transparent rule otherwise. */
[data-theme="dark"] .form-floating > .form-control::placeholder {
    color: transparent;
}

/* MultiSelectDropdown: invisible fixed backdrop closes on outside click;
   the panel floats above it with a scrollable option list. */
.velkaris-msd-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.velkaris-msd-menu {
    position: absolute;
    z-index: 1045;
}

.velkaris-msd-list {
    max-height: 260px;
    overflow-y: auto;
}

/* Flag/icon shown inside a SearchSelectDropdown option (self-hosted SVGs, no CDN).
   4:3 flags; the hairline ring keeps white flags (DK/CH) visible on a light menu. */
.velkaris-select-icon {
    width: 1.33em;
    height: 1em;
    object-fit: cover;
    flex: 0 0 auto;
    border-radius: 1px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .12);
}

/* Optgroup-style zone header inside a grouped SearchSelectDropdown. */
.velkaris-msd-group {
    pointer-events: none;
}

/* Row-action dropdowns (kebab menus) inside a velkaris-table would be clipped
   by the wrapper's scroll context — while a menu is open, let it overflow. */
.velkaris-table:has(.velkaris-msd-menu) {
    overflow: visible;
}

/* Breadcrumb segments: cap each label so deep folder chains and long file
   names truncate with an ellipsis instead of wrapping the whole trail. */
.velkaris-crumb-label {
    max-width: 220px;
}

[data-theme="dark"] .input-group .btn {
    border-color: var(--vk-border);
}

[data-theme="dark"] .btn-outline-primary {
    color: var(--vk-accent);
    border-color: var(--vk-accent-border);
}

[data-theme="dark"] .btn-outline-secondary {
    color: var(--vk-text-secondary);
    border-color: var(--vk-border);
}

[data-theme="dark"] .btn-outline-warning {
    color: var(--vk-warning-text);
    border-color: var(--vk-warning-bg);
}

[data-theme="dark"] .btn-outline-danger {
    color: var(--vk-danger-text);
    border-color: var(--vk-danger-bg);
}

[data-theme="dark"] .alert-warning {
    background-color: var(--vk-warning-bg);
    border-color: transparent;
    color: var(--vk-warning-text);
}

[data-theme="dark"] .alert-info {
    background-color: var(--vk-info-bg);
    border-color: transparent;
    color: var(--vk-info-text);
}

[data-theme="dark"] .alert-danger {
    background-color: var(--vk-danger-bg);
    border-color: transparent;
    color: var(--vk-danger-text);
}

[data-theme="dark"] .text-dark {
    color: var(--vk-text) !important;
}

[data-theme="dark"] .text-muted {
    color: var(--vk-text-muted) !important;
}

[data-theme="dark"] .breadcrumb-item a {
    color: var(--vk-accent);
}

[data-theme="dark"] .breadcrumb-item.active {
    color: var(--vk-text-muted);
}

[data-theme="dark"] .list-group-item {
    background-color: var(--vk-bg-card);
    border-color: var(--vk-border);
    color: var(--vk-text);
}

[data-theme="dark"] .list-group-item-action:hover {
    background-color: var(--vk-bg-card-hover);
    color: var(--vk-text);
}

/* Subtle status-badge palette — replaces Bootstrap's saturated default
   .bg-success / .bg-danger (which produced unreadable contrast in light mode
   because Bootstrap 5.3 no longer forces white text on .badge). Uses the same
   --vk-* tokens both themes already define for alerts and policy badges. */
.badge.bg-success {
    background-color: var(--vk-success-bg) !important;
    color: var(--vk-success-text) !important;
}

.badge.bg-secondary {
    background-color: var(--vk-bg-inset) !important;
    /* Secondary (not muted): badge text is informational and must pass 4.5:1
       on the inset surface in both themes. */
    color: var(--vk-text-secondary) !important;
}

.badge.bg-danger {
    background-color: var(--vk-danger-bg) !important;
    color: var(--vk-danger-text) !important;
}

[data-theme="dark"] .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

[data-theme="dark"] dt {
    color: var(--vk-text-muted);
}

[data-theme="dark"] dd {
    color: var(--vk-text);
}

[data-theme="dark"] code {
    color: var(--vk-accent);
    background: var(--vk-accent-subtle);
}

[data-theme="dark"] .spinner-border.text-primary {
    color: var(--vk-accent) !important;
}

/* ============================================================
   App Layout
   ============================================================ */
.velkaris-app {
    display: flex;
    min-height: 100vh;
}

/* ============================================================
   Sidebar
   ============================================================ */
.velkaris-sidebar {
    width: var(--vk-sidebar-width);
    background: var(--vk-bg-sidebar);
    color: var(--vk-text-sidebar);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1000;
    /* Not the scroller: the nav list scrolls instead (see .velkaris-sidebar-nav), so brand and
       footer stay pinned. Otherwise a long nav (system admin) would push the collapse toggle
       in the footer out of view — exactly the control that must always be reachable. */
    overflow: hidden;
    border-right: 1px solid var(--vk-border-sidebar);
    transition: width 0.25s ease;
}

/* Collapsed = icon rail: the sidebar stays in place, only shrinks to icon width. */
.sidebar-collapsed .velkaris-sidebar {
    width: var(--vk-sidebar-rail);
}

.velkaris-sidebar-brand {
    padding: 1rem 1.25rem;
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--vk-border-sidebar);
    color: inherit;
    text-decoration: none;
}

.velkaris-sidebar-brand:hover {
    opacity: 0.85;
}

.velkaris-sidebar-brand .brand-logo {
    height: 32px;
    width: auto;
    object-fit: contain;
}

/* Logo swap: full wordmark expanded, icon-only in the rail. */
.velkaris-sidebar-brand .brand-logo-icon {
    display: none;
}

.sidebar-collapsed .velkaris-sidebar-brand {
    padding: 1rem 0;
    justify-content: center;
}

.sidebar-collapsed .velkaris-sidebar-brand .brand-logo-full {
    display: none;
}

.sidebar-collapsed .velkaris-sidebar-brand .brand-logo-icon {
    display: block;
    height: 28px;
    max-width: calc(var(--vk-sidebar-rail) - 1.25rem);
}

.velkaris-sidebar-nav {
    list-style: none;
    padding: 0.75rem 0.75rem;
    margin: 0;
    flex: 1;
    /* min-height:0 is what actually lets a flex child shrink and scroll. */
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Foot of the sidebar: holds the collapse toggle. Pinned below the scrolling nav. */
.velkaris-sidebar-footer {
    display: flex;
    justify-content: flex-end;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--vk-border-sidebar);
    flex-shrink: 0;
}

/* In the icon rail there is no room to sit right-aligned — centre it under the icons. */
.sidebar-collapsed .velkaris-sidebar-footer {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
}

/* The sidebar is dark; the default outline button would be near-invisible on it. */
.velkaris-sidebar-toggle {
    color: var(--vk-text-sidebar);
    border: 1px solid var(--vk-border-sidebar);
    background: transparent;
}

.velkaris-sidebar-toggle:hover {
    color: var(--vk-text-sidebar);
    background: rgba(255, 255, 255, 0.08);
}

.velkaris-sidebar-nav .nav-section {
    padding: 1.25rem 0.75rem 0.375rem;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--vk-text-sidebar-section);
    font-weight: 700;
}

.velkaris-sidebar-nav .nav-item a {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.55rem 0.875rem;
    color: var(--vk-text-sidebar);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 450;
    border-radius: var(--vk-radius-sm);
    transition: background-color var(--vk-transition), color var(--vk-transition);
}

.velkaris-sidebar-nav .nav-item a:hover {
    background: var(--vk-bg-sidebar-hover);
    color: var(--vk-text-sidebar-active);
}

.velkaris-sidebar-nav .nav-item a.active {
    background: var(--vk-bg-sidebar-active);
    color: var(--vk-text-sidebar-active);
    font-weight: 550;
}

.velkaris-sidebar-nav .nav-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    opacity: 0.7;
}

.velkaris-sidebar-nav .nav-item a.active .nav-icon {
    opacity: 1;
}

/* --- Rail mode: hide labels + section headers, center the icons --- */
.sidebar-collapsed .velkaris-sidebar-nav {
    padding-left: 0;
    padding-right: 0;
    align-items: center;
}

.sidebar-collapsed .velkaris-sidebar-nav .nav-item {
    width: 100%;
}

.sidebar-collapsed .velkaris-sidebar-nav .nav-item a {
    justify-content: center;
    gap: 0;
    padding: 0.55rem 0;
}

.sidebar-collapsed .velkaris-sidebar-nav .nav-item a span {
    display: none;
}

/* Keep section breaks as a thin divider but drop the (now clipped) label text. */
.sidebar-collapsed .velkaris-sidebar-nav .nav-section {
    padding: 0.5rem 0.75rem;
    font-size: 0;
    border-top: 1px solid var(--vk-border-sidebar);
    margin: 0.375rem 0.75rem 0;
}

/* ============================================================
   Content Area
   ============================================================ */
.velkaris-content {
    flex: 1;
    margin-left: var(--vk-sidebar-width);
    display: flex;
    flex-direction: column;
    height: 100vh;
    min-height: 0;
    min-width: 0;
    overflow: hidden;
    transition: margin-left 0.25s ease;
}

.sidebar-collapsed .velkaris-content {
    margin-left: var(--vk-sidebar-rail);
}

/* ============================================================
   TopBar
   ============================================================ */
.velkaris-topbar {
    height: var(--vk-topbar-height);
    background: var(--vk-bg-topbar);
    border-bottom: 1px solid var(--vk-border);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    /* Horizontal padding matches .velkaris-main so the crumbs and the user menu
       line up with the page content below. */
    padding: 0 2rem;
    gap: 0.625rem;
    flex-shrink: 0;
}

/* Breadcrumb hoisted into the TopBar (next to the sidebar toggle). min-width:0 lets
   long crumb chains truncate instead of pushing the user menu off the right edge. */
.velkaris-topbar-crumbs {
    min-width: 0;
    overflow: hidden;
}

.velkaris-topbar-crumbs .breadcrumb {
    margin-bottom: 0;
    flex-wrap: nowrap;
}

.velkaris-topbar .tenant-badge {
    background: var(--vk-accent-subtle);
    color: var(--vk-accent);
    padding: 0.25rem 0.75rem;
    border-radius: 100px;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    border: 1px solid var(--vk-accent-border);
}

/* The dark accent (#3b82f6) on its subtle background is 4.0:1 — the lighter
   hover shade passes for this small bold pill. */
[data-theme="dark"] .velkaris-topbar .tenant-badge {
    color: var(--vk-accent-hover);
}

.velkaris-topbar .tenant-badge-system {
    background: var(--vk-danger);
    color: #fff;
    border-color: var(--vk-danger);
}

.velkaris-topbar .user-info {
    font-size: 0.85rem;
    color: var(--vk-text-secondary);
    font-weight: 450;
}

.velkaris-topbar .btn-sm {
    font-size: 0.8rem;
    border-radius: var(--vk-radius-sm);
}

/* ============================================================
   Language Switcher — Standard Bootstrap dropdown (Look 1:1 zum
   E-Rechnungsportal). Blazor toggelt .show (kein Bootstrap-JS nötig),
   daher wird die Position hier ohne Popper gesetzt.
   ============================================================ */
/* Toggle: Portal-Pill. Neutrale Farben fuer helle Topbars (Admin); die Demo-Topbar
   ueberschreibt unten auf Ghost-Weiss. */
.vk-lang .dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--vk-text);
    background: transparent;
    border: 1px solid var(--vk-border);
    border-radius: 0.4rem;
}

.vk-lang .dropdown-toggle:hover,
.vk-lang .dropdown-toggle:focus,
.vk-lang .dropdown-toggle.show {
    background: var(--vk-bg-inset);
    border-color: var(--vk-border);
}

/* Menu: ueber Bootstraps eigene --bs-dropdown-*-Variablen auf die vk-Tokens gemappt
   (= dieselben Werte wie --df-* im Portal); ohne Popper manuell rechtsbuendig positioniert. */
.vk-lang .dropdown-menu {
    --bs-dropdown-min-width: 11rem;
    --bs-dropdown-bg: var(--vk-bg-card);
    --bs-dropdown-color: var(--vk-text);
    --bs-dropdown-border-color: var(--vk-border);
    --bs-dropdown-link-color: var(--vk-text);
    --bs-dropdown-link-hover-bg: var(--vk-bg-inset);
    --bs-dropdown-link-hover-color: var(--vk-text);
    --bs-dropdown-link-active-bg: var(--vk-accent);
    --bs-dropdown-link-active-color: #fff;
    --bs-dropdown-border-radius: 0.4rem;
    top: 100%;
    right: 0;
    left: auto;
    margin-top: 0.25rem;
    box-shadow: var(--vk-shadow);
}

/* Zweispaltiger Eintrag: feste Code-Spalte + Name (wie df-lang-code im Portal). */
.vk-lang .vk-lang-code {
    flex: 0 0 28px;
    width: 28px;
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.5px;
    opacity: 0.7;
}

.vk-lang .dropdown-item.active .vk-lang-code {
    opacity: 1;
}

/* Demo-Topbar (dunkel): Ghost-Weiss-Toggle — 1:1 wie das E-Rechnungsportal. */
.velkaris-demo-topbar .vk-lang .dropdown-toggle {
    color: #e9ecef;
    background: transparent;
    border-color: rgba(255, 255, 255, 0.25);
}

.velkaris-demo-topbar .vk-lang .dropdown-toggle:hover,
.velkaris-demo-topbar .vk-lang .dropdown-toggle:focus,
.velkaris-demo-topbar .vk-lang .dropdown-toggle.show {
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.45);
}

/* ============================================================
   Main Content
   ============================================================ */
/* License notice bar: the horizontal padding must match .velkaris-topbar and
   .velkaris-main (2rem) so the key icon starts exactly under the breadcrumb's home icon
   and the close button lines up with the user menu. Bootstrap's .alert brings 1rem and
   there is no 2rem spacer utility, so this is the one property that needs custom CSS —
   the rest of the bar is plain Bootstrap (d-flex/align-items-center/gap-2/ms-auto). */
.velkaris-license-banner {
    padding-left: 2rem;
    padding-right: 2rem;
}

.velkaris-main {
    flex: 1;
    min-height: 0;
    padding: 1.5rem 2rem;
    background: var(--vk-bg-body);
    overflow-y: auto;
    /* Keep keyboard-focused rows visible below sticky table heads (2.4.11). */
    scroll-padding-top: 3rem;
}

/* The viewer needs a flex column so .velkaris-viewer (flex:1) fills the height
   and manages its own internal scrolling. Normal pages stay a plain block
   scroll container — making .velkaris-main both a flex column and the scroller
   breaks vertical scrolling once content (e.g. many uploaded docs) overflows. */
.velkaris-main:has(.velkaris-viewer) {
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.velkaris-main h1,
.velkaris-main .h1,
.velkaris-main h2,
.velkaris-main .h2,
.velkaris-main h4,
.velkaris-main .h4,
.velkaris-main h5,
.velkaris-main .h5 {
    color: var(--vk-text);
    font-weight: 650;
    letter-spacing: -0.3px;
}

/* ============================================================
   Stat Cards
   ============================================================ */
/* Workflow stepper (project home) — one connected panel, per-step next action.
   Visual language mirrors the analysis mockup: eyebrow, progress bar, large number,
   gradient wash + accent rail for the active step, green wash for done steps. */
.velkaris-stepper {
    display: flex;
    flex-wrap: wrap;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius);
    overflow: hidden;
    background: var(--vk-bg-card);
    box-shadow: var(--vk-shadow-xs);
}
/* The inner padding sits on the two children, not here: the body is the hover surface, and a
   padding on the tile would inset its highlight from the tile edges. */
.velkaris-step {
    flex: 1 1 0;
    min-width: 172px;
    border-right: 1px solid var(--vk-border);
    position: relative;
    display: flex;
    flex-direction: column;
}
.velkaris-step:last-child {
    border-right: none;
}
/* The tile body is a link — reset anchor defaults and give it a hover affordance so it reads as
   clickable, not just the CTA button below it. The tile itself is a div: a step can carry two
   actions (deposit offers upload AND fetch), and nested anchors are invalid HTML. */
.velkaris-step-link {
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    transition: background-color var(--vk-transition);
}
.velkaris-step-link:hover {
    text-decoration: none;
    color: inherit;
    background-color: var(--vk-accent-subtle);
}
/* Fills the tile above the CTA row so the click target stays the whole upper area. */
.velkaris-step-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    padding: 1rem 1.15rem 0.35rem;
}
.velkaris-step-icon {
    color: var(--vk-text-muted);
    margin-bottom: 0.55rem;
    line-height: 1;
}
.velkaris-step-done .velkaris-step-icon {
    color: var(--vk-success);
}
/* The open step is "work still to do", not a failure — hence warning orange.
   Red (--vk-danger) stays reserved for actual error states. */
.velkaris-step-active .velkaris-step-icon {
    color: var(--vk-warning);
}
.velkaris-step-eyebrow {
    font-family: ui-monospace, "Cascadia Code", "Consolas", monospace;
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--vk-text-muted);
    font-weight: 600;
}
.velkaris-step-title {
    font-weight: 700;
    font-size: 1rem;
    color: var(--vk-text);
    margin: 0.15rem 0 0.6rem;
}
.velkaris-step-bar {
    height: 4px;
    border-radius: 3px;
    background: var(--vk-border);
    overflow: hidden;
    margin-bottom: 0.75rem;
}
.velkaris-step-bar i {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--vk-text-muted);
    transition: width var(--vk-transition);
}
.velkaris-step-count {
    font-size: 1.9rem;
    font-weight: 750;
    line-height: 1;
    letter-spacing: -0.5px;
    color: var(--vk-text);
    font-variant-numeric: tabular-nums;
}
.velkaris-step-count-muted {
    color: var(--vk-text-muted);
    font-weight: 600;
}
.velkaris-step-sub {
    font-size: 0.78rem;
    color: var(--vk-text-muted);
    min-height: 1.1rem;
    margin: 0.35rem 0 0.85rem;
}
/* The row holds the CTAs and carries the push-to-bottom; the buttons themselves must not, or a
   second one would be pushed onto its own line. */
.velkaris-step-ctas {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: auto;
    padding: 0 1.15rem 1.1rem;
}
.velkaris-step-cta {
    align-self: flex-start;
}
.velkaris-step-done {
    background: linear-gradient(180deg, var(--vk-success-bg), transparent 62%);
}
.velkaris-step-done .velkaris-step-bar i {
    background: var(--vk-success);
}
.velkaris-step-active {
    background: linear-gradient(180deg, var(--vk-warning-subtle), transparent 62%);
}
.velkaris-step-active .velkaris-step-bar i {
    background: var(--vk-warning);
}
.velkaris-step-active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: var(--vk-warning);
}

/* Metric-card board: one flex column per workflow step, aligned under the stepper.
   Column count is driven by the stepper (4 redaction / 5 pseudonymization) so the
   columns shrink/grow together with the steps and keep their visual belonging. */
.velkaris-stat-board {
    margin-top: 4.5rem;
    margin-bottom: 1.5rem;
    flex-wrap: wrap;
}
.velkaris-stat-col {
    flex: 1 1 0;
    min-width: 172px;
}
/* Section label above a group of stat cards (mirrors a workflow step) */
.velkaris-stat-section {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--vk-text-muted);
    margin-bottom: 0.6rem;
}
/* Icon at the top of a stat card */
.velkaris-stat-card .velkaris-stat-icon {
    color: var(--vk-text-muted);
    opacity: 0.75;
    margin-bottom: 0.5rem;
    line-height: 1;
}
.velkaris-stat-card .stat-value-empty {
    color: var(--vk-text-muted);
    font-weight: 600;
}

.velkaris-stat-card {
    background: var(--vk-bg-card);
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius);
    padding: 1.25rem;
    box-shadow: var(--vk-shadow-xs);
    transition: border-color var(--vk-transition), box-shadow var(--vk-transition), transform var(--vk-transition);
    overflow: hidden;
    min-width: 0;
    min-height: 88px;
    height: 100%;
    position: relative;
}

.velkaris-stat-card .stat-value {
    font-size: 1.75rem;
    font-weight: 750;
    color: var(--vk-text);
    letter-spacing: -0.5px;
    line-height: 1.2;
}

.velkaris-stat-card .stat-label {
    font-size: 0.75rem;
    color: var(--vk-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 550;
    margin-top: 0.125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.velkaris-stat-card .stat-label.stat-label-wrap {
    white-space: normal;
}

.velkaris-stat-export {
    position: absolute;
    top: 8px;
    right: 8px;
}

.velkaris-stat-clickable {
    cursor: pointer;
}

.velkaris-stat-clickable:hover {
    border-color: var(--vk-accent-border);
    box-shadow: var(--vk-shadow-sm);
    transform: translateY(-1px);
}

.velkaris-stat-clickable.active {
    border-color: var(--vk-accent);
    box-shadow: 0 0 0 3px var(--vk-accent-subtle);
}

.velkaris-stat-error {
    border-color: var(--vk-danger-bg);
    background: var(--vk-danger-bg);
}

.velkaris-stat-error .stat-value {
    color: var(--vk-danger-text);
}

.velkaris-stat-error:hover {
    border-color: var(--vk-danger);
    box-shadow: 0 2px 8px rgba(220, 38, 38, 0.12);
}

.velkaris-stat-error.active {
    border-color: var(--vk-danger);
    box-shadow: 0 0 0 3px var(--vk-danger-bg);
}

.velkaris-stat-pending {
    border-color: var(--vk-warning);
    background: var(--vk-warning-bg);
}

.velkaris-stat-pending .stat-value {
    color: var(--vk-warning-text);
}

/* ============================================================
   Project Cards
   ============================================================ */
.velkaris-project-card {
    background: var(--vk-bg-card);
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius);
    padding: 1.25rem;
    box-shadow: var(--vk-shadow-xs);
    transition: box-shadow var(--vk-transition), transform var(--vk-transition), border-color var(--vk-transition);
}

.velkaris-project-card:hover {
    box-shadow: var(--vk-shadow);
    transform: translateY(-2px);
    border-color: var(--vk-accent-border);
}

.velkaris-project-card .project-name {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--vk-text);
}

.velkaris-project-card .project-desc {
    font-size: 0.85rem;
    color: var(--vk-text-muted);
}

/* ============================================================
   Deletion Policy Badges
   ============================================================ */
.badge-policy-neverdelete {
    background-color: var(--vk-success-bg);
    color: var(--vk-success-text);
}

.badge-policy-retentionperiod {
    background-color: var(--vk-warning-bg);
    color: var(--vk-warning-text);
}

.badge-policy-immediatewithaudit {
    background-color: var(--vk-danger-bg);
    color: var(--vk-danger-text);
}

/* ============================================================
   Table Styling
   ============================================================ */
.velkaris-table {
    background: var(--vk-bg-card);
    border-radius: var(--vk-radius);
    overflow-x: auto;
    border: 1px solid var(--vk-border);
    box-shadow: var(--vk-shadow-xs);
}

/* Scrollbarer Wrapper für lange Listen-Tabellen (z. B. Dict-Import/PII-Find).
   Ersetzt inline style="max-height:NNNpx; overflow-y:auto;" auf Wrapper-divs. */
.velkaris-scroll {
    overflow-x: auto;
    overflow-y: auto;
    max-height: 500px;
}

.velkaris-scroll-sm {
    overflow-x: auto;
    overflow-y: auto;
    max-height: 350px;
}

.velkaris-table th {
    background-color: var(--vk-bg-inset);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--vk-text-muted);
    font-weight: 600;
    border-bottom-color: var(--vk-border) !important;
}

.velkaris-table td {
    border-bottom-color: var(--vk-border-light) !important;
    vertical-align: middle;
}

/* Header cells shrink their font for the uppercase labels, and .form-check-input sizes
   itself in em — so a select-all checkbox in the header would render smaller than the
   row checkboxes it controls. Pin it back to the body size. */
.velkaris-table th .form-check-input {
    font-size: 1rem;
}

/* Cell padding matches the .card-header inset (8px 16px) so a table sitting under a
   card header lines its first column up with the heading above it. Set on the cells
   directly: our bundled Bootstrap hardcodes `padding: 0.5rem` here and never reads
   --bs-table-cell-padding-x, so overriding the variable has no effect. */
.velkaris-table > .table > :not(caption) > * > * {
    padding-left: 1rem;
    padding-right: 1rem;
}

/* Action column hugs its buttons against the right edge. Without the width clamp the
   cell stretches to whatever the auto-layout leaves over, and the buttons drift left
   by a different amount in every table. */
.velkaris-col-actions {
    width: 1%;
    white-space: nowrap;
}

/* SystemSettings renders one table per prefix group. Each would auto-size its columns
   to its own content, so the groups never line up vertically — fixed layout plus
   explicit widths makes them read as one continuous table. */
.vk-settings-table {
    table-layout: fixed;
}

.vk-settings-table .vk-settings-col-key {
    width: 28rem;
}

.vk-settings-table .vk-settings-col-enc {
    width: 9rem;
}

.vk-settings-table .velkaris-col-actions {
    width: 15rem;
}

/* Long unbroken values (detector lists, URLs) must wrap instead of forcing the fixed
   layout to overflow horizontally. */
.vk-settings-table td:nth-child(2) {
    overflow-wrap: anywhere;
}

/* Tenant management renders two stacked tables (reserved realm + customers). Auto layout
   would size each table's columns to its own content, so the two never line up. Fixed
   layout plus the shared explicit widths on the headers makes them read as one table. */
.vk-tenant-table {
    table-layout: fixed;
}

/* List-table affordances: clickable rows (open the entity) + sortable column headers.
   Row-hover feedback comes from Bootstrap `table-hover`; these only add the cursor. */
.velkaris-table tbody tr.velkaris-row-link { cursor: pointer; }
.velkaris-sortable { cursor: pointer; user-select: none; white-space: nowrap; }

/* Name/label cell in a clickable row: styled as a link (accent color, underline on
   row hover) so the primary open affordance is visually discoverable. */
.velkaris-name-link { color: var(--vk-accent); }
.velkaris-table tbody tr.velkaris-row-link:hover .velkaris-name-link { text-decoration: underline; }

/* Compact toolbar search box above list tables. */
.velkaris-search { max-width: 320px; }

/* Column-width utilities. Replace inline `style="width:NNNpx"` on <th>/<td>
   elements — used widely in admin tables (action columns, date columns,
   icon-only chevron columns). Bootstrap offers no pixel-width helpers, so a
   small velkaris-prefixed scale plugs the gap. */
.velkaris-col-30  { width: 30px; }
.velkaris-col-32  { width: 32px; }
.velkaris-col-36  { width: 36px; }
.velkaris-col-40  { width: 40px; }
.velkaris-col-42  { width: 42px; }
.velkaris-col-50  { width: 50px; }
.velkaris-col-54  { width: 54px; }
.velkaris-col-60  { width: 60px; }
.velkaris-col-70  { width: 70px; }
.velkaris-col-80  { width: 80px; }
.velkaris-col-90  { width: 90px; }
.velkaris-col-100 { width: 100px; }
.velkaris-col-120 { width: 120px; }
.velkaris-col-140 { width: 140px; }
.velkaris-col-145 { width: 145px; }
.velkaris-col-150 { width: 150px; }
.velkaris-col-160 { width: 160px; }
.velkaris-col-180 { width: 180px; }
.velkaris-col-200 { width: 200px; }
.velkaris-col-240 { width: 240px; }
.velkaris-col-280 { width: 280px; }
.velkaris-col-min-160 { min-width: 160px; }
.velkaris-col-max-100 { max-width: 100px; }
.velkaris-col-max-180 { max-width: 180px; }
.velkaris-col-max-200 { max-width: 200px; }
.velkaris-col-max-250 { max-width: 250px; }
.velkaris-col-max-300 { max-width: 300px; }
.velkaris-col-max-350 { max-width: 350px; }
.velkaris-col-max-400 { max-width: 400px; }
.velkaris-col-max-500 { max-width: 500px; }

/* Max-width utilities for form controls + content containers (not table columns).
   Bootstrap only offers .mw-100 (%); these plug the fixed-px gap that inputs,
   selects and centered demo containers need. */
.velkaris-mw-160 { max-width: 160px; }
.velkaris-mw-250 { max-width: 250px; }
.velkaris-mw-300 { max-width: 300px; }
.velkaris-mw-360 { max-width: 360px; }
.velkaris-mw-400 { max-width: 400px; }
.velkaris-mw-720 { max-width: 720px; }
.velkaris-mw-980 { max-width: 980px; }

/* Sub-rem font-size utilities. Bootstrap's .fs-* scale stops at fs-6 (1rem) and
   .fs-xs (0.75rem) already exists above; these cover the remaining micro-sizes
   used in the viewer Info tab and compact badges. */
.velkaris-fs-08  { font-size: 0.8rem; }
.velkaris-fs-078 { font-size: 0.78rem; }
.velkaris-fs-072 { font-size: 0.72rem; }
.velkaris-fs-06  { font-size: 0.6rem; }

/* Semantic var-based badge tints — replace repeated inline
   style="background:var(--vk-success-bg);color:var(--vk-success-text)" combos.
   Mirror the .badge.bg-* overrides but as standalone opt-in classes. */
.velkaris-badge-success { background: var(--vk-success-bg); color: var(--vk-success-text); }
.velkaris-badge-accent  { background: var(--vk-accent-subtle); color: var(--vk-accent); }

/* Light border-color override for Bootstrap .border-* on inset separators. */
.velkaris-border-light { border-color: var(--vk-border-light) !important; }

/* Accent text + the viewer's relation pill (Ctrl-key relation badge). Replace
   inline style="color:var(--vk-accent)" / background+border combos. */
.velkaris-text-accent { color: var(--vk-accent); }
.velkaris-relation-pill {
    background: var(--vk-accent-subtle);
    border: 1px solid var(--vk-accent);
}

/* Progress-bar heights. Bootstrap has no height utility for .progress; these replace the
   per-page inline style="height:..px" copies (slim = job/export progress, upload = the
   FolderBrowser upload rows). */
.velkaris-progress-6 { height: 6px; }
.velkaris-progress-8 { height: 8px; }
.velkaris-progress-10 { height: 10px; }
.velkaris-progress-20 { height: 20px; }

.velkaris-badge-xs { font-size: 0.6em; }
.velkaris-badge-sm { font-size: 0.65em; }
.velkaris-key-display { word-break: break-all; font-size: 0.9rem; }
.velkaris-tag-preview { min-width: 60px; }
.velkaris-cursor-pointer { cursor: pointer; }

/* PII-Find result table — sticky header inside .velkaris-scroll wrapper, and
   filter toolbar above the table. Replaces inline `style="position:sticky..."`
   and `style="background: var(--vk-bg-inset)"` on the toolbar/thead. */
.velkaris-pii-filter-bar {
    background: var(--vk-bg-inset);
}
.velkaris-pii-sticky-head th,
.velkaris-thead-sticky th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--vk-bg-inset);
}
.velkaris-pii-tolerance-badge {
    min-width: 60px;
    text-align: center;
}

/* ============================================================
   Folder Browser
   ============================================================ */
.velkaris-folder-row:hover td {
    background-color: var(--vk-bg-card-hover);
}

.velkaris-row-failed td {
    color: var(--vk-danger-text) !important;
}

.velkaris-row-processing td {
    color: var(--vk-text-muted) !important;
}

/* ============================================================
   Grid / Tile View
   ============================================================ */
.velkaris-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.velkaris-grid-item {
    width: 150px;
    cursor: pointer;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius);
    background: var(--vk-bg-card);
    overflow: hidden;
    transition: box-shadow 0.15s, border-color 0.15s;
}

.velkaris-grid-item:hover {
    /* --vk-primary never existed — the hover border silently fell through. */
    border-color: var(--vk-accent);
    box-shadow: 0 2px 8px var(--vk-accent-subtle);
}

.velkaris-grid-preview {
    width: 150px;
    height: 150px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--vk-bg-inset);
    overflow: hidden;
    position: relative;
}

.velkaris-grid-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.velkaris-grid-fallback-icon {
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
}

.velkaris-grid-name {
    padding: 6px 8px;
    font-size: 0.75rem;
    font-weight: 500;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-top: 1px solid var(--vk-border-light);
}

.velkaris-grid-folder .velkaris-grid-name {
    font-weight: 600;
}

.velkaris-grid-failed {
    border-color: var(--vk-danger-bg);
}

.velkaris-grid-failed:hover {
    border-color: var(--vk-danger);
}

.velkaris-grid-badge {
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.65rem;
    padding: 1px 6px;
    border-radius: 3px;
    color: #fff;
    white-space: nowrap;
}

/* ============================================================
   Upload Dropzone
   ============================================================ */
.velkaris-upload-card {
    border: 1px solid var(--vk-border);
    background: var(--vk-bg-card);
    border-radius: var(--vk-radius);
}

.velkaris-dropzone {
    position: relative;
    border: 2px dashed var(--vk-border);
    border-radius: var(--vk-radius);
    padding: 2rem;
    text-align: center;
    transition: border-color var(--vk-transition), background-color var(--vk-transition);
    cursor: pointer;
}

.velkaris-dropzone:hover,
.velkaris-dropzone.dragover {
    border-color: var(--vk-accent);
    background-color: var(--vk-accent-subtle);
}

.velkaris-dropzone-icon {
    font-size: 2.5rem;
    margin-bottom: 0.5rem;
}

/* Unsichtbares <input type="file">-Overlay: fängt native Drag&Drop und Klick
   auf der gesamten Dropzone-Fläche ab — kein JS-Interop nötig. */
.velkaris-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* ============================================================
   Search Results
   ============================================================ */
.velkaris-search-result:hover {
    background-color: var(--vk-bg-card-hover);
}

.velkaris-search-highlight {
    font-style: italic;
    line-height: 1.6;
}

.velkaris-search-highlight b {
    font-weight: 700;
    color: var(--vk-text);
    background-color: var(--vk-highlight-bg);
    padding: 0 3px;
    border-radius: 3px;
}

/* ============================================================
   Tag Management
   ============================================================ */
.velkaris-tag-dot {
    display: inline-block;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    vertical-align: middle;
}

/* ============================================================
   Document Viewer
   ============================================================ */
.velkaris-viewer {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.velkaris-viewer-toolbar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1fr);
    align-items: center;
    column-gap: 8px;
    padding: 6px 4px 6px 4px;
    background: var(--vk-bg-card);
    border-bottom: 1px solid var(--vk-border);
    flex-shrink: 0;
    min-height: 44px;
    overflow: hidden;
}

.velkaris-toolbar-left,
.velkaris-toolbar-center,
.velkaris-toolbar-right {
    min-width: 0;
    overflow: hidden;
    flex-wrap: nowrap;
}
.velkaris-toolbar-left { justify-self: start; }
.velkaris-toolbar-center { justify-self: center; }
.velkaris-toolbar-right { justify-self: end; }

/* Toolbar-Buttons dürfen niemals umbrechen oder schrumpfen — sonst
   verteilen sie sich auf zwei Zeilen oder werden unleserlich gestaucht. */
.velkaris-viewer-toolbar .btn,
.velkaris-viewer-toolbar a.btn {
    flex-shrink: 0;
    white-space: nowrap;
}

/* Dateiname: schrumpft mit der Fensterbreite und verschwindet bei sehr schmalen
   Layouts ganz. Den vollen Namen hat Tooltip (title=) und Tab-Title. */
.velkaris-viewer-filename {
    min-width: 0;
    max-width: 280px;
    flex: 0 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Relations-Badge (erscheint bei Strg-Taste / aktiver Relation): schwebt unten links
   über dem Seitenbereich statt in der Toolbar — der Hinweis ist flüchtig, gehört zum
   Dokument und soll der Toolbar keine Breite wegnehmen. Anker ist
   .velkaris-viewer-main-wrap (position: relative). */
.velkaris-viewer-relation {
    position: absolute;
    bottom: 14px;
    left: 14px;
    max-width: calc(100% - 28px);
    overflow: hidden;
    flex-wrap: nowrap;
    background: var(--vk-bg-card);
    border: 1px solid var(--vk-border);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
    /* Über den Seiten, aber unter Dropdowns/Modals — gleiche Ebene wie der frühere Strip. */
    z-index: 5;
    pointer-events: none;
}

/* ── Progressive Hide-Breakpoints: zuerst weniger wichtige Information ausblenden,
   damit Buttons komplett bestehen bleiben und nichts mehr überlappt.
   Der Dateiname (früher der erste Kandidat zum Schrumpfen) steht jetzt in der
   Breadcrumb und ist nur noch im Demo-Modus in der Toolbar. ── */

@media (max-width: 1500px) {
    .velkaris-viewer-filename { max-width: 200px; }
}
@media (max-width: 1350px) {
    .velkaris-viewer-filename { max-width: 130px; }
    .velkaris-viewer-navindex,
    .velkaris-viewer-relation-hint { display: none; }
}

/* Dateiname ausblenden ab Bootstrap-XL-Breakpoint.
   "← Demo"-Button und Toolbar-Divider werden inline via d-none d-xl-* versteckt. */
@media (max-width: 1199.98px) {
    .velkaris-viewer-filename { display: none; }
    /* Seitenzähler "/ N" ist redundant zum Eingabefeld-Max und weicht als Erstes. */
    .velkaris-strip-total { display: none; }
}

/* Sehr schmal: Zoom-Label und Relation-Label ausblenden — Kernfunktionen
   (Zoom, Seite, Navigation, Home) bleiben sichtbar.
   Rotation/Fit/OCR werden inline via d-none d-lg-inline-flex versteckt. */
@media (max-width: 991.98px) {
    .velkaris-zoom-label { display: none; }
    .velkaris-viewer-relation-label { display: none; }
    /* Trenner weglassen, bevor Bedienelemente selbst verschwinden. */
    .velkaris-strip-sep { display: none; }
}

/* Extrem schmal: Zoom-Slider weg (nur Plus/Minus-Buttons) und Relations-Badge ganz */
@media (max-width: 900px) {
    .velkaris-zoom-slider { display: none; }
    .velkaris-viewer-relation { display: none; }
}

.velkaris-viewer-body {
    display: flex;
    flex: 1;
    overflow: hidden;
}

/* Left panel column (thumbnails / search / info). All three share one resizable
   width driven by --vk-viewer-leftpanel-width (set on .velkaris-viewer-body by
   viewer-toolpanel.js) with a hard min-width floor. Only one is mounted at a time. */
.velkaris-viewer-sidebar {
    width: var(--vk-viewer-leftpanel-width, 240px);
    min-width: 180px;
    background: var(--vk-bg-inset);
    border-right: 1px solid var(--vk-border);
    overflow-y: auto;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Left search + info panels — moved out of the right tool panel into the switchable
   left rail. Reuse the global .velkaris-tab-header/.velkaris-section/.velkaris-search-*
   styles (they carry their own padding), so only the column chrome is defined here.
   Same resizable width/background as the thumbnail sidebar they share the column with. */
.velkaris-viewer-searchpanel,
.velkaris-viewer-infopanel {
    width: var(--vk-viewer-leftpanel-width, 240px);
    min-width: 180px;
    background: var(--vk-bg-inset);
    border-right: 1px solid var(--vk-border);
    overflow-y: auto;
}

/* Drag handle on the right edge of the left panel column. 4px hit zone, visible
   only on hover. Mirrors .velkaris-viewer-toolpanel-resize-handle on the right side. */
.velkaris-viewer-leftpanel-resize-handle {
    /* 8px wide: a 4px strip is far below the 24px target guidance (2.5.8);
       keyboard resize (arrow keys) is the full alternative. */
    flex: 0 0 8px;
    width: 8px;
    cursor: ew-resize;
    background: transparent;
    transition: background var(--vk-transition);
    z-index: 10;
}

.velkaris-viewer-leftpanel-resize-handle:hover,
.velkaris-viewer-leftpanel-resize-handle.dragging {
    background: var(--vk-accent);
}

.velkaris-viewer-main {
    flex: 1;
    min-width: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-gutter: stable;
    background: var(--vk-bg-viewer);
    display: flex;
    justify-content: center;
    padding: 16px;
    user-select: none;
    -webkit-user-select: none;
}

.velkaris-pages-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding-bottom: 16px;
}

/* Wrapper so the vertical zoom/paging strip can anchor over the (scrolling) page area. */
.velkaris-viewer-main-wrap {
    position: relative;
    flex: 1;
    min-width: 0;
    display: flex;
}

.velkaris-viewer-main-wrap > .velkaris-viewer-main {
    flex: 1;
}

/* Seiten-/Zoom-/Rotier-/OCR-Controls in der Toolbar-Mitte. Lagen zwischenzeitlich als
   schwebender vertikaler Strip über dem Seitenbereich, weil der Dateiname die Toolbar
   belegte; der steht jetzt in der Breadcrumb, also sind sie wieder hier. Kein eigener
   Rahmen/Schatten mehr — die Toolbar ist bereits die Fläche. */
.velkaris-viewer-pagecontrols {
    justify-self: center;
    min-width: 0;
    flex-wrap: nowrap;
}

.velkaris-viewer-pagecontrols .btn {
    flex-shrink: 0;
}

.velkaris-viewer-pagecontrols .velkaris-page-input {
    width: 44px;
    text-align: center;
    flex-shrink: 0;
}

.velkaris-strip-total {
    font-size: 11px;
    color: var(--vk-text-muted);
    line-height: 1;
    flex-shrink: 0;
}

/* Trenner zwischen den Control-Gruppen — jetzt eine senkrechte Linie in einer waagrechten
   Leiste (war umgekehrt, solange die Controls vertikal standen). */
.velkaris-strip-sep {
    width: 1px;
    height: 20px;
    background: var(--vk-border);
    margin: 0 3px;
    flex-shrink: 0;
}

/* Vertical icon rail (Acrobat-style side nav). Left rail toggles thumbnails/search/info;
   the .rail-right modifier mirrors it on the right edge for redact/pseudonymize/comments. */
.velkaris-viewer-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 8px 4px;
    background: var(--vk-bg-inset);
    border-right: 1px solid var(--vk-border);
    flex-shrink: 0;
}

.velkaris-viewer-rail.rail-right {
    border-right: none;
    border-left: 1px solid var(--vk-border);
}

/* Count badge on a rail toggle icon (redacted/pseudonymized/comment counts). */
.velkaris-rail-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 15px;
    height: 15px;
    padding: 0 3px;
    border-radius: 8px;
    background: var(--vk-accent);
    color: #fff;
    font-size: 9px;
    line-height: 15px;
    text-align: center;
    font-weight: 600;
    pointer-events: none;
}

.velkaris-page-wrapper {
    position: relative;
    line-height: 0;
    box-shadow: var(--vk-shadow-lg);
    scroll-margin-top: 8px;
    background: #fff;
    border-radius: 2px;
    max-width: 100%;
}

.velkaris-page-image {
    display: block;
    width: 100%;
    height: auto;
    background: #fff;
}

.velkaris-page-placeholder {
    width: 100%;
    aspect-ratio: inherit;
    background: var(--vk-bg-inset);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--vk-text-muted);
    font-size: 1.25rem;
}

.velkaris-thumb-item {
    cursor: pointer;
    text-align: center;
    padding: 4px;
    border: 2px solid transparent;
    border-radius: var(--vk-radius-sm);
    transition: border-color var(--vk-transition), background var(--vk-transition);
}

.velkaris-thumb-item:hover {
    border-color: var(--vk-border);
    background: var(--vk-bg-card-hover);
}

.velkaris-thumb-item.active {
    border-color: var(--vk-accent);
    background: var(--vk-accent-subtle);
}

.velkaris-thumb-img-wrapper {
    position: relative;
    overflow: hidden;
    box-shadow: var(--vk-shadow-sm);
    background: #fff;
    line-height: 0;
    border-radius: 2px;
}

.velkaris-thumb-img-wrapper img {
    width: 100%;
    height: auto;
    display: block;
}

.velkaris-thumb-label {
    display: block;
    font-size: 0.7rem;
    color: var(--vk-text-muted);
    margin-top: 3px;
    font-weight: 500;
}

.velkaris-page-input {
    width: 48px;
    text-align: center;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius-sm);
    padding: 2px 4px;
    font-size: 0.875rem;
    background: var(--vk-bg-card);
    color: var(--vk-text);
}

.velkaris-zoom-slider {
    width: 120px;
    height: 4px;
    cursor: pointer;
    accent-color: var(--vk-accent);
    vertical-align: middle;
}

.velkaris-zoom-label {
    min-width: 42px;
    text-align: center;
    display: inline-block;
    color: var(--vk-text-secondary);
    font-size: 0.8rem;
}

/* ============================================================
   Right Tool Panel
   ============================================================ */
.velkaris-viewer-toolpanel {
    position: relative;
    width: var(--vk-viewer-toolpanel-width, 360px);
    min-width: 280px;
    background: var(--vk-bg-card);
    border-left: 1px solid var(--vk-border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    flex-shrink: 0;
}

/* Drag handle on the left edge for width resizing. 4px wide hit zone,
   visible only on hover so it doesn't clutter the borderline. */
.velkaris-viewer-toolpanel-resize-handle {
    position: absolute;
    top: 0;
    left: 0;
    width: 8px;
    height: 100%;
    cursor: ew-resize;
    background: transparent;
    transition: background var(--vk-transition);
    z-index: 10;
}

.velkaris-viewer-toolpanel-resize-handle:hover,
.velkaris-viewer-toolpanel-resize-handle.dragging {
    background: var(--vk-accent);
}

.velkaris-toolpanel-body {
    flex: 1 1 auto;
    overflow-y: auto;
}

/* Sticky-Status-Footer — sits at the bottom of the toolpanel, always
   visible. Shows aggregate redaction counts and a reset shortcut. */
.velkaris-viewer-status-footer {
    flex: 0 0 auto;
    border-top: 1px solid var(--vk-border);
    background: var(--vk-bg-inset);
    padding: 6px 10px;
    font-size: 0.72rem;
    color: var(--vk-text-secondary);
    display: flex;
    align-items: center;
    gap: 6px;
    justify-content: space-between;
}

.velkaris-viewer-status-footer .vk-status-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px;
    flex-grow: 1;
    min-width: 0;
}

.velkaris-viewer-status-footer .vk-status-chip {
    white-space: nowrap;
}

.velkaris-viewer-status-footer .vk-status-chip.muted {
    color: var(--vk-text-muted);
}

/* Collapsible <details>-based sections used in Redact / Pseudo / Info. */
.velkaris-section {
    border-bottom: 1px solid var(--vk-border-light);
}

.velkaris-section:last-child {
    border-bottom: none;
}

.velkaris-section > summary {
    list-style: none;
    cursor: pointer;
    padding: 8px 12px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--vk-text);
    display: flex;
    align-items: center;
    /* No justify-content so the section title sits flush-left next to the
       chevron; action buttons (e.g. "Verwalten") use ms-auto in markup to
       float right. */
    gap: 6px;
    user-select: none;
}

.velkaris-section > summary::-webkit-details-marker {
    display: none;
}

.velkaris-section > summary::before {
    content: "\25B6"; /* ▶ collapsed */
    font-size: 0.6rem;
    color: var(--vk-text-muted);
    margin-right: 4px;
    transition: transform 0.15s ease;
}

.velkaris-section[open] > summary::before {
    transform: rotate(90deg);
}

.velkaris-section > summary:hover {
    background: var(--vk-bg-inset);
}

.velkaris-section-content {
    padding: 4px 12px 10px;
}

/* Click-mode hint popover at the top of the Redact tab. */
.velkaris-clickmode-hint {
    margin: 0 12px 8px;
    border: 1px solid var(--vk-border-light);
    border-radius: var(--vk-radius-sm);
    background: var(--vk-bg-inset);
}

.velkaris-clickmode-hint > summary {
    list-style: none;
    cursor: pointer;
    padding: 4px 8px;
    font-size: 0.72rem;
    color: var(--vk-text-secondary);
    display: flex;
    align-items: center;
    gap: 4px;
    user-select: none;
}

.velkaris-clickmode-hint > summary::-webkit-details-marker {
    display: none;
}

.velkaris-clickmode-hint[open] > summary {
    border-bottom: 1px solid var(--vk-border-light);
}

.velkaris-clickmode-hint-body {
    padding: 6px 10px;
    font-size: 0.72rem;
    color: var(--vk-text-secondary);
}

.velkaris-clickmode-hint-body kbd {
    font-size: 0.68rem;
}

/* 2×4 matrix table inside the click-hint modal. Compact cell spacing so the
   whole matrix fits a small modal without horizontal scrolling. */
.velkaris-clickhint-table th,
.velkaris-clickhint-table td {
    font-size: 0.72rem;
    padding: 4px 6px;
    vertical-align: middle;
}

.velkaris-clickhint-table thead th {
    font-weight: 600;
    color: var(--vk-text-muted);
    border-bottom: 1px solid var(--vk-border);
}

.velkaris-clickhint-table tbody th {
    color: var(--vk-text-secondary);
    font-weight: 500;
}

.velkaris-clickmode-hint-body dl {
    margin: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 8px;
}

.velkaris-clickmode-hint-body dt {
    font-weight: 600;
}

.velkaris-clickmode-hint-body dd {
    margin: 0;
}

/* Header sitzt am oberen Rand jedes Tab-Bodys. padding-top/-x ist Teil des
   Headers selbst, sodass Tabs ohne weiteren Wrapper-Container (Redact,
   Pseudo, die ihre Reihen schon mit eigenem Padding rendern) konsistent
   aussehen, ohne doppeltes Einrücken zu provozieren. */
.velkaris-tab-header {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--vk-text);
    padding: 12px 12px 0;
    margin-bottom: 8px;
}

.velkaris-search-input-row {
    margin-bottom: 6px;
}

/* Document history in the viewer info panel: cap the height and scroll, so a long
   audit trail does not push the "Integrity" section far below the fold. The
   "load more" button stays outside this wrapper and remains reachable. */
.velkaris-viewer-history-scroll {
    max-height: 320px;
    overflow-y: auto;
}

/* Floating-label textareas need an explicit height — Bootstrap pins
   .form-floating > .form-control to a single-row height, which clips a rows="2"
   box to ~1 visible line. The element+class selector outranks Bootstrap's pin. */
.form-floating > textarea.velkaris-floating-tall {
    height: 5rem;
    min-height: 5rem;
}

/* ============================================================
   Explorer layout (FolderBrowser): folder tree + content pane
   ============================================================ */
.velkaris-explorer {
    --vk-explorer-tree-width: 260px;
    display: flex;
    align-items: flex-start;
}

.velkaris-explorer-tree {
    flex: 0 0 var(--vk-explorer-tree-width);
    width: var(--vk-explorer-tree-width);
    min-width: 0;
    /* Sticky with its own scroll so the tree stays put while the listing scrolls.
       The offset approximates the page chrome above it (topbar + breadcrumb + toolbar). */
    position: sticky;
    top: 12px;
    max-height: calc(100vh - 200px);
    overflow: auto;
    padding: 4px 4px 4px 0;
    border-right: 1px solid var(--vk-border);
}

/* Mirrors .velkaris-viewer-leftpanel-resize-handle: invisible until hovered/dragged. */
.velkaris-explorer-resize-handle {
    flex: 0 0 8px;
    width: 8px;
    align-self: stretch;
    cursor: ew-resize;
    background: transparent;
    transition: background var(--vk-transition);
}

.velkaris-explorer-resize-handle:hover,
.velkaris-explorer-resize-handle.dragging {
    background: var(--vk-accent);
}

.velkaris-explorer-content {
    flex: 1;
    min-width: 0;
    padding-left: 12px;
}

/* Collapsed: tree + handle drop out, the listing spans the full width. */
.velkaris-explorer.tree-collapsed .velkaris-explorer-tree,
.velkaris-explorer.tree-collapsed .velkaris-explorer-resize-handle {
    display: none;
}

.velkaris-explorer.tree-collapsed .velkaris-explorer-content {
    padding-left: 0;
}

/* ── Tree nodes ─────────────────────────────────────────────── */
.velkaris-tree {
    display: flex;
    flex-direction: column;
    gap: 1px;
    font-size: 0.875rem;
}

/* --vk-tree-depth is set per row (dynamic value → inline custom property). */
.velkaris-tree-node {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px 4px calc(6px + var(--vk-tree-depth, 0) * 14px);
    border-radius: var(--vk-radius-sm);
    cursor: pointer;
    transition: background var(--vk-transition);
}

.velkaris-tree-node:hover {
    background: var(--vk-bg-card-hover);
}

.velkaris-tree-node.active {
    background: var(--vk-accent-subtle);
    color: var(--vk-accent);
    font-weight: 500;
}

.velkaris-tree-chevron {
    /* Visual glyph stays 16px; the negative-margin padding widens the hit area
       to >= 24x24 without shifting the tree layout (WCAG 2.5.8). */
    flex: 0 0 16px;
    width: 16px;
    height: 16px;
    box-sizing: content-box;
    padding: 4px !important;
    margin: -4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--vk-text-muted);
    line-height: 1;
}

.velkaris-tree-chevron-spacer {
    flex: 0 0 16px;
    width: 16px;
}

.velkaris-tree-label {
    min-width: 0;
}
/* Only the label may give up space. Without this the flex default (shrink: 1) squeezes the
   folder icon itself once a long name has to truncate — it collapsed to half width while
   keeping full height, so icons looked inconsistent in a narrow tree column. */
.velkaris-tree-node > svg,
.velkaris-tree-chevron,
.velkaris-tree-chevron-spacer {
    flex-shrink: 0;
}

/* Drop target while dragging a row from the list onto a tree node. */
.velkaris-tree-node.drop-target {
    background-color: var(--vk-accent-subtle);
    outline: 2px solid var(--vk-accent);
    outline-offset: -2px;
}

/* Separates the project subtree from the export area — the "This PC" / "Network" break. */
.velkaris-tree-divider {
    margin: 8px 8px 6px;
    border-top: 1px solid var(--vk-border);
}

/* ── Folder icon colour (Windows-like amber) ─────────────────
   Outline icons come from <Icon>, which strokes with currentColor, so colouring
   the element is enough. The solid grid tile paints its own fill instead.
   The active tree node keeps the accent colour on its label but the folder icon
   stays amber, so the row still reads as a folder. */
.velkaris-folder-icon {
    color: var(--vk-folder);
}

.velkaris-folder-tile-icon {
    fill: var(--vk-folder-solid);
}

/* ============================================================
   Dropdowns inside modals must not be clipped
   ============================================================
   SearchSelectDropdown/MultiSelectDropdown render an absolutely positioned
   .dropdown-menu. Bootstrap clips it: .modal-body scrolls (overflow:auto) and
   .modal-content hides overflow (for the rounded corners). In a short dialog —
   e.g. "Verschieben", whose body is ~127px while the folder list needs ~184px —
   the list was cut to a sliver and looked missing.
   Only while a menu is open do we stop clipping, so normal modals keep their
   scrolling body and clipped corners. */
.modal-content:has(.dropdown-menu.show),
.modal-body:has(.dropdown-menu.show) {
    overflow: visible;
}

.velkaris-search-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 8px;
}

.velkaris-search-option {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    color: var(--vk-text-secondary);
    cursor: pointer;
    margin: 0;
}

.velkaris-search-option input[type="checkbox"] {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--vk-accent);
}

.velkaris-search-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 0;
}

.velkaris-search-results {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius-sm);
    margin-top: 6px;
}

.velkaris-search-page-group {
    border-bottom: 1px solid var(--vk-border-light);
}

.velkaris-search-page-group:last-child {
    border-bottom: none;
}

.velkaris-search-page-header {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--vk-text-muted);
    background: var(--vk-bg-inset);
    padding: 3px 8px;
    position: sticky;
    top: 0;
}

/* Collapsible affordance — only when the header is a <summary> (search results).
   The comments tab reuses these classes as plain <div>s and must stay flat. */
summary.velkaris-search-page-header {
    list-style: none;
    cursor: pointer;
    user-select: none;
    display: flex;
    align-items: center;
}

summary.velkaris-search-page-header::-webkit-details-marker {
    display: none;
}

summary.velkaris-search-page-header::before {
    content: "\25B6"; /* ▶ collapsed */
    font-size: 0.55rem;
    color: var(--vk-text-muted);
    margin-right: 4px;
    transition: transform 0.15s ease;
}

.velkaris-search-page-group[open] > summary.velkaris-search-page-header::before {
    transform: rotate(90deg);
}

.velkaris-search-result-item {
    font-size: 0.8rem;
    padding: 2px 8px 2px 16px;
    cursor: pointer;
    color: var(--vk-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Individual comment row inside a page group. Replaces ad-hoc inline-styled
   borders that the CommentsTab used to render directly. */
.velkaris-comment-item {
    padding: 4px 8px;
    border-bottom: 1px solid var(--vk-border-light);
}

.velkaris-comment-item:last-child {
    border-bottom: none;
}

.velkaris-search-result-item:hover {
    background: var(--vk-accent-subtle);
}

.velkaris-search-result-item.active {
    background: var(--vk-accent-subtle);
    color: var(--vk-accent);
    font-weight: 600;
}

/* Metadata table (Info tab): label column shrinks to its content, the value
   column takes the remaining width. Cells marked .velkaris-meta-value ellipsize
   overlong values (e.g. long file names, paired with .text-truncate) instead of
   widening the table past the panel. */
.velkaris-meta-table {
    width: 100%;
}

.velkaris-meta-table td:first-child {
    width: 1%;
    white-space: nowrap;
}

.velkaris-meta-table td.velkaris-meta-value {
    max-width: 0;
}

/* Localized file picker (LocalizedFileInput.razor): the native <input type=file>
   is visually hidden but still triggered via its <label for>, so we control the
   button text and file-name display ("Choose file"/"No file chosen" would
   otherwise follow the browser locale, not the app culture). */
.velkaris-file-picker-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}

.velkaris-file-picker-name {
    min-width: 0;
}

.velkaris-file-picker.disabled {
    opacity: 0.6;
}

.velkaris-file-picker.disabled label {
    pointer-events: none;
}

/* ============================================================
   Redaction Panel
   ============================================================ */
.velkaris-masking-dict-list {
    max-height: 250px;
    overflow-y: auto;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius-sm);
    margin: 0 12px;
}

.velkaris-masking-dict-item {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    font-size: 0.8rem;
    border-bottom: 1px solid var(--vk-border-light);
    color: var(--vk-text-secondary);
}

.velkaris-dict-delete-btn {
    flex-shrink: 0;
    border: none;
    background: transparent;
    color: var(--vk-text-muted);
    font-size: 1rem;
    line-height: 1;
    padding: 0 2px;
    cursor: pointer;
    transition: color var(--vk-transition);
    /* WCAG 2.5.8: the 12px glyph alone was a ~16x12 target. */
    min-width: 24px;
    min-height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.velkaris-dict-delete-btn:hover {
    color: var(--vk-danger);
}

.velkaris-masking-dict-item:last-child {
    border-bottom: none;
}

.velkaris-masking-dict-item.inactive {
    opacity: 0.5;
    text-decoration: line-through;
}

.velkaris-masking-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    border: 1px solid var(--vk-border);
    flex-shrink: 0;
    background: var(--vk-swatch-color, transparent);
}

.velkaris-masking-quickadd {
    padding: 8px 12px;
}

/* Trailing cell of both quickadd rows (the down-arrow addon and the add button).
   A fixed width is the only way to make a span.input-group-text and a button.btn
   line up exactly — their default paddings differ, and Bootstrap has no
   "match my sibling's width" utility. Equal width keeps both input fields the
   same size and puts the arrow directly above the button it points at. */
.velkaris-quickadd-addon {
    width: 32px;
    padding-left: 0;
    padding-right: 0;
}

/* Redaction overlays on page */
.velkaris-masking-rect {
    position: absolute;
    pointer-events: none;
}

/* Clickable variant for area / image-region rects — toggle off on click */
.velkaris-masking-rect-clickable {
    pointer-events: auto;
    cursor: pointer;
}

/* Drawn rectangles are draggable while the area tool is active. They must sit ABOVE the
   draw overlay (z-index 15), otherwise grabbing one would start a new rectangle instead. */
.velkaris-area-movable {
    pointer-events: auto;
    cursor: move;
    z-index: 16;
}

.velkaris-area-movable.dragging {
    opacity: 0.75;
}

/* Full-page capture layer during a drag — see the markup comment: the pointer leaves the
   small rectangle constantly, so the page owns mousemove/mouseup. */
.velkaris-area-drag-capture {
    position: absolute;
    inset: 0;
    z-index: 20;
    cursor: move;
}

/* Relation: gleicher Hintergrund wie Einzelwort-Schwärzungen (Blackout-Style),
   nur der Rahmen bleibt braun, damit Relationen visuell unterscheidbar sind. */
.velkaris-masking-rect.mask-relation {
    border: 4px solid rgba(34, 197, 94, 0.7);
    background: rgba(0, 0, 0, 0.6);
    border-radius: 3px;
    box-sizing: border-box;
}

/* Einzel-Wort-Schwärzungen im Viewer: gleicher Stil wie Relationen
   (Rahmen + dezenter Tint), damit das Originalwort zur Prüfung sichtbar bleibt.
   Die tatsächliche Schwärzung beim Export bleibt davon unberührt. */
.velkaris-masking-rect.mask-filled {
    border: 4px solid rgba(220, 38, 38, 0.75);
    background: rgba(0, 0, 0, 0.6);
    border-radius: 3px;
    box-sizing: border-box;
}

.velkaris-masking-rect.mask-highlight {
    border: 4px solid rgba(220, 38, 38, 0.75);
    background: rgba(255, 215, 0, 0.7);
    border-radius: 3px;
    box-sizing: border-box;
}

.velkaris-masking-rect.mask-blur {
    border: 4px solid rgba(220, 38, 38, 0.75);
    background: rgba(148, 163, 184, 0.65);
    border-radius: 3px;
    box-sizing: border-box;
}

/* Manuell (lokal) geschwärzte Wörter: hellblauer Rahmen zur Unterscheidung
   von Wörterbuch-Schwärzungen. Background kommt vom jeweiligen redact-*-Style. */
.velkaris-masking-rect.mask-manual {
    border-color: rgba(96, 165, 250, 0.85);
}

.velkaris-masking-rect.mask-pseudonymize {
    background: var(--mask-bg, #fff);
    color: var(--mask-fg, #000);
    display: flex;
    /* Vertically center the alias on the (symmetrically padded) coverage box = centered on the
       original word. The export centers the alias the same way, so preview == export. */
    align-items: center;
    /* visible (not hidden): the alias font is sized larger than the box so its caps match
       the original word (see PseudonymFontFactor in DocumentViewer.razor), which makes
       ascenders/descenders extend past the box — clipping them cuts off 'g', 'p', cap tops.
       Width is still bounded by the JS auto-shrink (scrollWidth works under overflow:visible). */
    overflow: visible;
    white-space: nowrap;
    padding: 0 1px;
    font-family: var(--mask-font, Arial, sans-serif);
    font-weight: var(--mask-weight, normal);
    font-style: var(--mask-style, normal);
    line-height: 1;
    box-sizing: border-box;
}

/* Textmarker für Highlight-Pseudonyme: gelb wird ausschließlich der ALIAS-Textlauf (das
   inline-Span folgt exakt der Textbreite) — Parität zum Office-Run-Shading und zum
   PDF-Export, wo der Streifen mit der gemessenen Alias-Breite gebrannt wird. Die
   Abdeckbox dahinter behält den WYSIWYG-Hintergrund (sie verdeckt nur das Original).
   Ohne --hl-bg (Nicht-Highlight) bleibt das Span unsichtbar. */
.velkaris-masking-rect.mask-pseudonymize .mask-alias {
    background: var(--hl-bg, transparent);
}

/* Rückübersetzungs-Overlay im Rückläufer-Bereich: dezente Kennzeichnung, dass hier eine
   übersetzte Ansicht (Original über Alias) und kein Dokumentinhalt gerendert wird.
   outline statt border, damit die WYSIWYG-Box-Geometrie unangetastet bleibt. */
.velkaris-masking-rect.mask-reidentify {
    outline: 1px dashed rgba(22, 163, 74, 0.55);
    outline-offset: 1px;
}

/* Clickable word overlay for redaction tool */
.velkaris-word-click-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
}

.velkaris-word-clickable {
    position: absolute;
    pointer-events: auto;
    cursor: pointer;
    border: 1px solid transparent;
    border-radius: 2px;
    transition: border-color 0.1s, background-color 0.1s;
    box-sizing: border-box;
}

.velkaris-word-clickable:hover {
    border-color: rgba(59, 130, 246, 0.5);
    background: rgba(59, 130, 246, 0.1);
}

/* Bei bereits geschwärzten Wörtern wird die Optik vom darunterliegenden
   .velkaris-masking-rect erzeugt — der Klick-Overlay bleibt transparent,
   damit kein doppelter Rahmen entsteht. Nur Hover liefert Klick-Feedback. */
.velkaris-word-clickable.word-dict,
.velkaris-word-clickable.word-dict-relation,
.velkaris-word-clickable.word-manual {
    border-color: transparent;
    background: transparent;
}

.velkaris-word-clickable.word-dict:hover,
.velkaris-word-clickable.word-dict-relation:hover,
.velkaris-word-clickable.word-manual:hover {
    background: rgba(59, 130, 246, 0.12);
}

.velkaris-word-clickable.word-excluded {
    border-color: rgba(34, 197, 94, 0.4);
    background: rgba(34, 197, 94, 0.1);
    border-style: dashed;
}

.velkaris-word-clickable.word-excluded:hover {
    background: rgba(34, 197, 94, 0.2);
}

/* ============================================================
   Search Highlight Overlay
   ============================================================ */
.velkaris-highlight-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
}

.velkaris-highlight-rect {
    position: absolute;
    background: var(--vk-highlight-bg);
    border: 1px solid var(--vk-highlight-border);
    border-radius: 2px;
    transition: background-color 0.15s;
}

.velkaris-highlight-rect.current {
    background: var(--vk-highlight-active-bg);
    border-color: var(--vk-highlight-active-border);
    box-shadow: 0 0 4px rgba(234, 88, 12, 0.4);
}

/* ============================================================
   Area Drawing Overlay
   ============================================================ */
.velkaris-draw-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    cursor: crosshair;
    z-index: 15;
}

.velkaris-draw-rect {
    position: absolute;
    pointer-events: none;
}

/* ============================================================
   OCR Word Bounds Overlay
   ============================================================ */
.velkaris-ocr-bounds-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}

.velkaris-ocr-bound {
    position: absolute;
    border: 1px solid rgba(59, 130, 246, 0.5);
    background: rgba(59, 130, 246, 0.04);
    border-radius: 2px;
    pointer-events: auto;
    cursor: pointer;
    transition: background-color 0.1s, border-color 0.1s;
}

.velkaris-ocr-bound:hover {
    background: rgba(59, 130, 246, 0.18);
    border-color: rgba(59, 130, 246, 0.8);
    box-shadow: 0 0 3px rgba(59, 130, 246, 0.3);
}

.velkaris-ocr-bound.masked {
    border-color: rgba(168, 85, 247, 0.6);
    background: rgba(168, 85, 247, 0.15);
}

.velkaris-ocr-bound.masked:hover {
    background: rgba(168, 85, 247, 0.25);
    border-color: rgba(168, 85, 247, 0.9);
}

/* ============================================================
   Scrollbar Styling
   ============================================================ */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.15);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.25);
}

[data-theme="dark"] ::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.12);
}

[data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.2);
}

/* ============================================================
   Focus & Accessibility
   ============================================================ */
:focus-visible {
    outline: 2px solid var(--vk-accent);
    outline-offset: 2px;
}

h1:focus-visible,
h2:focus-visible,
h3:focus-visible,
h4:focus-visible,
h5:focus-visible,
h6:focus-visible {
    outline: none;
}

/* ============================================================
   Transitions for theme switching
   ============================================================ */
.velkaris-app,
.velkaris-sidebar,
.velkaris-topbar,
.velkaris-main,
.velkaris-stat-card,
.velkaris-project-card,
.velkaris-table,
.velkaris-viewer-toolbar,
.velkaris-viewer-toolpanel,
.velkaris-viewer-sidebar {
    transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

/* ============================================================
   DocumentViewer – Lightroom-style Guided Tour
   ============================================================ */

.velkaris-tour-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    pointer-events: auto;
    animation: velkaris-tour-fade 0.18s ease-out;
}

.velkaris-tour-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
}

.velkaris-tour-spotlight {
    position: absolute;
    border-radius: 8px;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55),
                0 0 0 2px var(--vk-accent),
                0 0 24px rgba(192, 52, 29, 0.45);
    pointer-events: none;
    transition: left 0.25s ease, top 0.25s ease, width 0.25s ease, height 0.25s ease;
}

.velkaris-tour-popover {
    position: absolute;
    width: 360px;
    max-width: calc(100vw - 16px);
    background: var(--vk-bg-card);
    color: var(--vk-text);
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
    padding: 16px 18px 14px;
    transition: left 0.25s ease, top 0.25s ease;
    pointer-events: auto;
}

.velkaris-tour-popover-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
}

.velkaris-tour-step-counter {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--vk-accent);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.velkaris-tour-close {
    background: transparent;
    border: 0;
    font-size: 1.4rem;
    line-height: 1;
    color: var(--vk-text-muted, #6b7280);
    cursor: pointer;
    padding: 0 4px;
    border-radius: 4px;
}

.velkaris-tour-close:hover {
    color: var(--vk-text);
    background: var(--vk-bg-inset);
}

.velkaris-tour-title {
    margin: 0 0 8px 0;
    font-size: 1.05rem;
    font-weight: 600;
}

.velkaris-tour-body {
    font-size: 0.875rem;
    line-height: 1.5;
    color: var(--vk-text);
}

.velkaris-tour-body p {
    margin: 0 0 8px 0;
}

.velkaris-tour-body p:last-child {
    margin-bottom: 0;
}

.velkaris-tour-body kbd {
    background: var(--vk-bg-inset);
    border: 1px solid var(--vk-border);
    border-radius: 4px;
    padding: 1px 6px;
    font-size: 0.78rem;
    font-family: inherit;
    color: var(--vk-text);
}

.velkaris-tour-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--vk-border-light, var(--vk-border));
}

.velkaris-tour-nav {
    display: flex;
    gap: 6px;
    margin-left: auto;
}

.velkaris-tour-progress {
    display: flex;
    justify-content: center;
    gap: 5px;
    margin-top: 10px;
}

.velkaris-tour-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--vk-border);
    transition: background 0.15s ease, transform 0.15s ease;
}

.velkaris-tour-dot.done {
    background: var(--vk-accent-border);
}

.velkaris-tour-dot.active {
    background: var(--vk-accent);
    transform: scale(1.35);
}

/* Popover arrow */
.velkaris-tour-popover::before {
    content: "";
    position: absolute;
    width: 12px;
    height: 12px;
    background: var(--vk-bg-card);
    border: 1px solid var(--vk-border);
    transform: rotate(45deg);
}

.velkaris-tour-popover.bottom::before {
    top: -7px;
    left: 50%;
    margin-left: -6px;
    border-right: 0;
    border-bottom: 0;
}

.velkaris-tour-popover.top::before {
    bottom: -7px;
    left: 50%;
    margin-left: -6px;
    border-left: 0;
    border-top: 0;
}

.velkaris-tour-popover.left::before {
    right: -7px;
    top: 50%;
    margin-top: -6px;
    border-left: 0;
    border-bottom: 0;
}

.velkaris-tour-popover.right::before {
    left: -7px;
    top: 50%;
    margin-top: -6px;
    border-right: 0;
    border-top: 0;
}

.velkaris-tour-popover.center::before {
    display: none;
}

@keyframes velkaris-tour-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

[data-theme="dark"] .velkaris-tour-popover {
    background: var(--vk-bg-card);
    border-color: var(--vk-border);
}

[data-theme="dark"] .velkaris-tour-popover::before {
    background: var(--vk-bg-card);
    border-color: var(--vk-border);
}

/* ============================================================
   /system/demo-sessions — moved from inline <style> block.
   Selectors are namespaced .velkaris-demo-* — no scope leakage.
   ============================================================ */
/* Inline-aligned icon inside small badges/buttons. Replaces ad-hoc
   style="vertical-align:-1px|-2px" attributes on <Icon> components. */
.velkaris-icon-inline {
    vertical-align: -2px;
    display: inline-block;
}
.velkaris-demo-sessions-stats {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0.75rem;
}
.velkaris-demo-stat {
    background: var(--vk-bg-card);
    border: 1px solid var(--vk-border);
    border-radius: 8px;
    padding: 0.75rem 1rem;
    text-align: center;
}
.velkaris-demo-stat-num {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1;
}
.velkaris-demo-stat-num--yellow {
    color: var(--vk-warning);
}
.velkaris-demo-stat-label {
    font-size: 0.78rem;
    color: var(--vk-text-muted, #6b7280);
    margin-top: 0.25rem;
}
.velkaris-demo-filter {
    max-width: 220px;
}
.velkaris-demo-sessions-table tbody tr.velkaris-demo-session-row { cursor: pointer; }
.velkaris-demo-session-row.open { background: var(--vk-bg-card-hover); }
.velkaris-demo-toggle {
    font-family: monospace;
    color: var(--vk-text-muted);
    font-size: 0.85rem;
}
/* Status indicator: semantic colors stay constant across themes (traffic-light metaphor). */
.velkaris-demo-light {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.08);
}
.velkaris-demo-light.green { background: #16a34a; }
.velkaris-demo-light.yellow { background: #facc15; }
.velkaris-demo-light.red { background: #dc2626; }
.velkaris-demo-light.unknown { background: #d1d5db; }
.velkaris-demo-session-id {
    font-family: monospace;
    font-size: 0.85rem;
    color: var(--vk-text);
}
.velkaris-demo-session-time {
    font-size: 0.78rem;
    color: var(--vk-text-muted);
}
.velkaris-demo-ip {
    font-family: monospace;
    font-size: 0.82rem;
}
.velkaris-demo-duration {
    font-size: 0.85rem;
    color: var(--vk-text-secondary);
    white-space: nowrap;
}
.velkaris-demo-detail-row td { background: var(--vk-bg-inset) !important; }
.velkaris-demo-detail-panel {
    padding: 0.75rem 0.5rem;
}
.velkaris-demo-detail-meta {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.85rem;
}
.velkaris-demo-detail-timeline {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    color: var(--vk-text-secondary);
}
.velkaris-demo-docs-table th {
    background: var(--vk-bg-card);
    font-weight: 600;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--vk-text-muted);
}
.velkaris-demo-doc-name {
    max-width: 360px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.88rem;
}
/* -text variants: the base tokens miss 4.5:1 as small text in one theme each. */
.velkaris-demo-conv-completed { color: var(--vk-success-text); font-weight: 500; }
.velkaris-demo-conv-failed { color: var(--vk-danger-text); font-weight: 500; }
.velkaris-demo-conv-pending { color: var(--vk-text-muted); }
.velkaris-demo-conv-processing { color: var(--vk-info-text); }
/* Cancelled = user ended/replaced the session mid-conversion — muted but distinct from pending */
.velkaris-demo-conv-cancelled { color: var(--vk-text-muted); font-style: italic; }


/* ── Toast notifications (ToastContainer.razor) ─────────────────────────── */
/* Above Bootstrap modals (1055) so feedback stays visible over dialogs. */
.velkaris-toast-container {
    z-index: 1090;
}
/* Entry: slide up + fade in (pure CSS — toasts render with .show directly,
   Bootstrap's JS-driven .showing/.hide phases are not used). */
.velkaris-toast-container .toast {
    animation: velkaris-toast-in 0.25s ease-out;
}
@keyframes velkaris-toast-in {
    from {
        opacity: 0;
        transform: translateY(0.5rem);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
/* Exit: keep .show (removing it would display:none instantly) and fade via
   this marker class; the component removes the element after 300ms. */
.velkaris-toast-container .toast.velkaris-toast-closing {
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* ── Responsive table action buttons ─────────────────────────────────────── */
/* Wrap the text of a table action button in .velkaris-btn-label: below the xl
   breakpoint only the icon remains, above it icon + text. The label is hidden
   visually-hidden-style instead of display:none so the button KEEPS its
   accessible name for screen readers and voice control (4.1.2/2.5.3) — the
   title attribute alone is not a reliable name. */
@media (max-width: 1199.98px) {
    .velkaris-btn-label {
        position: absolute !important;
        width: 1px !important;
        height: 1px !important;
        padding: 0 !important;
        margin: -1px !important;
        overflow: hidden !important;
        clip: rect(0, 0, 0, 0) !important;
        white-space: nowrap !important;
        border: 0 !important;
    }
}

/* Disabled buttons: Bootstrap sets pointer-events:none on .btn:disabled, which
   also suppresses any cursor feedback. Re-enable pointer events just for the
   cursor — the native disabled attribute still blocks clicks. */
.btn:disabled {
    pointer-events: auto;
    cursor: not-allowed;
}

/* Connector fetch: flat tree of a matter's folders and documents. Rendered as rows with a depth
   variable instead of nested lists — same approach as the folder explorer tree. */
.velkaris-fetch-tree {
    max-height: 26rem;
    border: 1px solid var(--vk-border);
    border-radius: var(--vk-radius-sm);
    padding: 0.35rem 0;
}
.velkaris-fetch-row {
    display: flex;
    align-items: center;
    padding: 0.2rem 0.6rem 0.2rem calc(0.6rem + var(--vk-tree-depth, 0) * 1.15rem);
    line-height: 1.5;
}
.velkaris-fetch-row:hover {
    background-color: var(--vk-accent-subtle);
}

/* ============================================================
   Accessibility (WCAG 2.2) — skip link, input borders, motion,
   small-viewport reflow. Added with the 2026-08 audit remediation.
   ============================================================ */

/* Skip link (2.4.1): first element in MainLayout; Bootstrap's
   .visually-hidden-focusable reveals it on keyboard focus. */
.velkaris-skip-link:focus,
.velkaris-skip-link:focus-visible {
    position: fixed;
    top: 0.75rem;
    left: 0.75rem;
    z-index: 2000;
    padding: 0.5rem 1rem;
    background: var(--vk-bg-card);
    color: var(--vk-text);
    border: 2px solid var(--vk-accent);
    border-radius: var(--vk-radius-sm);
    font-weight: 600;
    text-decoration: none;
}

/* Input borders (1.4.11): the decorative card border (~1.3:1) is the only
   visual boundary of a field because input bg equals the card bg — raise it
   to >= 3:1. The focus state keeps the accent border + ring. */
.form-control,
.form-select {
    border-color: var(--vk-border-input);
}

/* Reduced motion (2.3.3): the UI only uses short transitions, but they are
   now skippable — includes the sidebar/panel slide and toast/tour fades. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Reflow (1.4.10): below 900px the sidebar always renders as the icon rail —
   the fixed 260px column otherwise forces horizontal scrolling at 320px CSS
   width (400% zoom). Mirrors the .sidebar-collapsed rules; the manual toggle
   still works above the breakpoint. */
@media (max-width: 899.98px) {
    .velkaris-sidebar { width: var(--vk-sidebar-rail); }
    .velkaris-sidebar-brand { padding: 1rem 0; justify-content: center; }
    .velkaris-sidebar-brand .brand-logo-full { display: none; }
    .velkaris-sidebar-brand .brand-logo-icon {
        display: block;
        height: 28px;
        max-width: calc(var(--vk-sidebar-rail) - 1.25rem);
    }
    .velkaris-sidebar-footer { justify-content: center; padding-left: 0; padding-right: 0; }
    .velkaris-sidebar-nav { padding-left: 0; padding-right: 0; align-items: center; }
    .velkaris-sidebar-nav .nav-item { width: 100%; }
    .velkaris-sidebar-nav .nav-item a { justify-content: center; gap: 0; padding: 0.55rem 0; }
    .velkaris-sidebar-nav .nav-item a span { display: none; }
    .velkaris-sidebar-nav .nav-section {
        padding: 0.5rem 0.75rem;
        font-size: 0;
        border-top: 1px solid var(--vk-border-sidebar);
        margin: 0.375rem 0.75rem 0;
    }
    .velkaris-content { margin-left: var(--vk-sidebar-rail); }
    .velkaris-topbar { padding: 0 1rem; }
    .velkaris-main { padding: 1rem; }
}

/* Focus ring for the invisible full-area file input inside the upload dropzone
   (2.4.7): the input itself is opacity:0, so the ring is drawn on the zone. */
.velkaris-dropzone:has(.velkaris-dropzone-input:focus-visible) {
    outline: 2px solid var(--vk-accent);
    outline-offset: 2px;
}
