/* Voitta RAG Enterprise — Apple-flavoured UI, lifted from voitta-rag's palette. */

:root {
    /* Tell the browser this is a light UI so native controls — scrollbars,
       form widgets, the search-field clear button — render light. The dark
       override below flips it; without this, dark mode keeps white scrollbars. */
    color-scheme: light;

    --color-bg: #f5f5f7;
    --color-bg-elevated: #ffffff;
    --color-bg-hover: #e8e8ed;
    --color-text-primary: #1d1d1f;
    --color-text-secondary: #86868b;
    --color-text-tertiary: #aeaeb2;
    /* Alias used throughout the CSS (panels, tree, admin, modal). Defined here
       so those references resolve; tracks the active theme's primary text via
       --color-text-primary, so it flips correctly in dark mode too. */
    --color-text: var(--color-text-primary);
    --color-accent: #0071e3;
    --color-accent-hover: #0077ed;
    --color-border: #d2d2d7;
    --color-border-light: #e5e5ea;
    --color-success: #34c759;
    --color-error: #ff3b30;
    --color-warning: #ff9500;

    --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
        "Helvetica Neue", Helvetica, Arial, sans-serif;

    --xs: 4px;
    --sm: 8px;
    --md: 16px;
    --lg: 24px;
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-full: 9999px;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
    --t: 150ms ease;
}

[data-theme="dark"] {
    color-scheme: dark;

    --color-bg: #1d1d1f;
    --color-bg-elevated: #2c2c2e;
    --color-bg-hover: #3a3a3c;
    --color-text-primary: #f5f5f7;
    --color-text-secondary: #a1a1a6;
    --color-text-tertiary: #636366;
    --color-accent: #0a84ff;
    --color-accent-hover: #409cff;
    --color-border: #3a3a3c;
    --color-border-light: #48484a;
}

* { box-sizing: border-box; }

/* Re-assert the [hidden] attribute against display:flex/grid rules below. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
    margin: 0;
    background: var(--color-bg);
    color: var(--color-text-primary);
    font: 13px/1.4 var(--font);
    -webkit-font-smoothing: antialiased;
    /* Vertical flex so the main pane fills exactly the remaining viewport
       under the sticky header — lets the folder list scroll internally
       instead of pushing the page below the fold. */
    display: flex;
    flex-direction: column;
}

/* ---------- Header ---------- */

.app-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--color-bg-elevated);
    border-bottom: 1px solid var(--color-border-light);
}
.header-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 24px;
    max-width: 1600px;
    margin: 0 auto;
}
.logo {
    font-weight: 600;
    font-size: 15px;
    color: var(--color-text-primary);
    text-decoration: none;
}
.header-actions { display: flex; align-items: center; gap: 12px; }

.status-pill {
    display: inline-flex;
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: 11px;
    font-weight: 500;
    text-transform: lowercase;
}
.status-pill.connected {
    background: rgba(52, 199, 89, 0.15);
    color: var(--color-success);
}
.status-pill.disconnected {
    background: rgba(255, 59, 48, 0.15);
    color: var(--color-error);
}

/* ---------- Bootstrap loading overlay ---------- */

#boot-overlay {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: var(--color-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.3s ease;
}
#boot-overlay.hidden {
    opacity: 0;
    pointer-events: none;
}
.boot-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--color-border);
    border-top-color: var(--color-accent);
    border-radius: 50%;
    animation: boot-spin 0.7s linear infinite;
}
@keyframes boot-spin {
    to { transform: rotate(360deg); }
}

/* ---------- Layout ---------- */

.app-main {
    /* Fill the height left by the sticky app header so children can claim
       their share of the viewport with min-height:0 + flex:1. Without
       min-height:0 a flex child refuses to shrink below its intrinsic
       content size and the grid below would force the whole page to scroll. */
    width: 100%;
    max-width: 1600px;
    margin: 0 auto;
    padding: var(--lg);
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Box-sizing safety: padding shouldn't make us overflow. */
    box-sizing: border-box;
}
.browser-container {
    display: flex;
    flex-direction: column;
    gap: var(--md);
    flex: 1;
    min-height: 0;
}
.toolbar {
    position: relative;              /* anchor for the floating upload panel */
    display: flex;
    gap: var(--sm);
    align-items: center;
    flex-wrap: wrap;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-light);
    border-radius: var(--radius-lg);
    padding: 8px 12px;
}
.toolbar-group { display: flex; gap: 6px; align-items: center; }
.toolbar-divider {
    width: 1px;
    height: 22px;
    background: var(--color-border);
    margin: 0 4px;
}
/* Upload progress — a compact pill that FLOATS just below the toolbar's
   right edge (absolute, so it's out of the flex flow: the toolbar never wraps
   or changes height while files stream in). Its detail list drops below the
   pill as a second floating panel. The toolbar is position:relative so both
   pin to its bottom-right corner. */
