From 585caaee5803a2334f3c9d55a2e89e0cde2c0832 Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Mon, 10 Nov 2025 11:00:06 +0100 Subject: [PATCH] refactor styles --- frontend/src/desktop/DesktopWorkspace.css | 400 -- frontend/src/desktop/DesktopWorkspace.jsx | 5 +- frontend/src/index.jsx | 2 +- frontend/src/styles.css | 4465 ----------------- frontend/src/styles/auth/login.css | 131 + frontend/src/styles/base/controls.css | 99 + frontend/src/styles/base/iconography.css | 56 + frontend/src/styles/base/text-button.css | 14 + frontend/src/styles/base/theme.css | 295 ++ frontend/src/styles/detail/detail-panels.css | 777 +++ frontend/src/styles/documents/controls.css | 108 + frontend/src/styles/documents/listing.css | 736 +++ .../src/styles/documents/panel-sections.css | 133 + .../src/styles/documents/shared-snippets.css | 26 + .../styles/documents/tags-correspondents.css | 173 + frontend/src/styles/documents/viewer.css | 335 ++ frontend/src/styles/forms/elements.css | 29 + frontend/src/styles/index.css | 22 + .../styles/layout/panel-header-controls.css | 43 + frontend/src/styles/layout/responsive.css | 17 + frontend/src/styles/layout/structure.css | 147 + frontend/src/styles/modals/panel-modals.css | 44 + frontend/src/styles/modals/status-drop.css | 77 + frontend/src/styles/preview/preview-zoom.css | 113 + frontend/src/styles/settings/settings.css | 337 ++ frontend/src/styles/sidebar/sidebar.css | 584 +++ frontend/src/styles/uploads/overlay.css | 176 + .../src/styles/workspace/workspace-cards.css | 122 + .../src/styles/workspace/workspace-items.css | 135 + .../src/styles/workspace/workspace-layout.css | 45 + .../styles/workspace/workspace-overlays.css | 94 + 31 files changed, 4873 insertions(+), 4867 deletions(-) delete mode 100644 frontend/src/desktop/DesktopWorkspace.css delete mode 100644 frontend/src/styles.css create mode 100644 frontend/src/styles/auth/login.css create mode 100644 frontend/src/styles/base/controls.css create mode 100644 frontend/src/styles/base/iconography.css create mode 100644 frontend/src/styles/base/text-button.css create mode 100644 frontend/src/styles/base/theme.css create mode 100644 frontend/src/styles/detail/detail-panels.css create mode 100644 frontend/src/styles/documents/controls.css create mode 100644 frontend/src/styles/documents/listing.css create mode 100644 frontend/src/styles/documents/panel-sections.css create mode 100644 frontend/src/styles/documents/shared-snippets.css create mode 100644 frontend/src/styles/documents/tags-correspondents.css create mode 100644 frontend/src/styles/documents/viewer.css create mode 100644 frontend/src/styles/forms/elements.css create mode 100644 frontend/src/styles/index.css create mode 100644 frontend/src/styles/layout/panel-header-controls.css create mode 100644 frontend/src/styles/layout/responsive.css create mode 100644 frontend/src/styles/layout/structure.css create mode 100644 frontend/src/styles/modals/panel-modals.css create mode 100644 frontend/src/styles/modals/status-drop.css create mode 100644 frontend/src/styles/preview/preview-zoom.css create mode 100644 frontend/src/styles/settings/settings.css create mode 100644 frontend/src/styles/sidebar/sidebar.css create mode 100644 frontend/src/styles/uploads/overlay.css create mode 100644 frontend/src/styles/workspace/workspace-cards.css create mode 100644 frontend/src/styles/workspace/workspace-items.css create mode 100644 frontend/src/styles/workspace/workspace-layout.css create mode 100644 frontend/src/styles/workspace/workspace-overlays.css diff --git a/frontend/src/desktop/DesktopWorkspace.css b/frontend/src/desktop/DesktopWorkspace.css deleted file mode 100644 index 30975f0..0000000 --- a/frontend/src/desktop/DesktopWorkspace.css +++ /dev/null @@ -1,400 +0,0 @@ -/* Desktop workspace styles */ -.desk-main { - flex: 1; - display: flex; - flex-direction: column; - min-height: 0; -} - -.desk-item { - position: absolute; - display: block; - width: auto; - cursor: grab; - touch-action: none; - transform-origin: center center; - transition: box-shadow 0.16s ease; - outline: none; - will-change: transform; - -webkit-user-select: none; - user-select: none; - -webkit-touch-callout: none; -} - -.desk-shell { - flex: 1; - display: flex; - flex-direction: column; - grid-column: 2 / -1; - min-height: 0; - position: relative; -} - -.desk-canvas { - flex: 1; - position: relative; - overflow: hidden; - margin: 0; - outline: none; -} - -.desk-canvas:focus, -.desk-canvas:focus-visible { - outline: none; -} - -.desk-empty { - height: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: 3rem; - text-align: center; - color: var(--muted); - font-size: 0.95rem; -} - - - -.desk-item__body { - flex-grow: 1; - width: 100%; - height: 100%; -} - -.desk-item:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 4px; -} - -.desk-item.is-dragging { - cursor: grabbing; - transition: none; -} - -.desk-item.is-tag-target .desk-item__card { - outline: 0.35rem dashed var(--accent); - outline-offset: 0.35rem; -} - -.desk-item.is-tag-pending .desk-item__card { - outline: 0.25rem solid var(--accent-outline); - outline-offset: 0.25rem; -} - -.desk-item.is-filtered-out { - opacity: 0.12; - pointer-events: none; - filter: blur(15px) grayscale(100%); - transition: opacity 0.6s ease, filter 0.28s ease; - z-index: 0 !important; -} - -.desk-item.is-selected { - z-index: 5; -} - -.desk-item.is-selected .desk-item__card { - box-shadow: - 0 0 0 0.18rem color-mix(in oklch, var(--accent) 45%, transparent), - 0 0 0.35rem 0 color-mix(in oklch, var(--accent) 28%, transparent), - 0 12px 28px -14px color-mix(in oklch, var(--accent) 20%, transparent), - 0 10px 24px var(--shadow-medium); -} - -.desk-item.is-selected .desk-item__title { - color: var(--accent); -} - -.desk-item__tags { - position: absolute; - top: 0; - right: 0; - display: flex; - flex-direction: column; - gap: 0.35rem; - align-items: flex-end; - transform-origin: top right; - transform: translate(-0.5em, 0.5em); - transition: transform 0.28s ease; -} - -.desk-item__correspondents { - position: absolute; - bottom: 0; - left: 0; - display: flex; - flex-direction: column; - gap: 0.35rem; - align-items: flex-start; - transform-origin: bottom left; - transform: translate(0.5em, -0.5em); - pointer-events: none; -} - -.desk-correspondent-chip { - pointer-events: none; - font-size: 0.82rem; - padding: 0.18rem 0.55rem; - max-width: min(16rem, 80%); - display: inline-flex; - align-items: center; - overflow: hidden; - background: color-mix(in oklch, var(--surface-subtle) 90%, transparent); - color: var(--muted); -} - -.desk-correspondent-chip__label { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - - -.tag-chip--draggable { - user-select: none; - pointer-events: auto; - cursor: grab; - transition: transform 0.16s ease, opacity 0.2s ease, box-shadow 0.2s ease; -} - -.desk-help-overlay { - position: fixed; - inset: 0; - z-index: 5000000; - display: flex; - align-items: center; - justify-content: center; - padding: clamp(1.5rem, 4vw, 3rem); - pointer-events: none; -} - -.desk-help-overlay__backdrop { - position: absolute; - inset: 0; - background: var(--surface-overlay); - backdrop-filter: blur(8px); - pointer-events: auto; -} - -.desk-help-overlay__content { - position: relative; - width: min(640px, 92vw); - max-height: min(80vh, 640px); - background: var(--surface); - border: 1px solid var(--border); - box-shadow: 0 24px 64px var(--shadow-strong); - border-radius: 1.25rem; - display: flex; - flex-direction: column; - pointer-events: auto; - overflow: hidden; -} - -.desk-help-overlay__header, -.desk-help-overlay__footer { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1rem 1.25rem; -} - -.desk-help-overlay__header { - border-bottom: 1px solid var(--border); -} - -.desk-help-overlay__header h2 { - margin: 0; - font-size: 1.15rem; - font-weight: 600; -} - -.desk-help-overlay__body { - padding: 1rem 1.25rem 1.5rem; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 0.75rem; - line-height: 1.55; -} - -.desk-help-overlay__body p { - margin: 0; - color: var(--muted); -} - -.desk-help-overlay__list { - margin: 0; - padding-left: 1.1rem; - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.desk-help-overlay__list li { - color: var(--fg); -} - -.desk-help-overlay__body kbd { - display: inline-block; - padding: 0.15rem 0.4rem; - border-radius: 0.4rem; - border: 1px solid var(--border-strong); - background: var(--surface-subtle); - font-size: 0.85em; - line-height: 1; - font-family: inherit; -} - -.desk-help-overlay__footer { - border-top: 1px solid var(--border); - justify-content: flex-end; - gap: 0.5rem; -} - -.tag-chip--draggable:active { - cursor: grabbing; -} - -.tag-chip--draggable.is-drag-hidden { - opacity: 0.4; -} - -.desk-item__tags .tag-chip { - font-size: 0.85rem; - padding: 0.18rem 0.55rem; - gap: 0.3rem; -} - - -.desk-card__nav { - position: absolute; - bottom: 1.8rem; - left: 50%; - transform: translateX(-50%); - transform-origin: center; - display: flex; - gap: 1.5rem; - opacity: 0; - pointer-events: none; - transition: opacity 0.2s ease; -} - -.desk-item__card:hover .desk-card__nav { - opacity: 1; - pointer-events: auto; -} - -.desk-card__nav-button { - display: inline-flex; - align-items: center; - justify-content: center; - width: 2.4em; - height: 2.4em; - padding: 0.25em; - border-radius: 50%; - border: none; - background: var(--preview-nav-bg); - color: var(--preview-nav-fg); - cursor: pointer; - transition: background 0.15s ease, opacity 0.15s ease; -} - -.desk-card__nav-button:hover:not([disabled]) { - background: var(--preview-nav-bg-hover); -} - -.desk-card__nav-button:disabled { - opacity: 0.4; - cursor: default; -} - -.desk-card__nav-button:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.desk-card__nav-button svg { - width: 100%; - height: 100%; -} - -.desk-item__tags .tag-chip--tear-pending { - opacity: 0.35; -} - -body.desk-cursor-remove, -body.desk-cursor-remove * { - cursor: not-allowed !important; -} - -.desk-item__shadow { - display: none; -} - -.desk-item__card { - position: relative; - border-radius: 0; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - box-shadow: 0 12px 32px var(--shadow-medium); - overflow: hidden; -} - -.desk-item__card img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - pointer-events: none; - user-select: none; - -webkit-user-drag: none; -} - -.desk-item__card--empty { - box-shadow: 0 12px 32px var(--shadow-medium); - background: - radial-gradient(circle at 42% 38%, color-mix(in oklch, var(--surface-subtle) 75%, var(--selection) 25%), color-mix(in oklch, var(--surface-subtle) 85%, var(--selection) 15%) 70%), - linear-gradient(135deg, color-mix(in oklch, var(--surface-subtle) 88%, var(--selection-soft) 12%) 0%, color-mix(in oklch, var(--surface-subtle) 65%, var(--shadow-faint) 35%) 100%); - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; -} - -.desk-item__placeholder { - font-size: 0.95rem; - font-weight: 500; - letter-spacing: normal; - color: var(--muted); -} - -.desk-item__empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - gap: 0.5rem; - padding: 1rem; - text-align: center; -} - -.desk-item__title { - font-size: 0.95rem; - font-weight: 500; - color: var(--fg); - max-width: 90%; - overflow: hidden; - overflow-wrap: anywhere; - word-break: break-word; - white-space: normal; -} diff --git a/frontend/src/desktop/DesktopWorkspace.jsx b/frontend/src/desktop/DesktopWorkspace.jsx index 37c794d..c5924e9 100644 --- a/frontend/src/desktop/DesktopWorkspace.jsx +++ b/frontend/src/desktop/DesktopWorkspace.jsx @@ -26,7 +26,10 @@ import useDeskPointer from './pointer/useDeskPointer'; import useDeskTagInteractions from './tags/useDeskTagInteractions'; import DesktopDocumentCard from './DesktopDocumentCard'; import usePreviewMetadata from './hooks/usePreviewMetadata'; -import './DesktopWorkspace.css'; +import '../styles/workspace/workspace-layout.css'; +import '../styles/workspace/workspace-items.css'; +import '../styles/workspace/workspace-cards.css'; +import '../styles/workspace/workspace-overlays.css'; const DEBUG_DRAG = false; const DEBUG_FOCUS = false; diff --git a/frontend/src/index.jsx b/frontend/src/index.jsx index 78a38a0..4e334ad 100644 --- a/frontend/src/index.jsx +++ b/frontend/src/index.jsx @@ -3,7 +3,7 @@ import '@fontsource/inter/400.css'; import React from 'react'; import { createRoot } from 'react-dom/client'; import { HashRouter } from 'react-router-dom'; -import './styles.css'; +import './styles/index.css'; import { AppStateProvider } from './app/appState'; import AppRouter from './app/AppRouter'; diff --git a/frontend/src/styles.css b/frontend/src/styles.css deleted file mode 100644 index edfed4a..0000000 --- a/frontend/src/styles.css +++ /dev/null @@ -1,4465 +0,0 @@ -:root { - color-scheme: light dark; - - --neutral-hue: 180deg; - --foreground-hue-offset: 10deg; - --accent-hue-offset: -20deg; - --dark-hue-offset: 30deg; - --dark-foreground-hue-offset: 10deg; - - /* --- Neutrals --- */ - --bg: oklch(0.97 0.001 var(--neutral-hue)); - --surface: oklch(0.985 0.001 var(--neutral-hue)); - --surface-subtle: oklch(0.96 0.002 var(--neutral-hue)); - --fg: oklch(0.32 0.005 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --muted: oklch(0.54 0.008 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --sidebar-fg: oklch(0.56 0.007 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --border: oklch(0.92 0.002 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - - /* --- Accent (primary) --- */ - --accent: oklch(0.61 0.2 calc(var(--neutral-hue) + var(--foreground-hue-offset) + var(--accent-hue-offset))); - --accent-hover: oklch(0.70 0.02 calc(var(--neutral-hue) + var(--foreground-hue-offset) + var(--accent-hue-offset))); - --on-accent: oklch(1 0 0); - - --folder-icon-back: color-mix(in oklch, var(--accent) 78%, black 8%); - --folder-icon-mid: color-mix(in oklch, var(--accent) 60%, white 30%); - --folder-icon-front: color-mix(in oklch, var(--accent) 42%, white 58%); - - --success-hue: 140deg; - --warning-hue: 85deg; - --danger-hue: 25deg; - - --accent-soft: color-mix(in oklch, var(--accent) 12%, transparent); - --accent-elevated: color-mix(in oklch, var(--accent) 16%, transparent); - --accent-elevated-strong: color-mix(in oklch, var(--accent) 22%, transparent); - --accent-outline: color-mix(in oklch, var(--accent) 45%, transparent); - --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); - --accent-focus: color-mix(in oklch, var(--accent) 85%, transparent); - --surface-overlay: color-mix(in oklch, white 82%, transparent); - - /* -- Selection --- */ - --selection: oklch(0.61 0.01 var(--neutral-hue)); - - /* --- Derived accent states --- */ - --selection-soft: color-mix(in oklch, var(--selection) 12%, transparent); - - /* --- Shadows & overlays --- */ - --shadow-faint: color-mix(in oklch, black 6%, transparent); - --shadow-soft: color-mix(in oklch, black 12%, transparent); - --shadow-medium: color-mix(in oklch, black 18%, transparent); - --shadow-strong: color-mix(in oklch, black 28%, transparent); - --shadow-deep: color-mix(in oklch, black 55%, transparent); - --shadow-pop: color-mix(in oklch, black 25%, transparent); - --outline-subtle: color-mix(in oklch, black 6%, transparent); - --overlay-dark: color-mix(in oklch, black 55%, transparent); - --overlay-dim: color-mix(in oklch, oklch(0.28 0.01 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 20%, transparent); - --overlay-darker: color-mix(in oklch, black 75%, transparent); - --surface-danger-subtle: color-mix(in oklch, var(--danger) 12%, transparent); - --overlay-accent-subtle: color-mix(in oklch, var(--accent) 12%, transparent); - --border-strong: color-mix(in oklch, var(--fg) 24%, transparent); - --surface-hover: color-mix(in oklch, white 10%, transparent); - --overlay-accent-strong: color-mix(in oklch, var(--accent) 24%, transparent); - --overlay-backdrop: color-mix(in oklch, oklch(0.22 0.015 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 45%, transparent); - --overlay-shadow: color-mix(in oklch, oklch(0.22 0.015 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 18%, transparent); - - /* --- Semantic colors --- */ - --success: oklch(0.68 0.16 var(--success-hue)); - --warning: oklch(0.76 0.17 var(--warning-hue)); - --danger: oklch(0.64 0.2 var(--danger-hue)); - - --success-subtle: color-mix(in oklch, var(--success) 12%, transparent); - --warning-subtle: color-mix(in oklch, var(--warning) 12%, transparent); - --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); - --danger-soft: color-mix(in oklch, var(--danger) 12%, transparent); - --danger-subtle: color-mix(in oklch, var(--danger) 8%, transparent); - - /* --- Explorer states --- */ - --row-hover-bg: color-mix(in oklch, var(--selection) 6%, transparent); - --row-active-bg: color-mix(in oklch, var(--selection) 12%, transparent); - --sidebar-hover-bg: color-mix(in oklch, var(--selection) 8%, transparent); - --sidebar-active-bg: color-mix(in oklch, var(--selection) 16%, transparent); - --selection-ring: oklch(0.78 0.16 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 64%, transparent); - --link: var(--accent); - --link-visited: color-mix(in oklch, var(--accent) 75%, var(--fg) 25%); - --preview-nav-bg: oklch(0.18 0.05 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --preview-nav-bg-hover: oklch(0.14 0.05 calc(var(--neutral-hue) + var(--foreground-hue-offset))); - --preview-nav-fg: var(--on-accent); - --text-on-dark: color-mix(in oklch, white 90%, transparent); - --surface-ink-soft: color-mix(in oklch, var(--fg) 8%, transparent); - - font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - font-size: 15px; - --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; - - --detail-panel-width: 30em; - --documents-grid-title-size: 0.8rem; -} - -:root[data-theme='light'] { - color-scheme: light; -} - -:root[data-theme='dark'] { - color-scheme: dark; - - --dark-neutral-hue: calc(var(--neutral-hue) + var(--dark-hue-offset)); - --dark-foreground-hue: calc(var(--neutral-hue) + var(--dark-foreground-hue-offset)); - - --bg: oklch(0.15 0.01 var(--dark-neutral-hue)); - --surface: oklch(0.19 0.012 var(--dark-neutral-hue)); - --surface-subtle: oklch(0.23 0.012 var(--dark-neutral-hue)); - --fg: oklch(0.89 0.015 var(--dark-foreground-hue)); - --muted: oklch(0.72 0.02 var(--dark-foreground-hue)); - --sidebar-fg: oklch(0.78 0.02 var(--dark-foreground-hue)); - --border: oklch(0.33 0.01 var(--dark-foreground-hue)); - - --accent: oklch(0.75 0.2 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); - --accent-hover: oklch(0.82 0.16 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); - --on-accent: oklch(0.15 0.015 var(--dark-foreground-hue)); - - --folder-icon-back: color-mix(in oklch, var(--accent) 72%, black 12%); - --folder-icon-mid: color-mix(in oklch, var(--accent) 50%, white 24%); - --folder-icon-front: color-mix(in oklch, var(--accent) 30%, white 50%); - - --accent-soft: color-mix(in oklch, var(--accent) 22%, transparent); - --accent-elevated: color-mix(in oklch, var(--accent) 28%, transparent); - --accent-elevated-strong: color-mix(in oklch, var(--accent) 38%, transparent); - --accent-outline: color-mix(in oklch, var(--accent) 55%, transparent); - --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); - --accent-focus: color-mix(in oklch, var(--accent) 80%, transparent); - --surface-overlay: color-mix(in oklch, black 60%, transparent); - - --selection: oklch(0.44 0.04 220deg); - --selection-soft: color-mix(in oklch, var(--selection) 18%, transparent); - - --shadow-faint: color-mix(in oklch, black 35%, transparent); - --shadow-soft: color-mix(in oklch, black 50%, transparent); - --shadow-medium: color-mix(in oklch, black 65%, transparent); - --shadow-strong: color-mix(in oklch, black 80%, transparent); - --shadow-deep: color-mix(in oklch, black 90%, transparent); - --shadow-pop: color-mix(in oklch, black 70%, transparent); - --outline-subtle: color-mix(in oklch, white 10%, transparent); - --overlay-dark: color-mix(in oklch, black 70%, transparent); - --overlay-dim: color-mix(in oklch, oklch(0.42 0.04 var(--dark-neutral-hue)) 35%, transparent); - --overlay-darker: color-mix(in oklch, black 85%, transparent); - --surface-danger-subtle: color-mix(in oklch, var(--danger) 26%, transparent); - --overlay-accent-subtle: color-mix(in oklch, var(--accent) 32%, transparent); - --border-strong: color-mix(in oklch, var(--fg) 30%, transparent); - --surface-hover: color-mix(in oklch, white 6%, transparent); - --overlay-accent-strong: color-mix(in oklch, var(--accent) 55%, transparent); - --overlay-backdrop: color-mix(in oklch, oklch(0.1 0.015 var(--dark-neutral-hue)) 70%, transparent); - --overlay-shadow: color-mix(in oklch, oklch(0.12 0.015 var(--dark-neutral-hue)) 55%, transparent); - - --success: oklch(0.62 0.16 var(--success-hue)); - --warning: oklch(0.68 0.17 var(--warning-hue)); - --danger: oklch(0.60 0.2 var(--danger-hue)); - - --success-subtle: color-mix(in oklch, var(--success) 20%, transparent); - --warning-subtle: color-mix(in oklch, var(--warning) 20%, transparent); - --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); - --danger-soft: color-mix(in oklch, var(--danger) 24%, transparent); - --danger-subtle: color-mix(in oklch, var(--danger) 18%, transparent); - - --row-hover-bg: color-mix(in oklch, white 4%, transparent); - --row-active-bg: color-mix(in oklch, var(--selection) 20%, transparent); - --sidebar-hover-bg: color-mix(in oklch, white 6%, transparent); - --sidebar-active-bg: color-mix(in oklch, var(--selection) 26%, transparent); - --selection-ring: oklch(0.68 0.16 var(--dark-foreground-hue)); - --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 72%, transparent); - --link: color-mix(in oklch, var(--accent) 92%, transparent); - --link-visited: color-mix(in oklch, var(--accent) 70%, white 20%); - --preview-nav-bg: oklch(0.3 0.04 var(--dark-neutral-hue)); - --preview-nav-bg-hover: oklch(0.35 0.04 var(--dark-neutral-hue)); - --preview-nav-fg: var(--fg); - --text-on-dark: color-mix(in oklch, white 92%, transparent); - --surface-ink-soft: color-mix(in oklch, white 12%, transparent); -} - -@media (prefers-color-scheme: dark) { - :root:not([data-theme='light']) { - color-scheme: dark; - - --dark-neutral-hue: calc(var(--neutral-hue) + var(--dark-hue-offset)); - --dark-foreground-hue: calc(var(--neutral-hue) + var(--dark-foreground-hue-offset)); - - --bg: oklch(0.15 0.01 var(--dark-neutral-hue)); - --surface: oklch(0.19 0.012 var(--dark-neutral-hue)); - --surface-subtle: oklch(0.23 0.012 var(--dark-neutral-hue)); - --fg: oklch(0.89 0.015 var(--dark-foreground-hue)); - --muted: oklch(0.72 0.02 var(--dark-foreground-hue)); - --sidebar-fg: oklch(0.78 0.02 var(--dark-foreground-hue)); - --border: oklch(0.33 0.01 var(--dark-foreground-hue)); - - --accent: oklch(0.75 0.2 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); - --accent-hover: oklch(0.82 0.16 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); - --on-accent: oklch(0.15 0.015 var(--dark-foreground-hue)); - - --folder-icon-back: color-mix(in oklch, var(--accent) 72%, black 12%); - --folder-icon-mid: color-mix(in oklch, var(--accent) 50%, white 24%); - --folder-icon-front: color-mix(in oklch, var(--accent) 30%, white 50%); - - --accent-soft: color-mix(in oklch, var(--accent) 22%, transparent); - --accent-elevated: color-mix(in oklch, var(--accent) 28%, transparent); - --accent-elevated-strong: color-mix(in oklch, var(--accent) 38%, transparent); - --accent-outline: color-mix(in oklch, var(--accent) 55%, transparent); - --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); - --accent-focus: color-mix(in oklch, var(--accent) 80%, transparent); - --surface-overlay: color-mix(in oklch, black 60%, transparent); - - --selection: oklch(0.44 0.04 220deg); - --selection-soft: color-mix(in oklch, var(--selection) 18%, transparent); - - --shadow-faint: color-mix(in oklch, black 35%, transparent); - --shadow-soft: color-mix(in oklch, black 50%, transparent); - --shadow-medium: color-mix(in oklch, black 65%, transparent); - --shadow-strong: color-mix(in oklch, black 80%, transparent); - --shadow-deep: color-mix(in oklch, black 90%, transparent); - --shadow-pop: color-mix(in oklch, black 70%, transparent); - --outline-subtle: color-mix(in oklch, white 10%, transparent); - --overlay-dark: color-mix(in oklch, black 70%, transparent); - --overlay-dim: color-mix(in oklch, oklch(0.42 0.04 var(--dark-neutral-hue)) 35%, transparent); - --overlay-darker: color-mix(in oklch, black 85%, transparent); - --surface-danger-subtle: color-mix(in oklch, var(--danger) 26%, transparent); - --overlay-accent-subtle: color-mix(in oklch, var(--accent) 32%, transparent); - --border-strong: color-mix(in oklch, var(--fg) 30%, transparent); - --surface-hover: color-mix(in oklch, white 6%, transparent); - --overlay-accent-strong: color-mix(in oklch, var(--accent) 55%, transparent); - --overlay-backdrop: color-mix(in oklch, oklch(0.1 0.015 var(--dark-neutral-hue)) 70%, transparent); - --overlay-shadow: color-mix(in oklch, oklch(0.12 0.015 var(--dark-neutral-hue)) 55%, transparent); - - --success: oklch(0.62 0.16 var(--success-hue)); - --warning: oklch(0.68 0.17 var(--warning-hue)); - --danger: oklch(0.60 0.2 var(--danger-hue)); - - --success-subtle: color-mix(in oklch, var(--success) 20%, transparent); - --warning-subtle: color-mix(in oklch, var(--warning) 20%, transparent); - --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); - --danger-soft: color-mix(in oklch, var(--danger) 24%, transparent); - --danger-subtle: color-mix(in oklch, var(--danger) 18%, transparent); - - --row-hover-bg: color-mix(in oklch, white 4%, transparent); - --row-active-bg: color-mix(in oklch, var(--selection) 20%, transparent); - --sidebar-hover-bg: color-mix(in oklch, white 6%, transparent); - --sidebar-active-bg: color-mix(in oklch, var(--selection) 26%, transparent); - --selection-ring: oklch(0.68 0.16 var(--dark-foreground-hue)); - --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 72%, transparent); - --link: color-mix(in oklch, var(--accent) 92%, transparent); - --link-visited: color-mix(in oklch, var(--accent) 70%, white 20%); - --preview-nav-bg: oklch(0.3 0.04 var(--dark-neutral-hue)); - --preview-nav-bg-hover: oklch(0.35 0.04 var(--dark-neutral-hue)); - --preview-nav-fg: var(--fg); - --text-on-dark: color-mix(in oklch, white 92%, transparent); - --surface-ink-soft: color-mix(in oklch, white 12%, transparent); - } -} - -html, -body { - height: 100%; -} - -body { - margin: 0; - background: var(--bg); - color: var(--fg); - overflow: hidden; -} - -body.has-main-content { - background: var(--surface); -} - -a { - color: var(--accent); - text-decoration: underline; - text-decoration-thickness: 1px; - text-underline-offset: 0.18em; - transition: color 0.15s ease, text-decoration-color 0.15s ease; -} - -a:visited { - color: var(--link-visited); -} - -a:hover, -a:focus-visible { - color: var(--accent-hover); - outline: none; - text-decoration-color: currentColor; -} - -#app { - height: 100%; -} - -button { - font: inherit; - border-radius: 2px; - border: 1px solid transparent; - padding: 0.35rem 0.85rem; - background: var(--accent); - color: var(--on-accent); - cursor: pointer; - font-weight: 500; - transition: background 0.15s ease, border-color 0.15s ease; -} - -button[disabled] { - opacity: 0.55; - cursor: not-allowed; -} - -a.button-link { - display: inline-flex; - align-items: center; - gap: 0.35rem; - font: inherit; - border-radius: 2px; - border: 1px solid transparent; - padding: 0.35rem 0.85rem; - background: var(--accent); - color: var(--on-accent); - text-decoration: none; - font-weight: 500; - transition: background 0.15s ease, border-color 0.15s ease; -} - -a.button-link[aria-disabled='true'] { - opacity: 0.55; -} - -a.button-link:hover:not([aria-disabled='true']) { - background: var(--accent-hover); -} - -button.secondary { - background: transparent; - color: var(--fg); - border-color: var(--border); -} - -button.secondary:hover:not([disabled]) { - background: var(--surface-subtle); -} - -button.danger { - background: transparent; - color: var(--danger); - border-color: var(--danger-border); -} - -button.danger:hover:not([disabled]) { - border-color: var(--danger); - background: var(--danger-subtle); -} - -.icon-button { - display: inline-flex; - align-items: center; - justify-content: center; - border: none; - background: transparent; - color: var(--muted); - padding: 0.25rem; - border-radius: 4px; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease; -} - -.icon-button:hover:not([disabled]) { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.icon-button.danger { - color: var(--danger); -} - -.icon-button.danger:hover:not([disabled]) { - background: var(--danger-subtle); -} - -.icon-button.ghost { - border: none; - background: transparent; - color: var(--muted); - padding: 0.2rem; -} - -.icon-button.ghost:hover:not([disabled]) { - color: var(--danger); - background: transparent; -} - -.panel-header .icon-button, -.panel-header button, -.panel-header a.icon-button { - display: inline-flex; - align-items: center; - justify-content: flex-start; - border: none; - background: transparent; - color: var(--muted); - padding: 0.25rem; - border-radius: 4px; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease; - text-decoration: none; - text-align: left; -} - -.panel-header .icon-button:hover:not([disabled]), -.panel-header button:hover:not([disabled]), -.panel-header a.icon-button:hover { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.panel-header .icon-button.active:hover:not([disabled]), -.panel-header button.active:hover:not([disabled]), -.panel-header a.icon-button.active:hover { - background: var(--accent-soft); - color: var(--fg); -} - -.panel-header .icon-button.ghost, -.panel-header button.icon-button.ghost { - color: var(--muted); - padding: 0.25rem; -} - -.panel-header .icon-button.ghost:hover:not([disabled]), -.panel-header button.icon-button.ghost:hover:not([disabled]) { - color: var(--fg); - background: var(--sidebar-hover-bg); -} - -.preview-zoom-backdrop { - position: fixed; - inset: 0; - background: var(--overlay-backdrop); - transition: background 0.25s ease, opacity 0.25s ease; - display: flex; - align-items: center; - justify-content: center; - padding: 2rem; - z-index: 2000000; - cursor: zoom-out; - opacity: 0; - pointer-events: none; -} - -.preview-zoom-backdrop--visible { - opacity: 1; - background: var(--overlay-backdrop); - pointer-events: auto; -} - -.preview-zoom__stage { - position: relative; - display: flex; - align-items: center; - justify-content: center; - max-width: 95vw; - max-height: 95vh; - z-index: 3000000; -} - -.preview-zoom__image { - max-width: 95vw; - max-height: 95vh; - width: auto; - height: auto; -} - -.preview-zoom__scroll { - display: flex; - align-items: center; - justify-content: center; - max-width: 95vw; - max-height: 95vh; - box-shadow: 0 32px 120px var(--shadow-deep); -} - -.preview-zoom__scroll:focus { - outline: none; -} - -.preview-zoom__scroll--native { - overflow: auto; - cursor: zoom-out; - justify-content: flex-start; - align-items: flex-start; -} - -.preview-zoom__nav { - position: absolute; - bottom: 1em; - left: 50%; - transform: translateX(-50%); - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.9rem; - opacity: 0; - transition: opacity 0.18s ease; - pointer-events: none; -} - -.preview-zoom__stage:hover .preview-zoom__nav, -.preview-zoom__stage:focus-within .preview-zoom__nav { - opacity: 1; - pointer-events: auto; -} - -.preview-zoom__nav-button { - width: 2.8rem; - height: 2.8rem; - border: none; - border-radius: 999px; - background: var(--preview-nav-bg); - color: var(--preview-nav-fg); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - z-index: 1; - transition: background 0.15s ease, transform 0.15s ease; - box-shadow: 0 12px 28px var(--shadow-strong); -} - -.preview-zoom__nav-button:hover { - background: var(--preview-nav-bg-hover); -} - -.preview-zoom__nav-button:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 3px; -} - -.preview-zoom__nav-button svg { - width: 1.5rem; - height: 1.5rem; -} - -.preview-zoom__nav-button[disabled] { - opacity: 0.35; - cursor: default; -} - -.with-icon { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.icon-inline { - width: 1rem; - height: 1rem; -} - -.icon { - width: 1rem; - height: 1rem; - display: inline-flex; - align-items: center; - justify-content: center; -} - -@keyframes icon-spin { - to { - transform: rotate(360deg); - } -} - -.icon--spin { - animation: icon-spin 0.9s linear infinite; -} - -.icon--flip-y { - transform: scaleX(-1); -} - -.visually-hidden { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} - -.icon path { - stroke: currentColor; - stroke-width: 1.6; - fill: none; -} - -.icon--fill path { - stroke: none; - fill: currentColor; -} - - -.view-toggle { - display: inline-flex; - align-items: center; - gap: 0.25rem; -} - -.view-toggle__button { - border: 1px solid var(--border); - background: transparent; - color: var(--muted); - padding: 0.3rem 0.6rem; - border-radius: 4px; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; -} - -.view-toggle__button:hover, -.view-toggle__button:focus-visible { - background: var(--surface-subtle); - color: var(--fg); - outline: none; -} - -.view-toggle__button.active { - background: var(--accent); - color: var(--on-accent); - border-color: var(--accent); -} - -.view-toggle__icon { - width: 1.4rem; - height: 1.4rem; -} - -.documents-actions__sort-group { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.documents-sort { - display: inline-flex; - align-items: center; - position: relative; -} - -.documents-sort__trigger { - display: inline-flex; - align-items: center; - gap: 0.35rem; - font-size: 0.85rem; - white-space: nowrap; - padding: 0.25rem 0.5rem; - min-height: 2.1rem; -} - -.documents-sort__label { - display: inline-flex; - align-items: center; - line-height: 1.1; -} - -.documents-sort__trigger-content { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.documents-sort__quickmenu .menu__item, -.documents-sort__quickmenu .menu__item.active { - font-weight: 400; -} - -.documents-toolbar__toggle { - border: 1px solid var(--border); - border-radius: 4px; - padding: 0.3rem; - background: transparent; - color: var(--muted); - transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; -} - -.documents-toolbar__toggle:hover:not([disabled]) { - color: var(--fg); - border-color: var(--border); -} - -.documents-toolbar__toggle[aria-pressed='true'] { - border-color: var(--accent); - color: var(--accent); - background: var(--surface-subtle); -} - -.documents-sort__direction { - padding: 0.3rem 0.45rem; -} - -.documents-sort__direction[aria-pressed='true'] { - border-color: var(--border); - color: var(--muted); - background: transparent; -} - -.documents-sort__direction svg { - width: 1.1rem; - height: 1.1rem; -} - -.app-shell { - height: 100%; - display: flex; - flex-direction: column; - color: var(--fg); -} - - -.documents-main { - flex: 1; - display: flex; - min-height: 100vh; - width: 100%; - position: relative; -} - -.documents-main--sidebar-collapsed { - position: relative; -} - -.main-content { - display: flex; - flex-direction: column; - min-height: 0; - min-width: 0; - margin: 0; - border-radius: 0; - background: var(--surface); - flex-grow: 1; - box-shadow: -12px 0 24px -12px var(--shadow-faint); -} - -.documents-main:not(.documents-main--sidebar-collapsed) .main-content { - border-left: 1px solid var(--border); -} - -.main-content__header { - padding: 0.5rem 1.25rem; - justify-content: space-between; - align-items: center; - gap: 0.75rem; -} - -.main-content__header-wrapper { - position: relative; -} - -.main-content__body { - position: relative; - flex: 1 1 auto; - display: flex; - min-height: 0; -} - -.main-content__body > * { - min-width: 0; - min-height: 0; -} - -.main-content__body > *:not(.detail-panel) { - flex: 1 1 auto; -} - -.main-content__body--workspace.main-content__body--has-detail > .desk-shell { - margin-right: calc(-1 * var(--detail-panel-width)); -} - -.main-content--has-detail { - padding-right: var(--detail-panel-width); -} - -.main-content__title { - margin: 0; - font-size: 1rem; - font-weight: 600; - color: var(--fg); -} - - -.documents-main--sidebar-collapsed { - position: relative; - grid-template-columns: auto minmax(0, 1fr); -} - -.sidebar .panel-header .icon, -.main-content__header .icon, -.detail-panel .panel-header .icon { - width: 1.35rem; - height: 1.35rem; -} - -.main-content__actions { - display: flex; - align-items: center; - gap: 0.6rem; -} - -.main-content__actions-divider { - display: inline-flex; - align-items: center; - color: var(--muted); -} - -.main-content__title { - margin: 0; - font-size: 1rem; - font-weight: 600; - color: var(--fg); - display: flex; - align-items: center; - gap: 0.5rem; - min-width: 0; - flex: 1 1 auto; - overflow: hidden; -} - -.main-content__breadcrumbs { - flex: 1 1 auto; - overflow: hidden; -} - -.main-content__subtitle { - font-size: 0.9rem; - color: var(--muted); - font-weight: 400; - line-height: 1.2; - flex-shrink: 0; -} - -.panels-main { - flex: 1; - display: flex; - justify-content: center; - padding: 1.5rem; - overflow: auto; -} - -.panels-main > * { - flex: 0 1 720px; -} - -.preview-main { - flex: 1; - display: flex; - flex-direction: column; - min-height: 0; -} - -.document-viewer { - flex: 1; - display: grid; - grid-template-columns: minmax(0, 30em) minmax(0, 1fr); - gap: 1rem; - min-height: 0; - padding: 1rem 1rem; -} - -.document-drag-preview { - position: fixed; - pointer-events: none; - top: -9999px; - left: -9999px; - width: var(--drag-preview-size, 96px); - height: var(--drag-preview-size, 96px); - z-index: 9999; -} - -.document-drag-preview__thumb { - position: absolute; - top: 50%; - left: 50%; - width: 64px; - height: 64px; - border-radius: 6px; - box-shadow: 0 6px 12px var(--shadow-pop); - overflow: hidden; - background-color: var(--overlay-dim); - display: flex; - align-items: center; - justify-content: center; - color: #fff; - font-weight: 600; - font-size: 0.8rem; - text-transform: uppercase; - transform: translate(-50%, -50%) rotate(var(--rotation-deg, 0deg)); - transform-origin: center; -} - -.document-drag-preview__thumb--image { - background-color: #000; - background-repeat: no-repeat; - background-size: contain; - background-position: center; -} - -.document-drag-preview__thumb .document-thumbnail, -.document-drag-preview__thumb img { - width: 100%; - height: 100%; - object-fit: cover; - pointer-events: none; -} - -.document-drag-preview__thumb .thumb-placeholder, -.document-drag-preview__thumb .thumb-placeholder * { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; -} - -.document-drag-preview__folder-thumb { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; -} - -.document-drag-preview__folder-thumb svg { - width: 48px; - height: 48px; - color: var(--accent-strong, var(--accent)); -} - -.document-drag-preview__folder-placeholder { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.75rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--text-on-dark); -} - -.document-drag-preview__count { - position: absolute; - bottom: 4px; - right: 4px; - background-color: var(--accent); - color: var(--on-accent); - border-radius: 999px; - padding: 0.25rem 0.5rem; - font-size: 0.75rem; - font-weight: 600; - box-shadow: 0 4px 8px var(--shadow-pop); - pointer-events: none; -} - -.document-viewer__details { - display: flex; - flex-direction: column; - gap: 0.5rem; - min-height: 0; - flex: 1; -} - -.document-viewer__details-pane { - display: flex; - flex-direction: column; - min-height: 0; - overflow: auto; - flex: 1; -} -.document-viewer__tabs-wrapper { - display: flex; - flex-direction: column; - flex: 1; - min-height: 0; -} - -.document-viewer__section { - display: flex; - flex-direction: column; - flex: 1; - min-height: 0; - padding-top: 1rem; -} - -.document-viewer__section-title { - margin: 0; - font-size: 0.95rem; - font-weight: 600; - letter-spacing: 0.01em; -} - -.document-viewer__section-list { - margin: 0; - padding: 0; - list-style: none; - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: 0.75rem 1.25rem; -} - -.document-viewer__section-item { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.document-viewer__section-item dt { - font-size: 0.75rem; - color: var(--muted); -} - -.document-viewer__section-item dd { - margin: 0; - font-size: 0.9rem; - font-weight: 500; - word-break: break-word; -} - -.document-viewer__section-placeholder { - margin: 0; - font-size: 0.9rem; - color: var(--muted); -} - -.document-viewer__section-payload { - font-size: 0.85rem; -} - -.document-viewer__section-payload summary { - cursor: pointer; - font-weight: 500; - color: var(--accent-strong, var(--accent)); -} - -.document-viewer__section-payload pre { - margin: 0.75rem 0 0; - padding: 0.75rem; - background: var(--surface); - max-height: 280px; - overflow: auto; - font-size: 0.8rem; -} - -.document-viewer__section--metadata-json { - overflow: auto; -} - -.document-viewer__metadata-json { - margin: 0; - padding: 0.75rem; - background: var(--surface); - border-radius: 0.5rem; - font-size: 0.85rem; - line-height: 1.35; - overflow: auto; -} - -.document-viewer__tabs { - display: inline-flex; - align-items: center; - gap: 0.5rem; - border-bottom: 1px solid var(--outline-subtle); -} - -.document-viewer__tab { - appearance: none; - border: none; - background: transparent; - padding: 0.4rem 0.75rem; - font-size: 0.85rem; - font-weight: 500; - color: var(--muted); - cursor: pointer; - border-bottom: 2px solid transparent; - transition: - color 120ms ease, - border-color 120ms ease; -} - -.document-viewer__tab:hover, -.document-viewer__tab:focus-visible { - color: var(--accent); -} - -.document-viewer__tab.is-active { - color: var(--accent); - border-color: var(--accent); -} - -.document-viewer__tabpanes { - flex: 1; - min-height: 0; - display: flex; -} - -.document-viewer__tabpanes--single { - flex: 1; - min-height: 0; -} - -.document-viewer__tabpanel { - flex: 1; - min-height: 0; - display: flex; - position: relative; -} - -.document-viewer__object--ocr { - width: 100%; - height: 100%; -} - -.document-viewer__object--ocr-text { - width: 100%; - height: 100%; - margin: 0; - padding: 1rem 0; - font-size: 1rem; - white-space: pre-wrap; - font-family: inherit; -} - -.document-viewer__message--error { - color: var(--danger); -} - -.document-viewer__viewport { - flex: 1; - min-width: 0; - display: flex; - position: relative; - overflow: hidden; - align-items: flex-start; -} - -.document-viewer__object { - width: 100%; - height: 100%; - border: none; -} - -.document-viewer__object--image { - width: auto; - height: auto; - max-width: 100%; - max-height: 100%; - object-fit: contain; - align-self: flex-start; -} - -.document-viewer__unsupported { - height: 100%; - width: 100%; - padding: 2rem; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.75rem; - text-align: center; - background: var(--surface-subtle); -} - -.document-viewer__unsupported-filename { - font-size: 0.9rem; - color: var(--muted); -} - -.document-viewer__unsupported-message { - font-size: 0.95rem; - color: var(--fg); -} - -.document-viewer__unsupported-download { - font-weight: 600; -} - -.document-viewer__unsupported-download svg { - width: 1rem; - height: 1rem; -} - -.tags-panel__body { - overflow-y: auto; -} - -.tags-table { - width: 100%; - overflow: auto; -} - -.tags-table table { - width: 100%; - border-collapse: collapse; - min-width: 320px; -} - -.tags-table th, -.tags-table td { - padding: 0.45rem 0.6rem; - text-align: left; - font-size: 0.85rem; -} - -.tags-table th.numeric, -.tags-table td.numeric { - text-align: right; -} - -.tags-table th.actions, -.tags-table td.actions { - text-align: right; - width: 0; -} - -.tags-table tbody tr:hover { - background: var(--surface-subtle); -} - -.tags-table tr.editing { - background: var(--sidebar-hover-bg); -} - -.tags-table__label { - max-width: 24rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.tags-table__swatch { - display: inline-block; - width: 1rem; - height: 1rem; - border-radius: 2px; - box-shadow: inset 0 0 0 1px var(--shadow-faint); -} - -.tags-panel__error { - margin: 0.5rem 0; - color: var(--danger); - font-size: 0.8rem; -} - -.tags-table__label-input { - width: 100%; -} - -.tags-table__color-editor { - display: flex; - align-items: center; - gap: 0.4rem; -} - -.tags-table__color-picker { - width: 2.25rem; - height: 2.25rem; - padding: 0; - background: none; - cursor: pointer; -} - -.tags-table__edit-controls { - display: flex; - justify-content: flex-start; - padding: 0.25rem; - gap: 0.4rem; -} - -.tags-table__row-actions { - display: flex; - justify-content: flex-start; - padding: 0.25rem; - gap: 0.4rem; -} - -.correspondents-panel .header-actions { - gap: 0.5rem; -} - -.tags-actions { - display: flex; - flex-wrap: wrap; - gap: 0.6rem; - align-items: center; -} - -.tags-actions__form { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.4rem; -} - -.tags-actions__form input[type='text'] { - min-width: 14rem; -} - -.correspondents-actions__form { - display: flex; - gap: 0.4rem; -} - -.correspondents-actions__form input { - min-width: 14rem; -} - - - -.correspondent-pill { - display: inline-flex; - align-items: center; - gap: 0.35rem; - background: var(--surface-subtle); - border-radius: 999px; - padding: 0.15rem 0.5rem; - font-size: 0.9rem; - border: none; -} - -.correspondent-pill__label { - line-height: 1.2; -} - -.correspondent-pill__label strong { - font-size: 0.8rem; - text-transform: capitalize; - color: var(--muted); -} - -.correspondent-pill__remove { - border: none; - background: none; - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - color: var(--muted); - padding: 0; -} - -.correspondent-pill__remove:hover { - color: var(--danger); -} - -.correspondent-form { - display: flex; - gap: 0.4rem; - align-items: center; -} - -.correspondent-form input, -.correspondent-form select { - min-height: 32px; -} - -.document-viewer__message { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - color: var(--on-accent); - background: var(--overlay-dark); - padding: 0.5rem 1rem; - border-radius: 999px; - font-size: 0.9rem; -} - -.panel-section__header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; - padding: 0 0 0.5rem; -} - -.panel-section__titles { - display: flex; - flex-direction: column; - gap: 0.3rem; -} - -.panel-section__header h2 { - margin: 0; - font-size: 0.9rem; - font-weight: 600; -} - -.documents-panel__title { - display: flex; - align-items: center; - gap: 0.35rem; - margin: 0; - font-size: 0.9rem; - font-weight: 600; - min-width: 0; - flex-wrap: nowrap; - overflow: hidden; -} - -.panel-section__subtitle { - margin-top: 0.25rem; - font-size: 0.78rem; - color: var(--muted); -} - -.breadcrumb-trail { - display: flex; - align-items: center; - gap: 0.35rem; - flex-wrap: nowrap; - min-width: 0; - flex: 1 1 auto; - max-width: 100%; - overflow: hidden; -} - -.breadcrumb-trail--measure { - position: absolute; - visibility: hidden; - pointer-events: none; - left: -9999px; - top: -9999px; - max-width: none; - overflow: visible; -} - -.breadcrumb-trail__link { - display: inline-flex; - align-items: center; - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - border: none; - background: none; - padding: 0; - font: inherit; - color: inherit; - cursor: default; -} - -.breadcrumb-trail__link:not(.is-current) { - cursor: pointer; - color: var(--accent); -} - -.breadcrumb-trail__link:not(.is-current):hover, -.breadcrumb-trail__link:not(.is-current):focus-visible { - text-decoration: underline; -} - -.breadcrumb-trail__separator { - color: var(--muted); - margin: 0 0.2rem; -} - -.breadcrumb-trail__ellipsis { - position: relative; - display: inline-flex; -} - -.breadcrumb-trail__ellipsis-button { - cursor: pointer; -} - -.documents-panel__breadcrumbs { - flex: 1 1 auto; - min-width: 0; - max-width: 100%; - overflow: hidden; -} - -.documents-panel__breadcrumbs { - max-width: 22rem; -} - -.panel-section__body { - flex: 1; - display: flex; - flex-direction: column; - min-height: 0; -} - -.panel-section__body--scrollable, -.panel-section__body.scrollable { - overflow-y: auto; -} - -.folder-tree { - list-style: none; - margin: 0; - padding: 0; -} - -.folder-node { - margin: 0; -} - -.folder-row { - display: flex; - align-items: center; - gap: 0.22rem; - padding: 0.32rem 0.48rem; - border-radius: 8px; - cursor: pointer; - color: inherit; - transition: background 0.12s ease, color 0.12s ease; - position: relative; - overflow: hidden; - user-select: none; - -webkit-user-select: none; -} - -.folder-row .name-wrap { - display: inline-flex; - align-items: center; - gap: 0.25rem; - flex: 1; - min-width: 0; -} - -.folder-row .name-wrap .name__label { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.folder-row .folder-icon-image { - flex-shrink: 0; -} - -.folder-row:hover { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.folder-row.active { - background: var(--sidebar-active-bg); - color: var(--fg); -} - -.folder-row .toggle { - width: 1.05rem; - display: inline-flex; - align-items: center; - justify-content: center; - user-select: none; - flex-shrink: 0; - transition: transform 0.18s ease; -} - -.folder-row .toggle.invisible { - visibility: hidden; -} - -.toggle-icon { - width: 0.9rem; - height: 0.9rem; - transition: transform 0.18s ease; -} - -.folder-row .toggle.expanded .toggle-icon { - transform: rotate(90deg); -} - -.folder-row__actions { - position: absolute; - right: 0; - top: 50%; - transform: translateY(-50%); - display: flex; - gap: 0; - opacity: 0; - pointer-events: none; - transition: opacity 0.12s ease; - background-color: var(--surface-overlay); - border-radius: 8px; - padding: 0 0.18rem; -} - -.folder-row__actions .icon-button { - margin: 0; -} - -.folder-row:hover .folder-row__actions, -.folder-row:focus-within .folder-row__actions { - opacity: 1; - pointer-events: auto; -} - -.folder-children { - list-style: none; - margin: 0 0 0 0.45rem; - padding: 0; -} - - - -.sidebar-section { - margin-top: 1rem; - display: flex; - flex-direction: column; - gap: 0.4rem; -} - -.sidebar { - gap: 0; - overflow: hidden; - color: var(--sidebar-fg); - display: flex; - flex-direction: column; - width: 20em; - max-width: 20em; - flex: 0 0 20em; - background: var(--bg); -} - -.sidebar__body { - flex: 1; - display: flex; - flex-direction: column; - padding: 0.5rem 1rem; - gap: 0.75rem; - overflow-y: auto; - min-height: 0; -} - -.sidebar__footer { - margin-top: auto; - padding: 0.75rem 1rem 1rem; - border-top: 1px solid var(--border); - background: var(--surface-subtle); - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -.sidebar__title { - margin: 0; - font-size: 1rem; - font-weight: 600; - color: var(--fg); - padding-left: 0.25rem; -} - -.sidebar__tenant { - color: var(--muted); - font-weight: 500; -} - -.sidebar__header { - position: relative; -} - -.sidebar__title-button { - display: inline-flex; - align-items: center; - gap: 0.35rem; - border: none; - background: none; - color: inherit; - font: inherit; - cursor: pointer; - padding: 0; -} - -.sidebar__title-button:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.sidebar__title-chevron { - transition: transform 0.2s ease; -} - -.sidebar__title-chevron.is-open { - transform: rotate(180deg); -} - -.menu { - position: absolute; - top: 100%; - left: 1em; - right: auto; - background: var(--surface); - border: 1px solid var(--border-muted, var(--border)); - border-radius: 0.5rem; - box-shadow: 0 12px 28px var(--shadow-strong); - min-width: 220px; - z-index: 20; - overflow: hidden; -} - -.menu__list { - max-height: 260px; - overflow-y: auto; - padding: 0.35rem 0; - display: flex; - flex-direction: column; - gap: 0.15rem; -} - -.menu__heading { - padding: 0.5rem 1rem 0.25rem; - font-size: 0.82rem; - font-weight: 600; - color: var(--muted); -} - -.menu button.menu__item, -.menu .menu__item { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 0.6rem; - width: 100%; - padding: 0.55rem 1rem; - border: none; - background: none; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease; -} - -.menu button.menu__item:hover, -.menu button.menu__item:focus-visible, -.menu .menu__item:hover, -.menu .menu__item:focus-visible { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.menu button.menu__item.active, -.menu .menu__item.active { - font-weight: 600; - color: var(--accent); -} - -.menu button.menu__item:focus-visible, -.menu .menu__item:focus-visible { - outline: 2px solid var(--accent); - outline-offset: -2px; -} - -.menu__label { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; -} - -.menu__check-slot { - width: 1rem; - display: flex; - align-items: center; - justify-content: center; - color: var(--accent); -} - -.menu__active-indicator { - font-size: 0.75rem; - color: var(--muted); -} - -.menu__empty { - display: block; - padding: 0.6rem 0.75rem; - color: var(--muted); - font-size: 0.85rem; -} - -.menu__footer { - border-top: 1px solid var(--border-muted, var(--border)); - padding: 0.35rem 0.5rem; - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.menu--simple .menu__footer { - border-top: none; -} - -.menu__settings { - width: 100%; - display: inline-flex; - align-items: center; - gap: 0.4rem; - border: none; - background: none; - color: inherit; - font: inherit; - cursor: pointer; - padding: 0.4rem 0.5rem; - border-radius: 0.35rem; -} - -.menu__settings:hover, -.menu__settings:focus-visible { - background: var(--sidebar-hover-bg); -} - -.menu__logout { - width: 100%; - display: inline-flex; - align-items: center; - gap: 0.4rem; - border: none; - background: none; - color: var(--danger); - font: inherit; - cursor: pointer; - padding: 0.4rem 0.5rem; - border-radius: 0.35rem; -} - -.menu__logout:hover, -.menu__logout:focus-visible { - background: var(--surface-danger-subtle); -} - -.sidebar__search { - display: flex; - align-items: center; - gap: 0.4rem; - margin: 0 0 0.75rem; -} - -.sidebar__search input[type='search'] { - flex: 1; - padding: 0.4rem 0.6rem; - border-radius: 4px; - border: 1px solid var(--border); - background: var(--surface); - color: var(--fg); -} - -.sidebar__search button { - padding: 0.35rem 0.75rem; - border: 1px solid transparent; - border-radius: 4px; - background: transparent; - color: var(--accent); - font-size: 0.85rem; - cursor: pointer; -} - -.sidebar__search button:hover:not([disabled]) { - background: var(--sidebar-hover-bg); -} - -.sidebar__footer .sidebar-section { - margin-top: 0; -} - -.sidebar__footer .sidebar-section__actions { - gap: 0.4rem; -} - -.sidebar-section:first-of-type, -.sidebar-section--folders { - margin-top: 0; -} - -.sidebar-section--folders { - display: flex; - flex-direction: column; -} - -.sidebar-section__header { - display: flex; - align-items: center; - font-size: 0.75rem; - justify-content: space-between; - color: var(--muted); -} - -.sidebar-section__title { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.4rem; - width: 100%; - background: transparent; - border: none; - border-radius: 6px; - padding: 0.25rem 0.35rem; - margin: -0.25rem -0.35rem; - color: inherit; - font: inherit; - cursor: pointer; - text-align: left; -} - -.sidebar-section__title:hover:not([disabled]), -.sidebar-section__title:focus-visible { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.sidebar-section__title:hover:not([disabled]) h3, -.sidebar-section__title:focus-visible h3 { - color: var(--fg); -} - -.sidebar-section__header h3 { - margin: 0; - font-weight: 600; -} - -.sidebar-section__actions { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.sidebar-section__actions .meta { - font-size: 0.75rem; - color: var(--muted); -} - -.sidebar-slider { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.8rem; - color: var(--muted); -} - -.sidebar-slider input[type='range'] { - flex: 1; - accent-color: var(--accent); -} - -.sidebar-slider__value { - min-width: 3rem; - text-align: right; - color: var(--fg); - font-variant-numeric: tabular-nums; -} - -.sidebar-item { - background: transparent; - padding: 0.16rem 0.26rem; - text-align: left; - color: var(--sidebar-fg); - border-radius: 2px; - cursor: pointer; - transition: background 0.12s ease, color 0.12s ease; - display: flex; - align-items: center; - gap: 0.38rem; - width: 100%; -} - -.sidebar-item:hover { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.sidebar-item.active { - background: var(--sidebar-active-bg); - color: var(--fg); - font-weight: 600; -} - -.sidebar-item:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.sidebar-item__icon { - width: 1rem; - height: 1rem; - flex-shrink: 0; - color: var(--accent); -} - -.sidebar-item.active .sidebar-item__icon { - color: currentColor; -} - -.sidebar-tag-cloud { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; - padding: 0.25rem 0 0.1rem; -} - -.sidebar-tag-pill { - border-radius: 999px; - padding: 0.25rem 0.6rem; - font-size: 0.75rem; - font-weight: 600; - line-height: 1; - cursor: pointer; - background: var(--surface-soft); - color: var(--fg); - transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, - opacity 0.12s ease; - box-shadow: 0 1px 2px var(--shadow-faint); -} - -.sidebar-tag-pill:hover { - transform: none; - box-shadow: 0 2px 6px var(--shadow-pop); - border-color: var(--accent-soft); -} - -.sidebar-tag-pill:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.sidebar-tag-pill.active { - border-color: var(--sidebar-active-pill-border); - box-shadow: 0 0 0 1.5px var(--sidebar-active-pill-border); -} - -.sidebar-tag-pill--untagged { - border: 1px dashed var(--border); - background: var(--surface-subtle); - color: var(--muted); -} - -.sidebar-tag-pill--untagged.active { - color: var(--fg); -} - -.sidebar-tag-cloud--has-active .sidebar-tag-pill:not(.active) { - opacity: 0.45; -} - -.sidebar-correspondent-list { - list-style: none; - margin: 0.4rem 0 0; - padding: 0; - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.sidebar-correspondent-item { - display: block; - background: transparent; - border-radius: 4px; - padding: 0.35rem 0.5rem; - text-align: left; - color: var(--sidebar-fg); - cursor: pointer; - font-size: 0.85rem; - transition: background 0.15s ease, box-shadow 0.15s ease; -} - -.sidebar-correspondent-item:hover { - background: var(--sidebar-hover-bg); - color: var(--fg); -} - -.sidebar-correspondent-item:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.sidebar-correspondent-item.active { - background: var(--sidebar-active-bg); - color: var(--fg); -} - - -.documents-panel { - padding: 0 0.75rem 0.75rem 0.75rem; - display: flex; - flex-direction: column; - min-height: 0; -} - -.tags-panel, -.correspondents-panel { - padding: 1.25rem; - display: flex; - flex-direction: column; - min-height: 0; -} - -.folder-row.is-drop-target { - outline: 2px dashed var(--accent); - outline-offset: 2px; -} - -.documents-panel .panel-section__header { - display: flex; - align-items: center; - justify-content: space-between; - position: relative; -} - -.documents-panel .panel-section__header .header-actions { - display: flex; - gap: 0.5rem; -} - -.documents-panel__title { - display: flex; - align-items: center; - gap: 0.35rem; - margin: 0; - font-size: 0.9rem; - font-weight: 600; - min-width: 0; - white-space: nowrap; - overflow: hidden; -} - -.documents-panel__breadcrumbs { - flex: 1 1 auto; - overflow: hidden; -} - -.documents-panel .panel-section__body { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.panel-floating { - position: absolute; - top: calc(50% + 0.25rem); - left: 50%; - transform: translate(-50%, -50%); - background: color-mix(in oklch, var(--surface) 100%, transparent); - border: 1px solid color-mix(in oklch, var(--border) 95%, transparent); - padding: 0.45rem 0.85rem; - border-radius: 1rem; - font-size: 0.95rem; - font-weight: 400; - color: var(--fg); - box-shadow: 0 2px 6px color-mix(in oklch, var(--shadow-soft) 60%, transparent); - pointer-events: auto; - display: flex; - align-items: center; - justify-content: center; - flex-wrap: nowrap; - gap: 0.75rem; - z-index: 2000000; -} - -.panel-floating__label { - white-space: nowrap; - pointer-events: none; - font-size: 0.95rem; - color: var(--fg); -} - -.selection-summary { - display: inline-flex; - align-items: center; - gap: 0.4rem; -} - -.selection-summary__token { - display: inline-flex; - align-items: center; - gap: 0.3rem; -} - -.selection-summary__count { - font-weight: 600; - font-variant-numeric: tabular-nums; -} - -.selection-summary__icon { - width: 1rem; - height: 1rem; -} - -.selection-summary--text { - font-weight: 600; -} - -.selection-summary__separator { - opacity: 0.45; -} - -.panel-floating-actions { - display: inline-flex; - align-items: center; - gap: 0.4rem; - flex-wrap: nowrap; - pointer-events: auto; -} - -.panel-floating-actions .quick-add { - pointer-events: auto; -} - -.panel-floating-actions .quick-add__trigger { - pointer-events: auto; -} - -.panel-floating-actions .quick-add__trigger[disabled] { - opacity: 0.45; - cursor: not-allowed; -} - -.panel-floating-actions__button { - display: inline-flex; - align-items: center; - gap: 0; - pointer-events: auto; - font-size: 1.35rem; -} - -.panel-floating-actions__button .icon-inline { - display: inline-flex; - width: 1.35rem; - height: 1.35rem; -} - -.documents-panel .documents-scroll { - overflow-y: auto; - background: transparent; - min-height: 0; - padding-right: 0.3rem; - flex-grow: 1; -} - -.documents-panel .documents-scroll:focus-visible { - outline: 2px solid var(--selection-ring); - outline-offset: 2px; - border-radius: 0.25rem; -} - -.documents-panel table { - max-width: 100%; - border-collapse: collapse; - font-size: 0.88rem; - margin-top: 0.4rem; -} - -.documents-panel thead th { - background-color: var(--surface); - position: sticky; - top: 0; - z-index: 1; - padding: 0.45rem 0.6rem; - color: var(--muted); -} - - -.documents-panel th, -.documents-panel td { - padding: 0.45rem 0.6rem; - text-align: left; -} - -.documents-panel--view-grid .documents-scroll { - padding: 0.35rem 0.5rem 1rem; -} - -.documents-panel th.thumb-column, -.documents-panel td.thumb-cell { - width: 54px; - text-align: center; -} - -.documents-panel--view-grid .document-thumbnail-wrapper { - width: var(--documents-grid-icon-size); - height: var(--documents-grid-icon-size); - padding: 8px; - border-radius: 10px; - display: flex; - justify-content: center; - align-items: center; -} - -.documents-panel--view-grid .folder-card__icon { - width: var(--documents-grid-icon-size); - height: var(--documents-grid-icon-size); - padding: 8px; - border-radius: 10px; - display: flex; - justify-content: center; - align-items: center; -} - -.document-thumbnail-inner { - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.document-thumbnail-inner--multipage::after { - content: ''; - position: absolute; - top: 0; - right: 0; - width: 24px; - height: 24px; - background-image: url('./assets/papercorner.svg'); - background-repeat: no-repeat; - background-size: contain; - pointer-events: none; -} - -.documents-panel--view-grid .document-thumbnail-inner--multipage::after { - width: 28px; - height: 28px; -} - -.document-thumbnail { - max-width: 100%; - max-height: 100%; - box-shadow: 0 1px 6px var(--shadow-medium); -} - -.documents-panel--view-grid .document-thumbnail { - box-shadow: 0 1px 12px var(--shadow-medium); -} - -.thumb-placeholder { - width: 100%; - height: 100%; - border-radius: 1px; - background: var(--surface-subtle); - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 0.68rem; - font-weight: 600; - letter-spacing: 0.08em; - box-shadow: 0 1px 3px var(--shadow-medium); -} - -.documents-panel--view-grid .thumb-placeholder { - font-size: 1.1rem; - letter-spacing: 0.12em; - display: inline-flex; - width: 100%; - height: 100%; -} - -.thumb-icon { - width: 100%; - height: 100%; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.thumb-icon__image { - width: 32px; - height: 32px; - display: block; -} - -.documents-panel th.actions-column, -.documents-panel td.actions { - width: 1%; - white-space: nowrap; -} - -.documents-panel td.doc-list__name { - width: 100%; -} - -.doc-title-edit { - display: inline-flex; - align-items: center; - gap: 0.35rem; - flex-wrap: nowrap; -} - -.doc-title-edit input[type='text'] { - padding: 0.3rem 0.55rem; - border-radius: 4px; - border: 1px solid var(--border); - background: var(--surface); - color: var(--fg); - min-width: 8rem; -} - -.doc-title-edit input[type='text']:focus-visible { - outline: 2px solid var(--selection-ring); - outline-offset: 1px; -} - -.doc-title-edit .icon-button { - flex-shrink: 0; -} - -.documents-panel .doc-name__primary { - display: inline-flex; - align-items: center; - gap: 0.35rem; - flex-wrap: wrap; -} - -.documents-panel .doc-name__primary-text { - overflow-wrap: anywhere; -} - - -.doc-entry { - display: flex; - align-items: center; - gap: 0.6rem; -} - -.doc-entry--with-thumb .doc-entry__thumb { - flex: 0 0 auto; - display: flex; - align-items: center; - justify-content: center; -} - -.doc-entry__thumb .document-thumbnail-wrapper { - display: flex; - align-items: center; - justify-content: center; -} - -.doc-entry__main { - display: flex; - flex-direction: column; - gap: 0.35rem; - min-width: 0; -} - -.doc-entry__name { - font-weight: 600; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 100%; -} - -.doc-entry__tags { - display: flex; - flex-wrap: wrap; - gap: 0.3rem; -} - -.documents-panel td.actions .action-buttons { - display: inline-flex; - align-items: center; - gap: 0.3rem; -} - -.documents-panel tbody tr { - background: transparent; - transition: background 0.15s ease; -} - -.documents-panel tbody tr.folder { - cursor: pointer; -} - -.documents-panel tbody tr.folder.focused { - box-shadow: inset 2px 0 0 var(--accent-outline); - background: var(--sidebar-hover-bg); -} - -.documents-panel tbody tr.document { - cursor: pointer; -} - -.documents-panel tbody tr.document.selected, -.documents-panel tbody tr.folder.selected { - background: var(--selection-soft); - box-shadow: inset 2px 0 0 var(--accent-outline-strong); -} - -.documents-panel tbody tr.document, -.documents-panel tbody tr.document * { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; -} - -.documents-panel tbody tr.document.focused:not(.selected) { - box-shadow: inset 2px 0 0 var(--accent-outline); -} - -.doc-name { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.documents-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(var(--documents-grid-icon-size), 1fr)); - gap: 0.3rem 1.3rem; - padding: 0; -} - -.document-card { - padding: 0rem; - display: flex; - flex-direction: column; - gap: 0.3rem; - cursor: pointer; - align-items: center; - text-align: center; -} - -.document-card.selected .document-thumbnail-wrapper, -.folder-card.selected .folder-card__icon { - background-color: var(--selection-soft); -} - -.document-card:focus-visible .document-thumbnail-wrapper { - background-color: var(--selection-ring); -} - -.document-card.is-dragging { - opacity: 0.55; -} - -.document-card__meta { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.35rem; - width: 100%; -} - -.document-card__title { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.35rem; - color: var(--fg); -} - -.document-card__title-row { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.35rem; - flex-wrap: wrap; -} - -.document-card__title-badge { - padding: 0.2rem 0.7rem; - border-radius: 1rem; - max-width: 100%; - word-break: break-word; - font-size: var(--documents-grid-title-size); - color: inherit; -} - -.document-card .doc-correspondent-link { - font-size: var(--documents-grid-title-size); -} - -.document-card.selected .document-card__title-badge { - background-color: var(--accent); - color: var(--on-accent); -} - -.document-card__subtitle { - font-size: 0.78rem; - color: var(--muted); -} - -.document-card__tags { - display: flex; - flex-wrap: wrap; - gap: 0.25rem; - justify-content: center; -} - -.folder-card { - align-items: center; - text-align: center; -} - -.folder-card__icon { - display: flex; - align-items: center; - justify-content: center; - width: var(--documents-grid-icon-size); - height: var(--documents-grid-icon-size); -} - -.folder-card__icon-svg { - width: 100%; - height: 100%; - object-fit: contain; -} - -.folder-card__meta { - display: flex; - flex-direction: column; - gap: 0.28rem; - padding-top: 0.35rem; -} - -.folder-card__label-row { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.35rem; - flex-wrap: wrap; -} - -.folder-card__name { - color: var(--fg); - overflow: hidden; - text-overflow: ellipsis; - white-space: break-word; - font-size: var(--documents-grid-title-size); - padding: 0.2rem 0.7rem; - border-radius: 1rem; -} - -.folder-card__edit { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.35rem; -} - -.folder-card.selected .folder-card__name { - background-color: var(--accent); - color: var(--on-accent); -} - - -.doc-name__title { - max-width: 100%; - word-break: break-word; -} - -.doc-name__tags { - display: flex; - flex-wrap: wrap; - gap: 0.25rem; -} - -.doc-correspondents { - display: inline; - color: inherit; -} - -.doc-correspondent-link { - background: none; - background-color: transparent; - border: none; - padding: 0; - margin: 0; - color: var(--accent); - text-decoration: none; - font: inherit; - cursor: pointer; - box-shadow: none; - appearance: none; -} - -.doc-correspondent-link:not(.is-static):hover, -.doc-correspondent-link:not(.is-static):focus-visible { - color: var(--accent-strong, var(--accent)); - text-decoration: underline; - text-decoration-thickness: 1.5px; - background-color: transparent; -} - -.doc-correspondent-link:not(.is-static):focus-visible { - outline: 2px solid currentColor; - outline-offset: 2px; -} - -.documents-panel tbody tr.document.selected .doc-correspondents, -.documents-panel tbody tr.document.selected .doc-correspondent-link, -.document-card.selected .doc-correspondent-link { - color: inherit; -} - -.document-card.selected .doc-correspondents { - color: inherit; -} - -.doc-correspondent-link.is-active { - font-weight: 600; -} - -.doc-correspondent-link.is-static { - color: inherit; - cursor: default; - text-decoration: none; -} - -.doc-correspondent-link__separator { - color: inherit; -} - -.documents-panel tbody tr.document.dragging { - opacity: 0.4; -} - -.documents-panel tbody tr.document.tag-drop-target { - background: var(--accent-soft); - box-shadow: inset 0 0 0 2px var(--accent); -} - -.document-card.tag-drop-target { - box-shadow: 0 0 0 2px var(--accent); - border-color: var(--accent); -} - -.document-card.tag-drop-target .document-card__title { - color: var(--accent); -} - -.filter-bar { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.32rem; - margin-bottom: 0.5rem; -} - -.filter-bar input[type='search'] { - flex: 1; - min-width: 180px; -} - -.filter-actions { - display: flex; - gap: 0.32rem; -} - -.search-hint { - margin-top: 0.75rem; - font-size: 0.85rem; - color: var(--muted); -} - -.badge { - display: inline-flex; - align-items: center; - padding: 0.15rem 0.35rem; - border-radius: 2px; - background: var(--surface-subtle); - color: var(--fg); - font-size: 0.74rem; -} - -.tag-chip { - gap: 0.25rem; - border-radius: 1rem; - padding: 0.2rem 0.4rem; - font-weight: 600; -} - -.tag-chip--more { - background: transparent; - border-color: var(--border-strong); - color: var(--muted); -} - -.tag-chip--removable { - gap: 0.35rem; -} - -.tag-chip__remove { - background: none; - border: none; - color: inherit; - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - line-height: 1; - cursor: pointer; - opacity: 0.8; -} - -.tag-chip__remove:hover, -.tag-chip__remove:focus-visible { - opacity: 1; -} - -.tag-chip__remove:focus-visible { - outline: 2px solid currentColor; - outline-offset: 2px; - border-radius: 50%; -} - -.empty-state { - border: 1px dashed var(--border); - border-radius: 0; - text-align: center; - padding: 1.1rem 0.9rem; - color: var(--muted); - margin-top: 0.75rem; - background: var(--surface-subtle); -} - -.empty-state--global { - border-style: solid; -} - -.panel.detail-panel { - position: fixed; - top: 0; - right: 0; - width: min(100vw, var(--detail-panel-width)); - min-height: 100vh; - height: 100%; - height: 100%; - background: var(--bg); - box-shadow: 0 0 24px var(--shadow-soft); - border-left: 1px solid var(--border); - display: flex; - flex-direction: column; - z-index: 1000000; -} - -.panel-header { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.5rem; - min-width: 0; -} - -.panel-header__leading, -.panel-header__actions { - display: flex; - align-items: center; - gap: 0.25rem; -} - -.panel-header__title { - margin: 0; - font-size: 1rem; - font-weight: 600; - line-height: 1.2; - flex: 1 1 auto; - min-width: 0; - display: flex; - align-items: center; - gap: 0.5rem; - overflow: hidden; - text-wrap: nowrap; -} - -.panel-header > .panel-header__title:first-child { - padding-left: 0.5rem; -} - -.panel-header__actions { - margin-left: auto; -} - -.panel-body { - padding: 0.5rem 1rem; -} - - -.detail-panel .panel-body { - flex: 1; - display: flex; - flex-direction: column; - overflow-y: auto; - min-height: 0; - padding: 0; -} - -.detail-section__header { - display: flex; - align-items: center; - gap: 0.5rem; - margin-bottom: 0.5rem; -} - -.detail-section__title { - margin: 0; - font-weight: 600; - flex: 1; - min-width: 0; -} - -.quick-add { - display: inline-flex; - align-items: center; - position: relative; -} - -.quick-add__trigger { - white-space: nowrap; -} - -.documents-sort__trigger.quick-add__trigger { - padding: 0.25rem 0.5rem; - min-height: 2.1rem; -} - -.quick-add__chip { - display: inline-flex; - align-items: center; - gap: 0.35rem; - white-space: nowrap; - border: 1px dashed var(--border); - border-radius: 999px; - padding: 0.18rem 0.6rem; - font-size: 0.85rem; - background: transparent; - color: var(--muted); - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; -} - -.quick-add__chip:hover, -.quick-add__chip:focus-visible { - border-style: solid; - background: var(--selection-soft); - color: var(--fg); - outline: none; -} - -.quick-add__chip .icon-inline { - width: 1rem; - height: 1rem; -} - -.quick-add__chip-label { - display: inline-flex; - align-items: center; - gap: 0.25rem; -} - -.quick-add__menu { - padding: 0.25rem 0; -} - -.quick-add__form { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.5rem 0.75rem; - border-bottom: 1px solid var(--border); -} - -.quick-add__form input { - flex: 1; - min-width: 0; -} - -.quick-add__list { - max-height: 240px; - overflow-y: auto; -} - -.quick-add__option { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.quick-add__swatch { - width: 0.75rem; - height: 0.75rem; - border-radius: 9999px; - border: 1px solid var(--border); - background: var(--surface-subtle); -} - -.selection-assignment { - display: inline-flex; - position: relative; -} - -.selection-assignment__menu { - font-size: 0.95rem; - font-weight: 400; - padding: 0.4rem 0; - max-width: min(22rem, 90vw); -} - -.selection-assignment__header { - padding: 0.4rem 0.75rem 0.3rem; - border-bottom: 1px solid var(--border-subtle); -} - -.selection-assignment__header input { - width: 100%; - padding: 0.35rem 0.6rem; - border: 1px solid var(--border-subtle); - border-radius: 0.5rem; - background: var(--surface-subtle); - color: var(--fg); - font-size: 0.95rem; -} - -.selection-assignment__header input:focus-visible { - outline: none; - border-color: var(--selection-border); - box-shadow: 0 0 0 2px color-mix(in oklch, var(--selection) 25%, transparent); -} - -.selection-assignment__list { - max-height: 240px; - overflow-y: auto; -} - -.selection-assignment__item { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; - font-weight: 400; -} - -.selection-assignment__label { - flex: 1 1 auto; - display: inline-flex; - align-items: center; - gap: 0.25rem; -} - -.selection-assignment__spinner { - margin-left: 0.4rem; -} - -.selection-assignment__label--nowrap { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.selection-assignment__indent { - display: inline-block; - flex: 0 0 auto; -} - -.selection-assignment__folder-label { - display: inline-flex; - flex-direction: column; - gap: 0.15rem; - min-width: 0; - max-width: 16rem; -} - -.selection-assignment__folder-name { - font-weight: 500; - color: var(--fg); - min-width: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.selection-assignment__folder-path { - font-size: 0.8rem; - color: var(--muted); - white-space: normal; - word-break: break-word; -} - -.selection-assignment__slash { - color: var(--muted); - margin: 0 0.25rem; -} - -.selection-assignment__segment { - display: inline-block; -} - -.selection-assignment__item--all .selection-assignment__icon { - color: var(--success); -} - -.selection-assignment__item--partial .selection-assignment__icon { - color: var(--warning); -} - -.selection-assignment__icon { - width: 1rem; - height: 1rem; - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.selection-assignment__icon--empty { - border: 1px solid var(--border-subtle); - border-radius: 999px; - opacity: 0.6; -} - -.selection-assignment__label { - flex: 1 1 auto; - min-width: 0; - text-align: left; - font-weight: 400; -} - -.selection-assignment__count { - font-size: 0.8rem; - color: var(--muted); -} - -.selection-assignment__empty { - padding: 0.75rem; -} - -.selection-assignment__create { - border-top: 1px solid var(--border-subtle); - display: flex; - align-items: center; - gap: 0.5rem; -} - - -.preview-pane { - margin-top: 0.4rem; - background: transparent; - display: flex; - flex-direction: column; - gap: 1.25rem; - min-height: 0; - flex: 1; - overflow: auto; - position: relative; - padding: 1.25rem; -} - -.preview-pane__media { - border-radius: 0; - background: transparent; - min-height: 220px; - display: flex; - align-items: center; - justify-content: center; - overflow: visible; - position: relative; -} - -.preview-image { - width: 100%; - max-width: 360px; - max-height: 100%; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - pointer-events: auto; - position: relative; -} - -.preview-image__content { - display: block; - width: 100%; - height: auto; - max-width: 100%; - max-height: 100%; - object-fit: contain; - background: transparent; - cursor: pointer; - transition: - outline-color 120ms ease, - box-shadow 120ms ease, - filter 120ms ease, - background-color 120ms ease; - outline: 2px solid transparent; - outline-offset: -2px; -} - -.preview-image__content:hover, -.preview-image__content:focus-visible { - outline-color: var(--accent-focus); - box-shadow: - inset 0 0 0 999px var(--accent-elevated), - 0 6px 18px var(--accent-elevated-strong); -} - -.thumbnail-preview { - display: flex; - flex-direction: column; - gap: 0.32rem; - margin: 0.4rem 0 0.6rem; -} - -.thumbnail-image { - max-width: 100%; - border-radius: 0; - box-shadow: none; -} - -.detail-panel .meta, -.document-summary .meta { - font-size: 0.9rem; - color: var(--muted); - margin: 0.5rem 0; -} - -.detail-panel .detail-folder-path, -.document-summary .detail-folder-path { - display: inline-flex; - flex-wrap: wrap; - gap: 0.25rem; - align-items: center; -} - -.detail-folder-path--block { - display: flex; - gap: 0.25rem; - flex-wrap: wrap; - align-items: center; - margin: 0.5rem 0; -} - -.detail-panel .detail-folder-path__link, -.document-summary .detail-folder-path__link { - color: var(--accent); - text-decoration: none; -} - -.detail-panel .detail-folder-path__link:hover, -.detail-panel .detail-folder-path__link:focus-visible, -.document-summary .detail-folder-path__link:hover, -.document-summary .detail-folder-path__link:focus-visible { - text-decoration: underline; - outline: none; -} - -.detail-panel .detail-folder-path__separator, -.document-summary .detail-folder-path__separator { - color: var(--muted); -} - -.detail-panel .detail-folder-path__segment, -.document-summary .detail-folder-path__segment { - color: var(--fg); -} - -.detail-panel .doc-title-row, -.document-summary .doc-title-row { - display: flex; - flex-direction: column; - gap: 0.35rem; - margin: 0.25rem 0 1.25rem; - max-width: 100%; - word-break: break-word; -} - -.doc-title-row__primary { - display: flex; - align-items: center; - gap: 0.4rem; - width: 100%; -} - -.doc-title-row__title { - margin: 0; -} - -.doc-title-row__path { - font-size: 0.85rem; - color: var(--muted); - display: flex; - flex-wrap: wrap; - gap: 0.25rem; -} - -.detail-panel .doc-title-edit, -.document-summary .doc-title-edit { - display: flex; - align-items: center; - gap: 0.4rem; - width: 100%; -} - -.detail-panel .doc-title-edit input, -.document-summary .doc-title-edit input { - flex: 1; - min-width: 0; -} - -.status-inline { - font-size: 0.85rem; - margin-top: 0.2rem; -} - -.detail-meta { - display: flex; - flex-direction: column; - gap: 0.35rem; - margin: 1rem 0; -} - -.detail-meta__row { - display: inline-flex; - align-items: center; - gap: 0.35rem; - font-size: 0.9rem; - color: var(--muted); -} - -.detail-meta__label { - font-weight: 600; - color: var(--fg); -} - -.detail-meta__value { - color: var(--fg); -} - -.detail-meta__row > .icon-button { - margin: -0.25rem; -} - -.doc-issued-row { - display: inline-flex; - align-items: center; - gap: 0.35rem; - font-size: 0.9rem; - color: var(--muted); - margin: 0.25rem 0 0.5rem; -} - -.doc-issued-row__label { - font-weight: 600; - color: var(--fg); -} - -.doc-issued-row__value { - color: var(--fg); -} - -.doc-issued-edit { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.doc-issued-edit input[type='date'] { - font: inherit; - padding: 0.35rem 0.5rem; -} - -.status-inline.error { - color: var(--danger); -} - -.bulk-detail-actions { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin: 0.6rem 0; -} - -.bulk-detail-actions .inline { - display: flex; - gap: 0.4rem; -} - -.bulk-move { - display: flex; - flex-direction: column; - gap: 0.3rem; - margin: 0.6rem 0; -} - -.bulk-move select { - max-width: 100%; -} - -.preview-stack { - position: relative; - display: flex; - align-items: center; - justify-content: center; -} - -.preview-stack--stacked { - width: 100%; - min-height: 420px; - flex-shrink: 0; -} - -.preview-stack--empty { - width: 100%; - min-height: 420px; - flex-shrink: 0; -} - -.preview-stack__item { - position: absolute; - top: 50%; - left: 50%; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - transition: transform 120ms ease; - filter: drop-shadow(0 2px 6px var(--shadow-soft)); - transform-origin: center; - border-radius: 6px; - pointer-events: none; -} - -.preview-stack .preview-stack__item.orientation-portrait { - width: 80%; - height: 100%; -} - -.preview-stack .preview-stack__item.orientation-landscape { - width: 100%; - height: 80%; -} - -.preview-pane__unsupported { - width: 100%; - max-width: 320px; - display: flex; - flex-direction: column; - gap: 0.6rem; - align-items: center; - text-align: center; - padding: 1.5rem; - border-radius: 8px; - background: var(--surface-subtle); - color: var(--fg); -} - -.preview-pane__unsupported-message { - font-size: 0.95rem; - font-weight: 500; -} - -.preview-pane__unsupported-filename { - font-size: 0.85rem; - color: var(--muted); - word-break: break-word; -} - -.preview-pane__unsupported-download { - font-weight: 600; -} - -.preview-pane__unsupported-download svg { - width: 1rem; - height: 1rem; -} - -.preview-pane--stack { - min-height: 460px; - position: relative; - --preview-nav-scale: 1; -} - -.preview-pane__nav-button { - display: inline-flex; - align-items: center; - justify-content: center; - width: 2.2em; - height: 2.2em; - padding: 0.45em; - border-radius: 999px; - background: var(--preview-nav-bg); - color: var(--preview-nav-fg); - cursor: pointer; - transition: background 0.15s ease, opacity 0.15s ease; - pointer-events: auto; -} - -.preview-pane__nav-button:hover:not([disabled]) { - background: var(--preview-nav-bg-hover); -} - -.preview-pane__nav-button:disabled { - opacity: 0.4; - cursor: default; -} - -.preview-pane__nav-button:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; -} - -.preview-pane__nav { - margin-top: 0.5rem; - display: flex; - justify-content: center; - gap: 0.5rem; -} - -.preview-pane__nav--overlay { - position: absolute; - bottom: 0.75rem; - left: 50%; - transform: translateX(-50%) scale(var(--preview-nav-scale, 1)); - margin-top: 0; - pointer-events: none; - z-index: 20; - opacity: 0; - transition: opacity 0.2s ease; -} - -.preview-pane__nav--overlay .preview-pane__nav-button { - pointer-events: auto; - transform: scale(calc(1 / var(--preview-nav-scale, 1))); -} - -.preview-pane__media:hover .preview-pane__nav--overlay, -.desk-item__card:hover .preview-pane__nav--overlay { - opacity: 1; -} - -.desk-card__nav { - bottom: 0.5rem; -} - -.bulk-tags { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; - margin: 0.4rem 0 0.6rem; -} - -.detail-field { - margin: 0.9rem 0; -} - -.detail-field__label { - font-weight: 600; - margin-bottom: 0.25rem; -} - -.detail-field__value { - display: flex; - align-items: center; - gap: 0.5rem; - flex-wrap: wrap; - margin-bottom: 0.5rem; -} - -.detail-field__value .meta { - color: var(--muted); -} - -.detail-panel dl { - margin: 0; -} - -.detail-panel dt { - font-weight: 600; - margin-top: 0.8rem; -} - -.detail-panel dd { - margin: 0.2rem 0 0; -} - -.detail-panel .tag-list, -.document-summary .tag-list, -.correspondent-list { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin: 1rem 0; - align-items: center; -} - -.tag-list__empty { - color: var(--muted); -} - -.detail-metadata__block { - margin: 0.35rem 0 0; - padding: 0.5rem 0.6rem; - background: var(--surface-soft); - border-radius: 4px; - border: 1px solid var(--border-muted, var(--border)); - white-space: pre-wrap; - word-break: break-word; - font-family: var(--font-mono); - font-size: 0.82rem; - line-height: 1.45; -} - -input, -textarea, -select { - font: inherit; - border-radius: 2px; - border: 1px solid var(--border); - padding: 0.4rem 0.5rem; - background: var(--surface); - color: inherit; - width: 100%; - box-sizing: border-box; -} - -input:focus, -textarea:focus, -select:focus { - outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 2px var(--accent-soft); - background: var(--surface); -} - -textarea { - resize: vertical; -} - -form.inline { - display: flex; - gap: 0.32rem; - margin-top: 0.5rem; -} - -.status-banner { - padding: 0.45rem 0.8rem; - border-radius: 2px; - font-size: 0.85rem; -} - -.status-banner.info { - background: var(--surface-subtle); - color: var(--muted); -} - -.status-banner.success { - background: var(--success-subtle); - color: var(--success); -} - -.status-banner.error { - background: var(--danger-soft); - color: var(--danger); -} - -.drop-overlay { - position: fixed; - inset: 0; - background: var(--accent-soft); - backdrop-filter: blur(4px); - display: none; - align-items: center; - justify-content: center; - z-index: 9999; -} - -.drop-overlay.active { - display: flex; -} - -.drop-overlay__content { - background: var(--surface); - color: var(--fg); - padding: 1.25rem 1.75rem; - border-radius: 2px; - text-align: center; - font-size: 0.95rem; - box-shadow: none; -} -.modal-backdrop { - position: fixed; - inset: 0; - background: var(--overlay-backdrop); - display: flex; - align-items: center; - justify-content: center; - padding: 1.5rem; - z-index: 3000; -} - -.modal { - background: var(--surface); - border-radius: 4px; - box-shadow: 0 18px 42px var(--overlay-shadow); - width: min(360px, 100%); - padding: 1.6rem; - display: flex; - flex-direction: column; - gap: 1rem; -} - -.modal--panel { - width: 80vw; - max-width: 960px; - max-height: 90vh; - padding: 0; - border-radius: 12px; - overflow: hidden; - gap: 0; -} - -.settings-modal__body { - display: grid; - grid-template-columns: 12rem 1fr; - gap: 1.5rem; - height: 90vh; - padding: 1.5rem; -} - -.settings-modal__sidebar { - border-right: 1px solid var(--border-muted, var(--border)); - padding-right: 1rem; -} - -.settings-modal__sidebar ul { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - gap: 0.4rem; -} - -.settings-modal__sidebar button { - width: 100%; - display: inline-flex; - align-items: center; - justify-content: flex-start; - gap: 0.4rem; - border: none; - background: none; - color: inherit; - font: inherit; - padding: 0.45rem 0.6rem; - border-radius: 0.35rem; - cursor: pointer; -} - -.settings-modal__sidebar button:hover, -.settings-modal__sidebar button:focus-visible { - background: var(--sidebar-hover-bg); -} - -.settings-modal__sidebar button.active { - background: var(--accent-soft); - font-weight: 600; -} - -.settings-modal__content { - overflow-y: auto; - padding-bottom: 1rem; -} - -.settings-section h4 { - margin-top: 0; -} - -.settings-section { - display: flex; - flex-direction: column; -} - -.settings-actions { - display: flex; - justify-content: flex-end; - margin-bottom: 1rem; -} - -.settings-actions .secondary { - min-width: 7rem; -} - -.settings-form { - display: flex; - flex-wrap: wrap; - gap: 1rem; - align-items: flex-end; - margin-bottom: 0.75rem; -} - -.settings-form__field { - display: flex; - flex-direction: column; - gap: 0.35rem; - min-width: 14rem; -} - -.settings-form__field--full { - flex: 1 1 100%; - min-width: 100%; -} - -fieldset.settings-form__field { - border: 1px solid var(--border-muted, var(--border)); - border-radius: 0.5rem; - padding: 0.75rem 0.9rem 0.85rem; - background: var(--surface-soft); -} - -fieldset.settings-form__field legend { - padding: 0 0.35rem; - font-weight: 600; - color: var(--muted-strong, inherit); -} - -.settings-form__field input[type='text'], -.settings-form__field input[type='datetime-local'] { - padding: 0.45rem 0.6rem; - border: 1px solid var(--border); - border-radius: 0.35rem; - background: var(--surface-soft); - color: inherit; -} - -.settings-form__choices { - display: flex; - flex-direction: column; - gap: 0.4rem; - align-items: flex-start; -} - -.settings-capability-picker { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.capability-dropdown { - position: relative; - width: 100%; -} - -.capability-dropdown__trigger { - width: 100%; - display: inline-flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; - padding: 0.5rem 0.75rem; - border: 1px solid var(--border); - border-radius: 0.45rem; - background: var(--surface-soft); - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; - transition: border-color 0.15s ease, background 0.15s ease; -} - -.capability-dropdown__trigger:hover:not(:disabled), -.capability-dropdown__trigger:focus-visible { - border-color: var(--accent); - background: var(--surface); - outline: none; -} - -.capability-dropdown__trigger:disabled { - cursor: not-allowed; - color: var(--muted); - background: var(--surface-muted, var(--surface-soft)); -} - -.capability-dropdown__chevron { - flex-shrink: 0; - opacity: 0.8; -} - -.capability-dropdown__menu { - margin-top: 0.35rem; - max-height: 18rem; - overflow-y: auto; - padding: 0.25rem 0; - width: 100%; -} - -.capability-dropdown__option { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.45rem 0.75rem; -} - -.capability-dropdown__option-icon { - width: 1.1rem; - display: flex; - align-items: center; - justify-content: center; - color: var(--accent); -} - -.capability-dropdown__option:not(.is-selected) .capability-dropdown__option-icon { - color: transparent; -} - -.capability-dropdown__option-label { - flex: 1; - text-align: left; -} - -.capability-dropdown__empty { - padding: 0.6rem 0.8rem; - color: var(--muted); -} - -.settings-capability-picker__chips { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin-top: 0.25rem; -} - -.settings-capability-picker__chips--inline { - margin-top: 0.35rem; -} - -.settings-capabilities-summary { - display: inline-block; - margin-top: 0.4rem; - color: var(--muted); - font-size: 0.9rem; -} - -.settings-capability-picker__placeholder { - color: var(--muted); - font-size: 0.9rem; -} - -.settings-capability-list { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; - margin-top: 0.35rem; -} - -.settings-capability-list--compact { - margin-top: 0.2rem; - gap: 0.25rem; -} - -.settings-capability-list__item { - display: inline-flex; - align-items: center; -} - -.settings-choice { - display: inline-flex; - align-items: center; - gap: 0.4rem; - font-size: 0.9rem; - font-weight: 500; - color: inherit; -} - -.settings-choice input[type='checkbox'] { - width: 1.05rem; - height: 1.05rem; - cursor: pointer; - accent-color: var(--accent); -} - -.settings-choice input[type='checkbox']:disabled + span { - color: var(--muted); -} - -.settings-form__actions { - display: flex; - gap: 0.5rem; -} - -.settings-form__error { - color: var(--danger); - font-size: 0.85rem; - margin: 0 0 0.75rem; -} - -.settings-empty { - margin: 1rem 0; - color: var(--muted); -} - -.settings-table { - width: 100%; - border-collapse: collapse; - margin-top: 0.5rem; -} - -.settings-table th, -.settings-table td { - padding: 0.55rem 0.75rem; - border-bottom: 1px solid var(--border-muted, var(--border)); - text-align: left; - font-size: 0.9rem; -} - -.settings-table tr:last-child td { - border-bottom: none; -} - -.settings-table__actions { - white-space: nowrap; -} - -.settings-status { - color: var(--muted); - font-size: 0.9rem; -} - -.settings-table tr.is-revoked { - opacity: 0.65; -} - -.settings-notice { - border: 1px solid var(--accent); - background: var(--accent-soft); - padding: 0.9rem 1rem; - border-radius: 0.5rem; - margin-bottom: 1rem; -} - -.token-display { - background: var(--surface-ink-soft); - padding: 0.5rem 0.65rem; - border-radius: 0.35rem; - font-family: var(--font-mono); - font-size: 0.95rem; - overflow-x: auto; -} - -.settings-notice__actions { - display: flex; - gap: 0.5rem; - margin-top: 0.6rem; -} - -.settings-notice__actions button { - flex: 0 0 auto; -} - -.panel-modal__header { - padding: 1rem 1rem 1rem 0.5rem; - border-bottom: 1px solid var(--border); -} - -.panel-modal__body { - flex: 1; - overflow: auto; - padding: 0; -} - -.modal__body { - width: 100%; -} - -.modal h3 { - margin: 0; - font-size: 1.15rem; - font-weight: 600; -} - -.modal__form { - display: flex; - flex-direction: column; - gap: 0.9rem; -} - -.modal__form label { - font-weight: 600; - font-size: 0.9rem; -} - -.modal__error { - margin: -0.45rem 0 0; - font-size: 0.85rem; - color: var(--danger); -} - -.modal__actions { - display: flex; - justify-content: flex-start; - padding: 0.25rem; - gap: 0.6rem; -} - -@media (max-width: 768px) { - .app-bar { - flex-direction: column; - align-items: flex-start; - gap: 0.75rem; - } - .app-main { - grid-template-columns: 1fr; - } - .sidebar, - .documents-panel, - .detail-panel, - .tags-panel, - .correspondents-panel { - min-height: auto; - } -} -.login-screen { - min-height: 100vh; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background: var(--bg); - padding: 2rem; -} - -.login-card { - width: min(340px, 100%); - background: var(--surface); - border-radius: 2px; - padding: 1.75rem; - box-shadow: none; - display: flex; - flex-direction: column; - gap: 1rem; -} - -.login-card h1 { - margin: 0; - font-size: 1.6rem; - font-weight: 600; -} - -.login-card p { - margin: 0; - color: var(--muted); - font-size: 0.9rem; -} - -.login-card form { - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -.login-card label { - font-size: 0.85rem; - font-weight: 600; - color: var(--muted); -} - -.login-card__fields { - display: flex; - flex-direction: column; - gap: 0.75rem; - width: 100%; -} - -.login-card__passkey-button { - margin-top: 1rem; - width: 100%; - display: inline-flex; - justify-content: center; -} - -.login-card__signup-button { - margin-top: 0.75rem; - width: 100%; - display: inline-flex; - justify-content: center; -} - -.login-card .status-banner { - margin-bottom: 0; -} - -.login-card__selection { - display: flex; - flex-direction: column; - gap: 0.9rem; -} - -.login-card__tenant-list { - display: flex; - flex-direction: column; - gap: 0.6rem; -} - -.login-card__tenant-button { - display: inline-flex; - align-items: center; - justify-content: center; - width: 100%; - padding: 0.65rem 0.75rem; - border-radius: 0.6rem; - border: 1px solid var(--border); - background: var(--surface); - color: inherit; - font-weight: 600; - font-size: 0.95rem; - cursor: pointer; - transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease; -} - -.login-card__tenant-button:hover:not([disabled]) { - background: var(--surface-hover); - border-color: var(--border-strong); -} - -.login-card__tenant-button:disabled { - opacity: 0.6; - cursor: wait; -} - -.login-card__tenant-button.is-loading { - opacity: 0.6; -} - -.login-card__back-button { - align-self: flex-start; - background: none; - border: none; - padding: 0; - color: var(--accent); - font-size: 0.85rem; - cursor: pointer; - text-decoration: underline; -} - -.login-card__back-button:hover { - text-decoration: none; -} - -.login-card__back-button:disabled { - opacity: 0.6; - cursor: default; -} -.doc-list__name { - width: 100%; -} - -.doc-list__name-content { - display: inline-flex; - align-items: center; - gap: 0.22rem; - max-width: 100%; -} - -.doc-list__name-content span { - max-width: 100%; - overflow-wrap: anywhere; - word-break: break-word; -} - -.preview-pane__nav-button svg { - width: 100%; - height: 100%; -} - -.panel-header .icon-button svg { - width: 1.41rem; - height: 1.41rem; -} - -.upload-queue-overlay { - position: fixed; - bottom: 24px; - right: 24px; - width: min(360px, calc(100vw - 32px)); - background: var(--surface); - border: 1px solid var(--border); - border-radius: 14px; - box-shadow: 0 18px 45px var(--shadow-pop); - z-index: 400; - display: flex; - flex-direction: column; - gap: 0.5rem; - padding: 0.9rem; - color: var(--fg); -} - - -.upload-queue-overlay__header { - padding: 0; - border: none; -} - -.upload-queue-overlay__title { - display: inline-flex; - align-items: center; - gap: 0.4rem; - font-weight: 600; - font-size: 0.95rem; - min-width: 0; -} - -.upload-queue-overlay__summary { - font-size: 0.8rem; - color: var(--muted); - white-space: nowrap; -} - -.upload-queue-overlay__controls { - display: inline-flex; - align-items: center; - gap: 0.35rem; -} - -.upload-queue-overlay__list { - list-style: none; - margin: 0; - padding: 0; - max-height: 260px; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 0.6rem; -} - -.upload-queue-overlay--collapsed .upload-queue-overlay__list { - display: none; -} - -.upload-queue-overlay__item { - display: grid; - grid-template-columns: auto 1fr; - gap: 0.6rem; - padding: 0.15rem 0; -} - -.upload-queue-overlay__status { - width: 28px; - height: 28px; - border-radius: 999px; - display: inline-flex; - align-items: center; - justify-content: center; - background: var(--surface-subtle); - color: var(--muted); -} - -.upload-queue-overlay__status--muted { - background: var(--surface-subtle); - color: var(--muted); -} - -.upload-queue-overlay__status--accent { - background: var(--accent-soft); - color: var(--accent); -} - -.upload-queue-overlay__status--success { - background: var(--success-subtle); - color: var(--success); -} - -.upload-queue-overlay__status--info { - background: var(--selection-soft); - color: var(--accent); -} - -.upload-queue-overlay__status--danger { - background: var(--danger-subtle); - color: var(--danger); -} - -.upload-queue-overlay__details { - min-width: 0; - display: flex; - flex-direction: column; - gap: 0.15rem; -} - -.upload-queue-overlay__name { - font-size: 0.88rem; - font-weight: 500; - color: var(--fg); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.upload-queue-overlay__name-link { - font-size: 0.88rem; - font-weight: 500; - color: inherit; - background: none; - border: none; - padding: 0; - text-align: left; - cursor: pointer; - text-decoration: none; -} - -.upload-queue-overlay__name-link:hover { - color: var(--accent); - text-decoration: underline; -} - -.upload-queue-overlay__meta-line { - font-size: 0.72rem; - color: var(--muted); - display: flex; - align-items: center; - gap: 0.35rem; - flex-wrap: wrap; -} - -.upload-queue-overlay__meta-id, -.upload-queue-overlay__meta-secondary { - color: inherit; -} - -.upload-queue-overlay__meta-link { - border: none; - background: none; - font: inherit; - cursor: pointer; - padding: 0; - color: inherit; - text-decoration: none; -} - -.upload-queue-overlay__meta-link:hover { - color: var(--accent); - text-decoration: underline; -} - -.upload-queue-overlay__meta-link:disabled { - cursor: default; - opacity: 0.5; -} - -.upload-queue-overlay__meta-error { - color: var(--danger); -} - -.upload-queue-overlay__item--error .upload-queue-overlay__name { - color: var(--danger); -} - -.text-button { - background: none; - border: none; - color: var(--accent); - font-weight: 500; - font-size: 0.8rem; - cursor: pointer; - padding: 0.1rem 0.25rem; -} - -.text-button:disabled { - opacity: 0.4; - cursor: not-allowed; -} diff --git a/frontend/src/styles/auth/login.css b/frontend/src/styles/auth/login.css new file mode 100644 index 0000000..2e1bd87 --- /dev/null +++ b/frontend/src/styles/auth/login.css @@ -0,0 +1,131 @@ +.login-screen { + min-height: 100vh; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg); + padding: 2rem; +} + +.login-card { + width: min(340px, 100%); + background: var(--surface); + border-radius: 2px; + padding: 1.75rem; + box-shadow: none; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.login-card h1 { + margin: 0; + font-size: 1.6rem; + font-weight: 600; +} + +.login-card p { + margin: 0; + color: var(--muted); + font-size: 0.9rem; +} + +.login-card form { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.login-card label { + font-size: 0.85rem; + font-weight: 600; + color: var(--muted); +} + +.login-card__fields { + display: flex; + flex-direction: column; + gap: 0.75rem; + width: 100%; +} + +.login-card__passkey-button { + margin-top: 1rem; + width: 100%; + display: inline-flex; + justify-content: center; +} + +.login-card__signup-button { + margin-top: 0.75rem; + width: 100%; + display: inline-flex; + justify-content: center; +} + +.login-card .status-banner { + margin-bottom: 0; +} + +.login-card__selection { + display: flex; + flex-direction: column; + gap: 0.9rem; +} + +.login-card__tenant-list { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.login-card__tenant-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 0.65rem 0.75rem; + border-radius: 0.6rem; + border: 1px solid var(--border); + background: var(--surface); + color: inherit; + font-weight: 600; + font-size: 0.95rem; + cursor: pointer; + transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease; +} + +.login-card__tenant-button:hover:not([disabled]) { + background: var(--surface-hover); + border-color: var(--border-strong); +} + +.login-card__tenant-button:disabled { + opacity: 0.6; + cursor: wait; +} + +.login-card__tenant-button.is-loading { + opacity: 0.6; +} + +.login-card__back-button { + align-self: flex-start; + background: none; + border: none; + padding: 0; + color: var(--accent); + font-size: 0.85rem; + cursor: pointer; + text-decoration: underline; +} + +.login-card__back-button:hover { + text-decoration: none; +} + +.login-card__back-button:disabled { + opacity: 0.6; + cursor: default; +} diff --git a/frontend/src/styles/base/controls.css b/frontend/src/styles/base/controls.css new file mode 100644 index 0000000..68b8bbe --- /dev/null +++ b/frontend/src/styles/base/controls.css @@ -0,0 +1,99 @@ +button { + font: inherit; + border-radius: 2px; + border: 1px solid transparent; + padding: 0.35rem 0.85rem; + background: var(--accent); + color: var(--on-accent); + cursor: pointer; + font-weight: 500; + transition: background 0.15s ease, border-color 0.15s ease; +} + +button[disabled] { + opacity: 0.55; + cursor: not-allowed; +} + +a.button-link { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font: inherit; + border-radius: 2px; + border: 1px solid transparent; + padding: 0.35rem 0.85rem; + background: var(--accent); + color: var(--on-accent); + text-decoration: none; + font-weight: 500; + transition: background 0.15s ease, border-color 0.15s ease; +} + +a.button-link[aria-disabled='true'] { + opacity: 0.55; +} + +a.button-link:hover:not([aria-disabled='true']) { + background: var(--accent-hover); +} + +button.secondary { + background: transparent; + color: var(--fg); + border-color: var(--border); +} + +button.secondary:hover:not([disabled]) { + background: var(--surface-subtle); +} + +button.danger { + background: transparent; + color: var(--danger); + border-color: var(--danger-border); +} + +button.danger:hover:not([disabled]) { + border-color: var(--danger); + background: var(--danger-subtle); +} + +.icon-button { + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + background: transparent; + color: var(--muted); + padding: 0.25rem; + border-radius: 4px; + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease; +} + +.icon-button:hover:not([disabled]) { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.icon-button.danger { + color: var(--danger); +} + +.icon-button.danger:hover:not([disabled]) { + background: var(--danger-subtle); +} + +.icon-button.ghost { + border: none; + background: transparent; + color: var(--muted); + padding: 0.2rem; +} + +.icon-button.ghost:hover:not([disabled]) { + color: var(--danger); + background: transparent; +} + diff --git a/frontend/src/styles/base/iconography.css b/frontend/src/styles/base/iconography.css new file mode 100644 index 0000000..fa84f2a --- /dev/null +++ b/frontend/src/styles/base/iconography.css @@ -0,0 +1,56 @@ +.with-icon { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.icon-inline { + width: 1rem; + height: 1rem; +} + +.icon { + width: 1rem; + height: 1rem; + display: inline-flex; + align-items: center; + justify-content: center; +} + +@keyframes icon-spin { + to { + transform: rotate(360deg); + } +} + +.icon--spin { + animation: icon-spin 0.9s linear infinite; +} + +.icon--flip-y { + transform: scaleX(-1); +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +.icon path { + stroke: currentColor; + stroke-width: 1.6; + fill: none; +} + +.icon--fill path { + stroke: none; + fill: currentColor; +} + + diff --git a/frontend/src/styles/base/text-button.css b/frontend/src/styles/base/text-button.css new file mode 100644 index 0000000..fceeabc --- /dev/null +++ b/frontend/src/styles/base/text-button.css @@ -0,0 +1,14 @@ +.text-button { + background: none; + border: none; + color: var(--accent); + font-weight: 500; + font-size: 0.8rem; + cursor: pointer; + padding: 0.1rem 0.25rem; +} + +.text-button:disabled { + opacity: 0.4; + cursor: not-allowed; +} diff --git a/frontend/src/styles/base/theme.css b/frontend/src/styles/base/theme.css new file mode 100644 index 0000000..f7581f9 --- /dev/null +++ b/frontend/src/styles/base/theme.css @@ -0,0 +1,295 @@ +:root { + color-scheme: light dark; + + --neutral-hue: 180deg; + --foreground-hue-offset: 10deg; + --accent-hue-offset: -20deg; + --dark-hue-offset: 30deg; + --dark-foreground-hue-offset: 10deg; + + /* --- Neutrals --- */ + --bg: oklch(0.97 0.001 var(--neutral-hue)); + --surface: oklch(0.985 0.001 var(--neutral-hue)); + --surface-subtle: oklch(0.96 0.002 var(--neutral-hue)); + --fg: oklch(0.32 0.005 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --muted: oklch(0.54 0.008 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --sidebar-fg: oklch(0.56 0.007 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --border: oklch(0.92 0.002 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + + /* --- Accent (primary) --- */ + --accent: oklch(0.61 0.2 calc(var(--neutral-hue) + var(--foreground-hue-offset) + var(--accent-hue-offset))); + --accent-hover: oklch(0.70 0.02 calc(var(--neutral-hue) + var(--foreground-hue-offset) + var(--accent-hue-offset))); + --on-accent: oklch(1 0 0); + + --folder-icon-back: color-mix(in oklch, var(--accent) 78%, black 8%); + --folder-icon-mid: color-mix(in oklch, var(--accent) 60%, white 30%); + --folder-icon-front: color-mix(in oklch, var(--accent) 42%, white 58%); + + --success-hue: 140deg; + --warning-hue: 85deg; + --danger-hue: 25deg; + + --accent-soft: color-mix(in oklch, var(--accent) 12%, transparent); + --accent-elevated: color-mix(in oklch, var(--accent) 16%, transparent); + --accent-elevated-strong: color-mix(in oklch, var(--accent) 22%, transparent); + --accent-outline: color-mix(in oklch, var(--accent) 45%, transparent); + --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); + --accent-focus: color-mix(in oklch, var(--accent) 85%, transparent); + --surface-overlay: color-mix(in oklch, white 82%, transparent); + + /* -- Selection --- */ + --selection: oklch(0.61 0.01 var(--neutral-hue)); + + /* --- Derived accent states --- */ + --selection-soft: color-mix(in oklch, var(--selection) 12%, transparent); + + /* --- Shadows & overlays --- */ + --shadow-faint: color-mix(in oklch, black 6%, transparent); + --shadow-soft: color-mix(in oklch, black 12%, transparent); + --shadow-medium: color-mix(in oklch, black 18%, transparent); + --shadow-strong: color-mix(in oklch, black 28%, transparent); + --shadow-deep: color-mix(in oklch, black 55%, transparent); + --shadow-pop: color-mix(in oklch, black 25%, transparent); + --outline-subtle: color-mix(in oklch, black 6%, transparent); + --overlay-dark: color-mix(in oklch, black 55%, transparent); + --overlay-dim: color-mix(in oklch, oklch(0.28 0.01 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 20%, transparent); + --overlay-darker: color-mix(in oklch, black 75%, transparent); + --surface-danger-subtle: color-mix(in oklch, var(--danger) 12%, transparent); + --overlay-accent-subtle: color-mix(in oklch, var(--accent) 12%, transparent); + --border-strong: color-mix(in oklch, var(--fg) 24%, transparent); + --surface-hover: color-mix(in oklch, white 10%, transparent); + --overlay-accent-strong: color-mix(in oklch, var(--accent) 24%, transparent); + --overlay-backdrop: color-mix(in oklch, oklch(0.22 0.015 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 45%, transparent); + --overlay-shadow: color-mix(in oklch, oklch(0.22 0.015 calc(var(--neutral-hue) + var(--foreground-hue-offset) - 5deg)) 18%, transparent); + + /* --- Semantic colors --- */ + --success: oklch(0.68 0.16 var(--success-hue)); + --warning: oklch(0.76 0.17 var(--warning-hue)); + --danger: oklch(0.64 0.2 var(--danger-hue)); + + --success-subtle: color-mix(in oklch, var(--success) 12%, transparent); + --warning-subtle: color-mix(in oklch, var(--warning) 12%, transparent); + --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); + --danger-soft: color-mix(in oklch, var(--danger) 12%, transparent); + --danger-subtle: color-mix(in oklch, var(--danger) 8%, transparent); + + /* --- Explorer states --- */ + --row-hover-bg: color-mix(in oklch, var(--selection) 6%, transparent); + --row-active-bg: color-mix(in oklch, var(--selection) 12%, transparent); + --sidebar-hover-bg: color-mix(in oklch, var(--selection) 8%, transparent); + --sidebar-active-bg: color-mix(in oklch, var(--selection) 16%, transparent); + --selection-ring: oklch(0.78 0.16 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 64%, transparent); + --link: var(--accent); + --link-visited: color-mix(in oklch, var(--accent) 75%, var(--fg) 25%); + --preview-nav-bg: oklch(0.18 0.05 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --preview-nav-bg-hover: oklch(0.14 0.05 calc(var(--neutral-hue) + var(--foreground-hue-offset))); + --preview-nav-fg: var(--on-accent); + --text-on-dark: color-mix(in oklch, white 90%, transparent); + --surface-ink-soft: color-mix(in oklch, var(--fg) 8%, transparent); + + font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font-size: 15px; + --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + + --detail-panel-width: 30em; + --documents-grid-title-size: 0.8rem; +} + +:root[data-theme='light'] { + color-scheme: light; +} + +:root[data-theme='dark'] { + color-scheme: dark; + + --dark-neutral-hue: calc(var(--neutral-hue) + var(--dark-hue-offset)); + --dark-foreground-hue: calc(var(--neutral-hue) + var(--dark-foreground-hue-offset)); + + --bg: oklch(0.15 0.01 var(--dark-neutral-hue)); + --surface: oklch(0.19 0.012 var(--dark-neutral-hue)); + --surface-subtle: oklch(0.23 0.012 var(--dark-neutral-hue)); + --fg: oklch(0.89 0.015 var(--dark-foreground-hue)); + --muted: oklch(0.72 0.02 var(--dark-foreground-hue)); + --sidebar-fg: oklch(0.78 0.02 var(--dark-foreground-hue)); + --border: oklch(0.33 0.01 var(--dark-foreground-hue)); + + --accent: oklch(0.75 0.2 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); + --accent-hover: oklch(0.82 0.16 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); + --on-accent: oklch(0.15 0.015 var(--dark-foreground-hue)); + + --folder-icon-back: color-mix(in oklch, var(--accent) 72%, black 12%); + --folder-icon-mid: color-mix(in oklch, var(--accent) 50%, white 24%); + --folder-icon-front: color-mix(in oklch, var(--accent) 30%, white 50%); + + --accent-soft: color-mix(in oklch, var(--accent) 22%, transparent); + --accent-elevated: color-mix(in oklch, var(--accent) 28%, transparent); + --accent-elevated-strong: color-mix(in oklch, var(--accent) 38%, transparent); + --accent-outline: color-mix(in oklch, var(--accent) 55%, transparent); + --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); + --accent-focus: color-mix(in oklch, var(--accent) 80%, transparent); + --surface-overlay: color-mix(in oklch, black 60%, transparent); + + --selection: oklch(0.44 0.04 220deg); + --selection-soft: color-mix(in oklch, var(--selection) 18%, transparent); + + --shadow-faint: color-mix(in oklch, black 35%, transparent); + --shadow-soft: color-mix(in oklch, black 50%, transparent); + --shadow-medium: color-mix(in oklch, black 65%, transparent); + --shadow-strong: color-mix(in oklch, black 80%, transparent); + --shadow-deep: color-mix(in oklch, black 90%, transparent); + --shadow-pop: color-mix(in oklch, black 70%, transparent); + --outline-subtle: color-mix(in oklch, white 10%, transparent); + --overlay-dark: color-mix(in oklch, black 70%, transparent); + --overlay-dim: color-mix(in oklch, oklch(0.42 0.04 var(--dark-neutral-hue)) 35%, transparent); + --overlay-darker: color-mix(in oklch, black 85%, transparent); + --surface-danger-subtle: color-mix(in oklch, var(--danger) 26%, transparent); + --overlay-accent-subtle: color-mix(in oklch, var(--accent) 32%, transparent); + --border-strong: color-mix(in oklch, var(--fg) 30%, transparent); + --surface-hover: color-mix(in oklch, white 6%, transparent); + --overlay-accent-strong: color-mix(in oklch, var(--accent) 55%, transparent); + --overlay-backdrop: color-mix(in oklch, oklch(0.1 0.015 var(--dark-neutral-hue)) 70%, transparent); + --overlay-shadow: color-mix(in oklch, oklch(0.12 0.015 var(--dark-neutral-hue)) 55%, transparent); + + --success: oklch(0.62 0.16 var(--success-hue)); + --warning: oklch(0.68 0.17 var(--warning-hue)); + --danger: oklch(0.60 0.2 var(--danger-hue)); + + --success-subtle: color-mix(in oklch, var(--success) 20%, transparent); + --warning-subtle: color-mix(in oklch, var(--warning) 20%, transparent); + --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); + --danger-soft: color-mix(in oklch, var(--danger) 24%, transparent); + --danger-subtle: color-mix(in oklch, var(--danger) 18%, transparent); + + --row-hover-bg: color-mix(in oklch, white 4%, transparent); + --row-active-bg: color-mix(in oklch, var(--selection) 20%, transparent); + --sidebar-hover-bg: color-mix(in oklch, white 6%, transparent); + --sidebar-active-bg: color-mix(in oklch, var(--selection) 26%, transparent); + --selection-ring: oklch(0.68 0.16 var(--dark-foreground-hue)); + --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 72%, transparent); + --link: color-mix(in oklch, var(--accent) 92%, transparent); + --link-visited: color-mix(in oklch, var(--accent) 70%, white 20%); + --preview-nav-bg: oklch(0.3 0.04 var(--dark-neutral-hue)); + --preview-nav-bg-hover: oklch(0.35 0.04 var(--dark-neutral-hue)); + --preview-nav-fg: var(--fg); + --text-on-dark: color-mix(in oklch, white 92%, transparent); + --surface-ink-soft: color-mix(in oklch, white 12%, transparent); +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme='light']) { + color-scheme: dark; + + --dark-neutral-hue: calc(var(--neutral-hue) + var(--dark-hue-offset)); + --dark-foreground-hue: calc(var(--neutral-hue) + var(--dark-foreground-hue-offset)); + + --bg: oklch(0.15 0.01 var(--dark-neutral-hue)); + --surface: oklch(0.19 0.012 var(--dark-neutral-hue)); + --surface-subtle: oklch(0.23 0.012 var(--dark-neutral-hue)); + --fg: oklch(0.89 0.015 var(--dark-foreground-hue)); + --muted: oklch(0.72 0.02 var(--dark-foreground-hue)); + --sidebar-fg: oklch(0.78 0.02 var(--dark-foreground-hue)); + --border: oklch(0.33 0.01 var(--dark-foreground-hue)); + + --accent: oklch(0.75 0.2 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); + --accent-hover: oklch(0.82 0.16 calc(var(--dark-foreground-hue) + var(--accent-hue-offset))); + --on-accent: oklch(0.15 0.015 var(--dark-foreground-hue)); + + --folder-icon-back: color-mix(in oklch, var(--accent) 72%, black 12%); + --folder-icon-mid: color-mix(in oklch, var(--accent) 50%, white 24%); + --folder-icon-front: color-mix(in oklch, var(--accent) 30%, white 50%); + + --accent-soft: color-mix(in oklch, var(--accent) 22%, transparent); + --accent-elevated: color-mix(in oklch, var(--accent) 28%, transparent); + --accent-elevated-strong: color-mix(in oklch, var(--accent) 38%, transparent); + --accent-outline: color-mix(in oklch, var(--accent) 55%, transparent); + --accent-outline-strong: color-mix(in oklch, var(--accent) 90%, transparent); + --accent-focus: color-mix(in oklch, var(--accent) 80%, transparent); + --surface-overlay: color-mix(in oklch, black 60%, transparent); + + --selection: oklch(0.44 0.04 220deg); + --selection-soft: color-mix(in oklch, var(--selection) 18%, transparent); + + --shadow-faint: color-mix(in oklch, black 35%, transparent); + --shadow-soft: color-mix(in oklch, black 50%, transparent); + --shadow-medium: color-mix(in oklch, black 65%, transparent); + --shadow-strong: color-mix(in oklch, black 80%, transparent); + --shadow-deep: color-mix(in oklch, black 90%, transparent); + --shadow-pop: color-mix(in oklch, black 70%, transparent); + --outline-subtle: color-mix(in oklch, white 10%, transparent); + --overlay-dark: color-mix(in oklch, black 70%, transparent); + --overlay-dim: color-mix(in oklch, oklch(0.42 0.04 var(--dark-neutral-hue)) 35%, transparent); + --overlay-darker: color-mix(in oklch, black 85%, transparent); + --surface-danger-subtle: color-mix(in oklch, var(--danger) 26%, transparent); + --overlay-accent-subtle: color-mix(in oklch, var(--accent) 32%, transparent); + --border-strong: color-mix(in oklch, var(--fg) 30%, transparent); + --surface-hover: color-mix(in oklch, white 6%, transparent); + --overlay-accent-strong: color-mix(in oklch, var(--accent) 55%, transparent); + --overlay-backdrop: color-mix(in oklch, oklch(0.1 0.015 var(--dark-neutral-hue)) 70%, transparent); + --overlay-shadow: color-mix(in oklch, oklch(0.12 0.015 var(--dark-neutral-hue)) 55%, transparent); + + --success: oklch(0.62 0.16 var(--success-hue)); + --warning: oklch(0.68 0.17 var(--warning-hue)); + --danger: oklch(0.60 0.2 var(--danger-hue)); + + --success-subtle: color-mix(in oklch, var(--success) 20%, transparent); + --warning-subtle: color-mix(in oklch, var(--warning) 20%, transparent); + --danger-border: color-mix(in oklch, var(--danger) 45%, transparent); + --danger-soft: color-mix(in oklch, var(--danger) 24%, transparent); + --danger-subtle: color-mix(in oklch, var(--danger) 18%, transparent); + + --row-hover-bg: color-mix(in oklch, white 4%, transparent); + --row-active-bg: color-mix(in oklch, var(--selection) 20%, transparent); + --sidebar-hover-bg: color-mix(in oklch, white 6%, transparent); + --sidebar-active-bg: color-mix(in oklch, var(--selection) 26%, transparent); + --selection-ring: oklch(0.68 0.16 var(--dark-foreground-hue)); + --sidebar-active-pill-border: color-mix(in oklch, var(--accent) 72%, transparent); + --link: color-mix(in oklch, var(--accent) 92%, transparent); + --link-visited: color-mix(in oklch, var(--accent) 70%, white 20%); + --preview-nav-bg: oklch(0.3 0.04 var(--dark-neutral-hue)); + --preview-nav-bg-hover: oklch(0.35 0.04 var(--dark-neutral-hue)); + --preview-nav-fg: var(--fg); + --text-on-dark: color-mix(in oklch, white 92%, transparent); + --surface-ink-soft: color-mix(in oklch, white 12%, transparent); + } +} + +html, +body { + height: 100%; +} + +body { + margin: 0; + background: var(--bg); + color: var(--fg); + overflow: hidden; +} + +body.has-main-content { + background: var(--surface); +} + +a { + color: var(--accent); + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 0.18em; + transition: color 0.15s ease, text-decoration-color 0.15s ease; +} + +a:visited { + color: var(--link-visited); +} + +a:hover, +a:focus-visible { + color: var(--accent-hover); + outline: none; + text-decoration-color: currentColor; +} + +#app { + height: 100%; +} + diff --git a/frontend/src/styles/detail/detail-panels.css b/frontend/src/styles/detail/detail-panels.css new file mode 100644 index 0000000..79c4f6b --- /dev/null +++ b/frontend/src/styles/detail/detail-panels.css @@ -0,0 +1,777 @@ +.panel.detail-panel { + position: fixed; + top: 0; + right: 0; + width: min(100vw, var(--detail-panel-width)); + min-height: 100vh; + height: 100%; + height: 100%; + background: var(--bg); + box-shadow: 0 0 24px var(--shadow-soft); + border-left: 1px solid var(--border); + display: flex; + flex-direction: column; + z-index: 1000000; +} + +.panel-header { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem; + min-width: 0; +} + +.panel-header__leading, +.panel-header__actions { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.panel-header__title { + margin: 0; + font-size: 1rem; + font-weight: 600; + line-height: 1.2; + flex: 1 1 auto; + min-width: 0; + display: flex; + align-items: center; + gap: 0.5rem; + overflow: hidden; + text-wrap: nowrap; +} + +.panel-header > .panel-header__title:first-child { + padding-left: 0.5rem; +} + +.panel-header__actions { + margin-left: auto; +} + +.panel-body { + padding: 0.5rem 1rem; +} + + +.detail-panel .panel-body { + flex: 1; + display: flex; + flex-direction: column; + overflow-y: auto; + min-height: 0; + padding: 0; +} + +.detail-section__header { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.detail-section__title { + margin: 0; + font-weight: 600; + flex: 1; + min-width: 0; +} + +.quick-add { + display: inline-flex; + align-items: center; + position: relative; +} + +.quick-add__trigger { + white-space: nowrap; +} + +.documents-sort__trigger.quick-add__trigger { + padding: 0.25rem 0.5rem; + min-height: 2.1rem; +} + +.quick-add__chip { + display: inline-flex; + align-items: center; + gap: 0.35rem; + white-space: nowrap; + border: 1px dashed var(--border); + border-radius: 999px; + padding: 0.18rem 0.6rem; + font-size: 0.85rem; + background: transparent; + color: var(--muted); + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; +} + +.quick-add__chip:hover, +.quick-add__chip:focus-visible { + border-style: solid; + background: var(--selection-soft); + color: var(--fg); + outline: none; +} + +.quick-add__chip .icon-inline { + width: 1rem; + height: 1rem; +} + +.quick-add__chip-label { + display: inline-flex; + align-items: center; + gap: 0.25rem; +} + +.quick-add__menu { + padding: 0.25rem 0; +} + +.quick-add__form { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + border-bottom: 1px solid var(--border); +} + +.quick-add__form input { + flex: 1; + min-width: 0; +} + +.quick-add__list { + max-height: 240px; + overflow-y: auto; +} + +.quick-add__option { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.quick-add__swatch { + width: 0.75rem; + height: 0.75rem; + border-radius: 9999px; + border: 1px solid var(--border); + background: var(--surface-subtle); +} + +.selection-assignment { + display: inline-flex; + position: relative; +} + +.selection-assignment__menu { + font-size: 0.95rem; + font-weight: 400; + padding: 0.4rem 0; + max-width: min(22rem, 90vw); +} + +.selection-assignment__header { + padding: 0.4rem 0.75rem 0.3rem; + border-bottom: 1px solid var(--border-subtle); +} + +.selection-assignment__header input { + width: 100%; + padding: 0.35rem 0.6rem; + border: 1px solid var(--border-subtle); + border-radius: 0.5rem; + background: var(--surface-subtle); + color: var(--fg); + font-size: 0.95rem; +} + +.selection-assignment__header input:focus-visible { + outline: none; + border-color: var(--selection-border); + box-shadow: 0 0 0 2px color-mix(in oklch, var(--selection) 25%, transparent); +} + +.selection-assignment__list { + max-height: 240px; + overflow-y: auto; +} + +.selection-assignment__item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + font-weight: 400; +} + +.selection-assignment__label { + flex: 1 1 auto; + display: inline-flex; + align-items: center; + gap: 0.25rem; +} + +.selection-assignment__spinner { + margin-left: 0.4rem; +} + +.selection-assignment__label--nowrap { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.selection-assignment__indent { + display: inline-block; + flex: 0 0 auto; +} + +.selection-assignment__folder-label { + display: inline-flex; + flex-direction: column; + gap: 0.15rem; + min-width: 0; + max-width: 16rem; +} + +.selection-assignment__folder-name { + font-weight: 500; + color: var(--fg); + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.selection-assignment__folder-path { + font-size: 0.8rem; + color: var(--muted); + white-space: normal; + word-break: break-word; +} + +.selection-assignment__slash { + color: var(--muted); + margin: 0 0.25rem; +} + +.selection-assignment__segment { + display: inline-block; +} + +.selection-assignment__item--all .selection-assignment__icon { + color: var(--success); +} + +.selection-assignment__item--partial .selection-assignment__icon { + color: var(--warning); +} + +.selection-assignment__icon { + width: 1rem; + height: 1rem; + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.selection-assignment__icon--empty { + border: 1px solid var(--border-subtle); + border-radius: 999px; + opacity: 0.6; +} + +.selection-assignment__label { + flex: 1 1 auto; + min-width: 0; + text-align: left; + font-weight: 400; +} + +.selection-assignment__count { + font-size: 0.8rem; + color: var(--muted); +} + +.selection-assignment__empty { + padding: 0.75rem; +} + +.selection-assignment__create { + border-top: 1px solid var(--border-subtle); + display: flex; + align-items: center; + gap: 0.5rem; +} + + +.preview-pane { + margin-top: 0.4rem; + background: transparent; + display: flex; + flex-direction: column; + gap: 1.25rem; + min-height: 0; + flex: 1; + overflow: auto; + position: relative; + padding: 1.25rem; +} + +.preview-pane__media { + border-radius: 0; + background: transparent; + min-height: 220px; + display: flex; + align-items: center; + justify-content: center; + overflow: visible; + position: relative; +} + +.preview-image { + width: 100%; + max-width: 360px; + max-height: 100%; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + pointer-events: auto; + position: relative; +} + +.preview-image__content { + display: block; + width: 100%; + height: auto; + max-width: 100%; + max-height: 100%; + object-fit: contain; + background: transparent; + cursor: pointer; + transition: + outline-color 120ms ease, + box-shadow 120ms ease, + filter 120ms ease, + background-color 120ms ease; + outline: 2px solid transparent; + outline-offset: -2px; +} + +.preview-image__content:hover, +.preview-image__content:focus-visible { + outline-color: var(--accent-focus); + box-shadow: + inset 0 0 0 999px var(--accent-elevated), + 0 6px 18px var(--accent-elevated-strong); +} + +.thumbnail-preview { + display: flex; + flex-direction: column; + gap: 0.32rem; + margin: 0.4rem 0 0.6rem; +} + +.thumbnail-image { + max-width: 100%; + border-radius: 0; + box-shadow: none; +} + +.detail-panel .meta, +.document-summary .meta { + font-size: 0.9rem; + color: var(--muted); + margin: 0.5rem 0; +} + +.detail-panel .detail-folder-path, +.document-summary .detail-folder-path { + display: inline-flex; + flex-wrap: wrap; + gap: 0.25rem; + align-items: center; +} + +.detail-folder-path--block { + display: flex; + gap: 0.25rem; + flex-wrap: wrap; + align-items: center; + margin: 0.5rem 0; +} + +.detail-panel .detail-folder-path__link, +.document-summary .detail-folder-path__link { + color: var(--accent); + text-decoration: none; +} + +.detail-panel .detail-folder-path__link:hover, +.detail-panel .detail-folder-path__link:focus-visible, +.document-summary .detail-folder-path__link:hover, +.document-summary .detail-folder-path__link:focus-visible { + text-decoration: underline; + outline: none; +} + +.detail-panel .detail-folder-path__separator, +.document-summary .detail-folder-path__separator { + color: var(--muted); +} + +.detail-panel .detail-folder-path__segment, +.document-summary .detail-folder-path__segment { + color: var(--fg); +} + +.detail-panel .doc-title-row, +.document-summary .doc-title-row { + display: flex; + flex-direction: column; + gap: 0.35rem; + margin: 0.25rem 0 1.25rem; + max-width: 100%; + word-break: break-word; +} + +.doc-title-row__primary { + display: flex; + align-items: center; + gap: 0.4rem; + width: 100%; +} + +.doc-title-row__title { + margin: 0; +} + +.doc-title-row__path { + font-size: 0.85rem; + color: var(--muted); + display: flex; + flex-wrap: wrap; + gap: 0.25rem; +} + +.detail-panel .doc-title-edit, +.document-summary .doc-title-edit { + display: flex; + align-items: center; + gap: 0.4rem; + width: 100%; +} + +.detail-panel .doc-title-edit input, +.document-summary .doc-title-edit input { + flex: 1; + min-width: 0; +} + +.status-inline { + font-size: 0.85rem; + margin-top: 0.2rem; +} + +.detail-meta { + display: flex; + flex-direction: column; + gap: 0.35rem; + margin: 1rem 0; +} + +.detail-meta__row { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.9rem; + color: var(--muted); +} + +.detail-meta__label { + font-weight: 600; + color: var(--fg); +} + +.detail-meta__value { + color: var(--fg); +} + +.detail-meta__row > .icon-button { + margin: -0.25rem; +} + +.doc-issued-row { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.9rem; + color: var(--muted); + margin: 0.25rem 0 0.5rem; +} + +.doc-issued-row__label { + font-weight: 600; + color: var(--fg); +} + +.doc-issued-row__value { + color: var(--fg); +} + +.doc-issued-edit { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.doc-issued-edit input[type='date'] { + font: inherit; + padding: 0.35rem 0.5rem; +} + +.status-inline.error { + color: var(--danger); +} + +.bulk-detail-actions { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin: 0.6rem 0; +} + +.bulk-detail-actions .inline { + display: flex; + gap: 0.4rem; +} + +.bulk-move { + display: flex; + flex-direction: column; + gap: 0.3rem; + margin: 0.6rem 0; +} + +.bulk-move select { + max-width: 100%; +} + +.preview-stack { + position: relative; + display: flex; + align-items: center; + justify-content: center; +} + +.preview-stack--stacked { + width: 100%; + min-height: 420px; + flex-shrink: 0; +} + +.preview-stack--empty { + width: 100%; + min-height: 420px; + flex-shrink: 0; +} + +.preview-stack__item { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + transition: transform 120ms ease; + filter: drop-shadow(0 2px 6px var(--shadow-soft)); + transform-origin: center; + border-radius: 6px; + pointer-events: none; +} + +.preview-stack .preview-stack__item.orientation-portrait { + width: 80%; + height: 100%; +} + +.preview-stack .preview-stack__item.orientation-landscape { + width: 100%; + height: 80%; +} + +.preview-pane__unsupported { + width: 100%; + max-width: 320px; + display: flex; + flex-direction: column; + gap: 0.6rem; + align-items: center; + text-align: center; + padding: 1.5rem; + border-radius: 8px; + background: var(--surface-subtle); + color: var(--fg); +} + +.preview-pane__unsupported-message { + font-size: 0.95rem; + font-weight: 500; +} + +.preview-pane__unsupported-filename { + font-size: 0.85rem; + color: var(--muted); + word-break: break-word; +} + +.preview-pane__unsupported-download { + font-weight: 600; +} + +.preview-pane__unsupported-download svg { + width: 1rem; + height: 1rem; +} + +.preview-pane--stack { + min-height: 460px; + position: relative; + --preview-nav-scale: 1; +} + +.preview-pane__nav-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.2em; + height: 2.2em; + padding: 0.45em; + border-radius: 999px; + background: var(--preview-nav-bg); + color: var(--preview-nav-fg); + cursor: pointer; + transition: background 0.15s ease, opacity 0.15s ease; + pointer-events: auto; +} + +.preview-pane__nav-button:hover:not([disabled]) { + background: var(--preview-nav-bg-hover); +} + +.preview-pane__nav-button:disabled { + opacity: 0.4; + cursor: default; +} + +.preview-pane__nav-button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.preview-pane__nav { + margin-top: 0.5rem; + display: flex; + justify-content: center; + gap: 0.5rem; +} + +.preview-pane__nav--overlay { + position: absolute; + bottom: 0.75rem; + left: 50%; + transform: translateX(-50%) scale(var(--preview-nav-scale, 1)); + margin-top: 0; + pointer-events: none; + z-index: 20; + opacity: 0; + transition: opacity 0.2s ease; +} + +.preview-pane__nav--overlay .preview-pane__nav-button { + pointer-events: auto; + transform: scale(calc(1 / var(--preview-nav-scale, 1))); +} + +.preview-pane__media:hover .preview-pane__nav--overlay, +.desk-item__card:hover .preview-pane__nav--overlay { + opacity: 1; +} + +.desk-card__nav { + bottom: 0.5rem; +} + +.bulk-tags { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + margin: 0.4rem 0 0.6rem; +} + +.detail-field { + margin: 0.9rem 0; +} + +.detail-field__label { + font-weight: 600; + margin-bottom: 0.25rem; +} + +.detail-field__value { + display: flex; + align-items: center; + gap: 0.5rem; + flex-wrap: wrap; + margin-bottom: 0.5rem; +} + +.detail-field__value .meta { + color: var(--muted); +} + +.detail-panel dl { + margin: 0; +} + +.detail-panel dt { + font-weight: 600; + margin-top: 0.8rem; +} + +.detail-panel dd { + margin: 0.2rem 0 0; +} + +.detail-panel .tag-list, +.document-summary .tag-list, +.correspondent-list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 1rem 0; + align-items: center; +} + +.tag-list__empty { + color: var(--muted); +} + +.detail-metadata__block { + display: flex; + flex-direction: column; + gap: 0.35rem; + padding: 0.75rem 0; + border-top: 1px solid var(--border); +} diff --git a/frontend/src/styles/documents/controls.css b/frontend/src/styles/documents/controls.css new file mode 100644 index 0000000..8c5c8ac --- /dev/null +++ b/frontend/src/styles/documents/controls.css @@ -0,0 +1,108 @@ +.view-toggle { + display: inline-flex; + align-items: center; + gap: 0.25rem; +} + +.view-toggle__button { + border: 1px solid var(--border); + background: transparent; + color: var(--muted); + padding: 0.3rem 0.6rem; + border-radius: 4px; + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; +} + +.view-toggle__button:hover, +.view-toggle__button:focus-visible { + background: var(--surface-subtle); + color: var(--fg); + outline: none; +} + +.view-toggle__button.active { + background: var(--accent); + color: var(--on-accent); + border-color: var(--accent); +} + +.view-toggle__icon { + width: 1.4rem; + height: 1.4rem; +} + +.documents-actions__sort-group { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.documents-sort { + display: inline-flex; + align-items: center; + position: relative; +} + +.documents-sort__trigger { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.85rem; + white-space: nowrap; + padding: 0.25rem 0.5rem; + min-height: 2.1rem; +} + +.documents-sort__label { + display: inline-flex; + align-items: center; + line-height: 1.1; +} + +.documents-sort__trigger-content { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.documents-sort__quickmenu .menu__item, +.documents-sort__quickmenu .menu__item.active { + font-weight: 400; +} + +.documents-toolbar__toggle { + border: 1px solid var(--border); + border-radius: 4px; + padding: 0.3rem; + background: transparent; + color: var(--muted); + transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; +} + +.documents-toolbar__toggle:hover:not([disabled]) { + color: var(--fg); + border-color: var(--border); +} + +.documents-toolbar__toggle[aria-pressed='true'] { + border-color: var(--accent); + color: var(--accent); + background: var(--surface-subtle); +} + +.documents-sort__direction { + padding: 0.3rem 0.45rem; +} + +.documents-sort__direction[aria-pressed='true'] { + border-color: var(--border); + color: var(--muted); + background: transparent; +} + +.documents-sort__direction svg { + width: 1.1rem; + height: 1.1rem; +} + diff --git a/frontend/src/styles/documents/listing.css b/frontend/src/styles/documents/listing.css new file mode 100644 index 0000000..751336e --- /dev/null +++ b/frontend/src/styles/documents/listing.css @@ -0,0 +1,736 @@ +.documents-panel { + padding: 0 0.75rem 0.75rem 0.75rem; + display: flex; + flex-direction: column; + min-height: 0; +} + +.tags-panel, +.correspondents-panel { + padding: 1.25rem; + display: flex; + flex-direction: column; + min-height: 0; +} + +.folder-row.is-drop-target { + outline: 2px dashed var(--accent); + outline-offset: 2px; +} + +.documents-panel .panel-section__header { + display: flex; + align-items: center; + justify-content: space-between; + position: relative; +} + +.documents-panel .panel-section__header .header-actions { + display: flex; + gap: 0.5rem; +} + +.documents-panel__title { + display: flex; + align-items: center; + gap: 0.35rem; + margin: 0; + font-size: 0.9rem; + font-weight: 600; + min-width: 0; + white-space: nowrap; + overflow: hidden; +} + +.documents-panel__breadcrumbs { + flex: 1 1 auto; + overflow: hidden; +} + +.documents-panel .panel-section__body { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.panel-floating { + position: absolute; + top: calc(50% + 0.25rem); + left: 50%; + transform: translate(-50%, -50%); + background: color-mix(in oklch, var(--surface) 100%, transparent); + border: 1px solid color-mix(in oklch, var(--border) 95%, transparent); + padding: 0.45rem 0.85rem; + border-radius: 1rem; + font-size: 0.95rem; + font-weight: 400; + color: var(--fg); + box-shadow: 0 2px 6px color-mix(in oklch, var(--shadow-soft) 60%, transparent); + pointer-events: auto; + display: flex; + align-items: center; + justify-content: center; + flex-wrap: nowrap; + gap: 0.75rem; + z-index: 2000000; +} + +.panel-floating__label { + white-space: nowrap; + pointer-events: none; + font-size: 0.95rem; + color: var(--fg); +} + +.selection-summary { + display: inline-flex; + align-items: center; + gap: 0.4rem; +} + +.selection-summary__token { + display: inline-flex; + align-items: center; + gap: 0.3rem; +} + +.selection-summary__count { + font-weight: 600; + font-variant-numeric: tabular-nums; +} + +.selection-summary__icon { + width: 1rem; + height: 1rem; +} + +.selection-summary--text { + font-weight: 600; +} + +.selection-summary__separator { + opacity: 0.45; +} + +.panel-floating-actions { + display: inline-flex; + align-items: center; + gap: 0.4rem; + flex-wrap: nowrap; + pointer-events: auto; +} + +.panel-floating-actions .quick-add { + pointer-events: auto; +} + +.panel-floating-actions .quick-add__trigger { + pointer-events: auto; +} + +.panel-floating-actions .quick-add__trigger[disabled] { + opacity: 0.45; + cursor: not-allowed; +} + +.panel-floating-actions__button { + display: inline-flex; + align-items: center; + gap: 0; + pointer-events: auto; + font-size: 1.35rem; +} + +.panel-floating-actions__button .icon-inline { + display: inline-flex; + width: 1.35rem; + height: 1.35rem; +} + +.documents-panel .documents-scroll { + overflow-y: auto; + background: transparent; + min-height: 0; + padding-right: 0.3rem; + flex-grow: 1; +} + +.documents-panel .documents-scroll:focus-visible { + outline: 2px solid var(--selection-ring); + outline-offset: 2px; + border-radius: 0.25rem; +} + +.documents-panel table { + max-width: 100%; + border-collapse: collapse; + font-size: 0.88rem; + margin-top: 0.4rem; +} + +.documents-panel thead th { + background-color: var(--surface); + position: sticky; + top: 0; + z-index: 1; + padding: 0.45rem 0.6rem; + color: var(--muted); +} + + +.documents-panel th, +.documents-panel td { + padding: 0.45rem 0.6rem; + text-align: left; +} + +.documents-panel--view-grid .documents-scroll { + padding: 0.35rem 0.5rem 1rem; +} + +.documents-panel th.thumb-column, +.documents-panel td.thumb-cell { + width: 54px; + text-align: center; +} + +.documents-panel--view-grid .document-thumbnail-wrapper { + width: var(--documents-grid-icon-size); + height: var(--documents-grid-icon-size); + padding: 8px; + border-radius: 10px; + display: flex; + justify-content: center; + align-items: center; +} + +.documents-panel--view-grid .folder-card__icon { + width: var(--documents-grid-icon-size); + height: var(--documents-grid-icon-size); + padding: 8px; + border-radius: 10px; + display: flex; + justify-content: center; + align-items: center; +} + +.document-thumbnail-inner { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.document-thumbnail-inner--multipage::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 24px; + height: 24px; + background-image: url('../../assets/papercorner.svg'); + background-repeat: no-repeat; + background-size: contain; + pointer-events: none; +} + +.documents-panel--view-grid .document-thumbnail-inner--multipage::after { + width: 28px; + height: 28px; +} + +.document-thumbnail { + max-width: 100%; + max-height: 100%; + box-shadow: 0 1px 6px var(--shadow-medium); +} + +.documents-panel--view-grid .document-thumbnail { + box-shadow: 0 1px 12px var(--shadow-medium); +} + +.thumb-placeholder { + width: 100%; + height: 100%; + border-radius: 1px; + background: var(--surface-subtle); + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.68rem; + font-weight: 600; + letter-spacing: 0.08em; + box-shadow: 0 1px 3px var(--shadow-medium); +} + +.documents-panel--view-grid .thumb-placeholder { + font-size: 1.1rem; + letter-spacing: 0.12em; + display: inline-flex; + width: 100%; + height: 100%; +} + +.thumb-icon { + width: 100%; + height: 100%; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.thumb-icon__image { + width: 32px; + height: 32px; + display: block; +} + +.documents-panel th.actions-column, +.documents-panel td.actions { + width: 1%; + white-space: nowrap; +} + +.documents-panel td.doc-list__name { + width: 100%; +} + +.doc-title-edit { + display: inline-flex; + align-items: center; + gap: 0.35rem; + flex-wrap: nowrap; +} + +.doc-title-edit input[type='text'] { + padding: 0.3rem 0.55rem; + border-radius: 4px; + border: 1px solid var(--border); + background: var(--surface); + color: var(--fg); + min-width: 8rem; +} + +.doc-title-edit input[type='text']:focus-visible { + outline: 2px solid var(--selection-ring); + outline-offset: 1px; +} + +.doc-title-edit .icon-button { + flex-shrink: 0; +} + +.documents-panel .doc-name__primary { + display: inline-flex; + align-items: center; + gap: 0.35rem; + flex-wrap: wrap; +} + +.documents-panel .doc-name__primary-text { + overflow-wrap: anywhere; +} + + +.doc-entry { + display: flex; + align-items: center; + gap: 0.6rem; +} + +.doc-entry--with-thumb .doc-entry__thumb { + flex: 0 0 auto; + display: flex; + align-items: center; + justify-content: center; +} + +.doc-entry__thumb .document-thumbnail-wrapper { + display: flex; + align-items: center; + justify-content: center; +} + +.doc-entry__main { + display: flex; + flex-direction: column; + gap: 0.35rem; + min-width: 0; +} + +.doc-entry__name { + font-weight: 600; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 100%; +} + +.doc-entry__tags { + display: flex; + flex-wrap: wrap; + gap: 0.3rem; +} + +.documents-panel td.actions .action-buttons { + display: inline-flex; + align-items: center; + gap: 0.3rem; +} + +.documents-panel tbody tr { + background: transparent; + transition: background 0.15s ease; +} + +.documents-panel tbody tr.folder { + cursor: pointer; +} + +.documents-panel tbody tr.folder.focused { + box-shadow: inset 2px 0 0 var(--accent-outline); + background: var(--sidebar-hover-bg); +} + +.documents-panel tbody tr.document { + cursor: pointer; +} + +.documents-panel tbody tr.document.selected, +.documents-panel tbody tr.folder.selected { + background: var(--selection-soft); + box-shadow: inset 2px 0 0 var(--accent-outline-strong); +} + +.documents-panel tbody tr.document, +.documents-panel tbody tr.document * { + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; +} + +.documents-panel tbody tr.document.focused:not(.selected) { + box-shadow: inset 2px 0 0 var(--accent-outline); +} + +.doc-name { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.documents-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(var(--documents-grid-icon-size), 1fr)); + gap: 0.3rem 1.3rem; + padding: 0; +} + +.document-card { + padding: 0rem; + display: flex; + flex-direction: column; + gap: 0.3rem; + cursor: pointer; + align-items: center; + text-align: center; +} + +.document-card.selected .document-thumbnail-wrapper, +.folder-card.selected .folder-card__icon { + background-color: var(--selection-soft); +} + +.document-card:focus-visible .document-thumbnail-wrapper { + background-color: var(--selection-ring); +} + +.document-card.is-dragging { + opacity: 0.55; +} + +.document-card__meta { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.35rem; + width: 100%; +} + +.document-card__title { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.35rem; + color: var(--fg); +} + +.document-card__title-row { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.35rem; + flex-wrap: wrap; +} + +.document-card__title-badge { + padding: 0.2rem 0.7rem; + border-radius: 1rem; + max-width: 100%; + word-break: break-word; + font-size: var(--documents-grid-title-size); + color: inherit; +} + +.document-card .doc-correspondent-link { + font-size: var(--documents-grid-title-size); +} + +.document-card.selected .document-card__title-badge { + background-color: var(--accent); + color: var(--on-accent); +} + +.document-card__subtitle { + font-size: 0.78rem; + color: var(--muted); +} + +.document-card__tags { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + justify-content: center; +} + +.folder-card { + align-items: center; + text-align: center; +} + +.folder-card__icon { + display: flex; + align-items: center; + justify-content: center; + width: var(--documents-grid-icon-size); + height: var(--documents-grid-icon-size); +} + +.folder-card__icon-svg { + width: 100%; + height: 100%; + object-fit: contain; +} + +.folder-card__meta { + display: flex; + flex-direction: column; + gap: 0.28rem; + padding-top: 0.35rem; +} + +.folder-card__label-row { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.35rem; + flex-wrap: wrap; +} + +.folder-card__name { + color: var(--fg); + overflow: hidden; + text-overflow: ellipsis; + white-space: break-word; + font-size: var(--documents-grid-title-size); + padding: 0.2rem 0.7rem; + border-radius: 1rem; +} + +.folder-card__edit { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.35rem; +} + +.folder-card.selected .folder-card__name { + background-color: var(--accent); + color: var(--on-accent); +} + + +.doc-name__title { + max-width: 100%; + word-break: break-word; +} + +.doc-name__tags { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; +} + +.doc-correspondents { + display: inline; + color: inherit; +} + +.doc-correspondent-link { + background: none; + background-color: transparent; + border: none; + padding: 0; + margin: 0; + color: var(--accent); + text-decoration: none; + font: inherit; + cursor: pointer; + box-shadow: none; + appearance: none; +} + +.doc-correspondent-link:not(.is-static):hover, +.doc-correspondent-link:not(.is-static):focus-visible { + color: var(--accent-strong, var(--accent)); + text-decoration: underline; + text-decoration-thickness: 1.5px; + background-color: transparent; +} + +.doc-correspondent-link:not(.is-static):focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; +} + +.documents-panel tbody tr.document.selected .doc-correspondents, +.documents-panel tbody tr.document.selected .doc-correspondent-link, +.document-card.selected .doc-correspondent-link { + color: inherit; +} + +.document-card.selected .doc-correspondents { + color: inherit; +} + +.doc-correspondent-link.is-active { + font-weight: 600; +} + +.doc-correspondent-link.is-static { + color: inherit; + cursor: default; + text-decoration: none; +} + +.doc-correspondent-link__separator { + color: inherit; +} + +.documents-panel tbody tr.document.dragging { + opacity: 0.4; +} + +.documents-panel tbody tr.document.tag-drop-target { + background: var(--accent-soft); + box-shadow: inset 0 0 0 2px var(--accent); +} + +.document-card.tag-drop-target { + box-shadow: 0 0 0 2px var(--accent); + border-color: var(--accent); +} + +.document-card.tag-drop-target .document-card__title { + color: var(--accent); +} + +.filter-bar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.32rem; + margin-bottom: 0.5rem; +} + +.filter-bar input[type='search'] { + flex: 1; + min-width: 180px; +} + +.filter-actions { + display: flex; + gap: 0.32rem; +} + +.search-hint { + margin-top: 0.75rem; + font-size: 0.85rem; + color: var(--muted); +} + +.badge { + display: inline-flex; + align-items: center; + padding: 0.15rem 0.35rem; + border-radius: 2px; + background: var(--surface-subtle); + color: var(--fg); + font-size: 0.74rem; +} + +.tag-chip { + gap: 0.25rem; + border-radius: 1rem; + padding: 0.2rem 0.4rem; + font-weight: 600; +} + +.tag-chip--more { + background: transparent; + border-color: var(--border-strong); + color: var(--muted); +} + +.tag-chip--removable { + gap: 0.35rem; +} + +.tag-chip__remove { + background: none; + border: none; + color: inherit; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; + cursor: pointer; + opacity: 0.8; +} + +.tag-chip__remove:hover, +.tag-chip__remove:focus-visible { + opacity: 1; +} + +.tag-chip__remove:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; + border-radius: 50%; +} + +.empty-state { + border: 1px dashed var(--border); + border-radius: 0; + text-align: center; + padding: 1.1rem 0.9rem; + color: var(--muted); + margin-top: 0.75rem; + background: var(--surface-subtle); +} + +.empty-state--global { + border-style: solid; +} diff --git a/frontend/src/styles/documents/panel-sections.css b/frontend/src/styles/documents/panel-sections.css new file mode 100644 index 0000000..de07a4f --- /dev/null +++ b/frontend/src/styles/documents/panel-sections.css @@ -0,0 +1,133 @@ +.document-viewer__message { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: var(--on-accent); + background: var(--overlay-dark); + padding: 0.5rem 1rem; + border-radius: 999px; + font-size: 0.9rem; +} + +.panel-section__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + padding: 0 0 0.5rem; +} + +.panel-section__titles { + display: flex; + flex-direction: column; + gap: 0.3rem; +} + +.panel-section__header h2 { + margin: 0; + font-size: 0.9rem; + font-weight: 600; +} + +.documents-panel__title { + display: flex; + align-items: center; + gap: 0.35rem; + margin: 0; + font-size: 0.9rem; + font-weight: 600; + min-width: 0; + flex-wrap: nowrap; + overflow: hidden; +} + +.panel-section__subtitle { + margin-top: 0.25rem; + font-size: 0.78rem; + color: var(--muted); +} + +.breadcrumb-trail { + display: flex; + align-items: center; + gap: 0.35rem; + flex-wrap: nowrap; + min-width: 0; + flex: 1 1 auto; + max-width: 100%; + overflow: hidden; +} + +.breadcrumb-trail--measure { + position: absolute; + visibility: hidden; + pointer-events: none; + left: -9999px; + top: -9999px; + max-width: none; + overflow: visible; +} + +.breadcrumb-trail__link { + display: inline-flex; + align-items: center; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border: none; + background: none; + padding: 0; + font: inherit; + color: inherit; + cursor: default; +} + +.breadcrumb-trail__link:not(.is-current) { + cursor: pointer; + color: var(--accent); +} + +.breadcrumb-trail__link:not(.is-current):hover, +.breadcrumb-trail__link:not(.is-current):focus-visible { + text-decoration: underline; +} + +.breadcrumb-trail__separator { + color: var(--muted); + margin: 0 0.2rem; +} + +.breadcrumb-trail__ellipsis { + position: relative; + display: inline-flex; +} + +.breadcrumb-trail__ellipsis-button { + cursor: pointer; +} + +.documents-panel__breadcrumbs { + flex: 1 1 auto; + min-width: 0; + max-width: 100%; + overflow: hidden; +} + +.documents-panel__breadcrumbs { + max-width: 22rem; +} + +.panel-section__body { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} + +.panel-section__body--scrollable, +.panel-section__body.scrollable { + overflow-y: auto; +} + diff --git a/frontend/src/styles/documents/shared-snippets.css b/frontend/src/styles/documents/shared-snippets.css new file mode 100644 index 0000000..e03be4e --- /dev/null +++ b/frontend/src/styles/documents/shared-snippets.css @@ -0,0 +1,26 @@ +.doc-list__name { + width: 100%; +} + +.doc-list__name-content { + display: inline-flex; + align-items: center; + gap: 0.22rem; + max-width: 100%; +} + +.doc-list__name-content span { + max-width: 100%; + overflow-wrap: anywhere; + word-break: break-word; +} + +.preview-pane__nav-button svg { + width: 100%; + height: 100%; +} + +.panel-header .icon-button svg { + width: 1.41rem; + height: 1.41rem; +} diff --git a/frontend/src/styles/documents/tags-correspondents.css b/frontend/src/styles/documents/tags-correspondents.css new file mode 100644 index 0000000..9fd9b87 --- /dev/null +++ b/frontend/src/styles/documents/tags-correspondents.css @@ -0,0 +1,173 @@ +.tags-panel__body { + overflow-y: auto; +} + +.tags-table { + width: 100%; + overflow: auto; +} + +.tags-table table { + width: 100%; + border-collapse: collapse; + min-width: 320px; +} + +.tags-table th, +.tags-table td { + padding: 0.45rem 0.6rem; + text-align: left; + font-size: 0.85rem; +} + +.tags-table th.numeric, +.tags-table td.numeric { + text-align: right; +} + +.tags-table th.actions, +.tags-table td.actions { + text-align: right; + width: 0; +} + +.tags-table tbody tr:hover { + background: var(--surface-subtle); +} + +.tags-table tr.editing { + background: var(--sidebar-hover-bg); +} + +.tags-table__label { + max-width: 24rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.tags-table__swatch { + display: inline-block; + width: 1rem; + height: 1rem; + border-radius: 2px; + box-shadow: inset 0 0 0 1px var(--shadow-faint); +} + +.tags-panel__error { + margin: 0.5rem 0; + color: var(--danger); + font-size: 0.8rem; +} + +.tags-table__label-input { + width: 100%; +} + +.tags-table__color-editor { + display: flex; + align-items: center; + gap: 0.4rem; +} + +.tags-table__color-picker { + width: 2.25rem; + height: 2.25rem; + padding: 0; + background: none; + cursor: pointer; +} + +.tags-table__edit-controls { + display: flex; + justify-content: flex-start; + padding: 0.25rem; + gap: 0.4rem; +} + +.tags-table__row-actions { + display: flex; + justify-content: flex-start; + padding: 0.25rem; + gap: 0.4rem; +} + +.correspondents-panel .header-actions { + gap: 0.5rem; +} + +.tags-actions { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; + align-items: center; +} + +.tags-actions__form { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.4rem; +} + +.tags-actions__form input[type='text'] { + min-width: 14rem; +} + +.correspondents-actions__form { + display: flex; + gap: 0.4rem; +} + +.correspondents-actions__form input { + min-width: 14rem; +} + + + +.correspondent-pill { + display: inline-flex; + align-items: center; + gap: 0.35rem; + background: var(--surface-subtle); + border-radius: 999px; + padding: 0.15rem 0.5rem; + font-size: 0.9rem; + border: none; +} + +.correspondent-pill__label { + line-height: 1.2; +} + +.correspondent-pill__label strong { + font-size: 0.8rem; + text-transform: capitalize; + color: var(--muted); +} + +.correspondent-pill__remove { + border: none; + background: none; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--muted); + padding: 0; +} + +.correspondent-pill__remove:hover { + color: var(--danger); +} + +.correspondent-form { + display: flex; + gap: 0.4rem; + align-items: center; +} + +.correspondent-form input, +.correspondent-form select { + min-height: 32px; +} diff --git a/frontend/src/styles/documents/viewer.css b/frontend/src/styles/documents/viewer.css new file mode 100644 index 0000000..74af8df --- /dev/null +++ b/frontend/src/styles/documents/viewer.css @@ -0,0 +1,335 @@ +.document-viewer { + flex: 1; + display: grid; + grid-template-columns: minmax(0, 30em) minmax(0, 1fr); + gap: 1rem; + min-height: 0; + padding: 1rem 1rem; +} + +.document-drag-preview { + position: fixed; + pointer-events: none; + top: -9999px; + left: -9999px; + width: var(--drag-preview-size, 96px); + height: var(--drag-preview-size, 96px); + z-index: 9999; +} + +.document-drag-preview__thumb { + position: absolute; + top: 50%; + left: 50%; + width: 64px; + height: 64px; + border-radius: 6px; + box-shadow: 0 6px 12px var(--shadow-pop); + overflow: hidden; + background-color: var(--overlay-dim); + display: flex; + align-items: center; + justify-content: center; + color: #fff; + font-weight: 600; + font-size: 0.8rem; + text-transform: uppercase; + transform: translate(-50%, -50%) rotate(var(--rotation-deg, 0deg)); + transform-origin: center; +} + +.document-drag-preview__thumb--image { + background-color: #000; + background-repeat: no-repeat; + background-size: contain; + background-position: center; +} + +.document-drag-preview__thumb .document-thumbnail, +.document-drag-preview__thumb img { + width: 100%; + height: 100%; + object-fit: cover; + pointer-events: none; +} + +.document-drag-preview__thumb .thumb-placeholder, +.document-drag-preview__thumb .thumb-placeholder * { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +} + +.document-drag-preview__folder-thumb { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +} + +.document-drag-preview__folder-thumb svg { + width: 48px; + height: 48px; + color: var(--accent-strong, var(--accent)); +} + +.document-drag-preview__folder-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--text-on-dark); +} + +.document-drag-preview__count { + position: absolute; + bottom: 4px; + right: 4px; + background-color: var(--accent); + color: var(--on-accent); + border-radius: 999px; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-weight: 600; + box-shadow: 0 4px 8px var(--shadow-pop); + pointer-events: none; +} + +.document-viewer__details { + display: flex; + flex-direction: column; + gap: 0.5rem; + min-height: 0; + flex: 1; +} + +.document-viewer__details-pane { + display: flex; + flex-direction: column; + min-height: 0; + overflow: auto; + flex: 1; +} +.document-viewer__tabs-wrapper { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; +} + +.document-viewer__section { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; + padding-top: 1rem; +} + +.document-viewer__section-title { + margin: 0; + font-size: 0.95rem; + font-weight: 600; + letter-spacing: 0.01em; +} + +.document-viewer__section-list { + margin: 0; + padding: 0; + list-style: none; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 0.75rem 1.25rem; +} + +.document-viewer__section-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.document-viewer__section-item dt { + font-size: 0.75rem; + color: var(--muted); +} + +.document-viewer__section-item dd { + margin: 0; + font-size: 0.9rem; + font-weight: 500; + word-break: break-word; +} + +.document-viewer__section-placeholder { + margin: 0; + font-size: 0.9rem; + color: var(--muted); +} + +.document-viewer__section-payload { + font-size: 0.85rem; +} + +.document-viewer__section-payload summary { + cursor: pointer; + font-weight: 500; + color: var(--accent-strong, var(--accent)); +} + +.document-viewer__section-payload pre { + margin: 0.75rem 0 0; + padding: 0.75rem; + background: var(--surface); + max-height: 280px; + overflow: auto; + font-size: 0.8rem; +} + +.document-viewer__section--metadata-json { + overflow: auto; +} + +.document-viewer__metadata-json { + margin: 0; + padding: 0.75rem; + background: var(--surface); + border-radius: 0.5rem; + font-size: 0.85rem; + line-height: 1.35; + overflow: auto; +} + +.document-viewer__tabs { + display: inline-flex; + align-items: center; + gap: 0.5rem; + border-bottom: 1px solid var(--outline-subtle); +} + +.document-viewer__tab { + appearance: none; + border: none; + background: transparent; + padding: 0.4rem 0.75rem; + font-size: 0.85rem; + font-weight: 500; + color: var(--muted); + cursor: pointer; + border-bottom: 2px solid transparent; + transition: + color 120ms ease, + border-color 120ms ease; +} + +.document-viewer__tab:hover, +.document-viewer__tab:focus-visible { + color: var(--accent); +} + +.document-viewer__tab.is-active { + color: var(--accent); + border-color: var(--accent); +} + +.document-viewer__tabpanes { + flex: 1; + min-height: 0; + display: flex; +} + +.document-viewer__tabpanes--single { + flex: 1; + min-height: 0; +} + +.document-viewer__tabpanel { + flex: 1; + min-height: 0; + display: flex; + position: relative; +} + +.document-viewer__object--ocr { + width: 100%; + height: 100%; +} + +.document-viewer__object--ocr-text { + width: 100%; + height: 100%; + margin: 0; + padding: 1rem 0; + font-size: 1rem; + white-space: pre-wrap; + font-family: inherit; +} + +.document-viewer__message--error { + color: var(--danger); +} + +.document-viewer__viewport { + flex: 1; + min-width: 0; + display: flex; + position: relative; + overflow: hidden; + align-items: flex-start; +} + +.document-viewer__object { + width: 100%; + height: 100%; + border: none; +} + +.document-viewer__object--image { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + object-fit: contain; + align-self: flex-start; +} + +.document-viewer__unsupported { + height: 100%; + width: 100%; + padding: 2rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.75rem; + text-align: center; + background: var(--surface-subtle); +} + +.document-viewer__unsupported-filename { + font-size: 0.9rem; + color: var(--muted); +} + +.document-viewer__unsupported-message { + font-size: 0.95rem; + color: var(--fg); +} + +.document-viewer__unsupported-download { + font-weight: 600; +} + +.document-viewer__unsupported-download svg { + width: 1rem; + height: 1rem; +} + diff --git a/frontend/src/styles/forms/elements.css b/frontend/src/styles/forms/elements.css new file mode 100644 index 0000000..29a58ca --- /dev/null +++ b/frontend/src/styles/forms/elements.css @@ -0,0 +1,29 @@ +select { + font: inherit; + border-radius: 2px; + border: 1px solid var(--border); + padding: 0.4rem 0.5rem; + background: var(--surface); + color: inherit; + width: 100%; + box-sizing: border-box; +} + +input:focus, +textarea:focus, +select:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 2px var(--accent-soft); + background: var(--surface); +} + +textarea { + resize: vertical; +} + +form.inline { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css new file mode 100644 index 0000000..884e2fd --- /dev/null +++ b/frontend/src/styles/index.css @@ -0,0 +1,22 @@ +@import './base/theme.css'; +@import './base/controls.css'; +@import './layout/panel-header-controls.css'; +@import './preview/preview-zoom.css'; +@import './base/iconography.css'; +@import './documents/controls.css'; +@import './layout/structure.css'; +@import './documents/viewer.css'; +@import './documents/tags-correspondents.css'; +@import './documents/panel-sections.css'; +@import './sidebar/sidebar.css'; +@import './documents/listing.css'; +@import './detail/detail-panels.css'; +@import './forms/elements.css'; +@import './modals/status-drop.css'; +@import './settings/settings.css'; +@import './modals/panel-modals.css'; +@import './layout/responsive.css'; +@import './auth/login.css'; +@import './documents/shared-snippets.css'; +@import './uploads/overlay.css'; +@import './base/text-button.css'; diff --git a/frontend/src/styles/layout/panel-header-controls.css b/frontend/src/styles/layout/panel-header-controls.css new file mode 100644 index 0000000..7846e7c --- /dev/null +++ b/frontend/src/styles/layout/panel-header-controls.css @@ -0,0 +1,43 @@ +.panel-header .icon-button, +.panel-header button, +.panel-header a.icon-button { + display: inline-flex; + align-items: center; + justify-content: flex-start; + border: none; + background: transparent; + color: var(--muted); + padding: 0.25rem; + border-radius: 4px; + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease; + text-decoration: none; + text-align: left; +} + +.panel-header .icon-button:hover:not([disabled]), +.panel-header button:hover:not([disabled]), +.panel-header a.icon-button:hover { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.panel-header .icon-button.active:hover:not([disabled]), +.panel-header button.active:hover:not([disabled]), +.panel-header a.icon-button.active:hover { + background: var(--accent-soft); + color: var(--fg); +} + +.panel-header .icon-button.ghost, +.panel-header button.icon-button.ghost { + color: var(--muted); + padding: 0.25rem; +} + +.panel-header .icon-button.ghost:hover:not([disabled]), +.panel-header button.icon-button.ghost:hover:not([disabled]) { + color: var(--fg); + background: var(--sidebar-hover-bg); +} + diff --git a/frontend/src/styles/layout/responsive.css b/frontend/src/styles/layout/responsive.css new file mode 100644 index 0000000..a3195d5 --- /dev/null +++ b/frontend/src/styles/layout/responsive.css @@ -0,0 +1,17 @@ +@media (max-width: 768px) { + .app-bar { + flex-direction: column; + align-items: flex-start; + gap: 0.75rem; + } + .app-main { + grid-template-columns: 1fr; + } + .sidebar, + .documents-panel, + .detail-panel, + .tags-panel, + .correspondents-panel { + min-height: auto; + } +} diff --git a/frontend/src/styles/layout/structure.css b/frontend/src/styles/layout/structure.css new file mode 100644 index 0000000..4f07e1e --- /dev/null +++ b/frontend/src/styles/layout/structure.css @@ -0,0 +1,147 @@ +.app-shell { + height: 100%; + display: flex; + flex-direction: column; + color: var(--fg); +} + + +.documents-main { + flex: 1; + display: flex; + min-height: 100vh; + width: 100%; + position: relative; +} + +.documents-main--sidebar-collapsed { + position: relative; +} + +.main-content { + display: flex; + flex-direction: column; + min-height: 0; + min-width: 0; + margin: 0; + border-radius: 0; + background: var(--surface); + flex-grow: 1; + box-shadow: -12px 0 24px -12px var(--shadow-faint); +} + +.documents-main:not(.documents-main--sidebar-collapsed) .main-content { + border-left: 1px solid var(--border); +} + +.main-content__header { + padding: 0.5rem 1.25rem; + justify-content: space-between; + align-items: center; + gap: 0.75rem; +} + +.main-content__header-wrapper { + position: relative; +} + +.main-content__body { + position: relative; + flex: 1 1 auto; + display: flex; + min-height: 0; +} + +.main-content__body > * { + min-width: 0; + min-height: 0; +} + +.main-content__body > *:not(.detail-panel) { + flex: 1 1 auto; +} + +.main-content__body--workspace.main-content__body--has-detail > .desk-shell { + margin-right: calc(-1 * var(--detail-panel-width)); +} + +.main-content--has-detail { + padding-right: var(--detail-panel-width); +} + +.main-content__title { + margin: 0; + font-size: 1rem; + font-weight: 600; + color: var(--fg); +} + + +.documents-main--sidebar-collapsed { + position: relative; + grid-template-columns: auto minmax(0, 1fr); +} + +.sidebar .panel-header .icon, +.main-content__header .icon, +.detail-panel .panel-header .icon { + width: 1.35rem; + height: 1.35rem; +} + +.main-content__actions { + display: flex; + align-items: center; + gap: 0.6rem; +} + +.main-content__actions-divider { + display: inline-flex; + align-items: center; + color: var(--muted); +} + +.main-content__title { + margin: 0; + font-size: 1rem; + font-weight: 600; + color: var(--fg); + display: flex; + align-items: center; + gap: 0.5rem; + min-width: 0; + flex: 1 1 auto; + overflow: hidden; +} + +.main-content__breadcrumbs { + flex: 1 1 auto; + overflow: hidden; +} + +.main-content__subtitle { + font-size: 0.9rem; + color: var(--muted); + font-weight: 400; + line-height: 1.2; + flex-shrink: 0; +} + +.panels-main { + flex: 1; + display: flex; + justify-content: center; + padding: 1.5rem; + overflow: auto; +} + +.panels-main > * { + flex: 0 1 720px; +} + +.preview-main { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} diff --git a/frontend/src/styles/modals/panel-modals.css b/frontend/src/styles/modals/panel-modals.css new file mode 100644 index 0000000..67f6791 --- /dev/null +++ b/frontend/src/styles/modals/panel-modals.css @@ -0,0 +1,44 @@ +.panel-modal__header { + padding: 1rem 1rem 1rem 0.5rem; + border-bottom: 1px solid var(--border); +} + +.panel-modal__body { + flex: 1; + overflow: auto; + padding: 0; +} + +.modal__body { + width: 100%; +} + +.modal h3 { + margin: 0; + font-size: 1.15rem; + font-weight: 600; +} + +.modal__form { + display: flex; + flex-direction: column; + gap: 0.9rem; +} + +.modal__form label { + font-weight: 600; + font-size: 0.9rem; +} + +.modal__error { + margin: -0.45rem 0 0; + font-size: 0.85rem; + color: var(--danger); +} + +.modal__actions { + display: flex; + justify-content: flex-start; + padding: 0.25rem; + gap: 0.6rem; +} diff --git a/frontend/src/styles/modals/status-drop.css b/frontend/src/styles/modals/status-drop.css new file mode 100644 index 0000000..128e485 --- /dev/null +++ b/frontend/src/styles/modals/status-drop.css @@ -0,0 +1,77 @@ +.status-banner { + padding: 0.45rem 0.8rem; + border-radius: 2px; + font-size: 0.85rem; +} + +.status-banner.info { + background: var(--surface-subtle); + color: var(--muted); +} + +.status-banner.success { + background: var(--success-subtle); + color: var(--success); +} + +.status-banner.error { + background: var(--danger-soft); + color: var(--danger); +} + +.drop-overlay { + position: fixed; + inset: 0; + background: var(--accent-soft); + backdrop-filter: blur(4px); + display: none; + align-items: center; + justify-content: center; + z-index: 9999; +} + +.drop-overlay.active { + display: flex; +} + +.drop-overlay__content { + background: var(--surface); + color: var(--fg); + padding: 1.25rem 1.75rem; + border-radius: 2px; + text-align: center; + font-size: 0.95rem; + box-shadow: none; +} +.modal-backdrop { + position: fixed; + inset: 0; + background: var(--overlay-backdrop); + display: flex; + align-items: center; + justify-content: center; + padding: 1.5rem; + z-index: 3000; +} + +.modal { + background: var(--surface); + border-radius: 4px; + box-shadow: 0 18px 42px var(--overlay-shadow); + width: min(360px, 100%); + padding: 1.6rem; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.modal--panel { + width: 80vw; + max-width: 960px; + max-height: 90vh; + padding: 0; + border-radius: 12px; + overflow: hidden; + gap: 0; +} + diff --git a/frontend/src/styles/preview/preview-zoom.css b/frontend/src/styles/preview/preview-zoom.css new file mode 100644 index 0000000..fc4e861 --- /dev/null +++ b/frontend/src/styles/preview/preview-zoom.css @@ -0,0 +1,113 @@ +.preview-zoom-backdrop { + position: fixed; + inset: 0; + background: var(--overlay-backdrop); + transition: background 0.25s ease, opacity 0.25s ease; + display: flex; + align-items: center; + justify-content: center; + padding: 2rem; + z-index: 2000000; + cursor: zoom-out; + opacity: 0; + pointer-events: none; +} + +.preview-zoom-backdrop--visible { + opacity: 1; + background: var(--overlay-backdrop); + pointer-events: auto; +} + +.preview-zoom__stage { + position: relative; + display: flex; + align-items: center; + justify-content: center; + max-width: 95vw; + max-height: 95vh; + z-index: 3000000; +} + +.preview-zoom__image { + max-width: 95vw; + max-height: 95vh; + width: auto; + height: auto; +} + +.preview-zoom__scroll { + display: flex; + align-items: center; + justify-content: center; + max-width: 95vw; + max-height: 95vh; + box-shadow: 0 32px 120px var(--shadow-deep); +} + +.preview-zoom__scroll:focus { + outline: none; +} + +.preview-zoom__scroll--native { + overflow: auto; + cursor: zoom-out; + justify-content: flex-start; + align-items: flex-start; +} + +.preview-zoom__nav { + position: absolute; + bottom: 1em; + left: 50%; + transform: translateX(-50%); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.9rem; + opacity: 0; + transition: opacity 0.18s ease; + pointer-events: none; +} + +.preview-zoom__stage:hover .preview-zoom__nav, +.preview-zoom__stage:focus-within .preview-zoom__nav { + opacity: 1; + pointer-events: auto; +} + +.preview-zoom__nav-button { + width: 2.8rem; + height: 2.8rem; + border: none; + border-radius: 999px; + background: var(--preview-nav-bg); + color: var(--preview-nav-fg); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + z-index: 1; + transition: background 0.15s ease, transform 0.15s ease; + box-shadow: 0 12px 28px var(--shadow-strong); +} + +.preview-zoom__nav-button:hover { + background: var(--preview-nav-bg-hover); +} + +.preview-zoom__nav-button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; +} + +.preview-zoom__nav-button svg { + width: 1.5rem; + height: 1.5rem; +} + +.preview-zoom__nav-button[disabled] { + opacity: 0.35; + cursor: default; +} + diff --git a/frontend/src/styles/settings/settings.css b/frontend/src/styles/settings/settings.css new file mode 100644 index 0000000..1714e2c --- /dev/null +++ b/frontend/src/styles/settings/settings.css @@ -0,0 +1,337 @@ +.settings-modal__body { + display: grid; + grid-template-columns: 12rem 1fr; + gap: 1.5rem; + height: 90vh; + padding: 1.5rem; +} + +.settings-modal__sidebar { + border-right: 1px solid var(--border-muted, var(--border)); + padding-right: 1rem; +} + +.settings-modal__sidebar ul { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.settings-modal__sidebar button { + width: 100%; + display: inline-flex; + align-items: center; + justify-content: flex-start; + gap: 0.4rem; + border: none; + background: none; + color: inherit; + font: inherit; + padding: 0.45rem 0.6rem; + border-radius: 0.35rem; + cursor: pointer; +} + +.settings-modal__sidebar button:hover, +.settings-modal__sidebar button:focus-visible { + background: var(--sidebar-hover-bg); +} + +.settings-modal__sidebar button.active { + background: var(--accent-soft); + font-weight: 600; +} + +.settings-modal__content { + overflow-y: auto; + padding-bottom: 1rem; +} + +.settings-section h4 { + margin-top: 0; +} + +.settings-section { + display: flex; + flex-direction: column; +} + +.settings-actions { + display: flex; + justify-content: flex-end; + margin-bottom: 1rem; +} + +.settings-actions .secondary { + min-width: 7rem; +} + +.settings-form { + display: flex; + flex-wrap: wrap; + gap: 1rem; + align-items: flex-end; + margin-bottom: 0.75rem; +} + +.settings-form__field { + display: flex; + flex-direction: column; + gap: 0.35rem; + min-width: 14rem; +} + +.settings-form__field--full { + flex: 1 1 100%; + min-width: 100%; +} + +fieldset.settings-form__field { + border: 1px solid var(--border-muted, var(--border)); + border-radius: 0.5rem; + padding: 0.75rem 0.9rem 0.85rem; + background: var(--surface-soft); +} + +fieldset.settings-form__field legend { + padding: 0 0.35rem; + font-weight: 600; + color: var(--muted-strong, inherit); +} + +.settings-form__field input[type='text'], +.settings-form__field input[type='datetime-local'] { + padding: 0.45rem 0.6rem; + border: 1px solid var(--border); + border-radius: 0.35rem; + background: var(--surface-soft); + color: inherit; +} + +.settings-form__choices { + display: flex; + flex-direction: column; + gap: 0.4rem; + align-items: flex-start; +} + +.settings-capability-picker { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.capability-dropdown { + position: relative; + width: 100%; +} + +.capability-dropdown__trigger { + width: 100%; + display: inline-flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + border: 1px solid var(--border); + border-radius: 0.45rem; + background: var(--surface-soft); + color: inherit; + font: inherit; + text-align: left; + cursor: pointer; + transition: border-color 0.15s ease, background 0.15s ease; +} + +.capability-dropdown__trigger:hover:not(:disabled), +.capability-dropdown__trigger:focus-visible { + border-color: var(--accent); + background: var(--surface); + outline: none; +} + +.capability-dropdown__trigger:disabled { + cursor: not-allowed; + color: var(--muted); + background: var(--surface-muted, var(--surface-soft)); +} + +.capability-dropdown__chevron { + flex-shrink: 0; + opacity: 0.8; +} + +.capability-dropdown__menu { + margin-top: 0.35rem; + max-height: 18rem; + overflow-y: auto; + padding: 0.25rem 0; + width: 100%; +} + +.capability-dropdown__option { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.45rem 0.75rem; +} + +.capability-dropdown__option-icon { + width: 1.1rem; + display: flex; + align-items: center; + justify-content: center; + color: var(--accent); +} + +.capability-dropdown__option:not(.is-selected) .capability-dropdown__option-icon { + color: transparent; +} + +.capability-dropdown__option-label { + flex: 1; + text-align: left; +} + +.capability-dropdown__empty { + padding: 0.6rem 0.8rem; + color: var(--muted); +} + +.settings-capability-picker__chips { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: 0.25rem; +} + +.settings-capability-picker__chips--inline { + margin-top: 0.35rem; +} + +.settings-capabilities-summary { + display: inline-block; + margin-top: 0.4rem; + color: var(--muted); + font-size: 0.9rem; +} + +.settings-capability-picker__placeholder { + color: var(--muted); + font-size: 0.9rem; +} + +.settings-capability-list { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + margin-top: 0.35rem; +} + +.settings-capability-list--compact { + margin-top: 0.2rem; + gap: 0.25rem; +} + +.settings-capability-list__item { + display: inline-flex; + align-items: center; +} + +.settings-choice { + display: inline-flex; + align-items: center; + gap: 0.4rem; + font-size: 0.9rem; + font-weight: 500; + color: inherit; +} + +.settings-choice input[type='checkbox'] { + width: 1.05rem; + height: 1.05rem; + cursor: pointer; + accent-color: var(--accent); +} + +.settings-choice input[type='checkbox']:disabled + span { + color: var(--muted); +} + +.settings-form__actions { + display: flex; + gap: 0.5rem; +} + +.settings-form__error { + color: var(--danger); + font-size: 0.85rem; + margin: 0 0 0.75rem; +} + +.settings-empty { + margin: 1rem 0; + color: var(--muted); +} + +.settings-table { + width: 100%; + border-collapse: collapse; + margin-top: 0.5rem; +} + +.settings-table th, +.settings-table td { + padding: 0.55rem 0.75rem; + border-bottom: 1px solid var(--border-muted, var(--border)); + text-align: left; + font-size: 0.9rem; +} + +.settings-table tr:last-child td { + border-bottom: none; +} + +.settings-table__actions { + white-space: nowrap; +} + +.settings-status { + color: var(--muted); + font-size: 0.9rem; +} + +.settings-table tr.is-revoked { + opacity: 0.65; +} + +.settings-notice { + border: 1px solid var(--accent); + background: var(--accent-soft); + padding: 0.9rem 1rem; + border-radius: 0.5rem; + margin-bottom: 1rem; +} + +.token-display { + background: var(--surface-ink-soft); + padding: 0.5rem 0.65rem; + border-radius: 0.35rem; + font-family: var(--font-mono); + font-size: 0.95rem; + overflow-x: auto; +} + +.settings-notice__actions { + display: flex; + gap: 0.5rem; + margin-top: 0.6rem; +} + +.settings-notice__actions button { + flex: 0 0 auto; +} + diff --git a/frontend/src/styles/sidebar/sidebar.css b/frontend/src/styles/sidebar/sidebar.css new file mode 100644 index 0000000..9f68787 --- /dev/null +++ b/frontend/src/styles/sidebar/sidebar.css @@ -0,0 +1,584 @@ +.folder-tree { + list-style: none; + margin: 0; + padding: 0; +} + +.folder-node { + margin: 0; +} + +.folder-row { + display: flex; + align-items: center; + gap: 0.22rem; + padding: 0.32rem 0.48rem; + border-radius: 8px; + cursor: pointer; + color: inherit; + transition: background 0.12s ease, color 0.12s ease; + position: relative; + overflow: hidden; + user-select: none; + -webkit-user-select: none; +} + +.folder-row .name-wrap { + display: inline-flex; + align-items: center; + gap: 0.25rem; + flex: 1; + min-width: 0; +} + +.folder-row .name-wrap .name__label { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.folder-row .folder-icon-image { + flex-shrink: 0; +} + +.folder-row:hover { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.folder-row.active { + background: var(--sidebar-active-bg); + color: var(--fg); +} + +.folder-row .toggle { + width: 1.05rem; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; + flex-shrink: 0; + transition: transform 0.18s ease; +} + +.folder-row .toggle.invisible { + visibility: hidden; +} + +.toggle-icon { + width: 0.9rem; + height: 0.9rem; + transition: transform 0.18s ease; +} + +.folder-row .toggle.expanded .toggle-icon { + transform: rotate(90deg); +} + +.folder-row__actions { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + display: flex; + gap: 0; + opacity: 0; + pointer-events: none; + transition: opacity 0.12s ease; + background-color: var(--surface-overlay); + border-radius: 8px; + padding: 0 0.18rem; +} + +.folder-row__actions .icon-button { + margin: 0; +} + +.folder-row:hover .folder-row__actions, +.folder-row:focus-within .folder-row__actions { + opacity: 1; + pointer-events: auto; +} + +.folder-children { + list-style: none; + margin: 0 0 0 0.45rem; + padding: 0; +} + + + +.sidebar-section { + margin-top: 1rem; + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.sidebar { + gap: 0; + overflow: hidden; + color: var(--sidebar-fg); + display: flex; + flex-direction: column; + width: 20em; + max-width: 20em; + flex: 0 0 20em; + background: var(--bg); +} + +.sidebar__body { + flex: 1; + display: flex; + flex-direction: column; + padding: 0.5rem 1rem; + gap: 0.75rem; + overflow-y: auto; + min-height: 0; +} + +.sidebar__footer { + margin-top: auto; + padding: 0.75rem 1rem 1rem; + border-top: 1px solid var(--border); + background: var(--surface-subtle); + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.sidebar__title { + margin: 0; + font-size: 1rem; + font-weight: 600; + color: var(--fg); + padding-left: 0.25rem; +} + +.sidebar__tenant { + color: var(--muted); + font-weight: 500; +} + +.sidebar__header { + position: relative; +} + +.sidebar__title-button { + display: inline-flex; + align-items: center; + gap: 0.35rem; + border: none; + background: none; + color: inherit; + font: inherit; + cursor: pointer; + padding: 0; +} + +.sidebar__title-button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.sidebar__title-chevron { + transition: transform 0.2s ease; +} + +.sidebar__title-chevron.is-open { + transform: rotate(180deg); +} + +.menu { + position: absolute; + top: 100%; + left: 1em; + right: auto; + background: var(--surface); + border: 1px solid var(--border-muted, var(--border)); + border-radius: 0.5rem; + box-shadow: 0 12px 28px var(--shadow-strong); + min-width: 220px; + z-index: 20; + overflow: hidden; +} + +.menu__list { + max-height: 260px; + overflow-y: auto; + padding: 0.35rem 0; + display: flex; + flex-direction: column; + gap: 0.15rem; +} + +.menu__heading { + padding: 0.5rem 1rem 0.25rem; + font-size: 0.82rem; + font-weight: 600; + color: var(--muted); +} + +.menu button.menu__item, +.menu .menu__item { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.6rem; + width: 100%; + padding: 0.55rem 1rem; + border: none; + background: none; + color: inherit; + font: inherit; + text-align: left; + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease; +} + +.menu button.menu__item:hover, +.menu button.menu__item:focus-visible, +.menu .menu__item:hover, +.menu .menu__item:focus-visible { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.menu button.menu__item.active, +.menu .menu__item.active { + font-weight: 600; + color: var(--accent); +} + +.menu button.menu__item:focus-visible, +.menu .menu__item:focus-visible { + outline: 2px solid var(--accent); + outline-offset: -2px; +} + +.menu__label { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; +} + +.menu__check-slot { + width: 1rem; + display: flex; + align-items: center; + justify-content: center; + color: var(--accent); +} + +.menu__active-indicator { + font-size: 0.75rem; + color: var(--muted); +} + +.menu__empty { + display: block; + padding: 0.6rem 0.75rem; + color: var(--muted); + font-size: 0.85rem; +} + +.menu__footer { + border-top: 1px solid var(--border-muted, var(--border)); + padding: 0.35rem 0.5rem; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.menu--simple .menu__footer { + border-top: none; +} + +.menu__settings { + width: 100%; + display: inline-flex; + align-items: center; + gap: 0.4rem; + border: none; + background: none; + color: inherit; + font: inherit; + cursor: pointer; + padding: 0.4rem 0.5rem; + border-radius: 0.35rem; +} + +.menu__settings:hover, +.menu__settings:focus-visible { + background: var(--sidebar-hover-bg); +} + +.menu__logout { + width: 100%; + display: inline-flex; + align-items: center; + gap: 0.4rem; + border: none; + background: none; + color: var(--danger); + font: inherit; + cursor: pointer; + padding: 0.4rem 0.5rem; + border-radius: 0.35rem; +} + +.menu__logout:hover, +.menu__logout:focus-visible { + background: var(--surface-danger-subtle); +} + +.sidebar__search { + display: flex; + align-items: center; + gap: 0.4rem; + margin: 0 0 0.75rem; +} + +.sidebar__search input[type='search'] { + flex: 1; + padding: 0.4rem 0.6rem; + border-radius: 4px; + border: 1px solid var(--border); + background: var(--surface); + color: var(--fg); +} + +.sidebar__search button { + padding: 0.35rem 0.75rem; + border: 1px solid transparent; + border-radius: 4px; + background: transparent; + color: var(--accent); + font-size: 0.85rem; + cursor: pointer; +} + +.sidebar__search button:hover:not([disabled]) { + background: var(--sidebar-hover-bg); +} + +.sidebar__footer .sidebar-section { + margin-top: 0; +} + +.sidebar__footer .sidebar-section__actions { + gap: 0.4rem; +} + +.sidebar-section:first-of-type, +.sidebar-section--folders { + margin-top: 0; +} + +.sidebar-section--folders { + display: flex; + flex-direction: column; +} + +.sidebar-section__header { + display: flex; + align-items: center; + font-size: 0.75rem; + justify-content: space-between; + color: var(--muted); +} + +.sidebar-section__title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.4rem; + width: 100%; + background: transparent; + border: none; + border-radius: 6px; + padding: 0.25rem 0.35rem; + margin: -0.25rem -0.35rem; + color: inherit; + font: inherit; + cursor: pointer; + text-align: left; +} + +.sidebar-section__title:hover:not([disabled]), +.sidebar-section__title:focus-visible { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.sidebar-section__title:hover:not([disabled]) h3, +.sidebar-section__title:focus-visible h3 { + color: var(--fg); +} + +.sidebar-section__header h3 { + margin: 0; + font-weight: 600; +} + +.sidebar-section__actions { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.sidebar-section__actions .meta { + font-size: 0.75rem; + color: var(--muted); +} + +.sidebar-slider { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.8rem; + color: var(--muted); +} + +.sidebar-slider input[type='range'] { + flex: 1; + accent-color: var(--accent); +} + +.sidebar-slider__value { + min-width: 3rem; + text-align: right; + color: var(--fg); + font-variant-numeric: tabular-nums; +} + +.sidebar-item { + background: transparent; + padding: 0.16rem 0.26rem; + text-align: left; + color: var(--sidebar-fg); + border-radius: 2px; + cursor: pointer; + transition: background 0.12s ease, color 0.12s ease; + display: flex; + align-items: center; + gap: 0.38rem; + width: 100%; +} + +.sidebar-item:hover { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.sidebar-item.active { + background: var(--sidebar-active-bg); + color: var(--fg); + font-weight: 600; +} + +.sidebar-item:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.sidebar-item__icon { + width: 1rem; + height: 1rem; + flex-shrink: 0; + color: var(--accent); +} + +.sidebar-item.active .sidebar-item__icon { + color: currentColor; +} + +.sidebar-tag-cloud { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + padding: 0.25rem 0 0.1rem; +} + +.sidebar-tag-pill { + border-radius: 999px; + padding: 0.25rem 0.6rem; + font-size: 0.75rem; + font-weight: 600; + line-height: 1; + cursor: pointer; + background: var(--surface-soft); + color: var(--fg); + transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, + opacity 0.12s ease; + box-shadow: 0 1px 2px var(--shadow-faint); +} + +.sidebar-tag-pill:hover { + transform: none; + box-shadow: 0 2px 6px var(--shadow-pop); + border-color: var(--accent-soft); +} + +.sidebar-tag-pill:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.sidebar-tag-pill.active { + border-color: var(--sidebar-active-pill-border); + box-shadow: 0 0 0 1.5px var(--sidebar-active-pill-border); +} + +.sidebar-tag-pill--untagged { + border: 1px dashed var(--border); + background: var(--surface-subtle); + color: var(--muted); +} + +.sidebar-tag-pill--untagged.active { + color: var(--fg); +} + +.sidebar-tag-cloud--has-active .sidebar-tag-pill:not(.active) { + opacity: 0.45; +} + +.sidebar-correspondent-list { + list-style: none; + margin: 0.4rem 0 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.sidebar-correspondent-item { + display: block; + background: transparent; + border-radius: 4px; + padding: 0.35rem 0.5rem; + text-align: left; + color: var(--sidebar-fg); + cursor: pointer; + font-size: 0.85rem; + transition: background 0.15s ease, box-shadow 0.15s ease; +} + +.sidebar-correspondent-item:hover { + background: var(--sidebar-hover-bg); + color: var(--fg); +} + +.sidebar-correspondent-item:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.sidebar-correspondent-item.active { + background: var(--sidebar-active-bg); + color: var(--fg); +} + + diff --git a/frontend/src/styles/uploads/overlay.css b/frontend/src/styles/uploads/overlay.css new file mode 100644 index 0000000..640432c --- /dev/null +++ b/frontend/src/styles/uploads/overlay.css @@ -0,0 +1,176 @@ +.upload-queue-overlay { + position: fixed; + bottom: 24px; + right: 24px; + width: min(360px, calc(100vw - 32px)); + background: var(--surface); + border: 1px solid var(--border); + border-radius: 14px; + box-shadow: 0 18px 45px var(--shadow-pop); + z-index: 400; + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 0.9rem; + color: var(--fg); +} + + +.upload-queue-overlay__header { + padding: 0; + border: none; +} + +.upload-queue-overlay__title { + display: inline-flex; + align-items: center; + gap: 0.4rem; + font-weight: 600; + font-size: 0.95rem; + min-width: 0; +} + +.upload-queue-overlay__summary { + font-size: 0.8rem; + color: var(--muted); + white-space: nowrap; +} + +.upload-queue-overlay__controls { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +.upload-queue-overlay__list { + list-style: none; + margin: 0; + padding: 0; + max-height: 260px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.upload-queue-overlay--collapsed .upload-queue-overlay__list { + display: none; +} + +.upload-queue-overlay__item { + display: grid; + grid-template-columns: auto 1fr; + gap: 0.6rem; + padding: 0.15rem 0; +} + +.upload-queue-overlay__status { + width: 28px; + height: 28px; + border-radius: 999px; + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--surface-subtle); + color: var(--muted); +} + +.upload-queue-overlay__status--muted { + background: var(--surface-subtle); + color: var(--muted); +} + +.upload-queue-overlay__status--accent { + background: var(--accent-soft); + color: var(--accent); +} + +.upload-queue-overlay__status--success { + background: var(--success-subtle); + color: var(--success); +} + +.upload-queue-overlay__status--info { + background: var(--selection-soft); + color: var(--accent); +} + +.upload-queue-overlay__status--danger { + background: var(--danger-subtle); + color: var(--danger); +} + +.upload-queue-overlay__details { + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.15rem; +} + +.upload-queue-overlay__name { + font-size: 0.88rem; + font-weight: 500; + color: var(--fg); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.upload-queue-overlay__name-link { + font-size: 0.88rem; + font-weight: 500; + color: inherit; + background: none; + border: none; + padding: 0; + text-align: left; + cursor: pointer; + text-decoration: none; +} + +.upload-queue-overlay__name-link:hover { + color: var(--accent); + text-decoration: underline; +} + +.upload-queue-overlay__meta-line { + font-size: 0.72rem; + color: var(--muted); + display: flex; + align-items: center; + gap: 0.35rem; + flex-wrap: wrap; +} + +.upload-queue-overlay__meta-id, +.upload-queue-overlay__meta-secondary { + color: inherit; +} + +.upload-queue-overlay__meta-link { + border: none; + background: none; + font: inherit; + cursor: pointer; + padding: 0; + color: inherit; + text-decoration: none; +} + +.upload-queue-overlay__meta-link:hover { + color: var(--accent); + text-decoration: underline; +} + +.upload-queue-overlay__meta-link:disabled { + cursor: default; + opacity: 0.5; +} + +.upload-queue-overlay__meta-error { + color: var(--danger); +} + +.upload-queue-overlay__item--error .upload-queue-overlay__name { + color: var(--danger); +} diff --git a/frontend/src/styles/workspace/workspace-cards.css b/frontend/src/styles/workspace/workspace-cards.css new file mode 100644 index 0000000..4079627 --- /dev/null +++ b/frontend/src/styles/workspace/workspace-cards.css @@ -0,0 +1,122 @@ +/* Workspace cards, thumbnails, and hover controls */ +.desk-item__shadow { + display: none; +} + +.desk-item__card { + position: relative; + border-radius: 0; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + box-shadow: 0 12px 32px var(--shadow-medium); + overflow: hidden; +} + +.desk-item__card img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; + pointer-events: none; + user-select: none; + -webkit-user-drag: none; +} + +.desk-item__card--empty { + box-shadow: 0 12px 32px var(--shadow-medium); + background: + radial-gradient(circle at 42% 38%, color-mix(in oklch, var(--surface-subtle) 75%, var(--selection) 25%), color-mix(in oklch, var(--surface-subtle) 85%, var(--selection) 15%) 70%), + linear-gradient(135deg, color-mix(in oklch, var(--surface-subtle) 88%, var(--selection-soft) 12%) 0%, color-mix(in oklch, var(--surface-subtle) 65%, var(--shadow-faint) 35%) 100%); + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.5rem; +} + +.desk-item__placeholder { + font-size: 0.95rem; + font-weight: 500; + letter-spacing: normal; + color: var(--muted); +} + +.desk-item__empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + gap: 0.5rem; + padding: 1rem; + text-align: center; +} + +.desk-item__title { + font-size: 0.95rem; + font-weight: 500; + color: var(--fg); + max-width: 90%; + overflow: hidden; + overflow-wrap: anywhere; + word-break: break-word; + white-space: normal; +} + +.desk-card__nav { + position: absolute; + bottom: 1.8rem; + left: 50%; + transform: translateX(-50%); + transform-origin: center; + display: flex; + gap: 1.5rem; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; +} + +.desk-item__card:hover .desk-card__nav { + opacity: 1; + pointer-events: auto; +} + +.desk-card__nav-button { + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.4em; + height: 2.4em; + padding: 0.25em; + border-radius: 50%; + border: none; + background: var(--preview-nav-bg); + color: var(--preview-nav-fg); + cursor: pointer; + transition: background 0.15s ease, opacity 0.15s ease; +} + +.desk-card__nav-button:hover:not([disabled]) { + background: var(--preview-nav-bg-hover); +} + +.desk-card__nav-button:disabled { + opacity: 0.4; + cursor: default; +} + +.desk-card__nav-button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.desk-card__nav-button svg { + width: 100%; + height: 100%; +} diff --git a/frontend/src/styles/workspace/workspace-items.css b/frontend/src/styles/workspace/workspace-items.css new file mode 100644 index 0000000..07061c7 --- /dev/null +++ b/frontend/src/styles/workspace/workspace-items.css @@ -0,0 +1,135 @@ +/* Workspace items, states, and inline badges */ +.desk-item { + position: absolute; + display: block; + width: auto; + cursor: grab; + touch-action: none; + transform-origin: center center; + transition: box-shadow 0.16s ease; + outline: none; + will-change: transform; + -webkit-user-select: none; + user-select: none; + -webkit-touch-callout: none; +} + +.desk-item__body { + flex-grow: 1; + width: 100%; + height: 100%; +} + +.desk-item:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 4px; +} + +.desk-item.is-dragging { + cursor: grabbing; + transition: none; +} + +.desk-item.is-tag-target .desk-item__card { + outline: 0.35rem dashed var(--accent); + outline-offset: 0.35rem; +} + +.desk-item.is-tag-pending .desk-item__card { + outline: 0.25rem solid var(--accent-outline); + outline-offset: 0.25rem; +} + +.desk-item.is-filtered-out { + opacity: 0.12; + pointer-events: none; + filter: blur(15px) grayscale(100%); + transition: opacity 0.6s ease, filter 0.28s ease; + z-index: 0 !important; +} + +.desk-item.is-selected { + z-index: 5; +} + +.desk-item.is-selected .desk-item__card { + box-shadow: + 0 0 0 0.18rem color-mix(in oklch, var(--accent) 45%, transparent), + 0 0 0.35rem 0 color-mix(in oklch, var(--accent) 28%, transparent), + 0 12px 28px -14px color-mix(in oklch, var(--accent) 20%, transparent), + 0 10px 24px var(--shadow-medium); +} + +.desk-item.is-selected .desk-item__title { + color: var(--accent); +} + +.desk-item__tags { + position: absolute; + top: 0; + right: 0; + display: flex; + flex-direction: column; + gap: 0.35rem; + align-items: flex-end; + transform-origin: top right; + transform: translate(-0.5em, 0.5em); + transition: transform 0.28s ease; +} + +.desk-item__correspondents { + position: absolute; + bottom: 0; + left: 0; + display: flex; + flex-direction: column; + gap: 0.35rem; + align-items: flex-start; + transform-origin: bottom left; + transform: translate(0.5em, -0.5em); + pointer-events: none; +} + +.desk-correspondent-chip { + pointer-events: none; + font-size: 0.82rem; + padding: 0.18rem 0.55rem; + max-width: min(16rem, 80%); + display: inline-flex; + align-items: center; + overflow: hidden; + background: color-mix(in oklch, var(--surface-subtle) 90%, transparent); + color: var(--muted); +} + +.desk-correspondent-chip__label { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.tag-chip--draggable { + user-select: none; + pointer-events: auto; + cursor: grab; + transition: transform 0.16s ease, opacity 0.2s ease, box-shadow 0.2s ease; +} + +.tag-chip--draggable:active { + cursor: grabbing; +} + +.tag-chip--draggable.is-drag-hidden { + opacity: 0.4; +} + +.desk-item__tags .tag-chip { + font-size: 0.85rem; + padding: 0.18rem 0.55rem; + gap: 0.3rem; +} + +.desk-item__tags .tag-chip--tear-pending { + opacity: 0.35; +} diff --git a/frontend/src/styles/workspace/workspace-layout.css b/frontend/src/styles/workspace/workspace-layout.css new file mode 100644 index 0000000..223e693 --- /dev/null +++ b/frontend/src/styles/workspace/workspace-layout.css @@ -0,0 +1,45 @@ +/* Workspace layout & canvas scaffolding */ +.desk-main { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} + +.desk-shell { + flex: 1; + display: flex; + flex-direction: column; + grid-column: 2 / -1; + min-height: 0; + position: relative; +} + +.desk-canvas { + flex: 1; + position: relative; + overflow: hidden; + margin: 0; + outline: none; +} + +.desk-canvas:focus, +.desk-canvas:focus-visible { + outline: none; +} + +.desk-empty { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: 3rem; + text-align: center; + color: var(--muted); + font-size: 0.95rem; +} + +body.desk-cursor-remove, +body.desk-cursor-remove * { + cursor: not-allowed !important; +} diff --git a/frontend/src/styles/workspace/workspace-overlays.css b/frontend/src/styles/workspace/workspace-overlays.css new file mode 100644 index 0000000..b694779 --- /dev/null +++ b/frontend/src/styles/workspace/workspace-overlays.css @@ -0,0 +1,94 @@ +/* Workspace overlays (help, guidance, etc.) */ +.desk-help-overlay { + position: fixed; + inset: 0; + z-index: 5000000; + display: flex; + align-items: center; + justify-content: center; + padding: clamp(1.5rem, 4vw, 3rem); + pointer-events: none; +} + +.desk-help-overlay__backdrop { + position: absolute; + inset: 0; + background: var(--surface-overlay); + backdrop-filter: blur(8px); + pointer-events: auto; +} + +.desk-help-overlay__content { + position: relative; + width: min(640px, 92vw); + max-height: min(80vh, 640px); + background: var(--surface); + border: 1px solid var(--border); + box-shadow: 0 24px 64px var(--shadow-strong); + border-radius: 1.25rem; + display: flex; + flex-direction: column; + pointer-events: auto; + overflow: hidden; +} + +.desk-help-overlay__header, +.desk-help-overlay__footer { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.25rem; +} + +.desk-help-overlay__header { + border-bottom: 1px solid var(--border); +} + +.desk-help-overlay__header h2 { + margin: 0; + font-size: 1.15rem; + font-weight: 600; +} + +.desk-help-overlay__body { + padding: 1rem 1.25rem 1.5rem; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.75rem; + line-height: 1.55; +} + +.desk-help-overlay__body p { + margin: 0; + color: var(--muted); +} + +.desk-help-overlay__list { + margin: 0; + padding-left: 1.1rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.desk-help-overlay__list li { + color: var(--fg); +} + +.desk-help-overlay__body kbd { + display: inline-block; + padding: 0.15rem 0.4rem; + border-radius: 0.4rem; + border: 1px solid var(--border-strong); + background: var(--surface-subtle); + font-size: 0.85em; + line-height: 1; + font-family: inherit; +} + +.desk-help-overlay__footer { + border-top: 1px solid var(--border); + justify-content: flex-end; + gap: 0.5rem; +}