.upload-progress {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 30;
}
.upload-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    max-width: 260px;
    padding: 0 10px;
    overflow: hidden;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: 12px;
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background var(--t), border-color var(--t);
}
.upload-pill:hover { background: var(--color-bg-hover); border-color: var(--color-accent); }
.upload-pill-icon { flex-shrink: 0; color: var(--color-accent); }
.upload-progress-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-secondary);
}
.upload-pill-caret {
    flex-shrink: 0;
    font-size: 10px;
    color: var(--color-text-tertiary);
    transition: transform 120ms ease;
}
.upload-progress[data-open="true"] .upload-pill-caret { transform: rotate(180deg); }
/* The aggregate progress rides as a thin accent underline across the pill. */
.upload-pill-underline {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 0;
    background: var(--color-accent);
    transition: width 100ms linear;
}
.upload-pill.state-done { border-color: var(--color-accent); }
.upload-pill.state-failed { border-color: #c33; }
.upload-pill.state-failed .upload-pill-icon { color: #c33; }

/* Floating detail panel — overlays the folder list; never reflows layout. */
.upload-panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 30;
    width: 340px;
    max-width: 80vw;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
    padding: 6px;
    display: none;
}
.upload-progress[data-open="true"] .upload-panel { display: block; }
.upload-file-list {
    margin: 0;
    padding: 0;
    list-style: none;
    max-height: 240px;
    overflow-y: auto;
    font-size: 12px;
    color: var(--color-text-secondary);
}
.upload-file-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 6px;
    border-radius: var(--radius-sm);
}
.upload-file-list li:hover { background: var(--color-bg-hover); }
.upload-file-list li .glyph {
    flex-shrink: 0;
    width: 14px;
    text-align: center;
    color: var(--color-text-tertiary);
}
.upload-file-list li .name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.upload-file-list li .pct {
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-tertiary);
    min-width: 34px;
    text-align: right;
}
.upload-file-list li.active .glyph { color: var(--color-accent); }
.upload-file-list li.done .glyph,
.upload-file-list li.done .name,
.upload-file-list li.done .pct { color: var(--color-accent); }
.upload-file-list li.failed .glyph,
.upload-file-list li.failed .pct,
.upload-file-list li.failed .name { color: #c33; }
/* Persistent drag-drop discoverability hint. Muted one-liner between the
   toolbar and the list — makes the "drag several folders at once" path
   visible without the user first having to start a drag. */
.drop-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: -6px 0 0;
    padding: 0 2px;
    font-size: 11px;
    color: var(--color-text-tertiary);
    user-select: none;
}
.drop-hint-icon {
    flex-shrink: 0;
    font-size: 12px;
    opacity: 0.8;
}

.browser-layout {
    display: grid;
    grid-template-columns: 1fr 360px;
    gap: var(--lg);
    align-items: stretch;
    flex: 1;
    min-height: 0;
    position: relative;
}
/* Drag-and-drop drop zone. A faint dashed frame marks the whole folder
   area as droppable AT REST — so the capability is visible before any
   drag starts, not only once one is in flight. On an active drag the
   frame brightens, tints, and shows the prompt. It spans the entire
   browser-layout, which IS the drop target, so what lights up matches
   exactly where drops are accepted. pointer-events stay off so the
   child rows keep working (and dragover keeps bubbling) mid-drag. */
.browser-layout::after {
    content: "";
    position: absolute;
    inset: 0;
    border: 1.5px dashed var(--color-border);
    border-radius: 10px;
    background: transparent;
    color: var(--color-accent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    pointer-events: none;
    z-index: 10;
    opacity: 0.5;
    transition: opacity var(--t), border-color var(--t), background var(--t);
}
.browser-layout.drop-active::after {
    content: "Drop files or folders here — multiple folders OK, subfolders kept";
    border-color: var(--color-accent);
    border-width: 2px;
    background: rgba(0, 113, 227, 0.08);
    opacity: 1;
}


/* Startup banner — shown while the backend warms up (model load / workers).
   A thin accent strip across the top with a small spinner. */
.startup-banner {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 16px; font-size: 13px;
    background: #fff7ed; color: #9a3412;
    border-bottom: 1px solid #fed7aa;
}
.startup-banner .spinner {
    width: 12px; height: 12px; border-radius: 50%;
    border: 2px solid #fdba74; border-top-color: #9a3412;
    animation: voitta-spin 0.8s linear infinite;
    flex: 0 0 auto;
}
@keyframes voitta-spin { to { transform: rotate(360deg); } }

/* YubiKey touch prompt — a centred, pulsing strip across the top. More
   assertive than the startup banner because it demands a physical action.
   Uses an accent gradient so it reads in both light and dark themes. */
.touch-banner {
    position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
    display: flex; align-items: center; justify-content: center; gap: 10px;
    padding: 10px 16px; font-size: 14px; font-weight: 600;
    color: #fff; background: #2563eb;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
    animation: voitta-touch-pulse 1.1s ease-in-out infinite;
}
.touch-banner .touch-pulse {
    width: 12px; height: 12px; border-radius: 50%;
    background: #fff; flex: 0 0 auto;
    animation: voitta-touch-dot 1.1s ease-in-out infinite;
}
@keyframes voitta-touch-pulse {
    0%, 100% { background: #2563eb; }
    50% { background: #1d4ed8; }
}
@keyframes voitta-touch-dot {
    0%, 100% { opacity: 0.35; transform: scale(0.8); }
    50% { opacity: 1; transform: scale(1.15); }
}
