/* ======================================================== Docs — Local-first Office Suite Aesthetic: Refined Editorial + Industrial Utility No external font dependencies — system fonts only. ======================================================== */ /* --- Tokens --- */ :root { --color-bg: #f5f3f0; --color-bg: oklch(0.965 0.005 75); --color-surface: #ede9e4; --color-surface: oklch(0.935 0.008 75); --color-surface-alt: #e7e2dc; --color-surface-alt: oklch(0.915 0.01 75); --color-text: #221812; --color-text: oklch(0.22 0.02 55); --color-text-muted: #655c56; --color-text-muted: oklch(0.48 0.015 55); --color-text-faint: #8b8581; --color-text-faint: oklch(0.62 0.01 55); --color-accent: #ab413e; --color-accent: oklch(0.52 0.14 25); --color-accent-hover:#972e2d; --color-accent-hover:oklch(0.46 0.14 25); --color-teal: #006e6f; --color-teal: oklch(0.48 0.1 195); --color-teal-light: #bae0e0; --color-teal-light: oklch(0.88 0.04 195); --color-border: #d7d4cf; --color-border: oklch(0.87 0.008 75); --color-border-strong:#bbb7b0; --color-border-strong:oklch(0.78 0.01 75); --color-grid-line: #cecac3; --color-grid-line: oklch(0.84 0.01 75); --color-grid-header-line: #c9c3bc; --color-grid-header-line: oklch(0.82 0.012 75); --color-hover: #e9e4dd; --color-hover: oklch(0.92 0.01 75); --color-focus: #006e6f4d; --color-focus: oklch(0.48 0.1 195 / 0.3); --color-success: #1c985a; --color-success: oklch(0.6 0.14 155); --color-warning: #cd9c1f; --color-warning: oklch(0.72 0.14 85); --color-danger: #bd413f; --color-danger: oklch(0.55 0.16 25); --color-encrypted: #187c49; --color-encrypted: oklch(0.52 0.12 155); --font-display: Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif; --font-body: system-ui, -apple-system, 'Segoe UI', sans-serif; --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; --space-xs: 0.25rem; --space-sm: 0.5rem; --space-md: 1rem; --space-lg: 1.5rem; --space-xl: 2.5rem; --space-2xl: 4rem; --radius-sm: 3px; --radius-md: 6px; --radius-lg: 10px; --radius-pill: 9999px; --shadow-sm: 0 1px 2px #2218120f; --shadow-sm: 0 1px 2px oklch(0.22 0.02 55 / 0.06); --shadow-md: 0 2px 8px #22181214; --shadow-md: 0 2px 8px oklch(0.22 0.02 55 / 0.08); --shadow-lg: 0 8px 24px #2218121a; --shadow-lg: 0 8px 24px oklch(0.22 0.02 55 / 0.1); --transition-fast: 120ms ease-out; --transition-med: 200ms ease-out; --color-text-secondary: #655c56; --color-text-secondary: oklch(0.48 0.015 55); --color-bg-secondary: #ede9e4; --color-bg-secondary: oklch(0.935 0.008 75); --color-surface-raised: #eeeae5; --color-surface-raised: oklch(0.94 0.008 75); /* Colors that need dark-mode overrides but are used inline */ --color-btn-primary-text: #f7f5f1; --color-btn-primary-text: oklch(0.97 0.005 75); --color-collab-text: #f7f5f1; --color-collab-text: oklch(0.97 0.005 75); --color-cursor-label: #f7f5f1; --color-cursor-label: oklch(0.97 0.005 75); --color-cell-editor-bg: #fcfcfa; --color-cell-editor-bg: oklch(0.99 0.002 75); --color-modal-backdrop: #22181280; --color-modal-backdrop: oklch(0.22 0.02 55 / 0.5); --color-btn-active-bg: #ab413e14; --color-btn-active-bg: oklch(0.52 0.14 25 / 0.08); /* Comment highlight */ --color-comment-bg: #f7e2b8; --color-comment-bg: oklch(0.92 0.06 85); --color-comment-border: #cd9c1f; --color-comment-border: oklch(0.72 0.14 85); --color-comment-bg-hover: #f0d49b; --color-comment-bg-hover: oklch(0.88 0.08 85); /* Search highlight */ --color-search-match: #fcd176; --color-search-match: oklch(0.88 0.12 85); --color-search-match-active: #ef852e; --color-search-match-active: oklch(0.72 0.16 55); --color-search-match-text: #f7f5f1; --color-search-match-text: oklch(0.97 0.005 75); /* Range selection */ --color-range-bg: #006e6f1f; --color-range-bg: oklch(0.48 0.1 195 / 0.12); --color-range-header-bg: #006e6f26; --color-range-header-bg: oklch(0.48 0.1 195 / 0.15); --color-merge-active-bg: #006e6f1a; --color-merge-active-bg: oklch(0.48 0.1 195 / 0.1); /* Color swatch */ --color-swatch-height: 4px; --color-highlight-default: #ffefb1; --color-highlight-default: oklch(0.95 0.08 95); /* Shadows (use dark base) */ --shadow-color: #221812; --shadow-color: oklch(0.22 0.02 55); /* Z-Index Scale — documented stacking context hierarchy. Grid-internal micro-stacking (0-6) uses literal values. Everything above uses these tokens for consistency. */ --z-component: 10; /* toolbar, cell editor, diagram panels */ --z-float: 50; /* dropdowns, block handle, version badge */ --z-popover: 60; /* comment popover, block context menu */ --z-sticky: 80; /* sort indicator, validation dropdown */ --z-overlay: 100; /* resize lines, autocomplete, slash menu */ --z-tooltip: 200; /* tooltips, link preview, suggestions */ --z-drop: 300; /* drop zone overlay, notification toast */ --z-panel: 900; /* gallery sidebar, floating panels */ --z-modal: 1000; /* modal dialog, print preview, presenter */ --z-above-modal: 1100; /* formula tooltip, find-replace overlay */ --z-menu: 9999; /* context menu, command palette */ --z-skip: 10000;/* skip-to-content link */ } /* --- Dark theme --- */ [data-theme="dark"] { color-scheme: dark; --color-bg: #0f0d0b; --color-bg: oklch(0.16 0.005 75); --color-surface: #181612; --color-surface: oklch(0.20 0.008 75); --color-surface-alt: #221f1a; --color-surface-alt: oklch(0.24 0.01 75); --color-text: #dbd7d0; --color-text: oklch(0.88 0.01 75); --color-text-muted: #938e89; --color-text-muted: oklch(0.65 0.01 75); --color-text-faint: #837e78; --color-text-faint: oklch(0.62 0.008 75); --color-text-secondary: #938e89; --color-text-secondary: oklch(0.65 0.01 75); --color-bg-secondary: #181612; --color-bg-secondary: oklch(0.20 0.008 75); --color-surface-raised: #1d1a17; --color-surface-raised: oklch(0.22 0.008 75); --color-accent: #cd605a; --color-accent: oklch(0.62 0.14 25); --color-accent-hover: #b84d49; --color-accent-hover: oklch(0.56 0.14 25); --color-teal: #0f9293; --color-teal: oklch(0.60 0.1 195); --color-teal-light: #0b2f2f; --color-teal-light: oklch(0.28 0.04 195); --color-border: #2b2825; --color-border: oklch(0.28 0.008 75); --color-border-strong:#46423d; --color-border-strong:oklch(0.38 0.01 75); --color-grid-line: #262420; --color-grid-line: oklch(0.26 0.008 75); --color-grid-header-line: #312d28; --color-grid-header-line: oklch(0.30 0.01 75); --color-hover: #201c18; --color-hover: oklch(0.23 0.01 75); --color-focus: #0f92934d; --color-focus: oklch(0.60 0.1 195 / 0.3); --color-success: #33a868; --color-success: oklch(0.65 0.14 155); --color-warning: #cd9c1f; --color-warning: oklch(0.72 0.14 85); --color-danger: #ce514d; --color-danger: oklch(0.60 0.16 25); --color-encrypted: #3f9b65; --color-encrypted: oklch(0.62 0.12 155); --shadow-sm: 0 1px 2px #0100004d; --shadow-sm: 0 1px 2px oklch(0.05 0.005 75 / 0.3); --shadow-md: 0 2px 8px #01000066; --shadow-md: 0 2px 8px oklch(0.05 0.005 75 / 0.4); --shadow-lg: 0 8px 24px #01000080; --shadow-lg: 0 8px 24px oklch(0.05 0.005 75 / 0.5); --color-btn-primary-text: #f7f5f1; --color-btn-primary-text: oklch(0.97 0.005 75); --color-collab-text: #f7f5f1; --color-collab-text: oklch(0.97 0.005 75); --color-cursor-label: #f7f5f1; --color-cursor-label: oklch(0.97 0.005 75); --color-cell-editor-bg: #13110f; --color-cell-editor-bg: oklch(0.18 0.005 75); --color-modal-backdrop: #010000b3; --color-modal-backdrop: oklch(0.05 0.005 75 / 0.7); --color-btn-active-bg: #cd605a26; --color-btn-active-bg: oklch(0.62 0.14 25 / 0.15); --color-highlight-default: #563e00; --color-highlight-default: oklch(0.38 0.08 85); --color-comment-bg: #372c15; --color-comment-bg: oklch(0.30 0.04 85); --color-comment-border: #7d5e07; --color-comment-border: oklch(0.50 0.10 85); --color-comment-bg-hover: #46381a; --color-comment-bg-hover: oklch(0.35 0.05 85); --color-search-match: #4d3600; --color-search-match: oklch(0.35 0.08 85); --color-search-match-active: #964d09; --color-search-match-active: oklch(0.50 0.12 55); --color-search-match-text: #f7f5f1; --color-search-match-text: oklch(0.97 0.005 75); --color-range-bg: #0f929326; --color-range-bg: oklch(0.60 0.1 195 / 0.15); --color-range-header-bg: #0f929333; --color-range-header-bg: oklch(0.60 0.1 195 / 0.20); --color-merge-active-bg: #0f929326; --color-merge-active-bg: oklch(0.60 0.1 195 / 0.15); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { color-scheme: dark; --color-bg: #0f0d0b; --color-bg: oklch(0.16 0.005 75); --color-surface: #181612; --color-surface: oklch(0.20 0.008 75); --color-surface-alt: #221f1a; --color-surface-alt: oklch(0.24 0.01 75); --color-text: #dbd7d0; --color-text: oklch(0.88 0.01 75); --color-text-muted: #938e89; --color-text-muted: oklch(0.65 0.01 75); --color-text-faint: #837e78; --color-text-faint: oklch(0.62 0.008 75); --color-text-secondary: #938e89; --color-text-secondary: oklch(0.65 0.01 75); --color-bg-secondary: #181612; --color-bg-secondary: oklch(0.20 0.008 75); --color-surface-raised: #1d1a17; --color-surface-raised: oklch(0.22 0.008 75); --color-accent: #cd605a; --color-accent: oklch(0.62 0.14 25); --color-accent-hover: #b84d49; --color-accent-hover: oklch(0.56 0.14 25); --color-teal: #0f9293; --color-teal: oklch(0.60 0.1 195); --color-teal-light: #0b2f2f; --color-teal-light: oklch(0.28 0.04 195); --color-border: #2b2825; --color-border: oklch(0.28 0.008 75); --color-border-strong:#46423d; --color-border-strong:oklch(0.38 0.01 75); --color-grid-line: #262420; --color-grid-line: oklch(0.26 0.008 75); --color-grid-header-line: #312d28; --color-grid-header-line: oklch(0.30 0.01 75); --color-hover: #201c18; --color-hover: oklch(0.23 0.01 75); --color-focus: #0f92934d; --color-focus: oklch(0.60 0.1 195 / 0.3); --color-success: #33a868; --color-success: oklch(0.65 0.14 155); --color-warning: #cd9c1f; --color-warning: oklch(0.72 0.14 85); --color-danger: #ce514d; --color-danger: oklch(0.60 0.16 25); --color-encrypted: #3f9b65; --color-encrypted: oklch(0.62 0.12 155); --shadow-sm: 0 1px 2px #0100004d; --shadow-sm: 0 1px 2px oklch(0.05 0.005 75 / 0.3); --shadow-md: 0 2px 8px #01000066; --shadow-md: 0 2px 8px oklch(0.05 0.005 75 / 0.4); --shadow-lg: 0 8px 24px #01000080; --shadow-lg: 0 8px 24px oklch(0.05 0.005 75 / 0.5); --color-btn-primary-text: #f7f5f1; --color-btn-primary-text: oklch(0.97 0.005 75); --color-collab-text: #f7f5f1; --color-collab-text: oklch(0.97 0.005 75); --color-cursor-label: #f7f5f1; --color-cursor-label: oklch(0.97 0.005 75); --color-cell-editor-bg: #13110f; --color-cell-editor-bg: oklch(0.18 0.005 75); --color-modal-backdrop: #010000b3; --color-modal-backdrop: oklch(0.05 0.005 75 / 0.7); --color-btn-active-bg: #cd605a26; --color-btn-active-bg: oklch(0.62 0.14 25 / 0.15); --color-highlight-default: #563e00; --color-highlight-default: oklch(0.38 0.08 85); --color-comment-bg: #372c15; --color-comment-bg: oklch(0.30 0.04 85); --color-comment-border: #7d5e07; --color-comment-border: oklch(0.50 0.10 85); --color-comment-bg-hover: #46381a; --color-comment-bg-hover: oklch(0.35 0.05 85); --color-search-match: #4d3600; --color-search-match: oklch(0.35 0.08 85); --color-search-match-active: #964d09; --color-search-match-active: oklch(0.50 0.12 55); --color-search-match-text: #f7f5f1; --color-search-match-text: oklch(0.97 0.005 75); --color-range-bg: #0f929326; --color-range-bg: oklch(0.60 0.1 195 / 0.15); --color-range-header-bg: #0f929333; --color-range-header-bg: oklch(0.60 0.1 195 / 0.20); --color-merge-active-bg: #0f929326; --color-merge-active-bg: oklch(0.60 0.1 195 / 0.15); } } /* --- Reduced motion: disable transitions/animations for users who prefer it --- */ @media (prefers-contrast: more) { :root { --color-text-muted: #433831; --color-text-muted: oklch(0.35 0.02 55); --color-text-faint: #544b45; --color-text-faint: oklch(0.42 0.015 55); --color-border: #9c9792; --color-border: oklch(0.68 0.01 75); --color-border-strong: #76716a; --color-border-strong: oklch(0.55 0.012 75); --color-grid-line: #9d9790; --color-grid-line: oklch(0.68 0.012 75); --color-grid-header-line: #8c857c; --color-grid-header-line: oklch(0.62 0.015 75); --color-hover: #d7d0c6; --color-hover: oklch(0.86 0.015 75); --color-focus: #006e6f99; --color-focus: oklch(0.48 0.1 195 / 0.6); } [data-theme="dark"] { --color-text-muted: #bbb7b0; --color-text-muted: oklch(0.78 0.01 75); --color-text-faint: #a8a49e; --color-text-faint: oklch(0.72 0.01 75); --color-border: #59554f; --color-border: oklch(0.45 0.01 75); --color-border-strong: #76716a; --color-border-strong: oklch(0.55 0.012 75); --color-grid-line: #514c46; --color-grid-line: oklch(0.42 0.012 75); --color-grid-header-line: #635d54; --color-grid-header-line: oklch(0.48 0.015 75); --color-hover: #2d2821; --color-hover: oklch(0.28 0.015 75); --color-focus: #0f929399; --color-focus: oklch(0.60 0.1 195 / 0.6); } } @media (prefers-reduced-motion: reduce) { :root { --transition-fast: 0ms; --transition-med: 0ms; } *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } /* --- Reset --- */ *, *::before, *::after { box-sizing: border-box; margin: 0; } /* Prevent zoom on input focus on mobile (iOS double-tap-to-zoom) */ input, select, textarea { touch-action: manipulation; } html { font-size: clamp(15px, 1vw + 12px, 17px); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color-scheme: light dark; overflow-x: hidden; } body { font-family: var(--font-body); color: var(--color-text); background: var(--color-bg); line-height: 1.55; min-height: 100dvh; overflow-x: hidden; max-width: 100vw; transition: background-color var(--transition-med), color var(--transition-med); } /* Smooth transitions for theme switching on key surfaces */ .app-topbar, .toolbar, .formula-bar, .sheet-tabs, .docs-footer, .modal, .find-bar, .comment-popover, .toolbar-dropdown-menu, .toolbar-overflow-menu, .new-menu, .more-menu-panel, .doc-item, .folder-card, .sort-menu, .search-input, .modal-backdrop, .landing-header, .editor-container, .sheet-container { transition: background-color var(--transition-med), border-color var(--transition-med), color var(--transition-med); } /* --- Theme toggle button --- */ .theme-toggle { padding: 0.4rem; border-radius: var(--radius-sm); background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: all var(--transition-fast); font-size: 1rem; line-height: 1; } .theme-toggle:hover { color: var(--color-text); background: var(--color-hover); } /* --- Typography --- */ h1, h2, h3, h4, h5, h6 { font-family: var(--font-display); font-weight: 600; line-height: 1.2; letter-spacing: -0.01em; } h1 { font-size: clamp(2rem, 4vw, 3.2rem); } h2 { font-size: clamp(1.5rem, 2.5vw, 2rem); } h3 { font-size: clamp(1.2rem, 1.8vw, 1.5rem); } a { color: var(--color-teal); text-decoration-thickness: 1px; text-underline-offset: 2px; transition: color var(--transition-fast); } a:hover { color: var(--color-accent); } code, pre { font-family: var(--font-mono); font-size: 0.9em; } /* --- Buttons --- */ .btn { display: inline-flex; align-items: center; gap: var(--space-sm); padding: 0.55rem 1.2rem; font-family: var(--font-body); font-size: 0.875rem; font-weight: 500; border: 1px solid transparent; border-radius: var(--radius-sm); cursor: pointer; transition: all var(--transition-fast); text-decoration: none; line-height: 1.3; } .btn:active { transform: scale(0.98); } .btn-primary { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .btn-primary:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); color: var(--color-btn-primary-text); } .btn-secondary { background: transparent; color: var(--color-text); border-color: var(--color-border-strong); } .btn-secondary:hover { background: var(--color-hover); border-color: var(--color-text-muted); } .btn-ghost { background: transparent; color: var(--color-text-muted); padding: 0.4rem 0.7rem; } .btn-ghost:hover { color: var(--color-text); background: var(--color-hover); } .btn-icon { padding: 0.4rem; border-radius: var(--radius-sm); background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: all var(--transition-fast); font-size: 16px; line-height: 1; min-width: 28px; min-height: 28px; } .btn-icon:hover { color: var(--color-text); background: var(--color-hover); } .btn-icon.active { color: var(--color-accent); background: var(--color-btn-active-bg); } .btn-icon:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; } .btn-icon.btn-disabled { opacity: 0.35; cursor: default; pointer-events: none; } /* --- Styled Tooltips --- */ [data-tooltip] { position: relative; } [data-tooltip]::after { content: attr(data-tooltip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); padding: 4px 8px; border-radius: var(--radius-sm); background: #161616; background: oklch(0.2 0 0); color: #eeeeee; color: oklch(0.95 0 0); font-size: 11px; font-weight: 500; line-height: 1.3; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity var(--transition-fast); z-index: var(--z-menu); } [data-tooltip]:hover::after { opacity: 1; transition-delay: 400ms; } [data-tooltip]:active::after { opacity: 0; transition-delay: 0ms; } /* Bottom variant for topbar buttons */ [data-tooltip-pos="bottom"]::after { bottom: auto; top: calc(100% + 6px); } /* Dark mode tooltip */ [data-theme="dark"] [data-tooltip]::after { background: #cecece; background: oklch(0.85 0 0); color: #0b0b0b; color: oklch(0.15 0 0); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) [data-tooltip]::after { background: #cecece; background: oklch(0.85 0 0); color: #0b0b0b; color: oklch(0.15 0 0); } } /* --- Landing Page --- */ .landing { max-width: min(64rem, 100%); margin: 0 auto; padding: var(--space-2xl) var(--space-lg); min-width: 0; box-sizing: border-box; } .landing-header { padding-bottom: var(--space-2xl); border-bottom: 1px solid var(--color-border); } .brand { display: flex; align-items: center; gap: var(--space-md); margin-bottom: var(--space-sm); } .brand-name { font-family: var(--font-display); font-size: clamp(2.4rem, 5vw, 3.6rem); font-weight: 700; letter-spacing: -0.03em; color: var(--color-text); } .brand-badge { font-family: var(--font-mono); font-size: 0.65rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-encrypted); background: var(--color-teal-light); padding: 0.2rem 0.55rem; border-radius: var(--radius-sm); } .landing-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-lg); } .new-dropdown { position: relative; } .new-btn { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.55rem 1rem; background: var(--color-accent); color: var(--color-btn-primary-text); border: 1px solid var(--color-accent); border-radius: var(--radius-md); font: inherit; font-size: 0.95rem; font-weight: 600; cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast); } .new-btn:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); } .new-btn-plus { font-size: 1.15rem; line-height: 1; } .new-btn-caret { font-size: 0.7rem; opacity: 0.85; } .new-menu { display: none; position: absolute; top: calc(100% + 4px); left: 0; min-width: 200px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); z-index: var(--z-overlay); padding: var(--space-xs); flex-direction: column; } .new-dropdown.open .new-menu { display: flex; } .new-menu-item { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); background: none; border: none; border-radius: var(--radius-sm); color: var(--color-text); font: inherit; font-size: 0.9rem; text-align: left; cursor: pointer; transition: background var(--transition-fast); } .new-menu-item:hover:not(:disabled) { background: var(--color-hover); } .new-menu-item-disabled { opacity: 0.45; cursor: default; pointer-events: auto; } .new-menu-item-disabled .new-menu-badge { margin-left: auto; font-size: 0.7rem; padding: 1px 6px; border-radius: var(--radius-sm); background: var(--color-border); color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.03em; } .new-menu-icon { font-size: 1rem; width: 1.25rem; text-align: center; color: var(--color-text-muted); } .daily-note-btn { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.55rem 1rem; background: transparent; color: var(--color-text); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); font: inherit; font-size: 0.95rem; font-weight: 500; cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast); } .daily-note-btn:hover { background: var(--color-hover); border-color: var(--color-text-muted); } .daily-note-icon { color: var(--color-accent); font-size: 1rem; line-height: 1; } /* Document list */ /* ======================================================== Recent Documents (#116) ======================================================== */ .recent-section { margin-bottom: var(--space-lg); } .recent-heading { font-family: var(--font-body); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-faint); margin-bottom: var(--space-sm); } .recent-list { display: flex; gap: var(--space-sm); overflow-x: auto; padding-bottom: var(--space-xs); max-width: 100%; min-width: 0; -webkit-overflow-scrolling: touch; } .recent-card { display: flex; flex-direction: column; gap: 4px; min-width: 140px; max-width: 180px; padding: var(--space-sm) var(--space-md); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); text-decoration: none; color: var(--color-text); transition: border-color var(--transition-fast), box-shadow var(--transition-fast); } .recent-card:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-sm); } .recent-card-icon { font-size: 1.25rem; } .recent-card-name { font-size: 0.8rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .recent-card-type { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); } /* --- Pinned section --- */ .pinned-section { margin-top: var(--space-lg); } .pinned-heading { font-family: var(--font-body); font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-faint); margin-bottom: var(--space-sm); } .pinned-list { display: flex; gap: var(--space-sm); overflow-x: auto; padding-bottom: var(--space-sm); max-width: 100%; min-width: 0; -webkit-overflow-scrolling: touch; } .pinned-card { display: flex; flex-direction: column; gap: var(--space-xs); min-width: 140px; max-width: 180px; padding: var(--space-sm) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-md); text-decoration: none; color: inherit; transition: box-shadow var(--transition-fast), border-color var(--transition-fast); background: var(--color-bg-elevated); } .pinned-card:hover { box-shadow: var(--shadow-md); border-color: var(--color-accent); } .pinned-card-icon { font-size: 1.2rem; } .pinned-card-name { font-size: 0.8rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pinned-card-type { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); } /* --- View toggle --- */ .view-toggle { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); cursor: pointer; color: var(--color-text-secondary); transition: border-color var(--transition-fast), color var(--transition-fast); } .view-toggle:hover { border-color: var(--color-accent); color: var(--color-accent); } .view-icon { fill: currentColor; } .doc-section { margin-top: var(--space-2xl); } .doc-section-title { font-family: var(--font-body); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-faint); margin-bottom: var(--space-md); } .doc-list { display: flex; flex-direction: column; gap: 1px; background: var(--color-border); border-radius: var(--radius-md); overflow: hidden; } /* Grid view */ .doc-list.grid-view { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-md); background: transparent; overflow: visible; } .doc-grid-card { display: flex; flex-direction: column; gap: var(--space-xs); padding: var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-md); text-decoration: none; color: inherit; background: var(--color-bg); transition: box-shadow var(--transition-fast), border-color var(--transition-fast); position: relative; } .doc-grid-card:hover { box-shadow: var(--shadow-md); border-color: var(--color-accent); } .doc-grid-card-header { display: flex; justify-content: space-between; align-items: center; } .doc-grid-card-header .doc-item-icon { font-size: 1.5rem; } .doc-grid-card-name { font-size: 0.85rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .doc-grid-card-footer { display: flex; justify-content: space-between; align-items: center; margin-top: auto; } .doc-grid-card-footer .doc-item-type { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); } .doc-grid-card-footer .doc-item-date { font-size: 0.65rem; color: var(--color-text-faint); } .doc-grid-card-actions { display: none; position: absolute; bottom: var(--space-xs); right: var(--space-xs); gap: 2px; } .doc-grid-card:hover .doc-grid-card-actions { display: flex; } .doc-item { display: flex; align-items: center; gap: var(--space-md); padding: var(--space-md) var(--space-lg); background: var(--color-surface); text-decoration: none; color: inherit; transition: background var(--transition-fast); } .doc-item:hover { background: var(--color-hover); color: inherit; } .doc-item-icon { font-size: 1.2rem; opacity: 0.6; } .doc-item-name { font-weight: 500; flex: 1; } .doc-item-type { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-text-faint); } .doc-item-date { font-size: 0.8rem; color: var(--color-text-muted); } /* --- Document Tags (#133) --- */ .doc-item-tags { display: inline-flex; gap: 4px; flex-shrink: 0; } .doc-tag-pill { display: inline-block; padding: 1px 6px; font-size: 0.7rem; border-radius: 9px; background: var(--color-surface-raised); color: var(--color-text-muted); white-space: nowrap; } .tag-filter-bar { display: flex; align-items: center; gap: 6px; padding: 8px 0; flex-wrap: wrap; } .tag-filter-label { font-size: 0.8rem; color: var(--color-text-muted); margin-right: 2px; } .tag-filter-pill { padding: 2px 10px; font-size: 0.75rem; border: 1px solid var(--color-border); border-radius: 12px; background: transparent; color: var(--color-text); cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast); } .tag-filter-pill:hover { background: var(--color-surface-raised); } .tag-filter-pill.active { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .doc-item-delete, .doc-item-duplicate, .doc-item-move, .doc-item-tag-edit { opacity: 0; transition: opacity var(--transition-fast); } .doc-item:hover .doc-item-delete, .doc-item:hover .doc-item-duplicate, .doc-item:hover .doc-item-move, .doc-item:hover .doc-item-tag-edit { opacity: 1; } /* Touch devices: always show action buttons (no hover state) */ @media (hover: none) { .doc-item-delete, .doc-item-duplicate, .doc-item-move, .doc-item-tag-edit { opacity: 0.7; } } /* Star button */ .doc-star { font-size: 1.1rem; line-height: 1; color: var(--color-text-faint); cursor: pointer; transition: color var(--transition-fast); flex-shrink: 0; } .doc-star:hover { color: var(--color-warning); } .empty-state { text-align: left; padding: var(--space-xl) 0; color: var(--color-text-muted); font-size: 0.95rem; } .empty-state strong { display: block; color: var(--color-text); font-weight: 600; margin-bottom: var(--space-xs); } /* --- Document toolbar (search, sort, folders) --- */ .doc-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); margin-bottom: var(--space-md); flex-wrap: wrap; } .doc-toolbar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm); } /* Breadcrumbs */ .doc-breadcrumbs { display: flex; align-items: center; gap: var(--space-xs); font-size: 0.85rem; } .breadcrumb-link { background: none; border: none; color: var(--color-accent); cursor: pointer; font: inherit; padding: 0; text-decoration: underline; text-underline-offset: 2px; } .breadcrumb-link:hover { color: var(--color-accent-hover); } .breadcrumb-sep { color: var(--color-text-faint); } .breadcrumb-current { font-weight: 600; color: var(--color-text); } /* Search */ .search-box { position: relative; display: flex; align-items: center; } .search-input { width: 180px; padding: var(--space-xs) var(--space-sm); padding-right: 1.8rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font: inherit; font-size: 0.85rem; transition: border-color var(--transition-fast), width var(--transition-med); } .search-input:focus { outline: none; border-color: var(--color-accent); width: 240px; } .search-clear { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--color-text-faint); cursor: pointer; font-size: 1rem; line-height: 1; padding: 2px; } .search-clear:hover { color: var(--color-text); } .no-results { padding: var(--space-lg) 0; color: var(--color-text-muted); font-size: 0.9rem; } /* Sort dropdown */ .sort-dropdown { position: relative; } .sort-btn { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text-muted); font: inherit; font-size: 0.8rem; cursor: pointer; white-space: nowrap; transition: border-color var(--transition-fast); } .sort-btn:hover { border-color: var(--color-border-strong); } .sort-menu { display: none; position: absolute; top: 100%; right: 0; margin-top: 4px; min-width: 160px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); z-index: var(--z-overlay); overflow: hidden; } .sort-menu.open { display: flex; flex-direction: column; } .sort-option { padding: var(--space-sm) var(--space-md); background: none; border: none; color: var(--color-text); font: inherit; font-size: 0.85rem; text-align: left; cursor: pointer; transition: background var(--transition-fast); } .sort-option:hover { background: var(--color-hover); } /* More menu (overflow actions: folder / import / backup) */ .more-menu { position: relative; } .more-btn { display: inline-flex; align-items: center; justify-content: center; padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text-muted); font: inherit; cursor: pointer; transition: border-color var(--transition-fast), color var(--transition-fast); } .more-btn:hover { border-color: var(--color-border-strong); color: var(--color-text); } .more-menu-panel { display: none; position: absolute; top: 100%; right: 0; margin-top: 4px; min-width: 200px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); /* Raise above .table-toolbar (also z-overlay=100) so opening the kebab overflow while the cursor is inside a table doesn't leave the cell background picker bleeding over "Code block" etc. See #714. */ z-index: var(--z-tooltip); padding: var(--space-xs); flex-direction: column; } .more-menu.open .more-menu-panel { display: flex; } .more-menu-item { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); background: none; border: none; border-radius: var(--radius-sm); color: var(--color-text); font: inherit; font-size: 0.85rem; text-align: left; cursor: pointer; transition: background var(--transition-fast); white-space: nowrap; } .more-menu-item:hover { background: var(--color-hover); } .more-menu-icon { width: 1.25rem; text-align: center; color: var(--color-text-muted); } .more-menu-sep { height: 1px; margin: var(--space-xs) 0; background: var(--color-border); } /* Folder grid */ .folder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-sm); margin-bottom: var(--space-md); } .folder-card { display: flex; flex-direction: column; gap: var(--space-xs); padding: var(--space-md); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); cursor: pointer; transition: all var(--transition-fast); position: relative; } .folder-card:hover { border-color: var(--color-border-strong); background: var(--color-hover); } /* ── Forge Workspaces ── */ .forge-section { margin-bottom: var(--space-lg); } .forge-section-heading { font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); margin: 0 0 var(--space-sm) 0; } .forge-workspace-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-sm); } .forge-workspace-card { display: flex; flex-direction: column; gap: var(--space-xs); padding: var(--space-md); background: var(--color-surface); border: 1px solid oklch(0.45 0.06 250); border-radius: var(--radius-md); cursor: pointer; transition: all var(--transition-fast); text-decoration: none; color: inherit; } .forge-workspace-card:hover { border-color: oklch(0.6 0.12 250); background: var(--color-hover); } .forge-workspace-card-header { display: flex; justify-content: space-between; align-items: center; } .forge-workspace-card-type { font-size: 0.7rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; color: oklch(0.65 0.1 250); } .forge-workspace-card-time { font-size: 0.7rem; color: var(--color-text-faint); } .forge-workspace-card-name { font-weight: 500; font-size: 0.9rem; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .forge-workspace-card-footer { display: flex; gap: var(--space-sm); align-items: center; font-size: 0.7rem; color: var(--color-text-faint); min-height: 1em; } .forge-workspace-card-versions { background: oklch(0.3 0.03 250); padding: 1px 6px; border-radius: var(--radius-sm); font-size: 0.65rem; } .forge-workspace-card-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; } /* ── Forge Note Button (in doc editor) ── */ .forge-archive { margin-top: var(--space-sm); } .forge-archive-summary { font-size: 0.75rem; color: var(--color-text-faint); cursor: pointer; padding: var(--space-xs) 0; } .forge-archive-summary:hover { color: var(--color-text); } .forge-workspace-card--done { opacity: 0.6; border-color: var(--color-border); } .forge-workspace-card--done:hover { opacity: 0.8; } .forge-note-btn { position: fixed; bottom: var(--space-lg); right: var(--space-lg); padding: var(--space-xs) var(--space-md); background: oklch(0.3 0.05 250); color: oklch(0.8 0.05 250); border: 1px solid oklch(0.45 0.06 250); border-radius: var(--radius-md); font-size: 0.8rem; font-weight: 500; cursor: pointer; transition: all var(--transition-fast); z-index: 100; } .forge-note-btn:hover { background: oklch(0.35 0.08 250); border-color: oklch(0.6 0.12 250); } .folder-card-icon { font-size: 1.4rem; } .folder-card-name { font-weight: 500; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .folder-card-count { font-size: 0.75rem; color: var(--color-text-faint); } .folder-card-actions { position: absolute; top: var(--space-xs); right: var(--space-xs); display: flex; gap: 2px; opacity: 0; transition: opacity var(--transition-fast); } .folder-card:hover .folder-card-actions { opacity: 1; } /* Trash section */ .trash-section { margin-top: var(--space-xl); padding-top: var(--space-md); border-top: 1px solid var(--color-border); } .trash-toggle { display: flex; align-items: center; gap: var(--space-sm); background: none; border: none; color: var(--color-text-muted); font: inherit; font-size: 0.85rem; cursor: pointer; padding: var(--space-xs) 0; } .trash-toggle:hover { color: var(--color-text); } .trash-toggle-icon { font-size: 0.7rem; transition: transform var(--transition-fast); } .trash-count { font-size: 0.75rem; color: var(--color-text-faint); } .trash-actions { padding: 0.5rem 0; display: flex; justify-content: flex-end; } .trash-item { opacity: 0.6; } .trash-item:hover { opacity: 0.85; } .trash-name { text-decoration: line-through; } .btn-sm { padding: var(--space-xs) var(--space-sm); font-size: 0.75rem; } .btn-secondary { padding: var(--space-xs) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font: inherit; font-size: 0.85rem; cursor: pointer; transition: all var(--transition-fast); } .btn-secondary:hover { border-color: var(--color-border-strong); background: var(--color-hover); } .btn-primary { padding: var(--space-xs) var(--space-md); border: 1px solid transparent; border-radius: var(--radius-sm); background: var(--color-accent); color: var(--color-btn-primary-text); font: inherit; font-size: 0.85rem; cursor: pointer; transition: all var(--transition-fast); } .btn-primary:hover { background: var(--color-accent-hover); } .btn-danger { padding: var(--space-xs) var(--space-md); border: 1px solid transparent; border-radius: var(--radius-sm); background: var(--color-danger); color: var(--color-btn-primary-text); font: inherit; font-size: 0.85rem; cursor: pointer; transition: all var(--transition-fast); } .btn-danger:hover { opacity: 0.85; } /* Modal backdrop */ .modal-backdrop { position: fixed; inset: 0; background: var(--color-modal-backdrop); display: flex; align-items: center; justify-content: center; z-index: var(--z-modal); overflow-y: auto; padding: var(--space-md); box-sizing: border-box; -webkit-overflow-scrolling: touch; } .modal { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--space-xl); box-shadow: var(--shadow-lg); max-width: 400px; width: 90%; } .modal h2 { font-family: var(--font-display); font-size: 1.3rem; margin-bottom: var(--space-sm); } .modal p { font-size: 0.9rem; color: var(--color-text-muted); margin-bottom: var(--space-md); } /* Username modal */ .username-input, .folder-name-input { width: 100%; padding: var(--space-sm) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font: inherit; font-size: 0.95rem; margin-bottom: var(--space-md); } .username-input:focus, .folder-name-input:focus { outline: none; border-color: var(--color-accent); } /* Handle typeahead suggestions */ .handle-suggestions { position: absolute; left: 0; right: 0; bottom: 100%; z-index: 1001; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); margin-bottom: 4px; max-height: 280px; overflow-y: auto; box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.3); } .handle-suggestion { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); cursor: pointer; transition: background 0.1s; } .handle-suggestion:hover, .handle-suggestion.active { background: var(--color-hover); } .suggestion-avatar { width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; object-fit: cover; } .suggestion-avatar-placeholder { background: var(--color-border); } .suggestion-text { display: flex; flex-direction: column; min-width: 0; } .suggestion-name { font-weight: 500; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .suggestion-handle { font-size: 0.8rem; color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #username-modal { background: var(--color-bg); } .username-modal { overflow: visible; max-width: 440px; border: none; box-shadow: none; } .welcome-tagline { color: var(--color-text-secondary); font-size: 0.95rem; margin-bottom: var(--space-md); } .welcome-features { list-style: none; padding: 0; margin: 0 0 var(--space-lg); font-size: 0.85rem; color: var(--color-text-muted); line-height: 1.6; } .welcome-features li::before { content: "\2713\00a0"; color: var(--color-accent); font-weight: 600; } .welcome-signin-label { font-size: 0.85rem; font-weight: 500; color: var(--color-text-secondary); margin-bottom: var(--space-sm); } .handle-input-wrapper { position: relative; margin-bottom: var(--space-md); } .handle-input-wrapper .username-input { margin-bottom: 0; } .username-modal-actions, .folder-modal-actions, .move-modal-actions { display: flex; justify-content: flex-end; gap: var(--space-sm); } /* Setup screen */ .setup-modal { max-width: 480px; } .setup-modal h3 { font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); margin-bottom: var(--space-xs); } .setup-capabilities, .setup-limitations { list-style: none; padding: 0; margin: 0 0 var(--space-md); font-size: 0.85rem; color: var(--color-text-muted); line-height: 1.6; } .setup-capabilities li::before { content: "\2713\00a0"; color: var(--color-accent); font-weight: 600; } .setup-limitations li::before { content: "\2022\00a0"; color: var(--color-text-faint); } .setup-disclaimer { border-top: 1px solid var(--color-border); padding-top: var(--space-sm); margin-bottom: var(--space-md); } .setup-disclaimer p { font-size: 0.78rem; color: var(--color-text-faint); line-height: 1.5; margin: 0; } .setup-modal .btn-primary { width: 100%; } .setup-preview-banner { background: var(--color-accent); color: var(--color-bg); font-size: 0.75rem; font-weight: 600; text-align: center; padding: var(--space-xs) var(--space-sm); border-radius: var(--radius-sm); margin-bottom: var(--space-md); } /* Waitlist modal */ .waitlist-modal { max-width: 460px; text-align: center; } .waitlist-modal h2 { margin-bottom: var(--space-sm); } .waitlist-handle { font-size: 0.95rem; font-weight: 600; color: var(--color-accent); margin-bottom: var(--space-md); } .waitlist-message { font-size: 0.9rem; color: var(--color-text-secondary); line-height: 1.5; margin-bottom: var(--space-md); } .waitlist-cta { font-size: 0.9rem; color: var(--color-text); line-height: 1.5; margin-bottom: var(--space-md); } .waitlist-cta a { color: var(--color-accent); font-weight: 600; text-decoration: none; } .waitlist-cta a:hover { text-decoration: underline; } .waitlist-source { font-size: 0.8rem; color: var(--color-text-muted); line-height: 1.5; margin-bottom: var(--space-lg); } .waitlist-source a { color: var(--color-text-secondary); text-decoration: underline; } .waitlist-actions { display: flex; justify-content: center; } .waitlist-actions .btn-primary { text-decoration: none; display: inline-flex; align-items: center; } /* Move to folder modal */ .move-folder-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--space-md); max-height: 300px; overflow-y: auto; } .move-option { padding: var(--space-sm) var(--space-md); background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-text); font: inherit; font-size: 0.9rem; text-align: left; cursor: pointer; transition: all var(--transition-fast); } .move-option:hover { background: var(--color-hover); border-color: var(--color-border-strong); } .move-option.active { border-color: var(--color-accent); background: var(--color-btn-active-bg); } .move-empty { font-size: 0.85rem; color: var(--color-text-muted); padding: var(--space-md); } /* User badge in topbar */ .user-badge { display: none; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-pill); font-size: 0.8rem; color: var(--color-text-muted); cursor: pointer; transition: all var(--transition-fast); white-space: nowrap; } .user-badge:hover { background: var(--color-hover); color: var(--color-text); border-color: var(--color-accent); } .user-badge .user-avatar { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; } /* Doc owner in list */ .doc-item-owner { font-size: 0.75rem; color: var(--color-text-muted); margin-left: var(--space-xs); white-space: nowrap; } .doc-item-owner::before { content: 'by '; } /* --- Encryption indicator --- */ .encryption-bar { display: flex; align-items: center; gap: var(--space-sm); font-family: var(--font-mono); font-size: 0.7rem; color: var(--color-encrypted); padding: var(--space-sm) 0; letter-spacing: 0.02em; } .encryption-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-encrypted); animation: pulse 3s ease-in-out infinite; } @keyframes pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } } .instance-info-btn { margin-left: auto; background: none; border: 1px solid var(--color-border); border-radius: 50%; width: 18px; height: 18px; font-family: var(--font-mono); font-size: 0.6rem; font-weight: 600; color: var(--color-text-muted); cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; line-height: 1; flex-shrink: 0; } .instance-info-btn:hover { border-color: var(--color-text-muted); color: var(--color-text); } .instance-info-panel { max-width: 480px; width: 90vw; } .instance-info-panel h3 { font-family: var(--font-display); font-size: 1.1rem; font-weight: 600; margin: 0 0 var(--space-sm); color: var(--color-text); } .instance-info-panel .info-summary { font-size: 0.85rem; color: var(--color-text-muted); margin: 0 0 var(--space-md); line-height: 1.5; } .instance-info-panel .info-section-label { font-family: var(--font-mono); font-size: 0.65rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-faint); margin: var(--space-md) 0 var(--space-xs); } .instance-info-panel ul { list-style: none; padding: 0; margin: 0 0 var(--space-sm); } .instance-info-panel li { font-size: 0.8rem; color: var(--color-text); padding: var(--space-xs) 0; display: flex; align-items: baseline; gap: var(--space-sm); } .instance-info-panel li::before { flex-shrink: 0; font-size: 0.7rem; } .instance-info-panel .info-capabilities li::before { content: '\2713'; color: var(--color-success); } .instance-info-panel .info-limitations li::before { content: '\2014'; color: var(--color-text-faint); } .instance-info-panel .info-notice { font-size: 0.8rem; color: var(--color-text-muted); background: var(--color-surface); border-radius: var(--radius-sm); padding: var(--space-sm) var(--space-md); margin-top: var(--space-md); line-height: 1.5; } .instance-info-panel .info-flavor-badge { font-family: var(--font-mono); font-size: 0.6rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-encrypted); background: var(--color-teal-light); padding: 0.15rem 0.45rem; border-radius: var(--radius-sm); margin-left: var(--space-sm); } .site-footer { margin-top: var(--space-2xl); padding-top: var(--space-lg); border-top: 1px solid var(--color-border); } .site-footer-links { font-size: 0.75rem; color: var(--color-text-faint); padding: var(--space-sm) 0; line-height: 1.8; } .site-footer-links a { color: var(--color-text-muted); text-decoration: none; } .site-footer-links a:hover { color: var(--color-text); text-decoration: underline; } .footer-sep { margin: 0 0.3em; color: var(--color-text-faint); } .desktop-download { margin-top: var(--space-md); text-align: center; } .desktop-download-btn { display: inline-flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-md); font-size: 0.8rem; font-family: var(--font-mono); color: var(--color-text-muted); border: 1px solid var(--color-border); border-radius: var(--radius); text-decoration: none; transition: border-color var(--transition-fast), color var(--transition-fast); } .desktop-download-btn:hover { color: var(--color-text); border-color: var(--color-text-muted); } .desktop-download-version { opacity: 0.6; font-size: 0.75rem; } /* --- App Shell (docs + sheets) --- */ .app-shell { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; } .app-topbar { display: flex; align-items: center; gap: var(--space-md); padding: var(--space-sm) var(--space-md); padding-left: max(var(--space-md), env(safe-area-inset-left)); padding-right: max(var(--space-md), env(safe-area-inset-right)); border-bottom: 1px solid var(--color-border); background: var(--color-surface); flex-shrink: 0; } /* Electron traffic light padding — macOS hiddenInset titlebar */ .is-electron .app-topbar { padding-left: 96px; -webkit-app-region: drag; } .is-electron .app-topbar button, .is-electron .app-topbar input, .is-electron .app-topbar a, .is-electron .app-topbar select, .is-electron .app-topbar .collab-avatars { -webkit-app-region: no-drag; } .is-electron .brand { padding-left: 88px; } .app-logo { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--color-text); text-decoration: none; letter-spacing: -0.02em; } .app-logo:hover { color: var(--color-accent); } .doc-title-input { font-family: var(--font-body); font-size: 0.9rem; font-weight: 500; border: none; background: transparent; color: var(--color-text); padding: 0.3rem 0.5rem; border-radius: var(--radius-sm); outline: none; min-width: 12rem; transition: background var(--transition-fast); } .doc-title-input:hover { background: var(--color-hover); } .doc-title-input:focus { background: var(--color-surface-alt); } .topbar-spacer { flex: 1; } .status-indicator { display: flex; align-items: center; gap: var(--space-xs); font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); letter-spacing: 0.02em; } .status-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--color-text-faint); } .status-dot.connected { background: var(--color-success); } .status-dot.encrypted { background: var(--color-encrypted); } .collab-avatars { display: flex; align-items: center; } .collab-avatar { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.65rem; font-weight: 600; color: var(--color-collab-text); margin-left: -4px; border: 2px solid var(--color-surface); } .collab-avatar:first-child { margin-left: 0; } /* --- Toolbar (Google Docs-style) --- */ .toolbar { display: flex; align-items: center; gap: 2px; padding: var(--space-xs) var(--space-md); border-bottom: 1px solid var(--color-border); background: var(--color-bg); flex-shrink: 0; flex-wrap: wrap; } .toolbar.gdocs-toolbar { min-height: 40px; padding: 0 var(--space-sm); gap: 2px; flex-wrap: wrap; overflow: visible; } .toolbar-group { display: flex; align-items: center; gap: 1px; } .toolbar-sep { width: 1px; height: 24px; background: var(--color-border); margin: 0 4px; flex-shrink: 0; } /* Google Docs-style toolbar button */ .tb-btn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: none; border-radius: var(--radius-sm); background: transparent; color: var(--color-text-muted); cursor: pointer; font-size: 14px; line-height: 1; transition: background var(--transition-fast), color var(--transition-fast), transform var(--transition-fast); flex-shrink: 0; } .tb-btn:active { transform: scale(0.95); } .tb-btn:hover { color: var(--color-text); background: #eeeeee; background: oklch(0.95 0 0); } .tb-btn:active, .tb-btn.active { color: var(--color-accent); background: #c1dcf0; background: oklch(0.88 0.04 240); } /* Dark mode hover/active overrides for toolbar buttons */ [data-theme="dark"] .tb-btn:hover { background: #222222; background: oklch(0.25 0 0); } [data-theme="dark"] .tb-btn:active, [data-theme="dark"] .tb-btn.active { background: #14242f; background: oklch(0.25 0.03 240); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tb-btn:hover { background: #222222; background: oklch(0.25 0 0); } :root:not([data-theme="light"]) .tb-btn:active, :root:not([data-theme="light"]) .tb-btn.active { background: #14242f; background: oklch(0.25 0.03 240); } } /* Text-style toolbar buttons (smaller font for text labels) */ .tb-btn-text { font-size: 11px; font-weight: 600; font-family: var(--font-body); letter-spacing: -0.02em; width: auto; padding: 0 5px; } .tb-btn-underline { text-decoration: underline; } .tb-btn-strike { text-decoration: line-through; } .tb-btn-code { font-family: var(--font-mono); font-size: 11px; font-weight: 500; } /* Compact toolbar selects (Google Docs-style) */ .tb-select { font-family: var(--font-body); font-size: 13px; padding: 2px 18px 2px 6px; height: 28px; border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; color: var(--color-text); cursor: pointer; outline: none; transition: border-color var(--transition-fast), background var(--transition-fast); -webkit-appearance: none; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 4px center; background-size: 8px; } .tb-select:hover { border-color: var(--color-border); background-color: #eeeeee; background-color: oklch(0.95 0 0); } .tb-select:focus { border-color: var(--color-border-strong); } .tb-select-narrow { width: 52px; padding-right: 16px; } [data-theme="dark"] .tb-select:hover { background-color: #222222; background-color: oklch(0.25 0 0); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tb-select:hover { background-color: #222222; background-color: oklch(0.25 0 0); } } /* Color picker wrapper (shows swatch under icon) */ .tb-color-wrap { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--radius-sm); cursor: pointer; transition: background var(--transition-fast); } .tb-color-wrap:hover { background: #eeeeee; background: oklch(0.95 0 0); } [data-theme="dark"] .tb-color-wrap:hover { background: #222222; background: oklch(0.25 0 0); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tb-color-wrap:hover { background: #222222; background: oklch(0.25 0 0); } } .tb-color { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; border: none; padding: 0; } .tb-color-label { font-size: 14px; font-weight: 700; line-height: 1; color: var(--color-text-muted); pointer-events: none; position: relative; top: -4px; } .tb-color-swatch { position: absolute; bottom: 2px; left: 5px; right: 5px; height: var(--color-swatch-height, 4px); border-radius: 1px; background: var(--color-text); pointer-events: none; } .tb-color-swatch-highlight { background: var(--color-highlight-default); } /* Color palette dropdown (v0.58.0) — preset colors beside each picker */ .tb-color-palette-toggle { position: absolute; right: -8px; bottom: 0; width: 12px; height: 12px; padding: 0; border: none; background: transparent; color: var(--color-text-faint); font-size: 10px; line-height: 1; cursor: pointer; border-radius: 2px; z-index: 2; } .tb-color-palette-toggle:hover { color: var(--color-text); background: var(--color-bg-hover, oklch(0.92 0 0)); } [data-theme="dark"] .tb-color-palette-toggle:hover { background: oklch(0.3 0 0); } .tb-color-palette { position: absolute; top: 100%; left: 0; margin-top: 4px; padding: 6px; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12); display: grid; grid-template-columns: repeat(7, 20px); gap: 4px; z-index: 30; } .tb-color-palette[hidden] { display: none; } .tb-color-palette-swatch { width: 20px; height: 20px; padding: 0; border: 1px solid var(--color-border); border-radius: 3px; cursor: pointer; transition: transform 0.08s ease-out; } .tb-color-palette-swatch:hover, .tb-color-palette-swatch:focus-visible { transform: scale(1.15); outline: 2px solid var(--color-accent, oklch(0.62 0.18 240)); outline-offset: 1px; } /* Inline SVG toolbar icons */ .tb-icon { width: 16px; height: 16px; display: block; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; } /* Inline in buttons */ .tb-btn .tb-icon { display: block; } /* Inline in dropdown items */ .item-icon .tb-icon, .dd-icon .tb-icon { display: block; } /* Legacy toolbar select/color (non-gdocs toolbars) */ .toolbar select { font-family: var(--font-body); font-size: 0.8rem; padding: 0.3rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); cursor: pointer; } .toolbar select:hover { border-color: var(--color-border-strong); } .toolbar select:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; } .toolbar input[type="color"] { width: 24px; height: 24px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; padding: 1px; } .toolbar input[type="color"]:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; } /* --- Docs Editor --- */ .editor-container { flex: 1; overflow-y: auto; padding: var(--space-xl) var(--space-lg); display: flex; justify-content: center; position: relative; } /* Toolbar must sit above editor-container's stacking context so dropdowns aren't clipped */ .toolbar { position: relative; z-index: var(--z-component); } .editor-wrapper { width: 100%; max-width: 48rem; } .tiptap { outline: none; min-height: 60vh; font-family: var(--font-display); font-size: 1.05rem; line-height: 1.7; color: var(--color-text); } .tiptap > *:first-child { margin-top: 0; } .tiptap h1 { font-size: 2rem; margin: 1.8em 0 0.6em; } .tiptap h2 { font-size: 1.5rem; margin: 1.5em 0 0.5em; } .tiptap h3 { font-size: 1.2rem; margin: 1.3em 0 0.4em; } .tiptap p { margin: 0.6em 0; } .tiptap ul, .tiptap ol { padding-left: 1.4em; margin: 0.5em 0; } .tiptap blockquote { border-left: 3px solid var(--color-accent); padding-left: var(--space-md); margin: 1em 0; color: var(--color-text-muted); font-style: italic; } .tiptap pre { background: var(--color-surface-alt); padding: var(--space-md); border-radius: var(--radius-md); overflow-x: auto; margin: 1em 0; } .tiptap pre code { background: none; padding: 0; font-size: 0.85rem; } .tiptap code { background: var(--color-surface-alt); padding: 0.15em 0.35em; border-radius: var(--radius-sm); font-size: 0.88em; } .tiptap a { color: var(--color-teal); cursor: pointer; } .tiptap img { max-width: 100%; height: auto; border-radius: var(--radius-md); margin: 1em 0; } .tiptap hr { border: none; border-top: 1px solid var(--color-border); margin: 2em 0; } .tiptap table { border-collapse: collapse; width: 100%; margin: 1em 0; } .tiptap th, .tiptap td { border: 1px solid var(--color-border); padding: 0.5em 0.7em; text-align: left; } .tiptap th { background: var(--color-surface); font-weight: 600; font-family: var(--font-body); font-size: 0.85rem; } .tiptap ul[data-type="taskList"] { list-style: none; padding-left: 0; margin: 0.5em 0; } .tiptap ul[data-type="taskList"] li { display: flex; align-items: flex-start; gap: 0.375rem; margin-bottom: 0.15em; } /* Kill paragraph margins inside task items so text aligns with checkbox */ .tiptap ul[data-type="taskList"] li > div > p { margin: 0; } .tiptap ul[data-type="taskList"] li > label { /* Center 16px checkbox within the line: (line-height * 1em - 16px) / 2 ≈ 4.4px */ margin-top: calc((1.55em - 16px) / 2); flex-shrink: 0; line-height: 0; } /* Task list checkbox styling */ .tiptap ul[data-type="taskList"] li > label input[type="checkbox"] { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border: 1.5px solid var(--color-border-strong); border-radius: 3px; background: var(--color-bg); cursor: pointer; pointer-events: auto; position: relative; display: block; flex-shrink: 0; margin: 0; transition: background var(--transition-fast), border-color var(--transition-fast); } .tiptap ul[data-type="taskList"] li > label input[type="checkbox"]:hover { border-color: var(--color-accent); background: var(--color-hover); } .tiptap ul[data-type="taskList"] li > label input[type="checkbox"]:checked { background: var(--color-accent); border-color: var(--color-accent); } .tiptap ul[data-type="taskList"] li > label input[type="checkbox"]:checked::after { content: ''; position: absolute; left: 3.5px; top: 0.5px; width: 5.5px; height: 9px; border: solid var(--color-btn-primary-text); border-width: 0 2px 2px 0; transform: rotate(45deg); } .tiptap ul[data-type="taskList"] li > label input[type="checkbox"]:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; } /* Nested task lists */ .tiptap ul[data-type="taskList"] ul[data-type="taskList"] { margin-top: 0.15em; margin-bottom: 0; } /* Checked task items: muted text */ .tiptap ul[data-type="taskList"] li[data-checked="true"] > div { color: var(--color-text-muted); text-decoration: line-through; text-decoration-color: var(--color-text-faint); } /* Collaboration cursors */ .collaboration-cursor__caret { position: relative; border-left: 2px solid; border-right: none; margin-left: -1px; margin-right: -1px; pointer-events: none; word-break: normal; } .collaboration-cursor__label { position: absolute; bottom: 100%; left: -1px; font-family: var(--font-mono); font-size: 0.6rem; font-weight: 600; padding: 1px 5px; border-radius: 3px 3px 3px 0; white-space: nowrap; color: var(--color-cursor-label); user-select: none; pointer-events: none; } .tiptap .is-empty::before { content: attr(data-placeholder); float: left; color: var(--color-text-faint); pointer-events: none; height: 0; font-style: italic; } /* --- Sheets Spreadsheet --- */ .sheets-app { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; } .formula-bar { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-xs) var(--space-md); border-bottom: 1px solid var(--color-border); background: var(--color-bg); flex-shrink: 0; } .cell-address { font-family: var(--font-mono); font-size: 0.8rem; font-weight: 500; width: 5rem; text-align: center; padding: 0.3rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-text); } .formula-input { flex: 1; font-family: var(--font-mono); font-size: 0.85rem; padding: 0.3rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); outline: none; } .formula-input:focus { border-color: var(--color-teal); box-shadow: 0 0 0 2px var(--color-focus); } .sheet-body { display: flex; flex: 1; min-height: 0; overflow: hidden; } .sheet-main { display: flex; flex-direction: column; flex: 1; min-width: 0; overflow: hidden; } .sheet-container { flex: 1; overflow: auto; position: relative; scrollbar-width: thin; scrollbar-color: #bbb7b0 transparent; scrollbar-color: oklch(0.78 0.01 75) transparent; } [data-theme="dark"] .sheet-container { scrollbar-color: #3e3a35 transparent; scrollbar-color: oklch(0.35 0.01 75) transparent; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-container { scrollbar-color: #3e3a35 transparent; scrollbar-color: oklch(0.35 0.01 75) transparent; } } /* WebKit scrollbar styling — matches .sheet-tabs. Thin thumb that fills the full track width, so there's no gap around the visible scrollbar. */ .sheet-container::-webkit-scrollbar { width: 6px; height: 6px; } .sheet-container::-webkit-scrollbar-track { background: transparent; } .sheet-container::-webkit-scrollbar-thumb { background: #bbb7b0; background: oklch(0.78 0.01 75); border-radius: 3px; } .sheet-container::-webkit-scrollbar-thumb:hover { background: #9c9792; background: oklch(0.68 0.01 75); } [data-theme="dark"] .sheet-container::-webkit-scrollbar-thumb { background: #3e3a35; background: oklch(0.35 0.01 75); } [data-theme="dark"] .sheet-container::-webkit-scrollbar-thumb:hover { background: #59554f; background: oklch(0.45 0.01 75); } .sheet-container::-webkit-scrollbar-corner { background: transparent; } .sheet-grid { border-collapse: separate; border-spacing: 0; table-layout: fixed; font-family: var(--font-mono); font-size: 0.8rem; user-select: none; width: max-content; } /* * #698 — keyboard focus indicator for the grid itself. * The grid table carries tabindex=0 so Tab from the toolbar / formula bar * lands here. The native outline would draw around the entire table body * (visually noisy); the selected cell already has its own teal outline * (`.sheet-grid td.selected`), so the grid-level focus ring is scoped to * keyboard-only activation (data-a11y-focus is set on Tab-press by the * inline script in index.html). */ .sheet-grid:focus { outline: none; } [data-a11y-focus] .sheet-grid:focus-visible { outline: 2px solid var(--color-teal); outline-offset: -2px; } .sheet-grid th { background: var(--color-surface); border: none; border-right: 1px solid var(--color-grid-header-line); border-bottom: 1px solid var(--color-grid-header-line); padding: 0.25rem 0.5rem; font-weight: 500; font-size: 0.7rem; color: var(--color-text-muted); position: sticky; z-index: 2; text-align: center; min-width: 3rem; height: 26px; box-sizing: border-box; } /* Column resize handle in header */ .sheet-grid thead th .col-resize-handle { position: absolute; top: 0; right: -3px; width: 6px; height: 100%; cursor: col-resize; z-index: 5; } .sheet-grid thead th .col-resize-handle:hover, .sheet-grid thead th .col-resize-handle.resizing { background: var(--color-teal); opacity: 0.5; } /* Resize indicator line while dragging */ .col-resize-indicator { position: absolute; top: 0; width: 2px; height: 100%; background: var(--color-teal); z-index: var(--z-overlay); pointer-events: none; opacity: 0.7; } .sheet-grid th.corner { position: sticky; left: 0; top: 0; z-index: 6; width: 3rem; min-width: 3rem; } .sheet-grid thead th { top: 0; position: sticky; z-index: 3; background: var(--color-surface); cursor: s-resize; } .sheet-grid thead th.corner { cursor: default; } /* Column header resize handle */ .sheet-grid thead th .col-resize-handle { position: absolute; top: 0; right: -3px; width: 6px; height: 100%; cursor: col-resize; z-index: 5; } .sheet-grid thead th .col-resize-handle:hover, .sheet-grid thead th .col-resize-handle.active { background: var(--color-teal); opacity: 0.5; } /* Column resize guide line */ .col-resize-guide { position: absolute; top: 0; width: 2px; height: 100%; background: var(--color-teal); opacity: 0.6; z-index: 20; pointer-events: none; } /* Row resize handle (mirrors column resize handle pattern) */ .sheet-grid th.row-header .row-resize-handle { position: absolute; bottom: -3px; left: 0; width: 100%; height: 6px; cursor: row-resize; z-index: 5; } .sheet-grid th.row-header .row-resize-handle:hover, .sheet-grid th.row-header .row-resize-handle.active { background: var(--color-teal); opacity: 0.5; } /* Row resize guide line */ .row-resize-guide { position: absolute; left: 0; height: 2px; width: 100%; background: var(--color-teal); z-index: var(--z-overlay); pointer-events: none; opacity: 0.7; } /* Hidden row/column indicators */ .hidden-row-indicator { height: 12px; } .hidden-row-indicator td { padding: 0 !important; border: none !important; } .hidden-row-indicator-line { height: 6px; background: var(--color-teal); opacity: 0.6; cursor: pointer; border-radius: 3px; transition: opacity var(--transition-fast), height var(--transition-fast); position: relative; } .hidden-row-indicator-line:hover { opacity: 1; height: 10px; } .hidden-row-indicator-line::after { content: 'Click to unhide'; position: absolute; left: 50%; top: -22px; transform: translateX(-50%); font-size: 0.6rem; font-family: var(--font-body); color: var(--color-bg); background: var(--color-text); padding: 2px 6px; border-radius: 3px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity var(--transition-fast); } .hidden-row-indicator-line:hover::after { opacity: 1; } .hidden-col-boundary { border-right: 2px solid var(--color-teal) !important; position: relative; } /* Clickable column unhide indicator (matches row indicator pattern) */ .hidden-col-indicator { position: absolute; top: 0; right: -6px; width: 12px; height: 100%; cursor: pointer; z-index: 6; display: flex; align-items: center; justify-content: center; } .hidden-col-indicator-bar { width: 6px; height: 100%; background: var(--color-teal); opacity: 0.6; border-radius: 3px; transition: opacity var(--transition-fast), width var(--transition-fast); } .hidden-col-indicator:hover .hidden-col-indicator-bar { opacity: 1; width: 8px; } .hidden-col-indicator::after { content: 'Click to unhide'; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 4px; font-size: 0.6rem; font-family: var(--font-body); color: var(--color-bg); background: var(--color-text); padding: 2px 6px; border-radius: 3px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity var(--transition-fast); z-index: 20; } .hidden-col-indicator:hover::after { opacity: 1; } .hidden-row-boundary { border-bottom: 2px solid var(--color-teal) !important; position: relative; } .sheet-grid .row-header { position: sticky; left: 0; z-index: 1; width: 3rem; min-width: 3rem; text-align: center; cursor: e-resize; background: var(--color-surface); } .sheet-grid td { border: none; padding: 0; height: 26px; min-height: 26px; box-sizing: border-box; position: relative; overflow: hidden; background: var(--color-bg); /* Grid lines via box-shadow instead of borders — avoids double-line artifacts from border-collapse/separate + sticky + background-clip interactions. Shadows render on top of backgrounds reliably. */ box-shadow: inset -1px 0 0 var(--color-grid-line), inset 0 -1px 0 var(--color-grid-line); } /* All rows rendered — browser scrolls natively, no virtual scroll spacers needed */ .sheet-grid td .cell-display { padding: 0.15rem 0.4rem; width: 100%; height: 100%; display: flex; align-items: center; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: cell; } /* Cell overflow text: when the next cell is empty, allow text to visually spill over */ .sheet-grid td.cell-overflow .cell-display { overflow: visible; z-index: 1; position: relative; } /* When the adjacent cell has content, show ellipsis instead of overflow */ .sheet-grid td.cell-overflow-clip .cell-display { text-overflow: ellipsis; } .sheet-grid td.selected { outline: 2px solid var(--color-teal); outline-offset: -1px; z-index: 1; } /* Multi-cell selection range highlight */ .sheet-grid td.in-range { background: #53c2c11f !important; background: oklch(0.75 0.1 195 / 0.12) !important; } [data-theme="dark"] .sheet-grid td.in-range { background: #00656633 !important; background: oklch(0.45 0.1 195 / 0.2) !important; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid td.in-range { background: #00656633 !important; background: oklch(0.45 0.1 195 / 0.2) !important; } } /* Array formula spill range */ .sheet-grid td.spill-source, .sheet-grid td.spill-target { border: 1px dashed #2784d580; border: 1px dashed oklch(0.6 0.15 250 / 0.5); } .sheet-grid td.spill-target .cell-display { color: #717171; color: oklch(0.55 0 0); } [data-theme="dark"] .sheet-grid td.spill-target .cell-display { color: #9e9e9e; color: oklch(0.7 0 0); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid td.spill-target .cell-display { color: #9e9e9e; color: oklch(0.7 0 0); } } /* --- Rich cell types --- */ .cell-checkbox { cursor: pointer; font-size: 1.1em; user-select: none; display: flex; align-items: center; justify-content: center; width: 100%; } .cell-rating { display: flex; gap: 1px; align-items: center; width: 100%; } .cell-rating-star { cursor: pointer; color: #9e9e9e; color: oklch(0.7 0 0); font-size: 1em; line-height: 1; user-select: none; transition: color var(--transition-fast); } .cell-rating-star.filled { color: #d9a514; color: oklch(0.75 0.15 85); } .cell-rating-star:hover { color: #f2b200; color: oklch(0.8 0.18 85); } .cell-progress { display: flex; align-items: center; gap: 0.3rem; width: 100%; min-width: 60px; } .cell-progress-bar { height: 0.6rem; border-radius: 3px; transition: width var(--transition-med); flex-shrink: 0; } .cell-progress-label { font-size: 0.7rem; color: #808080; color: oklch(0.6 0 0); white-space: nowrap; } /* --- Image Cell Styles --- */ .cell-image-container { display: flex; align-items: center; justify-content: center; padding: 2px; min-height: 24px; } .cell-image-container img { border-radius: 2px; } /* --- Pivot Table Styles --- */ .pivot-section { padding: var(--space-sm) var(--space-md); } .pivot-section:empty { display: none; } .pivot-container { position: relative; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-md); background: var(--color-bg); margin-bottom: var(--space-md); overflow-x: auto; } .pivot-container h4 { margin: 0 0 var(--space-sm) 0; font-size: 0.9rem; } .pivot-actions { position: absolute; top: var(--space-xs); right: var(--space-xs); display: flex; gap: var(--space-xs); } .pivot-actions button { font-size: 0.75rem; padding: 2px 8px; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-bg); cursor: pointer; } .pivot-actions button:hover { background: var(--color-bg-hover); } .pivot-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; } .pivot-table th, .pivot-table td { border: 1px solid var(--color-border); padding: 4px 8px; text-align: right; } .pivot-table th { background: var(--color-bg-secondary); font-weight: 600; text-align: left; } .pivot-table td.pivot-row-header { font-weight: 600; text-align: left; background: var(--color-bg-secondary); } .pivot-table td.pivot-total { font-weight: 600; background: #f6ede0; } .pivot-table td.pivot-total { font-weight: 600; background: oklch(0.95 0.02 80); } [data-theme="dark"] .pivot-table td.pivot-total { background: #272117; } [data-theme="dark"] .pivot-table td.pivot-total { background: oklch(0.25 0.02 80); } .pivot-table tfoot td { font-weight: 600; background: var(--color-bg-secondary); } /* --- Database View Styles --- */ .database-view-section { padding: var(--space-sm) var(--space-md); } .database-view-section:empty { display: none; } .db-view-toolbar { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-bg-secondary); } .db-view-toolbar select, .db-view-toolbar button { font-size: 0.8rem; padding: 4px 8px; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-bg); } .db-view-close { margin-left: auto; cursor: pointer; } /* Kanban */ .kanban-board { display: flex; gap: var(--space-md); overflow-x: auto; padding-bottom: var(--space-sm); min-height: 200px; } .kanban-column { min-width: 220px; max-width: 280px; flex-shrink: 0; background: var(--color-bg-secondary); border-radius: var(--radius-md); padding: var(--space-sm); } .kanban-column-header { font-weight: 600; font-size: 0.85rem; margin-bottom: var(--space-sm); padding-bottom: var(--space-xs); border-bottom: 2px solid var(--color-border); display: flex; justify-content: space-between; align-items: center; } .kanban-column-count { font-size: 0.7rem; color: var(--color-text-secondary); background: var(--color-bg); border-radius: 99px; padding: 1px 6px; } .kanban-card { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); margin-bottom: var(--space-xs); cursor: pointer; font-size: 0.8rem; transition: box-shadow var(--transition-fast); } .kanban-card:hover { box-shadow: 0 2px 8px #0000001a; } .kanban-card:hover { box-shadow: 0 2px 8px oklch(0 0 0 / 0.1); } .kanban-card-title { font-weight: 600; margin-bottom: 2px; } .kanban-card-field { color: var(--color-text-secondary); font-size: 0.75rem; } /* Gallery */ .gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-md); } .gallery-card { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-md); cursor: pointer; transition: box-shadow var(--transition-fast); } .gallery-card:hover { box-shadow: 0 2px 8px #0000001a; } .gallery-card:hover { box-shadow: 0 2px 8px oklch(0 0 0 / 0.1); } .gallery-card-title { font-weight: 600; font-size: 0.9rem; margin-bottom: var(--space-xs); } .gallery-card-field { font-size: 0.8rem; color: var(--color-text-secondary); } .gallery-card-field-label { font-weight: 500; } /* Calendar */ .calendar-view { max-width: 900px; } .calendar-month-header { font-size: 1rem; font-weight: 600; margin: var(--space-md) 0 var(--space-sm); display: flex; align-items: center; gap: var(--space-sm); } .calendar-month-nav { font-size: 0.85rem; cursor: pointer; background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 2px 8px; } .calendar-view .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--color-border); border: 1px solid var(--color-border); border-radius: var(--radius-sm); } .calendar-view .calendar-day-header { background: var(--color-bg-secondary); padding: 4px; text-align: center; font-size: 0.75rem; font-weight: 600; } .calendar-view .calendar-day { background: var(--color-bg); min-height: 80px; padding: 4px; font-size: 0.75rem; vertical-align: top; } .calendar-view .calendar-day.calendar-day-other { opacity: 0.4; } .calendar-view .calendar-day-number { font-weight: 600; margin-bottom: 2px; } .calendar-view .calendar-event { background: #7ee3d0; color: #002922; background: oklch(0.85 0.1 180); color: oklch(0.25 0.05 180); border-radius: 3px; padding: 1px 4px; margin-bottom: 1px; font-size: 0.7rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; } [data-theme="dark"] .calendar-view .calendar-event { background: #004a3c; color: #abd9cf; } [data-theme="dark"] .calendar-view .calendar-event { background: oklch(0.35 0.1 180); color: oklch(0.85 0.05 180); } .calendar-view .calendar-event:hover { opacity: 0.8; } /* --- Form Builder Styles --- */ .form-builder-main { max-width: 720px; margin: 0 auto; padding: var(--space-md); } .form-builder-toolbar { display: flex; gap: var(--space-sm); margin-bottom: var(--space-md); padding: var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-bg-secondary); } .form-header { margin-bottom: var(--space-md); } .form-description { width: 100%; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-sm); font-size: 0.9rem; resize: vertical; background: var(--color-bg); color: var(--color-text); } .form-question-card { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-md); margin-bottom: var(--space-sm); background: var(--color-bg); transition: border-color var(--transition-fast); } .form-question-card:focus-within { border-color: var(--color-accent); } .form-question-header { display: flex; align-items: center; gap: var(--space-xs); margin-bottom: var(--space-sm); } .form-question-number { width: 24px; height: 24px; border-radius: 50%; background: var(--color-accent); color: white; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; flex-shrink: 0; } .form-question-type-badge { font-size: 0.7rem; padding: 2px 6px; border-radius: 99px; background: var(--color-bg-secondary); color: var(--color-text-secondary); } .form-question-label, .form-question-desc { width: 100%; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); font-size: 0.9rem; margin-bottom: var(--space-xs); background: var(--color-bg); color: var(--color-text); } .form-question-label { font-weight: 500; } .form-question-desc { font-size: 0.8rem; color: var(--color-text-secondary); } .form-question-required-label { font-size: 0.75rem; display: flex; align-items: center; gap: 4px; } .form-question-header button { background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 2px 6px; cursor: pointer; font-size: 0.8rem; } .form-question-header button:hover { background: var(--color-bg-hover); } .form-question-header button:disabled { opacity: 0.3; cursor: default; } .form-question-options { margin-top: var(--space-xs); } .form-option-row { display: flex; align-items: center; gap: var(--space-xs); margin-bottom: 4px; } .form-option-input { flex: 1; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 4px 8px; font-size: 0.8rem; background: var(--color-bg); color: var(--color-text); } .form-option-remove, .form-add-option { font-size: 0.75rem; background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 2px 6px; cursor: pointer; } .form-add-option { margin-top: 4px; } .form-question-type-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-xs); } .form-type-btn { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); cursor: pointer; font-size: 0.85rem; } .form-type-btn:hover { background: var(--color-bg-hover); border-color: var(--color-accent); } .form-type-icon { font-size: 1.1rem; width: 24px; text-align: center; } /* Form preview */ .form-preview-container { max-width: 600px; margin: 0 auto; } .form-preview-desc { color: var(--color-text-secondary); margin-bottom: var(--space-md); } .form-preview-question { margin-bottom: var(--space-md); } .form-preview-label { font-weight: 500; display: block; margin-bottom: 4px; } .form-required-mark { color: #de3b3d; } .form-required-mark { color: oklch(0.6 0.2 25); } .form-preview-hint { font-size: 0.8rem; color: var(--color-text-secondary); margin: 2px 0 6px; } .form-preview-input, .form-preview-textarea, .form-preview-select { width: 100%; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); font-size: 0.9rem; background: var(--color-bg); color: var(--color-text); } .form-preview-radio, .form-preview-checkbox { display: block; padding: 4px 0; font-size: 0.9rem; cursor: pointer; } .form-preview-rating, .form-preview-scale { display: flex; gap: 4px; } .form-rating-star { font-size: 1.5rem; background: none; border: none; cursor: pointer; color: var(--color-border); transition: color var(--transition-fast); } .form-rating-star:hover, .form-rating-star.active { color: #dfa11a; } .form-rating-star:hover, .form-rating-star.active { color: oklch(0.75 0.15 80); } .form-scale-btn { width: 32px; height: 32px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); cursor: pointer; font-size: 0.85rem; } .form-scale-btn:hover, .form-scale-btn.active { background: var(--color-accent); color: white; border-color: var(--color-accent); } .form-preview-error { color: #de3b3d; font-size: 0.8rem; min-height: 1.2em; } .form-preview-error { color: oklch(0.6 0.2 25); font-size: 0.8rem; min-height: 1.2em; } .form-preview-actions { margin-top: var(--space-lg); } /* File upload question */ .form-file-upload { margin-top: var(--space-xs); } .form-file-input { display: block; width: 100%; padding: var(--space-sm); border: 2px dashed var(--color-border); border-radius: var(--radius-sm, 4px); background: var(--color-bg); cursor: pointer; font-size: 0.85rem; } .form-file-input:hover { border-color: var(--color-accent); } .form-file-input:disabled { opacity: 0.5; cursor: wait; } .form-file-status { font-size: 0.8rem; margin-top: 4px; min-height: 1.2em; } .form-file-uploading { color: var(--color-text-secondary); } .form-file-success { color: oklch(0.6 0.18 145); } .form-file-error { color: oklch(0.6 0.2 25); } .form-file-name { font-weight: 500; } .form-file-size { color: var(--color-text-secondary); } .form-file-link { color: var(--color-accent); text-decoration: underline; } .sheet-grid td.editing .cell-display { display: none; } .cell-editor { position: absolute; top: 0; left: 0; min-width: 100%; min-height: 100%; font-family: var(--font-mono); font-size: 0.8rem; padding: 0.15rem 0.4rem; border: 2px solid var(--color-teal); border-radius: 1px; outline: none; background: var(--color-cell-editor-bg); color: var(--color-text); z-index: var(--z-component); box-shadow: 0 2px 8px #006e6f26; box-shadow: 0 2px 8px oklch(0.48 0.1 195 / 0.15); box-sizing: border-box; } .cell-editor::placeholder { color: var(--color-text-faint); font-style: italic; } /* --- Frozen panes --- */ .sheet-grid td.frozen-row, .sheet-grid td.frozen-col, .sheet-grid td.frozen-corner { position: sticky; background: var(--color-bg); /* Force own compositing layer — prevents WebKit/Blink from dropping the background paint of sticky cells during fast scrolling (oklch + custom properties exacerbate the bug). */ -webkit-backface-visibility: hidden; backface-visibility: hidden; } [data-theme="dark"] .sheet-grid td.frozen-row, [data-theme="dark"] .sheet-grid td.frozen-col, [data-theme="dark"] .sheet-grid td.frozen-corner { background: var(--color-bg); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid td.frozen-row, :root:not([data-theme="light"]) .sheet-grid td.frozen-col, :root:not([data-theme="light"]) .sheet-grid td.frozen-corner { background: var(--color-bg); } } .sheet-grid td.frozen-row { z-index: 3; } .sheet-grid td.frozen-col { z-index: 2; } .sheet-grid td.frozen-corner { z-index: 4; } /* Frozen column headers (thead th) that are also sticky-left need z-index 5 so they stay above frozen-corner cells (z-index 4) during scrolling. */ .sheet-grid thead th.frozen-col { z-index: 5; } /* Frozen row headers need z-index 4 so they stay above frozen-row cells (z-index 3) when scrolling horizontally. They're sticky in both directions (left from .row-header, top from inline style). */ .sheet-grid th.row-header.frozen-row { z-index: 4; background: var(--color-surface); } /* Freeze boundary: thicker line with shadow for clear visual separation */ .sheet-grid td.freeze-border-bottom, .sheet-grid th.freeze-border-bottom { border-bottom: 2px solid #006e6f99; border-bottom: 2px solid oklch(0.48 0.1 195 / 0.6); box-shadow: 0 2px 4px #006e6f26; box-shadow: 0 2px 4px oklch(0.48 0.1 195 / 0.15); } .sheet-grid td.freeze-border-right, .sheet-grid th.freeze-border-right { border-right: 2px solid #006e6f99; border-right: 2px solid oklch(0.48 0.1 195 / 0.6); box-shadow: 2px 0 4px #006e6f26; box-shadow: 2px 0 4px oklch(0.48 0.1 195 / 0.15); } /* Corner cells with both borders need combined box-shadow (CSS overwrites, not combines) */ .sheet-grid td.freeze-border-bottom.freeze-border-right, .sheet-grid th.freeze-border-bottom.freeze-border-right { box-shadow: 2px 0 4px #006e6f26, 0 2px 4px #006e6f26; box-shadow: 2px 0 4px oklch(0.48 0.1 195 / 0.15), 0 2px 4px oklch(0.48 0.1 195 / 0.15); } [data-theme="dark"] .sheet-grid td.freeze-border-bottom, [data-theme="dark"] .sheet-grid th.freeze-border-bottom { border-bottom-color: #0f9293b3; border-bottom-color: oklch(0.6 0.1 195 / 0.7); box-shadow: 0 2px 6px #00000066; box-shadow: 0 2px 6px oklch(0.05 0.005 195 / 0.4); } [data-theme="dark"] .sheet-grid td.freeze-border-right, [data-theme="dark"] .sheet-grid th.freeze-border-right { border-right-color: #0f9293b3; border-right-color: oklch(0.6 0.1 195 / 0.7); box-shadow: 2px 0 6px #00000066; box-shadow: 2px 0 6px oklch(0.05 0.005 195 / 0.4); } [data-theme="dark"] .sheet-grid td.freeze-border-bottom.freeze-border-right, [data-theme="dark"] .sheet-grid th.freeze-border-bottom.freeze-border-right { box-shadow: 2px 0 6px #00000066, 0 2px 6px #00000066; box-shadow: 2px 0 6px oklch(0.05 0.005 195 / 0.4), 0 2px 6px oklch(0.05 0.005 195 / 0.4); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid td.freeze-border-bottom, :root:not([data-theme="light"]) .sheet-grid th.freeze-border-bottom { border-bottom-color: #0f9293b3; border-bottom-color: oklch(0.6 0.1 195 / 0.7); box-shadow: 0 2px 6px #00000066; box-shadow: 0 2px 6px oklch(0.05 0.005 195 / 0.4); } :root:not([data-theme="light"]) .sheet-grid td.freeze-border-right, :root:not([data-theme="light"]) .sheet-grid th.freeze-border-right { border-right-color: #0f9293b3; border-right-color: oklch(0.6 0.1 195 / 0.7); box-shadow: 2px 0 6px #00000066; box-shadow: 2px 0 6px oklch(0.05 0.005 195 / 0.4); } :root:not([data-theme="light"]) .sheet-grid td.freeze-border-bottom.freeze-border-right, :root:not([data-theme="light"]) .sheet-grid th.freeze-border-bottom.freeze-border-right { box-shadow: 2px 0 6px #00000066, 0 2px 6px #00000066; box-shadow: 2px 0 6px oklch(0.05 0.005 195 / 0.4), 0 2px 6px oklch(0.05 0.005 195 / 0.4); } } /* Active state for freeze toolbar buttons */ .btn-icon.freeze-active, .tb-btn.freeze-active { color: var(--color-teal); background: var(--color-teal-light); } /* Cursor during column resize */ body.col-resizing, body.col-resizing * { cursor: col-resize !important; user-select: none !important; } /* Cell formatting classes */ .cell-bold { font-weight: 600; } .cell-italic { font-style: italic; } .cell-align-left { justify-content: flex-start; } .cell-align-center { justify-content: center; } .cell-align-right { justify-content: flex-end; } /* Sheet tabs — fixed-height strip with horizontally scrollable tabs and a sticky "add sheet" button that stays visible while scrolling. */ .sheet-tabs { display: flex; align-items: center; flex-wrap: nowrap; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); border-top: 1px solid var(--color-border); background: var(--color-surface); flex-shrink: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; scrollbar-color: oklch(0.78 0.01 75) transparent; } [data-theme="dark"] .sheet-tabs { scrollbar-color: oklch(0.35 0.01 75) transparent; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-tabs { scrollbar-color: oklch(0.35 0.01 75) transparent; } } /* Thin scrollbar matched to .sheet-container — no transparent border so the thumb fills the track, no "gappy" look. */ .sheet-tabs::-webkit-scrollbar { height: 6px; } .sheet-tabs::-webkit-scrollbar-track { background: transparent; } .sheet-tabs::-webkit-scrollbar-thumb { background: oklch(0.78 0.01 75); border-radius: 3px; } .sheet-tabs::-webkit-scrollbar-thumb:hover { background: oklch(0.68 0.01 75); } [data-theme="dark"] .sheet-tabs::-webkit-scrollbar-thumb { background: oklch(0.35 0.01 75); } [data-theme="dark"] .sheet-tabs::-webkit-scrollbar-thumb:hover { background: oklch(0.45 0.01 75); } .sheet-tabs::-webkit-scrollbar-corner { background: transparent; } .sheet-tab { font-family: var(--font-body); font-size: 0.75rem; font-weight: 500; padding: var(--space-xs) var(--space-sm); background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--color-text-muted); cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); position: relative; flex-shrink: 0; white-space: nowrap; line-height: 1.4; } .sheet-tab:hover { background: var(--color-hover); color: var(--color-text); } .sheet-tab.active { background: var(--color-bg); color: var(--color-text); border-color: var(--color-border); } /* Sheet tab drag reorder */ .sheet-tab.dragging { opacity: 0.4; } .sheet-tab.drag-over-left::before { content: ''; position: absolute; left: -2px; top: 2px; bottom: 2px; width: 2px; background: var(--color-teal); border-radius: 1px; } .sheet-tab.drag-over-right::after { content: ''; position: absolute; right: -2px; top: 2px; bottom: 2px; width: 2px; background: var(--color-teal); border-radius: 1px; } /* Sticky "add sheet" button — stays pinned to the right edge of the visible strip even while the tab list is scrolled. Uses a ::before gradient to softly fade tabs out as they scroll underneath, instead of hard-stopping at a box-shadow edge. */ .sheet-tab-add { position: sticky; right: 0; flex-shrink: 0; font-size: 0.9rem; line-height: 1; padding: var(--space-xs) var(--space-sm); margin-left: auto; background: var(--color-surface); border: 1px solid transparent; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); } .sheet-tab-add::before { content: ''; position: absolute; top: 0; bottom: 0; right: 100%; width: 24px; pointer-events: none; background: linear-gradient(to right, transparent, var(--color-surface)); } .sheet-tab-add:hover { background: var(--color-hover); color: var(--color-text); border-color: var(--color-border); } .sheet-tab-add:hover::before { background: linear-gradient(to right, transparent, var(--color-hover)); } /* Sheet tab color bar — colored underline indicator */ .sheet-tab-color-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; border-radius: 0 0 var(--radius-sm) var(--radius-sm); pointer-events: none; } /* Sheet tab label (inside button, next to color bar) */ .sheet-tab-label { position: relative; z-index: 1; } /* Inline rename input */ .sheet-tab-rename { outline: none; border: 1px solid var(--color-teal); border-radius: 2px; padding: 0 2px; background: var(--color-bg); color: var(--color-text); font: inherit; min-width: 2em; cursor: text; } /* Sheet tab color picker popup */ .sheet-tab-color-picker { display: flex; flex-wrap: wrap; gap: 4px; padding: 6px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); width: 148px; } .sheet-tab-color-swatch { width: 24px; height: 24px; border: 2px solid transparent; border-radius: var(--radius-sm); cursor: pointer; padding: 0; transition: border-color var(--transition-fast), transform var(--transition-fast); } .sheet-tab-color-swatch:hover { transform: scale(1.15); border-color: var(--color-text-muted); } .sheet-tab-color-swatch.selected { border-color: var(--color-teal); } /* "No color" swatch */ .sheet-tab-color-none { background: var(--color-bg); color: var(--color-text-muted); font-size: 0.7rem; line-height: 20px; text-align: center; border-color: var(--color-border); } /* --- Utility classes --- */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } .flex { display: flex; } .items-center { align-items: center; } .gap-sm { gap: var(--space-sm); } .gap-md { gap: var(--space-md); } /* --- Key entry modal --- */ .modal-overlay { position: fixed; inset: 0; background: var(--color-modal-backdrop); display: flex; align-items: center; justify-content: center; z-index: var(--z-overlay); backdrop-filter: blur(4px); } .modal { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--space-xl); max-width: 28rem; width: 90vw; box-shadow: var(--shadow-lg); } .modal h2 { margin-bottom: var(--space-sm); } .modal p { color: var(--color-text-muted); font-size: 0.9rem; margin-bottom: var(--space-lg); } .modal input[type="text"], .modal input[type="password"] { width: 100%; padding: 0.6rem 0.8rem; font-family: var(--font-mono); font-size: 0.85rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); outline: none; margin-bottom: var(--space-md); } .modal input:focus { border-color: var(--color-teal); box-shadow: 0 0 0 2px var(--color-focus); } .modal-actions { display: flex; gap: var(--space-sm); justify-content: flex-end; } /* --- Keyboard Shortcuts Modal --- */ .shortcuts-modal { max-width: 36rem; max-height: 80vh; overflow-y: auto; } .shortcuts-modal h2 { font-family: var(--font-display); font-size: 1.3rem; margin-bottom: var(--space-lg); display: flex; align-items: center; justify-content: space-between; } .shortcuts-modal-close { background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; font-size: 1.2rem; padding: var(--space-xs); border-radius: var(--radius-sm); line-height: 1; } .shortcuts-modal-close:hover { color: var(--color-text); background: var(--color-hover); } /* --- Toolbar Dropdowns --- */ .toolbar-dropdown { position: relative; display: inline-flex; } .toolbar-dropdown-toggle { padding: 0 5px; border-radius: var(--radius-sm); background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; display: inline-flex; align-items: center; gap: 0.2rem; font-size: 14px; height: 28px; transition: all var(--transition-fast); white-space: nowrap; } .toolbar-dropdown-toggle:hover { color: var(--color-text); background: var(--color-hover); } .toolbar-dropdown-toggle.active { color: var(--color-accent); background: var(--color-btn-active-bg); } .toolbar-dropdown-toggle .caret { font-size: 0.55rem; opacity: 0.5; margin-left: 0.1rem; } .toolbar-dropdown-menu { display: none; position: absolute; top: 100%; left: 0; z-index: var(--z-float); min-width: 10rem; padding: var(--space-xs) 0; margin-top: 2px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: 0 4px 16px #2218121f, 0 1px 3px #2218120f; box-shadow: 0 4px 16px oklch(0.22 0.02 55 / 0.12), 0 1px 3px oklch(0.22 0.02 55 / 0.06); } .toolbar-dropdown.open .toolbar-dropdown-menu { display: block; } .toolbar-dropdown-item { display: flex; align-items: center; gap: var(--space-sm); width: 100%; padding: 0.35rem 0.75rem; border: none; background: transparent; color: var(--color-text); font-family: var(--font-body); font-size: 0.8rem; cursor: pointer; text-align: left; transition: background var(--transition-fast); white-space: nowrap; } .toolbar-dropdown-item:hover { background: var(--color-hover); } .toolbar-dropdown-item.active { color: var(--color-accent); font-weight: 600; } .toolbar-dropdown-item .item-icon { width: 1.2rem; text-align: center; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; } .toolbar-dropdown-item .item-label { flex: 1; } .toolbar-dropdown-item .item-shortcut { font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); margin-left: var(--space-sm); } .toolbar-dropdown-divider { height: 1px; background: var(--color-border); margin: var(--space-xs) 0; } /* --- Overflow / More Menu --- */ .toolbar-overflow { position: relative; display: inline-flex; } .toolbar-overflow-toggle { padding: 0 6px; border-radius: var(--radius-sm); background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; display: inline-flex; align-items: center; gap: 0.25rem; font-size: 14px; height: 28px; transition: all var(--transition-fast); white-space: nowrap; } .toolbar-overflow-toggle:hover { color: var(--color-text); background: var(--color-hover); } .toolbar-overflow-menu { display: none; position: absolute; top: 100%; right: 0; z-index: var(--z-float); min-width: 13rem; padding: var(--space-xs) 0; margin-top: 2px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); } .toolbar-overflow.open .toolbar-overflow-menu { display: block; } /* --- Toolbar layout (flat, single-row) --- */ .toolbar { position: relative; } /* Gdocs toolbar dropdown/overflow toggles: hover/active match .tb-btn states */ .gdocs-toolbar .toolbar-dropdown-toggle:hover, .gdocs-toolbar .toolbar-overflow-toggle:hover { background: #eeeeee; background: oklch(0.95 0 0); } .gdocs-toolbar .toolbar-dropdown-toggle.active { background: #c1dcf0; background: oklch(0.88 0.04 240); } [data-theme="dark"] .gdocs-toolbar .toolbar-dropdown-toggle:hover, [data-theme="dark"] .gdocs-toolbar .toolbar-overflow-toggle:hover { background: #222222; background: oklch(0.25 0 0); } [data-theme="dark"] .gdocs-toolbar .toolbar-dropdown-toggle.active { background: #14242f; background: oklch(0.25 0.03 240); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .gdocs-toolbar .toolbar-dropdown-toggle:hover, :root:not([data-theme="light"]) .gdocs-toolbar .toolbar-overflow-toggle:hover { background: #222222; background: oklch(0.25 0 0); } :root:not([data-theme="light"]) .gdocs-toolbar .toolbar-dropdown-toggle.active { background: #14242f; background: oklch(0.25 0.03 240); } } .shortcut-category { margin-bottom: var(--space-lg); } .shortcut-category-title { font-family: var(--font-body); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-faint); margin-bottom: var(--space-sm); padding-bottom: var(--space-xs); border-bottom: 1px solid var(--color-border); } .shortcut-row { display: flex; align-items: center; justify-content: space-between; padding: var(--space-xs) 0; font-size: 0.85rem; } .shortcut-label { color: var(--color-text); } .shortcut-keys { display: flex; align-items: center; gap: 3px; } .shortcut-key { font-family: var(--font-mono); font-size: 0.7rem; font-weight: 500; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.15rem 0.4rem; color: var(--color-text-muted); min-width: 1.4rem; text-align: center; } /* --- Word/Character Count Footer --- */ .docs-footer { display: flex; align-items: center; gap: var(--space-lg); padding: var(--space-xs) var(--space-md); border-top: 1px solid var(--color-border); background: var(--color-surface); flex-shrink: 0; font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); letter-spacing: 0.02em; } /* --- Autosave Indicator --- */ .save-indicator { display: flex; align-items: center; gap: var(--space-xs); min-width: 12ch; font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); letter-spacing: 0.02em; transition: color var(--transition-fast); } .save-indicator.saving { color: var(--color-warning); } .save-indicator.unsaved { color: var(--color-accent); } .save-indicator.saved { color: var(--color-text-faint); } /* --- Improved Range Selection (#18) --- */ .sheet-grid td.in-range { background: var(--color-range-bg); } .sheet-grid td.range-top { border-top: 2px solid var(--color-teal); } .sheet-grid td.range-bottom { border-bottom: 2px solid var(--color-teal); } .sheet-grid td.range-left { border-left: 2px solid var(--color-teal); } .sheet-grid td.range-right { border-right: 2px solid var(--color-teal); } /* --- Drag-to-Fill Handle --- */ .sheet-grid td.has-fill-handle { overflow: visible; } .fill-handle { position: absolute; bottom: -4px; right: -4px; width: 7px; height: 7px; background: var(--color-teal); cursor: crosshair; z-index: 6; border: 1px solid var(--color-bg); pointer-events: auto; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fill-handle { border-color: var(--color-bg); } } .sheet-grid td.fill-preview { background: #c7eded; background: oklch(0.92 0.04 195); outline: 1px dashed var(--color-teal); outline-offset: -1px; } [data-theme="dark"] .sheet-grid td.fill-preview { background: #032728; background: oklch(0.25 0.04 195); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid td.fill-preview { background: #032728; background: oklch(0.25 0.04 195); } } /* Header hover states */ .sheet-grid th[data-col]:hover, .sheet-grid th.row-header:hover { background: #e2e9ee; background: oklch(0.93 0.01 240); } [data-theme="dark"] .sheet-grid th[data-col]:hover, [data-theme="dark"] .sheet-grid th.row-header:hover { background: #171b1f; background: oklch(0.22 0.01 240); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid th[data-col]:hover, :root:not([data-theme="light"]) .sheet-grid th.row-header:hover { background: #171b1f; background: oklch(0.22 0.01 240); } } .sheet-grid th.col-selected { /* Layer semi-transparent teal onto solid surface so sticky headers don't go transparent */ background: linear-gradient(var(--color-range-header-bg), var(--color-range-header-bg)), var(--color-surface); color: var(--color-teal); } .sheet-grid th.row-selected { background: linear-gradient(var(--color-range-header-bg), var(--color-range-header-bg)), var(--color-surface); color: var(--color-teal); } /* --- Cell Merge (#11) --- */ .btn-icon.merge-active, .tb-btn.merge-active { color: var(--color-teal); background: var(--color-merge-active-bg); } .sheet-grid td.merged-cell { z-index: 1; overflow: visible; background: var(--color-bg); } /* --- Format Painter (#active state) --- */ .tb-btn.format-painter-active, .tb-btn#tb-format-painter.active { color: var(--color-accent); background: #c1dcf0; background: oklch(0.88 0.04 240); } [data-theme="dark"] .tb-btn#tb-format-painter.active { background: #14242f; background: oklch(0.25 0.03 240); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tb-btn#tb-format-painter.active { background: #14242f; background: oklch(0.25 0.03 240); } } body.format-painter-active, body.format-painter-active .sheet-grid td { cursor: crosshair !important; } /* --- Responsive --- */ @media (max-width: 640px) { .landing-actions { flex-direction: column; align-items: stretch; } .new-dropdown, .new-btn, .daily-note-btn { width: 100%; justify-content: center; } .new-menu { left: 0; right: 0; } .editor-container { padding: var(--space-md); } .shortcuts-modal { max-width: 95vw; } .docs-footer { gap: var(--space-md); } } /* --- Inline Comments --- */ .tiptap .comment-mark { background: var(--color-comment-bg); border-bottom: 2px solid var(--color-comment-border); cursor: pointer; border-radius: 1px; transition: background var(--transition-fast); } .tiptap .comment-mark:hover { background: var(--color-comment-bg-hover); } .comment-popover { position: fixed; z-index: var(--z-popover); min-width: 14rem; max-width: 22rem; padding: var(--space-sm) var(--space-md); background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); font-family: var(--font-body); font-size: 0.85rem; } .comment-popover-header { display: flex; align-items: baseline; gap: var(--space-sm); margin-bottom: var(--space-xs); } .comment-popover-author { font-weight: 600; font-size: 0.8rem; color: var(--color-text); } .comment-popover-time { font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); } .comment-popover-text { color: var(--color-text); line-height: 1.5; margin-bottom: var(--space-sm); word-wrap: break-word; } .comment-popover-actions { display: flex; gap: var(--space-xs); justify-content: flex-end; border-top: 1px solid var(--color-border); padding-top: var(--space-xs); } .comment-resolve-btn { color: var(--color-success); font-size: 0.75rem; } .comment-resolve-btn:hover { color: var(--color-text); } .comment-delete-btn { color: var(--color-danger); font-size: 0.75rem; } .comment-delete-btn:hover { color: var(--color-text); } /* --- Toast notifications --- */ .toast-notification { position: fixed; bottom: 2rem; left: 50%; transform: translateX(-50%) translateY(1rem); background: var(--color-text); color: var(--color-bg); font-family: var(--font-body); font-size: 0.85rem; padding: 0.6rem 1.2rem; border-radius: var(--radius-md); box-shadow: var(--shadow-lg); opacity: 0; transition: opacity var(--transition-med), transform var(--transition-med); z-index: var(--z-tooltip); pointer-events: none; } .toast-notification.toast-visible { opacity: 1; transform: translateX(-50%) translateY(0); } .toast-notification.toast-error { background: var(--color-danger); } .toast-notification.toast-interactive { pointer-events: auto; } .toast-undo { font-weight: 700; text-decoration: underline; cursor: pointer; margin-left: 0.75rem; opacity: 0.9; } .toast-undo:hover { opacity: 1; } /* --- Offline indicator badge --- */ .offline-badge { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 0.75rem); right: calc(env(safe-area-inset-right, 0px) + 0.75rem); display: none; align-items: center; gap: 0.4rem; padding: 0.35rem 0.7rem; background: var(--color-warning, #d9974a); color: #fff; font-family: var(--font-body); font-size: 0.75rem; font-weight: 600; border-radius: var(--radius-sm, 4px); box-shadow: var(--shadow-md); z-index: var(--z-tooltip); pointer-events: none; user-select: none; } .offline-badge-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: #fff; animation: offline-badge-pulse 2s ease-in-out infinite; } @keyframes offline-badge-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } /* --- Drag-and-drop import overlay --- */ .drop-overlay { position: fixed; inset: 0; z-index: var(--z-drop); background: var(--color-modal-backdrop); backdrop-filter: blur(2px); display: flex; align-items: center; justify-content: center; animation: drop-overlay-in 150ms ease-out; } @keyframes drop-overlay-in { from { opacity: 0; } to { opacity: 1; } } .drop-overlay-content { display: flex; flex-direction: column; align-items: center; gap: var(--space-md); padding: var(--space-2xl); border: 2px dashed var(--color-teal); border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-lg); pointer-events: none; } .drop-overlay-icon { font-size: 3rem; line-height: 1; } .drop-overlay-text { font-family: var(--font-display); font-size: 1.4rem; font-weight: 600; color: var(--color-text); } .drop-overlay-hint { font-size: 0.85rem; color: var(--color-text-muted); } /* --- Find & Replace Bar --- */ .find-bar { position: absolute; top: 0; right: var(--space-md); z-index: var(--z-float); background: var(--color-bg); border: 1px solid var(--color-border); border-top: none; border-radius: 0 0 var(--radius-md) var(--radius-md); box-shadow: 0 4px 16px #2218121f; box-shadow: 0 4px 16px oklch(0.22 0.02 55 / 0.12); padding: var(--space-sm) var(--space-md); display: flex; flex-direction: column; gap: var(--space-xs); min-width: 22rem; max-width: 32rem; animation: find-bar-slide 150ms ease-out; } @keyframes find-bar-slide { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } } [data-theme="dark"] .find-bar { box-shadow: 0 4px 16px #01000080; box-shadow: 0 4px 16px oklch(0.05 0.005 75 / 0.5); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .find-bar { box-shadow: 0 4px 16px #01000080; box-shadow: 0 4px 16px oklch(0.05 0.005 75 / 0.5); } } .find-bar-row { display: flex; align-items: center; gap: var(--space-xs); } .find-bar-input { flex: 1; font-family: var(--font-body); font-size: 0.85rem; padding: 0.35rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); outline: none; min-width: 0; } .find-bar-input:focus { border-color: var(--color-teal); box-shadow: 0 0 0 2px var(--color-focus); } .find-bar-count { font-family: var(--font-mono); font-size: 0.7rem; color: var(--color-text-faint); white-space: nowrap; min-width: 4rem; text-align: center; } .find-bar-btn { padding: 0.3rem 0.5rem !important; font-size: 0.75rem !important; white-space: nowrap; border-radius: var(--radius-sm); transition: background var(--transition-fast), color var(--transition-fast); } .find-bar-replace { padding-left: 0; } /* Search highlight decorations */ .search-match { background: var(--color-search-match); border-radius: 1px; } .search-match-active { background: var(--color-search-match-active); color: var(--color-search-match-text); border-radius: 1px; } @media (max-width: 640px) { .find-bar { left: 0; right: 0; min-width: 0; max-width: none; border-radius: 0; } } /* --- Page Break --- */ .tiptap .page-break { position: relative; margin: 1.5em 0; border: none; text-align: center; page-break-after: always; break-after: page; pointer-events: none; } .tiptap .page-break::before { content: ''; display: block; border-top: 2px dashed var(--color-border-strong); } .tiptap .page-break::after { content: 'Page Break'; display: inline-block; position: relative; top: -0.75em; background: var(--color-bg); padding: 0 0.75em; font-family: var(--font-body); font-size: 0.65rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-faint); } .tiptap .page-break.ProseMirror-selectednode { pointer-events: auto; } .tiptap .page-break.ProseMirror-selectednode::before { border-color: var(--color-accent); } /* Dropdown icon-text variant (smaller icon for text symbols) */ .dd-icon-text { font-size: 13px; } /* --- Toggle Block (collapsible section) #131 --- */ .tiptap .toggle-block { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.5rem 0.75rem; margin: 0.75em 0; } .tiptap .toggle-block[open] { padding-bottom: 0.75rem; } .tiptap .toggle-summary { cursor: pointer; font-weight: 600; padding: 0.25rem 0; list-style: disclosure-closed; } .tiptap .toggle-block[open] > .toggle-summary { list-style: disclosure-open; margin-bottom: 0.5rem; } /* --- Footnotes (#122) --- */ .tiptap .footnote-marker { cursor: pointer; color: var(--color-accent); font-size: 0.75em; vertical-align: super; line-height: 0; padding: 0 1px; font-weight: 600; } .tiptap .footnote-marker:hover { text-decoration: underline; } .tiptap .footnote-marker.ProseMirror-selectednode { outline: 2px solid var(--color-accent); border-radius: 2px; } /* Minimap */ .minimap { position: fixed; right: 0; top: 60px; bottom: 0; width: 140px; background: var(--color-surface); border-left: 1px solid var(--color-border); overflow: hidden; z-index: var(--z-component); font-size: 0.65rem; line-height: 1.3; } .minimap-viewport { position: absolute; right: 0; left: 0; background: #5e93ca1a; background: oklch(0.65 0.1 250 / 0.1); border: 1px solid #5e93ca4d; border: 1px solid oklch(0.65 0.1 250 / 0.3); border-radius: 2px; pointer-events: none; transition: top var(--transition-fast), height var(--transition-fast); } .minimap-headings { padding: 8px 10px; cursor: pointer; } .minimap-heading { padding: 2px 0; color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color var(--transition-fast); } .minimap-heading:hover { color: var(--color-text); } .minimap-heading[data-level="1"] { font-weight: 600; color: var(--color-text); } .minimap-heading[data-level="2"] { padding-left: 8px; } .minimap-heading[data-level="3"] { padding-left: 16px; font-size: 0.6rem; } .footnote-section { border-top: 1px solid var(--color-border); margin-top: 2rem; padding-top: 1rem; font-size: 0.875rem; color: var(--color-text-muted); } .footnote-section h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 0.5rem; color: var(--color-text-muted); } .footnote-section ol { margin: 0; padding-left: 1.5rem; } .footnote-section li { margin-bottom: 0.25rem; } /* --- Resizable Images (#118) --- */ .tiptap .resizable-image-wrapper { margin: 0.75em 0; line-height: 0; } .tiptap .resizable-image-wrapper[data-align="left"] { text-align: left; } .tiptap .resizable-image-wrapper[data-align="center"] { text-align: center; } .tiptap .resizable-image-wrapper[data-align="right"] { text-align: right; } .tiptap .resizable-image-container { display: inline-block; position: relative; line-height: 0; } .tiptap .resizable-image-container img { display: block; max-width: 100%; border-radius: var(--radius-sm, 4px); } .tiptap .resizable-image-wrapper.selected .resizable-image-container { outline: 2px solid var(--color-accent); border-radius: var(--radius-sm, 4px); } /* Resize handles — only visible when selected */ .tiptap .resize-handle { display: none; position: absolute; width: 10px; height: 10px; background: var(--color-accent); border: 1px solid var(--color-bg); border-radius: 2px; z-index: var(--z-component); } .tiptap .resizable-image-wrapper.selected .resize-handle { display: block; } .tiptap .resize-handle-nw { top: -5px; left: -5px; cursor: nw-resize; } .tiptap .resize-handle-ne { top: -5px; right: -5px; cursor: ne-resize; } .tiptap .resize-handle-sw { bottom: -5px; left: -5px; cursor: sw-resize; } .tiptap .resize-handle-se { bottom: -5px; right: -5px; cursor: se-resize; } /* --- Print styles --- */ @media print { .app-topbar, .toolbar, .docs-footer, .find-bar, .comment-popover, .toast-notification { display: none !important; } .editor-container { overflow: visible !important; padding: 0 !important; } .editor-wrapper { max-width: none !important; } .tiptap .page-break { margin: 0; visibility: hidden; page-break-before: always; break-before: page; } .tiptap .page-break::before, .tiptap .page-break::after { display: none; } } /* ======================================================== Context Menu ======================================================== */ .context-menu { position: fixed; z-index: var(--z-menu); min-width: 12rem; padding: var(--space-xs) 0; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); font-family: var(--font-body); font-size: 0.8rem; color: var(--color-text); outline: none; } .context-menu-item { display: flex; align-items: center; gap: var(--space-sm); width: 100%; padding: 0.35rem 0.75rem; border: none; background: transparent; color: var(--color-text); font-family: var(--font-body); font-size: 0.8rem; cursor: pointer; text-align: left; transition: background var(--transition-fast); white-space: nowrap; outline: none; } .context-menu-item:hover, .context-menu-item:focus-visible { background: var(--color-hover); } .context-menu-item.disabled { color: var(--color-text-faint); cursor: default; } .context-menu-item.disabled:hover, .context-menu-item.disabled:focus-visible { background: transparent; } .context-menu-icon { width: 1.2rem; text-align: center; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 0.85rem; } .context-menu-label { flex: 1; } .context-menu-shortcut { font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); margin-left: var(--space-md); } .context-menu-separator { height: 1px; background: var(--color-border); margin: var(--space-xs) 0; } /* ======================================================== Print Preview Modal ======================================================== */ .print-preview-overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: var(--color-modal-backdrop); display: flex; align-items: flex-start; justify-content: center; padding: var(--space-xl); overflow-y: auto; } .print-preview-container { background: var(--color-bg); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); max-width: 900px; width: 100%; max-height: 90vh; display: flex; flex-direction: column; } .print-preview-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-md) var(--space-lg); border-bottom: 1px solid var(--color-border); } .print-preview-header h2 { font-family: var(--font-display); font-size: 1.1rem; font-weight: 600; margin: 0; } .print-preview-options { display: flex; gap: var(--space-md); padding: var(--space-sm) var(--space-lg); border-bottom: 1px solid var(--color-border); flex-wrap: wrap; } .print-preview-options label { display: flex; align-items: center; gap: var(--space-xs); font-size: 0.8rem; color: var(--color-text-muted); } .print-preview-options select { font-size: 0.8rem; padding: 2px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); } .print-preview-body { flex: 1; overflow-y: auto; padding: var(--space-lg); background: var(--color-surface-alt); } .print-preview-body iframe { width: 100%; min-height: 600px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); } .print-preview-footer { display: flex; justify-content: flex-end; gap: var(--space-sm); padding: var(--space-md) var(--space-lg); border-top: 1px solid var(--color-border); } /* Enhanced print styles */ @media print { .context-menu, .print-preview-overlay { display: none !important; } /* Sheets: hide UI chrome */ .sheets-toolbar, .tab-bar, .formula-bar, .sheets-footer { display: none !important; } .spreadsheet-container { overflow: visible !important; } } /* ======================================================== Charts Section ======================================================== */ .charts-section { display: flex; flex-wrap: wrap; gap: var(--space-md); padding: var(--space-md); } .charts-section:empty { display: none; } .chart-container { position: relative; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-md); background: var(--color-bg); max-width: 600px; width: 100%; margin: 0 auto; } .chart-container canvas { width: 100% !important; max-height: 400px; } .chart-actions { display: flex; gap: var(--space-xs); position: absolute; top: var(--space-xs); right: var(--space-xs); opacity: 0; transition: opacity var(--transition-fast); } .chart-container:hover .chart-actions { opacity: 1; } .chart-actions button { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 2px 8px; font-size: 0.75rem; cursor: pointer; color: var(--color-text-muted); transition: background var(--transition-fast), color var(--transition-fast); } .chart-actions button:hover { background: var(--color-hover); color: var(--color-text); } /* Dark mode chart background */ [data-theme="dark"] .chart-container { background: var(--color-surface); } /* ======================================================== Chart / Sort / Filter Dialogs (Modal) ======================================================== */ .sheet-dialog-overlay { position: fixed; inset: 0; background: var(--color-modal-backdrop); z-index: var(--z-overlay); display: flex; align-items: center; justify-content: center; } .sheet-dialog { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-lg); min-width: 340px; max-width: 480px; width: 90vw; font-family: var(--font-body); } .sheet-dialog h3 { margin: 0 0 var(--space-md); font-family: var(--font-display); font-size: 1.1rem; color: var(--color-text); } .sheet-dialog label { display: block; margin-bottom: var(--space-xs); font-size: 0.85rem; color: var(--color-text-muted); } .sheet-dialog input, .sheet-dialog select { width: 100%; padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-family: var(--font-mono); font-size: 0.85rem; margin-bottom: var(--space-sm); box-sizing: border-box; } .sheet-dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-sm); margin-top: var(--space-md); } .sheet-dialog-actions button { padding: var(--space-xs) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; font-size: 0.85rem; background: var(--color-surface); color: var(--color-text); transition: background var(--transition-fast); } .sheet-dialog-actions button:hover { background: var(--color-hover); } .sheet-dialog-actions button.btn-primary { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .sheet-dialog-actions button.btn-primary:hover { background: var(--color-accent-hover); } /* ======================================================== Paste Special Dialog ======================================================== */ .paste-special-dialog { min-width: 280px; max-width: 360px; } .paste-special-options { display: flex; flex-direction: column; gap: var(--space-xs); margin-bottom: var(--space-md); } .paste-special-option { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-xs) var(--space-sm); border-radius: var(--radius-sm); cursor: pointer; font-size: 0.9rem; color: var(--color-text); transition: background var(--transition-fast); margin-bottom: 0; } .paste-special-option:hover { background: var(--color-hover); } .paste-special-option input[type="radio"] { width: auto; margin: 0; accent-color: var(--color-accent); } .paste-special-option span { font-family: var(--font-body); } /* Sort level rows */ .sort-level { display: flex; gap: var(--space-sm); align-items: center; margin-bottom: var(--space-sm); } .sort-level select { flex: 1; margin-bottom: 0; } .sort-level .sort-level-label { font-size: 0.8rem; color: var(--color-text-muted); min-width: 60px; } /* ======================================================== Column Filter UI ======================================================== */ .sheet-grid thead th.filter-active::after { content: '\25BC'; font-size: 0.55rem; color: var(--color-teal); margin-left: 2px; vertical-align: middle; } .sheet-grid thead th .filter-arrow { display: inline-block; cursor: pointer; font-size: 0.6rem; margin-left: 2px; color: var(--color-text-faint); vertical-align: middle; transition: color var(--transition-fast); } .sheet-grid thead th .filter-arrow:hover { color: var(--color-accent); } .filter-dropdown { position: absolute; top: 100%; left: 0; min-width: 160px; max-height: 240px; overflow-y: auto; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); z-index: var(--z-sticky); padding: var(--space-xs) 0; font-size: 0.8rem; } .filter-dropdown label { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); cursor: pointer; transition: background var(--transition-fast); } .filter-dropdown label:hover { background: var(--color-hover); } .filter-dropdown .filter-actions { display: flex; justify-content: space-between; padding: var(--space-xs) var(--space-sm); border-top: 1px solid var(--color-border); margin-top: var(--space-xs); } .filter-dropdown .filter-actions button { background: none; border: none; color: var(--color-accent); cursor: pointer; font-size: 0.75rem; padding: 2px 4px; } .filter-dropdown .filter-actions button:hover { text-decoration: underline; } /* Filter mode active state on toolbar button */ #tb-filter.active { background: var(--color-btn-active-bg); color: var(--color-accent); } /* Hidden rows via filter */ .sheet-grid tr.filter-hidden { display: none; } /* --- Striped Rows --- */ .sheet-grid tr .striped-row { background: #e6e4e199; background: oklch(0.92 0.005 75 / 0.6); } [data-theme="dark"] .sheet-grid tr .striped-row { background: #211f1d80; background: oklch(0.24 0.005 75 / 0.5); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sheet-grid tr .striped-row { background: #211f1d80; background: oklch(0.24 0.005 75 / 0.5); } } /* --- Wrap Text --- */ .sheet-grid td .cell-display.cell-wrap { white-space: normal; word-wrap: break-word; overflow-wrap: break-word; overflow: visible; } /* --- Validation Invalid --- */ .sheet-grid td.validation-invalid { outline: 2px solid var(--color-danger); outline-offset: -2px; } .sheet-grid td.validation-invalid::after { content: ''; position: absolute; top: 0; right: 0; width: 0; height: 0; border-left: 6px solid transparent; border-top: 6px solid var(--color-danger); } /* --- Validation Dropdown Arrow --- */ .sheet-grid td .cell-dropdown-arrow { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); width: 14px; height: 14px; display: flex; align-items: center; justify-content: center; font-size: 0.6rem; color: var(--color-text-faint); cursor: pointer; border-radius: 2px; opacity: 0; transition: opacity var(--transition-fast); } .sheet-grid td:hover .cell-dropdown-arrow, .sheet-grid td.selected .cell-dropdown-arrow { opacity: 1; } .sheet-grid td .cell-dropdown-arrow:hover { background: var(--color-hover); color: var(--color-text); } /* --- Validation Dropdown Menu --- */ .validation-dropdown { position: fixed; z-index: var(--z-sticky); min-width: 8rem; max-height: 12rem; overflow-y: auto; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: var(--space-xs) 0; } .validation-dropdown-item { display: block; width: 100%; padding: var(--space-xs) var(--space-sm); text-align: left; font-family: var(--font-mono); font-size: 0.8rem; color: var(--color-text); background: none; border: none; cursor: pointer; } .validation-dropdown-item:hover { background: var(--color-hover); } /* --- Conditional Formatting Modal --- */ .cf-modal { max-width: 32rem; } .cf-modal h2 { font-family: var(--font-display); font-size: 1.1rem; margin: 0 0 var(--space-md); display: flex; justify-content: space-between; align-items: center; } .cf-rule-list { list-style: none; padding: 0; margin: 0 0 var(--space-md); } .cf-rule-item { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); margin-bottom: var(--space-xs); font-size: 0.8rem; font-family: var(--font-mono); } .cf-rule-item .cf-rule-preview { width: 1.5rem; height: 1.5rem; border-radius: 3px; flex-shrink: 0; border: 1px solid var(--color-border); } .cf-rule-item .cf-rule-text { flex: 1; } .cf-rule-item button { background: none; border: none; cursor: pointer; color: var(--color-text-faint); font-size: 0.75rem; padding: 0.15rem 0.3rem; border-radius: var(--radius-sm); } .cf-rule-item button:hover { color: var(--color-danger); background: var(--color-hover); } .cf-add-form { display: flex; flex-direction: column; gap: var(--space-sm); } .cf-add-form label { font-family: var(--font-body); font-size: 0.8rem; color: var(--color-text-muted); } .cf-add-form select, .cf-add-form input { font-family: var(--font-mono); font-size: 0.8rem; padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); } .cf-add-form .cf-color-row { display: flex; gap: var(--space-sm); align-items: center; } .cf-add-form .cf-color-row input[type="color"] { width: 2rem; height: 1.5rem; padding: 0; border: 1px solid var(--color-border); cursor: pointer; } .cf-add-form .cf-value-row { display: flex; gap: var(--space-sm); } .cf-add-form .cf-value-row input { flex: 1; } .cf-add-form .cf-btn-row { display: flex; gap: var(--space-sm); justify-content: flex-end; } .cf-add-form button { padding: var(--space-xs) var(--space-md); border-radius: var(--radius-sm); font-family: var(--font-body); font-size: 0.8rem; cursor: pointer; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); } .cf-add-form button.cf-btn-primary { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .cf-add-form button.cf-btn-primary:hover { background: var(--color-accent-hover); } /* --- Data Validation Modal --- */ .dv-modal { max-width: 28rem; } .dv-modal h2 { font-family: var(--font-display); font-size: 1.1rem; margin: 0 0 var(--space-md); display: flex; justify-content: space-between; align-items: center; } .dv-form { display: flex; flex-direction: column; gap: var(--space-sm); } .dv-form label { font-family: var(--font-body); font-size: 0.8rem; color: var(--color-text-muted); } .dv-form select, .dv-form input { font-family: var(--font-mono); font-size: 0.8rem; padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); } .dv-form .dv-btn-row { display: flex; gap: var(--space-sm); justify-content: flex-end; margin-top: var(--space-sm); } .dv-form button { padding: var(--space-xs) var(--space-md); border-radius: var(--radius-sm); font-family: var(--font-body); font-size: 0.8rem; cursor: pointer; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); } .dv-form button.dv-btn-primary { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .dv-form button.dv-btn-primary:hover { background: var(--color-accent-hover); } .dv-form button.dv-btn-danger { color: var(--color-danger); } .dv-form button.dv-btn-danger:hover { background: #bd413f14; background: oklch(0.55 0.16 25 / 0.08); } /* ======================================================== Version History Sidebar ======================================================== */ .editor-with-sidebar { display: flex; flex: 1; min-height: 0; overflow: hidden; } .editor-with-sidebar .editor-container { flex: 1; min-width: 0; } .version-sidebar { position: relative; width: 300px; border-left: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; overflow: hidden; flex-shrink: 0; } .version-sidebar-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); } .version-sidebar-header h3 { margin: 0; font-size: 0.875rem; font-weight: 600; font-family: var(--font-body); color: var(--color-text); } .version-sidebar-close { font-size: 1.25rem; color: var(--color-text-muted); } .version-list { flex: 1; overflow-y: auto; padding: var(--space-xs) 0; } .version-empty { padding: var(--space-lg); text-align: center; color: var(--color-text-faint); font-size: 0.8125rem; } .version-item { display: flex; flex-direction: column; gap: 2px; width: 100%; padding: var(--space-sm) var(--space-md); border: none; background: none; text-align: left; cursor: pointer; border-bottom: 1px solid var(--color-border); transition: background var(--transition-fast); font-family: var(--font-body); } .version-item:hover { background: var(--color-hover); } .version-time { font-size: 0.75rem; color: var(--color-text); font-weight: 500; } .version-meta { display: flex; gap: var(--space-sm); font-size: 0.6875rem; color: var(--color-text-muted); } .version-author { color: var(--color-text-faint); } .version-wc { color: var(--color-text-faint); } .version-delta { font-weight: 600; } .version-delta.positive { color: var(--color-success); } .version-delta.negative { color: var(--color-danger); } .version-preview { display: flex; flex-direction: column; position: absolute; inset: 0; background: var(--color-surface); z-index: 2; } .version-preview-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); gap: var(--space-sm); } .version-preview-content { flex: 1; overflow-y: auto; padding: var(--space-md); } .version-preview-text { font-family: var(--font-body); font-size: 0.875rem; line-height: 1.6; color: var(--color-text); white-space: pre-wrap; } .btn-primary.btn-sm { padding: var(--space-xs) var(--space-sm); font-size: 0.75rem; background: var(--color-accent); color: var(--color-btn-primary-text); border: none; border-radius: var(--radius-sm); cursor: pointer; white-space: nowrap; } .btn-primary.btn-sm:hover { background: var(--color-accent-hover); } /* ======================================================== Suggesting Mode ======================================================== */ .suggesting-toggle { display: flex; align-items: center; } .suggesting-toggle-btn { display: flex; align-items: center; gap: 4px; padding: 3px 8px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: none; cursor: pointer; font-family: var(--font-body); font-size: 0.75rem; color: var(--color-text-muted); transition: all var(--transition-fast); } .suggesting-toggle-btn:hover { background: var(--color-hover); } .suggesting-toggle-btn.active { background: #b7e6b7; background: oklch(0.88 0.08 145); border-color: #1c985a; border-color: oklch(0.6 0.14 155); color: #00391b; color: oklch(0.3 0.08 155); } [data-theme="dark"] .suggesting-toggle-btn.active { background: #102719; background: oklch(0.25 0.04 155); border-color: #2a7449; border-color: oklch(0.5 0.1 155); color: #a0caad; color: oklch(0.8 0.06 155); } .suggesting-toggle-icon { font-size: 0.875rem; } /* Suggestion marks in the editor */ .suggestion-insert { text-decoration: underline; text-decoration-color: #1c985a; text-decoration-color: oklch(0.6 0.14 155); text-decoration-thickness: 2px; text-underline-offset: 2px; background: #1c985a14; background: oklch(0.6 0.14 155 / 0.08); border-radius: 1px; cursor: pointer; position: relative; } .suggestion-delete { text-decoration: line-through; text-decoration-color: #bd413f; text-decoration-color: oklch(0.55 0.16 25); text-decoration-thickness: 2px; background: #bd413f14; background: oklch(0.55 0.16 25 / 0.08); color: var(--color-text-muted); border-radius: 1px; cursor: pointer; position: relative; } [data-theme="dark"] .suggestion-insert { text-decoration-color: #33a868; text-decoration-color: oklch(0.65 0.14 155); background: #33a8681f; background: oklch(0.65 0.14 155 / 0.12); } [data-theme="dark"] .suggestion-delete { text-decoration-color: #ce514d; text-decoration-color: oklch(0.60 0.16 25); background: #ce514d1f; background: oklch(0.60 0.16 25 / 0.12); } /* Suggestion popover (similar to comment popover) */ .suggestion-popover { position: fixed; z-index: var(--z-tooltip); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: var(--space-sm); min-width: 180px; max-width: 260px; font-family: var(--font-body); } .suggestion-popover-header { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-bottom: var(--space-xs); font-size: 0.75rem; } .suggestion-popover-author { font-weight: 600; color: var(--color-text); } .suggestion-popover-time { color: var(--color-text-faint); } .suggestion-popover-type { padding: 1px 6px; border-radius: var(--radius-sm); font-size: 0.6875rem; font-weight: 500; } .suggestion-popover-actions { display: flex; gap: var(--space-xs); } .suggestion-accept-btn { color: var(--color-success) !important; font-size: 0.75rem; } .suggestion-reject-btn { color: var(--color-danger) !important; font-size: 0.75rem; } .suggestion-popover-bulk { display: flex; gap: var(--space-xs); border-top: 1px solid var(--color-border); margin-top: var(--space-xs); padding-top: var(--space-xs); } .suggestion-accept-all-btn, .suggestion-reject-all-btn { font-size: 0.6875rem; color: var(--color-text-muted) !important; } .suggestion-accept-all-btn:hover { color: var(--color-success) !important; } .suggestion-reject-all-btn:hover { color: var(--color-danger) !important; } /* ======================================================== Offline Indicator ======================================================== */ .status-dot.offline { background: var(--color-warning); } .status-indicator .offline-badge { background: #cd9c1f26; background: oklch(0.72 0.14 85 / 0.15); color: #8d6000; color: oklch(0.52 0.14 85); padding: 1px 6px; border-radius: var(--radius-sm); font-size: 0.6875rem; font-weight: 500; } /* ======================================================== Accessibility — Skip Link ======================================================== */ .skip-link { position: absolute; top: -100%; left: 0; background: var(--color-accent); color: var(--color-btn-primary-text); padding: var(--space-sm) var(--space-md); z-index: var(--z-skip); font-size: 0.9rem; font-weight: 600; text-decoration: none; border-radius: 0 0 var(--radius-sm) 0; transition: top var(--transition-fast); } .skip-link:focus { top: 0; } /* ======================================================== Accessibility — Focus Visible Outlines Only show on keyboard navigation, not mouse clicks. ======================================================== */ /* Suppress focus outlines for mouse/touch — preserve :focus-visible for keyboard */ *:focus:not(:focus-visible) { outline: none; } /* Global keyboard focus ring — visible on Tab navigation */ *:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-radius: var(--radius-sm); } /* Tighter offset for buttons and toolbar controls */ button:focus-visible, .tb-btn:focus-visible, .toolbar-dropdown-toggle:focus-visible, .toolbar-overflow-toggle:focus-visible { outline-offset: 1px; } /* Flush offset for form elements */ input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 0; } /* Opt-out: elements with existing strong focus indicators or that manage their own focus */ .tiptap:focus-visible, .cell-editor:focus-visible, .sheet-tab-rename:focus-visible, .inline-text-edit textarea:focus-visible, .cmd-palette-input:focus-visible, .context-menu:focus-visible { outline: none; } /* Opt-out: inputs with box-shadow focus rings already */ .formula-input:focus-visible, .modal input:focus-visible, .modal input[type="password"]:focus-visible, .find-bar-input:focus-visible, .print-preview-sidebar select:focus-visible { outline: none; } /* Non-focus outlines (cell selection, validation) */ .sheet-grid td.selected { outline: 2px solid var(--color-teal); outline-offset: -1px; } .sheet-grid td.validation-invalid { outline: 2px solid var(--color-danger); outline-offset: -2px; } /* ======================================================== View-Only Badge ======================================================== */ .view-only-badge { background: var(--color-warning); color: var(--color-text); font-size: 0.75rem; font-weight: 600; text-align: center; padding: var(--space-xs) var(--space-md); letter-spacing: 0.05em; text-transform: uppercase; font-family: var(--font-mono); } /* ======================================================== Share Dialog ======================================================== */ .share-dialog-backdrop { position: fixed; inset: 0; background: var(--color-modal-backdrop); display: flex; align-items: center; justify-content: center; z-index: var(--z-modal); } .share-dialog { max-width: 480px; width: 90%; } .share-dialog-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-md); } .share-dialog-header h2 { font-family: var(--font-display); font-size: 1.2rem; margin: 0; } .share-dialog-close { font-size: 1.2rem; } .share-dialog-body { display: flex; flex-direction: column; gap: var(--space-md); } .share-link-row { display: flex; gap: var(--space-sm); } .share-link-input { flex: 1; padding: var(--space-sm) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font: inherit; font-size: 0.85rem; font-family: var(--font-mono); overflow: hidden; text-overflow: ellipsis; } /* ======================================================== Document Outline Sidebar ======================================================== */ .outline-sidebar { position: relative; width: 240px; border-right: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; overflow: hidden; flex-shrink: 0; transition: width var(--transition-med), opacity var(--transition-med); } .outline-sidebar-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); } .outline-sidebar-header h3 { margin: 0; font-size: 0.875rem; font-weight: 600; font-family: var(--font-body); color: var(--color-text); } .outline-sidebar-close { font-size: 1.25rem; color: var(--color-text-muted); } .outline-list { flex: 1; overflow-y: auto; padding: var(--space-xs) 0; } .outline-empty { padding: var(--space-lg); text-align: center; color: var(--color-text-faint); font-size: 0.8125rem; } .outline-item { display: block; width: 100%; padding: var(--space-xs) var(--space-md); border: none; background: none; text-align: left; cursor: pointer; font-family: var(--font-body); font-size: 0.8125rem; color: var(--color-text-muted); transition: background var(--transition-fast), color var(--transition-fast); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .share-mode-row, .share-expiry-row { display: flex; align-items: center; gap: var(--space-sm); } .share-mode-label, .share-expiry-label { font-size: 0.85rem; color: var(--color-text-muted); display: flex; align-items: center; gap: var(--space-sm); } .share-mode-label select, .share-expiry-label select { padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font: inherit; font-size: 0.85rem; cursor: pointer; } /* ======================================================== Mobile More Button (hidden on desktop) ======================================================== */ .toolbar-mobile-more { display: none; } /* ======================================================== Mobile Responsive — Tablet (max-width: 768px) ======================================================== */ @media (max-width: 768px) { /* Hide non-essential toolbar items on mobile */ .toolbar-mobile-hide { display: none !important; } /* Show mobile more button */ .toolbar-mobile-more, .mobile-more-btn { display: inline-flex; } /* Larger touch targets for toolbar buttons (44x44px minimum) */ .tb-btn { width: 44px; height: 44px; min-width: 44px; min-height: 44px; } .toolbar-dropdown-toggle, .toolbar-overflow-toggle { min-width: 44px; min-height: 44px; } /* Larger touch targets for icon buttons in topbar/inline controls */ .btn-icon { min-width: 44px; min-height: 44px; padding: 0.5rem; } /* Topbar wraps on narrow screens so buttons don't overflow horizontally */ .app-topbar { flex-wrap: wrap; row-gap: var(--space-xs); } /* Toolbar allow wrapping with wider gap for touch */ .toolbar.gdocs-toolbar { height: auto; flex-wrap: wrap; padding: var(--space-xs); gap: 4px; } /* Editor full-width on mobile */ .editor-wrapper { max-width: 100%; padding: 0 var(--space-sm); } .editor-container { padding: var(--space-md) var(--space-sm); } /* Responsive formula bar */ .formula-bar { flex-wrap: wrap; gap: var(--space-xs); font-size: 0.9rem; } .formula-input, .formula-input-wrap { min-width: 0; width: 100%; flex: 1 1 100%; font-size: 0.9rem; overflow-x: auto; } /* Sheet container: horizontal scroll with sticky column A */ .sheet-container { overflow-x: auto; -webkit-overflow-scrolling: touch; } .sheet-grid th:first-child, .sheet-grid td:first-child { position: sticky; left: 0; z-index: 2; background: var(--color-surface); } /* Larger fonts for readability */ .doc-title-input { font-size: 1rem; } /* Top bar compact layout */ .app-topbar { padding: var(--space-xs) var(--space-sm); gap: var(--space-sm); flex-wrap: wrap; } /* Preserve electron traffic-light padding even on narrow windows */ .is-electron .app-topbar { padding-left: 96px; } .status-indicator { font-size: 0.6rem; } /* Landing page adjustments */ .landing { padding: var(--space-lg) var(--space-md); } .landing-actions { flex-direction: column; align-items: stretch; } .doc-toolbar { flex-direction: column; align-items: stretch; } .doc-toolbar-actions { flex-wrap: wrap; } .search-input { width: 100%; } .search-input:focus { width: 100%; } .version-badge { font-size: 0.55rem; bottom: 0.25rem; right: 0.5rem; } /* Sidebars overlay on tablet/mobile */ .outline-sidebar { position: absolute; left: 0; top: 0; bottom: 0; z-index: 20; width: 260px; box-shadow: var(--shadow-lg); } .version-sidebar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 20; width: 300px; max-width: 85vw; box-shadow: var(--shadow-lg); } /* Link preview tooltip constrained to viewport */ .link-preview-tooltip { max-width: calc(100vw - 2rem); left: 1rem !important; right: 1rem; } } /* ======================================================== Mobile Responsive — Phone (max-width: 480px) ======================================================== */ @media (max-width: 480px) { /* Full-screen modals */ .modal { max-width: 100%; width: 100%; height: 100%; border-radius: 0; display: flex; flex-direction: column; } .modal-backdrop { align-items: stretch; } .share-dialog { max-width: 100%; width: 100%; border-radius: 0; } /* Even larger touch targets */ .tb-btn { width: 48px; height: 48px; } /* Compact topbar */ .app-topbar { padding: var(--space-xs); gap: var(--space-xs); } .is-electron .app-topbar { padding-left: 96px; } .doc-title-input { min-width: 8rem; font-size: 0.95rem; } /* Slightly larger body font */ body { font-size: 1rem; } .version-badge { display: none; } /* Sidebars full-width on phones */ .outline-sidebar, .version-sidebar { width: 100%; max-width: 100%; } /* Find/replace bar stacks vertically */ .search-replace-bar { flex-direction: column; gap: var(--space-xs); } .search-replace-bar input { width: 100%; } /* Compact save status */ .save-status { font-size: 0.65rem; } /* Toolbar dropdowns: full-width overlay */ .toolbar-dropdown-content { position: fixed; left: 0; right: 0; top: auto; width: 100%; max-height: 60vh; overflow-y: auto; border-radius: 0; } /* Command palette: slightly taller on phones for easier reach */ .cmd-palette { max-height: 70vh; } } .outline-item:hover { background: var(--color-hover); color: var(--color-text); } .outline-item[data-level="1"] { padding-left: var(--space-md); font-weight: 600; color: var(--color-text); } .outline-item[data-level="2"] { padding-left: calc(var(--space-md) + var(--space-md)); font-weight: 500; } .outline-item[data-level="3"] { padding-left: calc(var(--space-md) + var(--space-md) + var(--space-md)); font-weight: 400; font-size: 0.75rem; } /* ======================================================== Table Toolbar (Floating) ======================================================== */ .table-toolbar { position: fixed; z-index: var(--z-overlay); display: flex; align-items: center; gap: 2px; padding: 4px 6px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); font-family: var(--font-body); } .table-tb-btn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: none; border-radius: var(--radius-sm); background: none; color: var(--color-text-muted); cursor: pointer; transition: all var(--transition-fast); } .table-tb-btn:hover { background: var(--color-hover); color: var(--color-text); } .table-tb-btn .tb-icon { width: 14px; height: 14px; } .table-tb-sep { width: 1px; height: 20px; background: var(--color-border); margin: 0 2px; } .table-tb-color-wrap { position: relative; display: inline-flex; align-items: center; gap: 2px; } .table-tb-color { width: 24px; height: 24px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; padding: 0; background: none; } .table-tb-color-label { font-size: 0.625rem; color: var(--color-text-faint); font-weight: 600; pointer-events: none; } /* ======================================================== Link Preview Tooltip ======================================================== */ .link-preview-tooltip { position: fixed; z-index: var(--z-tooltip); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: var(--space-sm); min-width: 200px; max-width: 320px; font-family: var(--font-body); } .link-preview-url { font-size: 0.75rem; color: var(--color-teal); margin-bottom: var(--space-xs); word-break: break-all; line-height: 1.3; } .link-preview-actions { display: flex; gap: var(--space-xs); } .link-preview-btn { font-size: 0.75rem; padding: 2px 8px; } /* ======================================================== Focus/Zen Mode ======================================================== */ .zen-mode .app-topbar { opacity: 0; height: 0; padding: 0; overflow: hidden; transition: all var(--transition-med); } .zen-mode .toolbar { opacity: 0; height: 0; padding: 0; overflow: hidden; transition: all var(--transition-med); } .zen-mode .docs-footer { opacity: 0; height: 0; padding: 0; overflow: hidden; transition: all var(--transition-med); } .zen-mode .editor-wrapper { max-width: none; transition: max-width var(--transition-med); } .zen-mode .editor-container { padding: var(--space-xl) var(--space-2xl); } .zen-mode .outline-sidebar { display: none !important; } .zen-mode .version-sidebar { display: none !important; } .zen-exit-btn { position: fixed; top: var(--space-md); right: var(--space-md); z-index: var(--z-drop); padding: 6px 14px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text-muted); font-family: var(--font-body); font-size: 0.75rem; cursor: pointer; opacity: 0.5; transition: opacity var(--transition-fast); box-shadow: var(--shadow-sm); } .zen-exit-btn:hover { opacity: 1; color: var(--color-text); background: var(--color-hover); } /* Smooth transitions for entering/exiting zen */ .app-topbar, .toolbar, .docs-footer, .editor-wrapper { transition: all var(--transition-med); } /* ======================================================== Status Bar (selection aggregate stats) ======================================================== */ .status-bar { display: flex; align-items: center; justify-content: space-between; padding: 2px var(--space-sm); border-top: 1px solid var(--color-border); background: var(--color-surface); flex-shrink: 0; min-height: 24px; transition: background-color var(--transition-med), border-color var(--transition-med); } .status-bar-info { display: flex; align-items: center; gap: var(--space-sm); font-family: var(--font-mono); font-size: 0.65rem; color: var(--color-text-faint); } .status-bar-cell-ref { padding: 1px 4px; border-radius: 2px; background: var(--color-surface-alt); color: var(--color-text-muted); font-weight: 500; } .status-bar-dim { color: var(--color-text-faint); } .status-bar-freeze { padding: 1px 6px; border-radius: 2px; background: #53c2c126; background: oklch(0.75 0.1 195 / 0.15); color: #00686a; color: oklch(0.45 0.12 195); font-weight: 500; font-family: var(--font-body); font-size: 0.65rem; cursor: pointer; transition: background var(--transition-fast); } .status-bar-freeze:hover { background: #53c2c140; background: oklch(0.75 0.1 195 / 0.25); } [data-theme="dark"] .status-bar-freeze { background: #0047474d; background: oklch(0.35 0.08 195 / 0.3); color: #41b2b2; color: oklch(0.7 0.1 195); } [data-theme="dark"] .status-bar-freeze:hover { background: #00474773; background: oklch(0.35 0.08 195 / 0.45); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .status-bar-freeze { background: #0047474d; background: oklch(0.35 0.08 195 / 0.3); color: #41b2b2; color: oklch(0.7 0.1 195); } :root:not([data-theme="light"]) .status-bar-freeze:hover { background: #00474773; background: oklch(0.35 0.08 195 / 0.45); } } .status-bar-range { padding: 1px 4px; border-radius: 2px; background: var(--color-surface-alt); color: var(--color-text-muted); font-weight: 500; } .status-bar-mode { color: var(--color-text-faint); } .status-bar-cells { color: var(--color-text-faint); } .status-bar-stats { display: flex; align-items: center; gap: var(--space-md); font-family: var(--font-body); font-size: 0.7rem; color: var(--color-text-muted); user-select: text; } .status-bar-stat { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; cursor: pointer; padding: 1px 4px; border-radius: 2px; transition: background var(--transition-fast); } .status-bar-stat:hover { background: var(--color-hover); } .status-bar-stat-label { font-weight: 500; color: var(--color-text-faint); text-transform: uppercase; font-size: 0.6rem; letter-spacing: 0.04em; } .status-bar-stat-value { font-family: var(--font-mono); font-size: 0.7rem; color: var(--color-text); } /* Copy feedback on stat click */ .status-bar-stat.copied { background: #1c985a26; background: oklch(0.6 0.14 155 / 0.15); } .status-bar-stat.copied .status-bar-stat-value { color: var(--color-success); } [data-theme="dark"] .status-bar { background: var(--color-surface); border-top-color: var(--color-border); } /* ======================================================== Formula Auto-Complete ======================================================== */ .formula-autocomplete { position: absolute; z-index: var(--z-modal); min-width: 240px; max-width: 380px; max-height: 260px; overflow-y: auto; background: var(--color-bg); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 2px 0; font-family: var(--font-body); } .formula-autocomplete-item { display: flex; flex-direction: column; padding: 4px 10px; cursor: pointer; transition: background-color var(--transition-fast); } .formula-autocomplete-item:hover, .formula-autocomplete-item.selected { background: var(--color-hover); } .formula-autocomplete-item.selected { background: var(--color-teal-light); } .formula-autocomplete-name { font-weight: 600; font-size: 0.8rem; color: var(--color-text); } .formula-autocomplete-signature { font-family: var(--font-mono); font-size: 0.7rem; color: var(--color-text-muted); margin-top: 1px; } [data-theme="dark"] .formula-autocomplete { background: var(--color-surface); border-color: var(--color-border-strong); } [data-theme="dark"] .formula-autocomplete-item.selected { background: var(--color-teal-light); } /* ======================================================== Formula Syntax Highlighting ======================================================== */ /* Overlay container for formula bar highlighting */ .formula-input-wrap { position: relative; flex: 1; display: flex; } .formula-input-wrap .formula-input { /* Override flex:1 from base — the wrap handles flex now */ flex: 1; background: transparent; position: relative; z-index: 1; /* Make the text invisible (the highlight layer shows it) when formula */ caret-color: var(--color-text); } .formula-input-wrap .formula-input:focus { /* Keep focus ring on the input */ border-color: var(--color-teal); box-shadow: 0 0 0 2px var(--color-focus); } .formula-highlight-layer { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; font-family: var(--font-mono); font-size: 0.85rem; padding: 0.3rem 0.6rem; overflow: hidden; white-space: nowrap; border: 1px solid transparent; border-radius: var(--radius-sm); z-index: 0; color: transparent; display: flex; align-items: center; } /* When highlight layer is active, make input text transparent so highlighted text shows through */ .formula-input-wrap .formula-input.formula-highlighting { color: transparent; } /* Token colors — Light theme */ .formula-token-cell_ref { color: #0071df; color: oklch(0.55 0.2 250); } .formula-token-function { color: #773ac1; color: oklch(0.5 0.2 300); } .formula-token-string { color: #00792f; color: oklch(0.5 0.15 150); } .formula-token-number { color: #ae5600; color: oklch(0.55 0.15 60); } .formula-token-boolean { color: #773ac1; color: oklch(0.5 0.2 300); } .formula-token-operator { color: var(--color-text); } .formula-token-paren { color: var(--color-text-muted); } .formula-token-error { color: #cc272e; color: oklch(0.55 0.2 25); font-weight: 600; } .formula-token-whitespace { /* Preserve whitespace width */ white-space: pre; } .formula-token-identifier, .formula-token-unknown { color: var(--color-text); } /* Token colors — Dark theme */ [data-theme="dark"] .formula-token-cell_ref { color: #00a1ff; color: oklch(0.7 0.2 250); } [data-theme="dark"] .formula-token-function { color: #ad87ed; color: oklch(0.7 0.15 300); } [data-theme="dark"] .formula-token-string { color: #4cb86a; color: oklch(0.7 0.15 150); } [data-theme="dark"] .formula-token-number { color: #e18528; color: oklch(0.7 0.15 60); } [data-theme="dark"] .formula-token-boolean { color: #ad87ed; color: oklch(0.7 0.15 300); } [data-theme="dark"] .formula-token-error { color: #f14d4c; color: oklch(0.65 0.2 25); } /* Matching paren highlight */ .formula-token-paren-match { background: var(--color-teal-light); border-radius: 2px; } /* ======================================================== Range Highlight Overlays ======================================================== */ .range-highlight-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 5; box-sizing: border-box; } /* ======================================================== Formula Tooltip (Parameter Hints) ======================================================== */ .formula-tooltip { position: fixed; z-index: var(--z-above-modal); min-width: 200px; max-width: 420px; padding: 6px 10px; background: var(--color-bg); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-md); font-family: var(--font-body); font-size: 0.78rem; line-height: 1.45; color: var(--color-text); } .formula-tooltip-signature { font-family: var(--font-mono); font-size: 0.8rem; margin-bottom: 3px; white-space: nowrap; overflow-x: auto; } .formula-tooltip-fn { color: #773ac1; color: oklch(0.5 0.2 300); font-weight: 700; } .formula-tooltip-param { color: var(--color-text-muted); } .formula-tooltip-param-active { color: var(--color-text); font-weight: 700; text-decoration: underline; text-decoration-color: var(--color-teal); text-underline-offset: 2px; } .formula-tooltip-optional { color: var(--color-text-faint); } .formula-tooltip-param-desc { font-size: 0.75rem; color: var(--color-text-muted); margin-bottom: 2px; padding-left: 2px; } .formula-tooltip-param-desc strong { color: var(--color-text); font-weight: 600; } .formula-tooltip-desc { font-size: 0.72rem; color: var(--color-text-faint); border-top: 1px solid var(--color-border); margin-top: 3px; padding-top: 3px; } /* Dark theme for tooltip */ [data-theme="dark"] .formula-tooltip { background: var(--color-surface); border-color: var(--color-border-strong); } [data-theme="dark"] .formula-tooltip-fn { color: #ad87ed; color: oklch(0.7 0.15 300); } /* prefers-color-scheme fallback for syntax highlighting */ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .formula-token-cell_ref { color: #00a1ff; color: oklch(0.7 0.2 250); } :root:not([data-theme="light"]) .formula-token-function { color: #ad87ed; color: oklch(0.7 0.15 300); } :root:not([data-theme="light"]) .formula-token-string { color: #4cb86a; color: oklch(0.7 0.15 150); } :root:not([data-theme="light"]) .formula-token-number { color: #e18528; color: oklch(0.7 0.15 60); } :root:not([data-theme="light"]) .formula-token-boolean { color: #ad87ed; color: oklch(0.7 0.15 300); } :root:not([data-theme="light"]) .formula-token-error { color: #f14d4c; color: oklch(0.65 0.2 25); } :root:not([data-theme="light"]) .formula-tooltip { background: var(--color-surface); border-color: var(--color-border-strong); } :root:not([data-theme="light"]) .formula-tooltip-fn { color: #ad87ed; color: oklch(0.7 0.15 300); } } /* ======================================================== Cell Notes ======================================================== */ .cell-note-indicator { position: absolute; top: 0; right: 0; width: 0; height: 0; border-style: solid; border-width: 0 7px 7px 0; border-color: transparent var(--color-teal) transparent transparent; pointer-events: none; z-index: 1; } .cell-note-tooltip { position: absolute; z-index: calc(var(--z-modal) + 1); max-width: 280px; padding: 6px 10px; background: var(--color-surface-alt); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-md); font-family: var(--font-body); font-size: 0.75rem; color: var(--color-text); line-height: 1.4; white-space: pre-wrap; word-wrap: break-word; pointer-events: none; } [data-theme="dark"] .cell-note-indicator { border-color: transparent var(--color-teal) transparent transparent; } [data-theme="dark"] .cell-note-tooltip { background: var(--color-surface-alt); border-color: var(--color-border-strong); } /* Cell with note needs relative positioning for the indicator */ td[data-id].has-note { position: relative; } /* ======================================================== Error Tooltips (#208) ======================================================== */ .cell-error { color: var(--color-red) !important; } .error-tooltip { position: absolute; z-index: calc(var(--z-modal) + 2); max-width: 300px; padding: 8px 12px; background: var(--color-surface-alt); border: 1px solid var(--color-red); border-radius: var(--radius-md); box-shadow: var(--shadow-md); font-family: var(--font-body); font-size: 0.75rem; color: var(--color-text); line-height: 1.4; pointer-events: none; } .error-tooltip-title { font-weight: 700; color: var(--color-red); margin-bottom: 2px; } .error-tooltip-desc { margin-bottom: 4px; } .error-tooltip-hint { font-style: italic; opacity: 0.8; } /* ======================================================== Date Picker (#123) ======================================================== */ .date-picker { background: var(--color-surface); border: 1px solid var(--color-border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: 8px; width: 224px; font-family: var(--font-body); font-size: 0.75rem; } .dp-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; } .dp-title { font-weight: 600; font-size: 0.8rem; } .dp-nav { background: none; border: none; cursor: pointer; padding: 2px 6px; border-radius: var(--radius-sm); color: var(--color-text); font-size: 0.65rem; } .dp-nav:hover { background: var(--color-surface-alt); } .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; text-align: center; } .dp-day-header { font-weight: 600; color: var(--color-text-faint); padding: 4px 0; font-size: 0.65rem; } .dp-empty { padding: 4px; } .dp-day { background: none; border: none; padding: 4px; cursor: pointer; border-radius: var(--radius-sm); color: var(--color-text); font-size: 0.75rem; line-height: 1.6; } .dp-day:hover { background: var(--color-surface-alt); } .dp-today { font-weight: 700; outline: 1px solid var(--color-accent); outline-offset: -1px; } .dp-selected { background: var(--color-accent) !important; color: white; } .dp-footer { margin-top: 6px; text-align: center; } .dp-today-btn { background: none; border: none; cursor: pointer; color: var(--color-accent); font-size: 0.7rem; font-weight: 600; } .dp-today-btn:hover { text-decoration: underline; } /* ======================================================== Onboarding Tooltip ======================================================== */ .onboarding-overlay { position: fixed; inset: 0; z-index: var(--z-tooltip); display: flex; align-items: center; justify-content: center; background: #2218124d; background: oklch(0.22 0.02 55 / 0.3); backdrop-filter: blur(2px); animation: onboarding-fade-in 200ms ease-out; } @keyframes onboarding-fade-in { from { opacity: 0; } to { opacity: 1; } } .onboarding-card { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: 0 12px 40px #22181226; box-shadow: 0 12px 40px oklch(0.22 0.02 55 / 0.15); padding: var(--space-lg) var(--space-xl); max-width: 22rem; width: 90vw; animation: onboarding-slide-up 250ms ease-out; } @keyframes onboarding-slide-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } .onboarding-title { font-family: var(--font-display); font-size: 1.1rem; font-weight: 600; color: var(--color-text); margin-bottom: var(--space-md); } .onboarding-tips { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); } .onboarding-tip { display: flex; align-items: flex-start; gap: var(--space-sm); font-size: 0.82rem; line-height: 1.45; color: var(--color-text-muted); } .onboarding-tip kbd { display: inline-block; font-family: var(--font-mono); font-size: 0.7rem; padding: 1px 5px; background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: 3px; color: var(--color-text); white-space: nowrap; line-height: 1.4; } .onboarding-dismiss { display: block; width: 100%; margin-top: var(--space-md); padding: 0.45rem 0; border: none; border-radius: var(--radius-sm); background: var(--color-teal); color: var(--color-btn-primary-text); font-family: var(--font-body); font-size: 0.82rem; font-weight: 500; cursor: pointer; transition: background var(--transition-fast); } .onboarding-dismiss:hover { background: var(--color-teal-light); color: var(--color-teal); } [data-theme="dark"] .onboarding-overlay { background: #01000080; background: oklch(0.05 0.005 75 / 0.5); } [data-theme="dark"] .onboarding-card { box-shadow: 0 12px 40px #01000080; box-shadow: 0 12px 40px oklch(0.05 0.005 75 / 0.5); } /* ======================================================== Empty State Watermark ======================================================== */ .empty-state-watermark { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; z-index: 0; } .empty-state-text { font-family: var(--font-body); font-size: 0.9rem; color: var(--color-text-faint); opacity: 0.5; text-align: center; line-height: 1.6; max-width: 24rem; padding: var(--space-lg); } .empty-state-text kbd { display: inline-block; font-family: var(--font-mono); font-size: 0.75rem; padding: 1px 5px; background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: 3px; color: var(--color-text-muted); opacity: 0.8; } /* --- Markdown Source View --- */ .markdown-source-textarea { width: 100%; max-width: 48rem; min-height: 60vh; margin: 0 auto; padding: var(--space-lg); font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', 'Menlo', 'Consolas', monospace; font-size: 0.95rem; line-height: 1.7; color: var(--color-text); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); resize: vertical; outline: none; tab-size: 4; box-sizing: border-box; } .markdown-source-textarea:focus { border-color: var(--color-teal); } [data-theme="dark"] .markdown-source-textarea { background: var(--color-surface-alt); color: var(--color-text); border-color: var(--color-border); } [data-theme="dark"] .markdown-source-textarea:focus { border-color: var(--color-teal); } /* Active state for the MD toggle button */ #btn-md-toggle.active { background: var(--color-teal); color: var(--color-btn-primary-text); } /* Markdown mode indicator in the status area */ .md-mode-indicator { font-size: 0.75rem; color: var(--color-text-secondary); opacity: 0.7; margin-left: var(--space-sm); } /* ======================================================== Notion-style Editing: Slash Menu, Block Handles, Polish ======================================================== */ /* --- Slash Command Menu --- */ .slash-menu { position: fixed; z-index: var(--z-overlay); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); max-height: 320px; width: 300px; overflow-y: auto; padding: var(--space-xs) 0; font-family: var(--font-body); } .slash-menu-category { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); padding: var(--space-sm) var(--space-md) var(--space-xs); } .slash-menu-item { display: flex; align-items: center; gap: var(--space-sm); width: 100%; padding: var(--space-sm) var(--space-md); border: none; background: none; cursor: pointer; text-align: left; font-size: 0.875rem; color: var(--color-text); border-radius: 0; transition: background-color var(--transition-fast); } .slash-menu-item:hover, .slash-menu-item-selected { background: var(--color-hover); } .slash-menu-item-icon { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--radius-sm); background: var(--color-surface-alt); font-size: 0.8rem; font-weight: 600; flex-shrink: 0; color: var(--color-text-muted); } .slash-menu-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; } .slash-menu-item-name { font-weight: 500; line-height: 1.3; } .slash-menu-item-desc { font-size: 0.75rem; color: var(--color-text-muted); line-height: 1.3; } .slash-menu-item-shortcut { font-size: 0.7rem; color: var(--color-text-faint); font-family: var(--font-mono); flex-shrink: 0; } .slash-menu-empty { padding: var(--space-md); text-align: center; color: var(--color-text-muted); font-size: 0.85rem; } /* --- Block Handle --- */ .block-handle { position: fixed; z-index: var(--z-float); display: flex; align-items: center; gap: 2px; opacity: 0; transition: opacity var(--transition-fast); } .block-handle[style*="display: flex"] { opacity: 1; } .block-handle-grip, .block-handle-add { display: flex; align-items: center; justify-content: center; width: 20px; height: 24px; border: none; background: none; cursor: pointer; border-radius: var(--radius-sm); color: var(--color-text-faint); font-size: 1rem; padding: 0; transition: background-color var(--transition-fast), color var(--transition-fast); } .block-handle-grip:hover, .block-handle-add:hover { background: var(--color-hover); color: var(--color-text-muted); } .block-handle-grip { cursor: grab; font-size: 1.1rem; letter-spacing: -1px; } .block-handle-add { font-size: 1.1rem; font-weight: 300; } /* --- Block Context Menu --- */ .block-context-menu { position: fixed; z-index: var(--z-popover); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); min-width: 160px; padding: var(--space-xs) 0; } .block-context-sub-header { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); padding: var(--space-sm) var(--space-md) var(--space-xs); } .block-context-item { display: flex; align-items: center; gap: var(--space-sm); width: 100%; padding: var(--space-sm) var(--space-md); border: none; background: none; cursor: pointer; text-align: left; font-size: 0.85rem; color: var(--color-text); transition: background-color var(--transition-fast); } .block-context-item:hover { background: var(--color-hover); } .block-context-icon { width: 18px; text-align: center; flex-shrink: 0; color: var(--color-text-muted); } .block-context-label { flex: 1; } /* --- Block-level Visual Polish --- */ /* Add left margin to editor content for block handle space */ .ProseMirror { padding-left: 40px; } /* Subtle hover highlight on blocks */ .ProseMirror > * { transition: background-color var(--transition-fast); border-left: 2px solid transparent; padding-left: var(--space-xs); margin-left: calc(-1 * var(--space-xs) - 2px); } /* Current block (with cursor) gets a subtle left accent */ .ProseMirror > .has-focus, .ProseMirror > *:hover { background: #006e6f08; background: oklch(0.48 0.1 195 / 0.03); } .ProseMirror > .has-focus { border-left-color: var(--color-teal); } /* Smooth reorder transitions */ .ProseMirror > * { transition: background-color var(--transition-fast), border-color var(--transition-fast), transform var(--transition-med); } /* Notion-style placeholder styling */ .ProseMirror p.is-empty::before { color: var(--color-text-faint); font-style: italic; pointer-events: none; } .ProseMirror.is-empty p.is-empty:first-child::before { color: var(--color-text-muted); } /* --- Hide block handle and slash menu in zen/print mode --- */ .zen-mode .block-handle, .zen-mode .block-context-menu { display: none !important; } @media print { .block-handle, .block-context-menu, .slash-menu { display: none !important; } .ProseMirror > * { border-left: none; margin-left: 0; } .ProseMirror { padding-left: 0; } } /* --- Dark mode overrides --- */ [data-theme="dark"] .slash-menu { background: var(--color-surface); border-color: var(--color-border); } [data-theme="dark"] .slash-menu-item-icon { background: var(--color-surface-alt); } [data-theme="dark"] .slash-menu-item:hover, [data-theme="dark"] .slash-menu-item-selected { background: var(--color-hover); } [data-theme="dark"] .block-context-menu { background: var(--color-surface); border-color: var(--color-border); } [data-theme="dark"] .block-context-item:hover { background: var(--color-hover); } [data-theme="dark"] .ProseMirror > .has-focus, [data-theme="dark"] .ProseMirror > *:hover { background: #0f92930d; background: oklch(0.60 0.1 195 / 0.05); } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .slash-menu { background: var(--color-surface); border-color: var(--color-border); } :root:not([data-theme="light"]) .slash-menu-item-icon { background: var(--color-surface-alt); } :root:not([data-theme="light"]) .slash-menu-item:hover, :root:not([data-theme="light"]) .slash-menu-item-selected { background: var(--color-hover); } :root:not([data-theme="light"]) .block-context-menu { background: var(--color-surface); border-color: var(--color-border); } :root:not([data-theme="light"]) .block-context-item:hover { background: var(--color-hover); } :root:not([data-theme="light"]) .ProseMirror > .has-focus, :root:not([data-theme="light"]) .ProseMirror > *:hover { background: #0f92930d; background: oklch(0.60 0.1 195 / 0.05); } } /* ========================================================== Command Palette (Cmd+K / Ctrl+K) ========================================================== */ .cmd-palette-backdrop { position: fixed; inset: 0; background: var(--color-modal-backdrop); display: flex; align-items: flex-start; justify-content: center; padding-top: min(20vh, 160px); z-index: var(--z-menu); opacity: 0; transition: opacity var(--transition-fast); } .cmd-palette-backdrop.cmd-palette-open { opacity: 1; } .cmd-palette { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); width: 90%; max-width: 600px; max-height: 60vh; display: flex; flex-direction: column; overflow: hidden; transform: translateY(-8px) scale(0.98); transition: transform var(--transition-fast), opacity var(--transition-fast); opacity: 0; } .cmd-palette-backdrop.cmd-palette-open .cmd-palette { transform: translateY(0) scale(1); opacity: 1; } .cmd-palette-input { width: 100%; padding: var(--space-md) var(--space-lg); border: none; border-bottom: 1px solid var(--color-border); background: transparent; color: var(--color-text); font: inherit; font-size: 1.05rem; outline: none; } .cmd-palette-input::placeholder { color: var(--color-text-faint); } .cmd-palette-results { overflow-y: auto; flex: 1; padding: var(--space-xs) 0; } .cmd-palette-category { padding: var(--space-sm) var(--space-lg) var(--space-xs); font-family: var(--font-body); font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); } .cmd-palette-item { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-lg); cursor: pointer; color: var(--color-text); font-size: 0.9rem; transition: background var(--transition-fast); } .cmd-palette-item:hover, .cmd-palette-item-selected { background: var(--color-hover); } .cmd-palette-item-selected { background: var(--color-hover); } .cmd-palette-item-icon { flex-shrink: 0; width: 1.5rem; text-align: center; font-size: 0.95rem; color: var(--color-text-muted); } .cmd-palette-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .cmd-palette-item-shortcut { flex-shrink: 0; font-size: 0.75rem; font-family: var(--font-mono); color: var(--color-text-faint); background: var(--color-surface-alt); padding: 2px 6px; border-radius: var(--radius-sm); border: 1px solid var(--color-border); } .cmd-palette-empty { padding: var(--space-xl) var(--space-lg); text-align: center; color: var(--color-text-faint); font-size: 0.9rem; } @media print { .cmd-palette-backdrop { display: none !important; } } /* ======================================================== Save Dot Indicator ======================================================== */ .save-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; transition: background-color var(--transition-fast); } .save-dot--saved { background-color: var(--color-success); } .save-dot--saving { background-color: var(--color-warning); animation: save-dot-pulse 1s ease-in-out infinite; } .save-dot--error { background-color: var(--color-danger); animation: save-dot-pulse 0.6s ease-in-out infinite; } @keyframes save-dot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* ======================================================== Version Panel (slide-in from right) ======================================================== */ .version-panel { position: fixed; top: 0; right: -320px; width: 320px; height: 100vh; background: var(--color-surface); border-left: 1px solid var(--color-border); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; z-index: var(--z-panel); transition: right var(--transition-med); overflow: hidden; } .version-panel.open { right: 0; } .version-panel-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); flex-shrink: 0; } .version-panel-header h3 { margin: 0; font-size: 0.875rem; font-weight: 600; font-family: var(--font-body); color: var(--color-text); } .version-panel-close { font-size: 1.25rem; color: var(--color-text-muted); } .version-panel-list { flex: 1; overflow-y: auto; padding: var(--space-xs) 0; } .version-panel-item { display: flex; flex-direction: column; gap: 2px; width: 100%; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); cursor: pointer; transition: background var(--transition-fast); font-family: var(--font-body); position: relative; } .version-panel-item:hover { background: var(--color-hover); } .version-panel-item:focus-visible { outline: 2px solid var(--color-teal); outline-offset: -2px; } .version-panel-item-top { display: flex; align-items: center; gap: var(--space-sm); } .version-panel-time { font-size: 0.75rem; color: var(--color-text); font-weight: 500; } .version-panel-named-badge { display: inline-block; padding: 1px 6px; font-size: 0.625rem; font-weight: 600; color: var(--color-teal); background: var(--color-teal-light); border-radius: var(--radius-sm); text-transform: uppercase; letter-spacing: 0.03em; } .version-panel-item-meta { display: flex; gap: var(--space-sm); font-size: 0.6875rem; color: var(--color-text-muted); } .version-panel-author { color: var(--color-text-faint); } .version-panel-author--forge { color: oklch(0.65 0.1 250); font-weight: 500; } .version-panel-count { color: var(--color-text-faint); } .version-panel-delta { font-weight: 600; } .version-panel-delta.positive { color: var(--color-success); } .version-panel-delta.negative { color: var(--color-danger); } .version-panel-name-btn { position: absolute; right: var(--space-sm); top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--color-text-faint); cursor: pointer; font-size: 0.875rem; opacity: 0; transition: opacity var(--transition-fast); padding: 2px 4px; border-radius: var(--radius-sm); } .version-panel-item:hover .version-panel-name-btn { opacity: 1; } .version-panel-name-btn:hover { color: var(--color-text); background: var(--color-hover); } .version-panel-preview { display: flex; flex-direction: column; position: absolute; inset: 0; background: var(--color-surface); z-index: 2; } .version-panel-preview-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); gap: var(--space-sm); flex-shrink: 0; } .version-panel-preview-content { flex: 1; overflow-y: auto; padding: var(--space-md); } @media print { .version-panel { display: none !important; } } /* ======================================================== Diff Panel (slide-in from right, compare versions) ======================================================== */ .diff-panel { position: fixed; top: 0; right: -380px; width: 380px; height: 100vh; background: var(--color-surface); border-left: 1px solid var(--color-border); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; z-index: var(--z-panel); transition: right var(--transition-med); overflow: hidden; } .diff-panel.open { right: 0; } .diff-panel-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); flex-shrink: 0; } .diff-panel-header h3 { margin: 0; font-size: 0.875rem; font-weight: 600; font-family: var(--font-body); color: var(--color-text); } .diff-panel-close { font-size: 1.25rem; color: var(--color-text-muted); } .diff-panel-controls { display: flex; align-items: flex-end; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); flex-shrink: 0; flex-wrap: wrap; } .diff-panel-select-group { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; } .diff-panel-label { font-size: 0.625rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); font-family: var(--font-body); } .diff-panel-select { font-size: 0.75rem; font-family: var(--font-body); padding: 4px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); min-width: 0; width: 100%; cursor: pointer; } .diff-panel-select:focus-visible { outline: 2px solid var(--color-teal); outline-offset: -1px; } .diff-panel-arrow { color: var(--color-text-faint); font-size: 0.875rem; padding-bottom: 4px; flex-shrink: 0; } .diff-panel-run { flex-shrink: 0; white-space: nowrap; } .diff-panel-stats { display: flex; gap: var(--space-md); padding: var(--space-xs) var(--space-md); border-bottom: 1px solid var(--color-border); font-size: 0.75rem; font-family: var(--font-body); font-weight: 600; flex-shrink: 0; } .diff-stat-add { color: var(--color-success); } .diff-stat-del { color: var(--color-danger); } .diff-stat-forge { margin-left: auto; padding: 1px 6px; border-radius: 3px; background: oklch(0.92 0.04 250); color: oklch(0.45 0.1 250); font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; } .diff-option--forge { color: oklch(0.45 0.1 250); font-weight: 500; } .diff-panel-body { flex: 1; overflow-y: auto; padding: var(--space-md); } .diff-panel-empty { color: var(--color-text-faint); font-size: 0.8125rem; font-family: var(--font-body); text-align: center; padding: var(--space-xl) var(--space-md); } .diff-panel-content { font-family: var(--font-display); font-size: 0.875rem; line-height: 1.7; color: var(--color-text); word-wrap: break-word; } .diff-equal { color: var(--color-text); } .diff-insert { background: oklch(0.92 0.08 155); color: oklch(0.28 0.06 155); padding: 1px 2px; border-radius: 2px; } .diff-delete { background: oklch(0.92 0.08 25); color: oklch(0.38 0.08 25); text-decoration: line-through; padding: 1px 2px; border-radius: 2px; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { .diff-insert { background: oklch(0.28 0.06 155); color: oklch(0.85 0.08 155); } .diff-delete { background: oklch(0.28 0.06 25); color: oklch(0.78 0.08 25); } } } @media print { .diff-panel { display: none !important; } } /* ======================================================== Print Preview Dialog ======================================================== */ .print-preview-backdrop { position: fixed; inset: 0; background: var(--color-modal-backdrop); z-index: var(--z-above-modal); display: flex; align-items: center; justify-content: center; } .print-preview-dialog { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); display: flex; width: 90vw; max-width: 960px; height: 80vh; max-height: 720px; overflow: hidden; } .print-preview-sidebar { width: 260px; min-width: 260px; padding: var(--space-lg); border-right: 1px solid var(--color-border); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-sm); } .print-preview-sidebar h3 { margin: 0 0 var(--space-sm); font-family: var(--font-display); font-size: 1.1rem; color: var(--color-text); } .print-preview-sidebar label { display: block; margin-bottom: var(--space-xs); font-size: 0.8rem; color: var(--color-text-muted); font-weight: 500; } .print-preview-sidebar select { width: 100%; padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-family: var(--font-body); font-size: 0.82rem; margin-bottom: var(--space-xs); } .print-preview-sidebar select:focus { border-color: var(--color-teal); outline: none; box-shadow: 0 0 0 2px var(--color-focus); } .print-preview-radio-group { display: flex; gap: var(--space-md); margin-bottom: var(--space-xs); } .print-preview-radio-group label { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.82rem; color: var(--color-text); cursor: pointer; margin-bottom: 0; } .print-preview-radio-group input[type="radio"] { margin: 0; accent-color: var(--color-teal); } .print-preview-checkbox { display: flex; align-items: center; gap: 0.4rem; margin-bottom: var(--space-xs); } .print-preview-checkbox input[type="checkbox"] { margin: 0; accent-color: var(--color-teal); } .print-preview-checkbox label { font-size: 0.82rem; color: var(--color-text); margin-bottom: 0; cursor: pointer; } .print-preview-actions { display: flex; gap: var(--space-sm); margin-top: auto; padding-top: var(--space-md); border-top: 1px solid var(--color-border); } .print-preview-actions button { flex: 1; padding: var(--space-xs) var(--space-md); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; font-size: 0.85rem; font-family: var(--font-body); background: var(--color-surface); color: var(--color-text); transition: background var(--transition-fast); } .print-preview-actions button:hover { background: var(--color-hover); } .print-preview-actions button.btn-primary { background: var(--color-accent); color: var(--color-btn-primary-text); border-color: var(--color-accent); } .print-preview-actions button.btn-primary:hover { background: var(--color-accent-hover); } .print-preview-content { flex: 1; overflow: auto; background: var(--color-surface-alt); padding: var(--space-lg); display: flex; align-items: flex-start; justify-content: center; } .print-preview-page { background: #fff; box-shadow: var(--shadow-md); border-radius: 2px; overflow: hidden; transform-origin: top center; } .print-preview-page iframe { border: none; width: 100%; height: 100%; display: block; } @media (max-width: 640px) { .print-preview-dialog { flex-direction: column; width: 100%; max-width: 100%; height: 100%; max-height: 100%; border-radius: 0; } .print-preview-sidebar { width: 100%; min-width: 0; border-right: none; border-bottom: 1px solid var(--color-border); max-height: 40vh; overflow-y: auto; } } /* Wiki links */ a.wiki-link { color: var(--color-teal); text-decoration: none; border-bottom: 1px dashed var(--color-teal); cursor: pointer; padding: 0 0.1em; border-radius: 2px; transition: background var(--transition-fast); } a.wiki-link:hover { background: #a0dbda33; background: oklch(0.85 0.06 195 / 0.2); } a.wiki-link[href="#"] { color: var(--color-text-faint); border-bottom-color: var(--color-text-faint); font-style: italic; } /* ── Mermaid diagram blocks ──────────────────────────────────────────── */ .mermaid-block { border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; margin: var(--space-md) 0; background: var(--color-surface-raised, var(--color-surface)); } .mermaid-toolbar { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); background: var(--color-surface); border-bottom: 1px solid var(--color-border); font-size: 0.78rem; } .mermaid-label { font-weight: 600; color: var(--color-text-secondary); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; flex: 1; } .mermaid-btn { padding: 2px 8px; font-size: 0.78rem; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-surface-raised, var(--color-surface)); color: var(--color-text); cursor: pointer; line-height: 1.4; } .mermaid-btn:hover { background: var(--color-teal); color: #fff; border-color: var(--color-teal); } .mermaid-btn-danger:hover { background: var(--color-danger, #d94a4a); border-color: var(--color-danger, #d94a4a); } .mermaid-preview { padding: var(--space-md); display: flex; justify-content: center; min-height: 60px; overflow-x: auto; } .mermaid-preview svg { max-width: 100%; height: auto; } .mermaid-preview-loading { opacity: 0.5; } .mermaid-preview-error { padding: var(--space-sm); } .mermaid-error { background: color-mix(in oklch, var(--color-danger, #d94a4a) 10%, transparent); border: 1px solid var(--color-danger, #d94a4a); border-radius: var(--radius-sm); padding: var(--space-sm); color: var(--color-danger, #d94a4a); font-size: 0.85rem; width: 100%; } .mermaid-error pre { margin: var(--space-xs) 0 0; font-size: 0.78rem; white-space: pre-wrap; overflow-wrap: anywhere; } .mermaid-editor-wrap { border-top: 1px solid var(--color-border); } .mermaid-code-input { width: 100%; box-sizing: border-box; padding: var(--space-sm); font-family: monospace; font-size: 0.85rem; background: var(--color-surface); color: var(--color-text); border: none; outline: none; resize: vertical; min-height: 120px; line-height: 1.5; } .mermaid-code-input:focus { background: var(--color-surface-raised, var(--color-surface)); } /* Dark mode: invert mermaid SVG text colours if using default theme */ [data-theme="dark"] .mermaid-preview svg text { fill: var(--color-text) !important; } /* Version badge — z-index must exceed sticky cells (max 5) and sheet UI but stay below modals/dialogs (1000+). */ .version-badge { position: fixed; bottom: 0.5rem; right: 0.75rem; font-size: 0.65rem; font-family: ui-monospace, 'SF Mono', monospace; color: var(--color-text-faint, #808080); opacity: 0.5; pointer-events: none; z-index: var(--z-float); user-select: none; } /* Apps with a bottom UI strip (sheets tab strip, etc.) push the version badge above that strip so it doesn't overlap. */ body:has(.sheets-app) .version-badge { bottom: 3rem; } /* ── AI Chat Sidebar ─────────────────────────────────────────────────── */ .ai-chat-sidebar { position: relative; width: 400px; border-left: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; overflow: hidden; flex-shrink: 0; } /* --- Position modes: side (default) / bottom / popup --- */ .ai-chat-sidebar[data-pos="bottom"] { position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: 100%; height: 360px; min-height: 200px; max-height: 85vh; border-left: none; border-top: 1px solid var(--color-border); box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08); z-index: var(--z-tooltip); resize: vertical; } [data-theme="dark"] .ai-chat-sidebar[data-pos="bottom"] { box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.4); } .ai-chat-sidebar[data-pos="popup"] { position: fixed; right: 24px; bottom: 24px; top: auto; left: auto; width: 440px; height: min(640px, calc(100vh - 48px)); min-width: 320px; min-height: 320px; max-width: calc(100vw - 48px); max-height: calc(100vh - 48px); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18); z-index: var(--z-tooltip); resize: both; } [data-theme="dark"] .ai-chat-sidebar[data-pos="popup"] { box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6); } .ai-chat-position-btn { position: relative; } .ai-chat-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); gap: var(--space-sm); } .ai-chat-header-left { display: flex; align-items: center; gap: var(--space-sm); min-width: 0; } .ai-chat-title { font-size: 0.875rem; font-weight: 600; font-family: var(--font-body); color: var(--color-text); white-space: nowrap; } .ai-chat-model-badge { font-size: 0.7rem; color: var(--color-text-muted); background: var(--color-hover); padding: 1px 6px; border-radius: var(--radius-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; } .ai-chat-header-actions { display: flex; align-items: center; gap: 2px; } .ai-chat-close { font-size: 1.25rem; color: var(--color-text-muted); } /* Settings panel */ .ai-chat-settings { padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); background: var(--color-bg); display: flex; flex-direction: column; gap: var(--space-sm); } .ai-chat-settings-field { display: flex; flex-direction: column; gap: 2px; } .ai-chat-settings-field label { font-size: 0.75rem; font-weight: 500; color: var(--color-text-muted); } .ai-chat-hint { font-weight: 400; opacity: 0.7; } .ai-chat-settings-field input[type="text"], .ai-chat-settings-field input[type="password"], .ai-chat-settings-field select { font-size: 0.8125rem; padding: 4px 8px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font-family: ui-monospace, 'SF Mono', monospace; } .ai-chat-settings-field select { font-family: var(--font-body); } .ai-chat-model-custom { margin-top: 4px; } /* #675 — endpoint validation helper + error text. */ .ai-chat-endpoint-hint { margin: 2px 0 0; font-size: 0.7rem; color: var(--color-text-faint); line-height: 1.3; } .ai-chat-endpoint-hint code { font-family: ui-monospace, 'SF Mono', monospace; font-size: 0.95em; padding: 0 3px; background: var(--color-surface-alt, var(--color-surface)); border-radius: 2px; } .ai-chat-endpoint-error { margin: 2px 0 0; font-size: 0.7rem; color: var(--color-danger, #d32f2f); line-height: 1.3; } .ai-chat-settings-field input[aria-invalid="true"] { border-color: var(--color-danger, #d32f2f); } .ai-chat-context-row { flex-direction: row; align-items: center; } .ai-chat-toggle-label { display: flex; align-items: center; gap: var(--space-xs); font-size: 0.8125rem; color: var(--color-text); cursor: pointer; } .ai-chat-toggle-label input[type="checkbox"] { accent-color: var(--color-accent); } .ai-chat-advanced { margin-top: var(--space-xs); font-size: 0.8125rem; color: var(--color-text-muted); } .ai-chat-advanced summary { cursor: pointer; user-select: none; } .ai-chat-advanced .ai-chat-settings-field { margin-top: var(--space-xs); } /* Message area */ .ai-chat-messages { flex: 1; overflow-y: auto; padding: var(--space-sm); display: flex; flex-direction: column; gap: var(--space-sm); } .ai-chat-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; flex: 1; text-align: center; gap: var(--space-xs); padding: var(--space-xl); } .ai-chat-empty-icon { font-size: 2rem; opacity: 0.5; } .ai-chat-empty-text { font-size: 0.9375rem; font-weight: 500; color: var(--color-text); } .ai-chat-empty-hint { font-size: 0.8125rem; color: var(--color-text-muted); max-width: 240px; } /* Chat bubbles */ .ai-chat-bubble { padding: var(--space-sm) var(--space-md); border-radius: var(--radius-md); font-size: 0.875rem; line-height: 1.55; word-break: break-word; max-width: 100%; } .ai-chat-bubble--user { background: var(--color-accent); color: white; align-self: flex-end; border-bottom-right-radius: 4px; max-width: 85%; } .ai-chat-bubble--assistant { background: var(--color-hover); color: var(--color-text); align-self: flex-start; border-bottom-left-radius: 4px; } .ai-chat-thinking { display: inline-flex; align-items: center; gap: 4px; padding: 2px 0; } .ai-thinking-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-text-muted); animation: ai-bounce 1.4s ease-in-out infinite; } .ai-thinking-dot:nth-child(2) { animation-delay: 0.16s; } .ai-thinking-dot:nth-child(3) { animation-delay: 0.32s; } @keyframes ai-bounce { 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } 40% { transform: scale(1); opacity: 1; } } /* Code blocks in AI responses */ .ai-code-block { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-sm); margin: var(--space-xs) 0; overflow-x: auto; font-family: ui-monospace, 'SF Mono', monospace; font-size: 0.8125rem; line-height: 1.4; white-space: pre-wrap; } .ai-inline-code { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 3px; padding: 1px 4px; font-family: ui-monospace, 'SF Mono', monospace; font-size: 0.85em; } /* Headers in AI responses */ .ai-chat-bubble .ai-h { margin: var(--space-sm) 0 var(--space-xs); line-height: 1.3; } .ai-chat-bubble h1.ai-h { font-size: 1.1rem; } .ai-chat-bubble h2.ai-h { font-size: 1rem; } .ai-chat-bubble h3.ai-h { font-size: 0.9375rem; } .ai-chat-bubble h4.ai-h, .ai-chat-bubble h5.ai-h, .ai-chat-bubble h6.ai-h { font-size: 0.875rem; } /* Tables in AI responses */ .ai-table { border-collapse: collapse; width: 100%; margin: var(--space-xs) 0; font-size: 0.8125rem; } .ai-table th, .ai-table td { border: 1px solid var(--color-border); padding: 3px 6px; text-align: left; } .ai-table th { background: var(--color-surface-alt); font-weight: 600; } .ai-table tr:nth-child(even) td { background: var(--color-bg); } /* Lists in AI responses */ .ai-list { margin: var(--space-xs) 0; padding-left: 1.25em; } .ai-list li { margin-bottom: 2px; } /* Horizontal rule in AI responses */ .ai-hr { border: none; border-top: 1px solid var(--color-border); margin: var(--space-sm) 0; } /* Links in AI responses */ .ai-chat-bubble a { color: var(--color-accent); text-decoration: underline; text-underline-offset: 2px; } .ai-chat-bubble a:hover { color: var(--color-accent-hover); } /* Input area */ .ai-chat-input-area { padding: var(--space-sm) var(--space-md); border-top: 1px solid var(--color-border); background: var(--color-surface); } .ai-chat-input-row { display: flex; align-items: flex-end; gap: var(--space-xs); } .ai-chat-input { flex: 1; resize: none; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 8px 12px; font-size: 0.875rem; font-family: var(--font-body); line-height: 1.4; background: var(--color-bg); color: var(--color-text); min-height: 36px; max-height: 120px; transition: border-color var(--transition-fast); } .ai-chat-input:focus { border-color: var(--color-accent); } .ai-chat-input::placeholder { color: var(--color-text-muted); } .ai-chat-send, .ai-chat-stop { flex-shrink: 0; width: 36px; height: 36px; border: none; border-radius: var(--radius-md); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background var(--transition-fast), opacity var(--transition-fast); } .ai-chat-send { background: var(--color-accent); color: white; } .ai-chat-send:hover { opacity: 0.85; } .ai-chat-send:disabled { opacity: 0.4; cursor: default; } .ai-chat-stop { background: var(--color-error, #f14d4c); color: white; font-size: 1rem; } .ai-chat-stop:hover { opacity: 0.85; } /* AI action cards */ .ai-action-card { margin: var(--space-xs) var(--space-md); padding: var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); font-size: 0.8125rem; } .ai-action-card-desc { display: flex; align-items: center; gap: var(--space-xs); color: var(--color-text); margin-bottom: var(--space-xs); } .ai-action-card-desc .tb-icon { flex-shrink: 0; color: var(--color-accent); } .ai-action-card-buttons { display: flex; gap: var(--space-xs); } .ai-action-btn { padding: 3px 10px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-size: 0.75rem; cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast); } .ai-action-btn:hover { border-color: var(--color-accent); } .ai-action-btn--apply { background: var(--color-accent); color: white; border-color: var(--color-accent); } .ai-action-btn--apply:hover { opacity: 0.85; } .ai-action-btn--suggest { background: #7bc27e; background: oklch(0.75 0.12 145); color: white; border-color: #7bc27e; border-color: oklch(0.75 0.12 145); } .ai-action-btn--suggest:hover { opacity: 0.85; } .ai-action-btn--dismiss { color: var(--color-text-muted); } .ai-action-card-status { font-size: 0.75rem; color: var(--color-text-muted); font-style: italic; } .ai-action-card--applied { border-color: var(--color-accent); opacity: 0.7; } .ai-action-card--suggested { border-color: #7bc27e; border-color: oklch(0.75 0.12 145); opacity: 0.7; } .ai-action-card--dismissed { opacity: 0.4; } /* AI chat onboarding banner (shown when no endpoint is configured) */ .ai-chat-onboarding { margin: var(--space-sm) var(--space-md); padding: var(--space-sm) var(--space-md); border: 1px solid var(--color-accent); border-radius: var(--radius-md); background: color-mix(in oklch, var(--color-accent) 8%, var(--color-surface)); font-size: 0.8125rem; color: var(--color-text); display: flex; flex-direction: column; gap: var(--space-xs); } .ai-chat-onboarding-title { font-weight: 600; font-size: 0.875rem; } .ai-chat-onboarding-body { color: var(--color-text-muted); line-height: 1.4; } .ai-chat-onboarding-cta { align-self: flex-start; padding: 4px 12px; border: 1px solid var(--color-accent); border-radius: var(--radius-sm); background: var(--color-accent); color: white; font-size: 0.75rem; cursor: pointer; transition: opacity var(--transition-fast); } .ai-chat-onboarding-cta:hover { opacity: 0.85; } /* AI chat parse-error note (non-fatal action parse failures) */ .ai-chat-parse-errors { margin: var(--space-xs) var(--space-md); padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-warning, #d97706); border-left-width: 3px; border-radius: var(--radius-sm); background: color-mix(in oklch, var(--color-warning, #d97706) 6%, var(--color-surface)); color: var(--color-text); font-size: 0.75rem; } .ai-chat-parse-errors-title { font-weight: 600; margin-bottom: 2px; } .ai-chat-parse-errors ul { margin: 0; padding-left: 1.1rem; color: var(--color-text-muted); } /* AI chat error bubble */ .ai-chat-bubble--error { border: 1px solid var(--color-error, #f14d4c); background: color-mix(in oklch, var(--color-error, #f14d4c) 6%, var(--color-surface)); } .ai-chat-error { color: var(--color-error, #f14d4c); font-size: 0.8125rem; } .zen-mode .ai-chat-sidebar { display: none !important; } @media (max-width: 768px) { .ai-chat-sidebar { position: fixed; top: 0; right: 0; bottom: 0; width: 100%; z-index: var(--z-tooltip); } } /* ── Wireframe Component Palette ──────────────────────────────── */ .wireframe-dropdown { position: relative; } .wireframe-menu { position: absolute; top: 100%; left: 0; z-index: 50; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm, 4px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); padding: 4px; min-width: 140px; max-height: 320px; overflow-y: auto; } .wireframe-category { font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-faint); padding: 6px 8px 2px; } .wireframe-item { display: block; width: 100%; text-align: left; border: none; background: transparent; color: var(--color-text); font-size: 0.78rem; padding: 4px 8px; border-radius: 3px; cursor: pointer; } .wireframe-item:hover { background: var(--color-surface-alt); } /* ── Modal dialog (promise-based prompt/confirm) — #109 ─────────── */ .modal-dialog-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); display: flex; align-items: center; justify-content: center; z-index: var(--z-modal, 10000); animation: modal-fade-in 0.12s ease-out; } [data-theme="dark"] .modal-dialog-backdrop { background: rgba(0, 0, 0, 0.6); } @keyframes modal-fade-in { from { opacity: 0; } to { opacity: 1; } } .modal-dialog { background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2); padding: var(--space-lg); min-width: 320px; max-width: 480px; width: calc(100% - var(--space-xl)); display: flex; flex-direction: column; gap: var(--space-md); animation: modal-dialog-in 0.15s ease-out; } @keyframes modal-dialog-in { from { transform: translateY(-8px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .modal-dialog-title { font-size: 1rem; font-weight: 600; line-height: 1.3; } .modal-dialog-message { color: var(--color-text-muted); font-size: 0.875rem; line-height: 1.4; white-space: pre-wrap; } .modal-dialog-input { width: 100%; padding: var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-bg); color: var(--color-text); font-size: 0.875rem; font-family: inherit; } .modal-dialog-input:focus { outline: none; border-color: var(--color-accent); box-shadow: 0 0 0 2px color-mix(in oklch, var(--color-accent) 30%, transparent); } .modal-dialog-footer { display: flex; justify-content: flex-end; gap: var(--space-sm); } .modal-dialog-ok, .modal-dialog-cancel { padding: 6px 14px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-bg); color: var(--color-text); font-size: 0.8125rem; font-family: inherit; cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast), opacity var(--transition-fast); } .modal-dialog-cancel:hover { background: var(--color-surface-alt); } .modal-dialog-ok { background: var(--color-accent); color: white; border-color: var(--color-accent); } .modal-dialog-ok:hover { opacity: 0.88; } .modal-dialog-ok--destructive { background: var(--color-error, #f14d4c); border-color: var(--color-error, #f14d4c); } .modal-dialog-ok:focus-visible, .modal-dialog-cancel:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; } /* ── Electron traffic-light padding (landing page, supplements rules at line ~1850) ── */ .is-electron .landing-header .brand { padding-left: 88px; } /* ── Slides Editor ──────────────────────────────────────────────────── */ .slides-app { display: flex; flex-direction: column; height: 100vh; overflow: hidden; } .slides-main { display: flex; flex: 1; overflow: hidden; } /* Left: thumbnail panel */ .slides-panel { width: 200px; flex-shrink: 0; border-right: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; overflow: hidden; } .slides-thumbnail-list { flex: 1; overflow-y: auto; padding: var(--space-sm); display: flex; flex-direction: column; gap: var(--space-xs); } .slides-thumbnail { aspect-ratio: 16/9; border: 2px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 0.65rem; color: var(--color-text-muted); transition: border-color var(--transition-fast); position: relative; overflow: hidden; } .slides-thumbnail:hover { border-color: var(--color-border-strong); } .slides-thumbnail.active { border-color: var(--color-teal); } .slides-thumbnail-number { position: absolute; top: 2px; left: 4px; font-size: 0.55rem; color: var(--color-text-faint); } .slides-add-btn { margin: var(--space-sm); padding: var(--space-xs) var(--space-sm); border: 1px dashed var(--color-border-strong); border-radius: var(--radius-sm); background: transparent; color: var(--color-text-muted); cursor: pointer; font-size: 0.75rem; transition: background var(--transition-fast); } .slides-add-btn:hover { background: var(--color-hover); } /* Center: canvas area */ .slides-canvas-area { flex: 1; display: flex; flex-direction: column; overflow: hidden; } .slides-toolbar { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-xs) var(--space-sm); border-bottom: 1px solid var(--color-border); background: var(--color-surface); flex-wrap: wrap; } .slides-layout-select, .slides-theme-select, .slides-transition-select { padding: 3px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-size: 0.75rem; } .slides-canvas-wrapper { flex: 1; display: flex; align-items: center; justify-content: center; background: var(--color-surface-alt); padding: var(--space-lg); overflow: auto; } .slides-canvas { width: 960px; height: 540px; max-width: 100%; background: white; border-radius: var(--radius-md); box-shadow: var(--shadow-lg); position: relative; overflow: hidden; } [data-theme="dark"] .slides-canvas { background: #24211c; background: oklch(0.25 0.01 75); } /* Right: notes panel */ .slides-notes-panel { width: 240px; flex-shrink: 0; border-left: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; padding: var(--space-sm); } .slides-notes-title { font-size: 0.75rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: var(--space-xs); } .slides-notes-input { flex: 1; resize: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs); font-family: var(--font-body); font-size: 0.8rem; color: var(--color-text); background: var(--color-bg); } /* Slide elements */ .slide-element { position: absolute; cursor: move; user-select: none; } .slide-element.selected { outline: 2px solid var(--color-teal); outline-offset: 1px; } .slide-element-text { min-width: 40px; min-height: 20px; padding: 4px 8px; } .slide-element-text[contenteditable="true"] { cursor: text; outline: 1px dashed var(--color-border-strong); } /* ── Presenter Overlay ──────────────────────────────────────────────── */ .presenter-overlay { position: fixed; inset: 0; z-index: var(--z-modal); background: #030303; background: oklch(0.10 0 0); color: #dedede; color: oklch(0.90 0 0); display: flex; } .presenter-current { flex: 1; display: flex; align-items: center; justify-content: center; padding: var(--space-lg); } .presenter-current .slides-canvas { width: 100%; height: 100%; max-width: none; } .presenter-sidebar { width: 320px; display: flex; flex-direction: column; border-left: 1px solid #2e2e2e; border-left: 1px solid oklch(0.30 0 0); background: #090909; background: oklch(0.14 0 0); } .presenter-next { padding: var(--space-sm); border-bottom: 1px solid #2e2e2e; border-bottom: 1px solid oklch(0.30 0 0); } .presenter-next h4 { font-size: 0.7rem; text-transform: uppercase; color: #808080; color: oklch(0.60 0 0); margin-bottom: var(--space-xs); } .presenter-next-preview { aspect-ratio: 16/9; background: #161616; background: oklch(0.20 0 0); border-radius: var(--radius-sm); overflow: hidden; } .presenter-notes { flex: 1; padding: var(--space-sm); overflow-y: auto; font-size: 0.85rem; line-height: 1.5; color: #bebebe; color: oklch(0.80 0 0); } .presenter-controls { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm); border-top: 1px solid #2e2e2e; border-top: 1px solid oklch(0.30 0 0); } .presenter-timer { font-family: var(--font-mono); font-size: 1.2rem; color: #9e9e9e; color: oklch(0.70 0 0); } .presenter-progress { font-size: 0.8rem; color: #808080; color: oklch(0.60 0 0); margin-left: auto; } /* ── Diagrams / Whiteboard ──────────────────────────────────────────── */ .diagrams-app { display: flex; flex-direction: column; height: 100vh; overflow: hidden; } .diagrams-main { flex: 1; display: flex; position: relative; overflow: hidden; } .diagrams-toolbar { position: absolute; top: var(--space-sm); left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 2px; padding: 4px 8px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); z-index: var(--z-component); } .diagrams-tool.active { background: var(--color-btn-active-bg); color: var(--color-accent); } .diagrams-zoom-label { font-size: 0.7rem; font-family: var(--font-mono); color: var(--color-text-muted); min-width: 3em; text-align: center; } .diagrams-canvas-area { flex: 1; overflow: hidden; cursor: crosshair; } .diagrams-canvas { width: 100%; height: 100%; display: block; } .diagrams-grid { pointer-events: none; } .diagrams-layer { pointer-events: all; } /* Properties panel */ .diagrams-props-title { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); margin-bottom: var(--space-sm); } .diagrams-prop-label { display: block; font-size: 0.75rem; color: var(--color-text-muted); margin-bottom: var(--space-xs); } .diagrams-prop-input { width: 100%; padding: 3px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-size: 0.8rem; margin-top: 2px; } .diagram-shape.selected rect, .diagram-shape.selected ellipse, .diagram-shape.selected polygon, .diagram-shape.selected path { stroke: var(--color-teal); } .resize-handle { fill: white; stroke: var(--color-teal); stroke-width: 1.5; cursor: pointer; } .marquee-rect { fill: var(--color-teal); fill-opacity: 0.08; stroke: var(--color-teal); stroke-width: 1; stroke-dasharray: 4 3; pointer-events: none; } .creation-preview { pointer-events: none; } .creation-preview rect, .creation-preview ellipse, .creation-preview polygon { fill: var(--color-teal); fill-opacity: 0.06; stroke: var(--color-teal); stroke-width: 1.5; stroke-dasharray: 6 3; } .arrow-preview { stroke: var(--color-text-muted); stroke-width: 1.5; stroke-dasharray: 6 3; pointer-events: none; } .arrow-hover-target rect, .arrow-hover-target ellipse, .arrow-hover-target polygon { stroke: var(--color-teal); stroke-dasharray: 4 2; } .rotation-handle { fill: white; stroke: var(--color-primary); stroke-width: 1.5; cursor: grab; } .rotation-handle:active { cursor: grabbing; } .rotation-line { pointer-events: none; } .freehand-preview { pointer-events: none; } .inline-text-edit textarea { width: 100%; height: 100%; border: none; background: transparent; resize: none; outline: none; text-align: center; color: var(--color-text); padding: 4px; box-sizing: border-box; } .diagram-arrow { cursor: pointer; } /* Style panel (right sidebar) */ .diagrams-style-panel { position: absolute; top: var(--space-sm); right: var(--space-sm); width: 220px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: var(--space-sm); z-index: var(--z-component); } .diagrams-style-row { display: flex; gap: var(--space-sm); margin-bottom: var(--space-xs); } .diagrams-style-row label { flex: 1; display: flex; flex-direction: column; font-size: 0.7rem; color: var(--color-text-muted); gap: 2px; } .diagrams-style-row input[type="color"] { width: 100%; height: 24px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 1px; cursor: pointer; background: none; } .diagrams-style-row select, .diagrams-style-row input[type="number"] { width: 100%; padding: 2px 4px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-size: 0.75rem; } .diagrams-style-row input[type="range"] { width: 100%; accent-color: var(--color-primary); } /* Toolbar divider for diagrams */ .diagrams-toolbar .toolbar-divider { width: 1px; height: 20px; background: var(--color-border); margin: 0 4px; } /* Context menu */ .diagrams-context-menu { position: fixed; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: 4px 0; z-index: var(--z-overlay); min-width: 160px; } .diagrams-context-menu button { display: flex; align-items: center; gap: var(--space-sm); width: 100%; padding: 6px 12px; border: none; background: none; color: var(--color-text); font-size: 0.8rem; cursor: pointer; text-align: left; } .diagrams-context-menu button:hover { background: var(--color-btn-hover-bg); } .diagrams-context-menu .menu-divider { height: 1px; background: var(--color-border); margin: 4px 0; } .diagrams-context-menu .shortcut { margin-left: auto; font-size: 0.65rem; color: var(--color-text-muted); } /* Snap guides */ .snap-guide { stroke: var(--color-teal); stroke-width: 0.5; stroke-dasharray: 3 2; pointer-events: none; } /* Shortcuts dialog */ .diagrams-shortcuts-dialog { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-lg); z-index: var(--z-tooltip); max-width: 480px; width: 90vw; max-height: 80vh; overflow-y: auto; } .diagrams-shortcuts-dialog h2 { font-size: 1rem; margin-bottom: var(--space-md); } .diagrams-shortcuts-dialog .shortcut-row { display: flex; justify-content: space-between; padding: 4px 0; font-size: 0.8rem; border-bottom: 1px solid var(--color-border-subtle, var(--color-border)); } .diagrams-shortcuts-dialog kbd { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 1px 6px; font-family: var(--font-mono); font-size: 0.7rem; } .diagrams-shortcuts-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.3); z-index: calc(var(--z-tooltip) - 1); } /* ── Comments Sidebar ───────────────────────────────────────────────── */ .comments-sidebar { width: 300px; flex-shrink: 0; border-left: 1px solid var(--color-border); background: var(--color-surface); display: flex; flex-direction: column; overflow: hidden; } .comments-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--color-border); } .comments-header h3 { font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); } .comments-list { flex: 1; overflow-y: auto; padding: var(--space-sm); } .comment-thread { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-sm); margin-bottom: var(--space-sm); background: var(--color-bg); transition: border-color var(--transition-fast); } .comment-thread:hover { border-color: var(--color-border-strong); } .comment-thread.resolved { opacity: 0.5; } .comment-author { font-size: 0.75rem; font-weight: 600; color: var(--color-text); } .comment-time { font-size: 0.65rem; color: var(--color-text-faint); margin-left: var(--space-xs); } .comment-body { font-size: 0.8rem; color: var(--color-text); margin-top: var(--space-xs); line-height: 1.45; } .comment-reply-input { width: 100%; margin-top: var(--space-xs); padding: 4px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-size: 0.75rem; background: var(--color-surface); color: var(--color-text); } .comment-actions { display: flex; gap: var(--space-xs); margin-top: var(--space-xs); } .comment-actions button { font-size: 0.65rem; padding: 2px 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: transparent; color: var(--color-text-muted); cursor: pointer; } .comment-actions button:hover { background: var(--color-hover); } /* ── Follow Mode ────────────────────────────────────────────────────── */ .follow-banner { position: fixed; top: var(--space-sm); left: 50%; transform: translateX(-50%); padding: 6px 16px; background: var(--color-teal); color: var(--color-btn-primary-text); border-radius: 999px; font-size: 0.75rem; font-weight: 600; z-index: var(--z-overlay); display: flex; align-items: center; gap: var(--space-sm); box-shadow: var(--shadow-md); } .follow-banner button { background: transparent; border: 1px solid currentColor; color: inherit; border-radius: var(--radius-sm); padding: 2px 8px; cursor: pointer; font-size: 0.7rem; } /* ── Split View ─────────────────────────────────────────────────────── */ .split-container { display: grid; width: 100%; height: 100%; overflow: hidden; } .split-pane { overflow: auto; border-right: 1px solid var(--color-border); position: relative; } .split-pane:last-child { border-right: none; } .split-handle { width: 4px; background: var(--color-border); cursor: col-resize; transition: background var(--transition-fast); } .split-handle:hover { background: var(--color-teal); } /* ── Focus / Typewriter Mode ────────────────────────────────────────── */ .typewriter-mode .tiptap .ProseMirror { padding-top: 40vh; padding-bottom: 40vh; } .typewriter-mode .tiptap .ProseMirror .is-active-node { opacity: 1; } .typewriter-mode .tiptap .ProseMirror > *:not(.is-active-node) { opacity: 0.4; transition: opacity var(--transition-med); } /* ── Responsive: Slides ─────────────────────────────────────────────── */ @media (max-width: 768px) { .slides-panel { width: 120px; } .slides-notes-panel { display: none; } .slides-canvas { width: 100%; height: auto; aspect-ratio: 16/9; } .presenter-sidebar { width: 200px; } .diagrams-toolbar { flex-wrap: wrap; gap: 1px; padding: 2px 4px; } .comments-sidebar { position: fixed; top: 0; right: 0; bottom: 0; width: 100%; z-index: var(--z-tooltip); } } @media (max-width: 480px) { .slides-panel { display: none; } /* When toggled open on phone, render as full-screen overlay above canvas */ .slides-panel.slides-panel--mobile-open { display: flex; position: fixed; top: 0; left: 0; bottom: 0; width: 75vw; max-width: 280px; z-index: var(--z-tooltip); box-shadow: var(--shadow-lg); background: var(--color-surface); } .presenter-sidebar { display: none; } .diagrams-props { width: 160px; } } /* Hide the mobile-only panel toggle on desktop */ .slides-panel-toggle { display: none; } @media (max-width: 480px) { .slides-panel-toggle { display: inline-flex; } } /* ============================================================ Syntax Highlighting (lowlight / highlight.js class-based) ============================================================ */ .tiptap pre { position: relative; } .tiptap pre code .hljs-comment, .tiptap pre code .hljs-quote { color: var(--color-text-faint); font-style: italic; } .tiptap pre code .hljs-keyword, .tiptap pre code .hljs-selector-tag, .tiptap pre code .hljs-built_in, .tiptap pre code .hljs-type { color: #8c54b2; color: oklch(0.55 0.15 310); } [data-theme="dark"] .tiptap pre code .hljs-keyword, [data-theme="dark"] .tiptap pre code .hljs-selector-tag, [data-theme="dark"] .tiptap pre code .hljs-built_in, [data-theme="dark"] .tiptap pre code .hljs-type { color: #bf8ae6; color: oklch(0.72 0.14 310); } .tiptap pre code .hljs-string, .tiptap pre code .hljs-addition { color: #2f7434; color: oklch(0.50 0.12 145); } [data-theme="dark"] .tiptap pre code .hljs-string, [data-theme="dark"] .tiptap pre code .hljs-addition { color: #6cb26f; color: oklch(0.70 0.12 145); } .tiptap pre code .hljs-number, .tiptap pre code .hljs-literal { color: #a34d00; color: oklch(0.52 0.14 55); } [data-theme="dark"] .tiptap pre code .hljs-number, [data-theme="dark"] .tiptap pre code .hljs-literal { color: #de8f57; color: oklch(0.72 0.12 55); } .tiptap pre code .hljs-title, .tiptap pre code .hljs-section { color: #0465af; color: oklch(0.50 0.14 250); } [data-theme="dark"] .tiptap pre code .hljs-title, [data-theme="dark"] .tiptap pre code .hljs-section { color: #67aaed; color: oklch(0.72 0.12 250); } .tiptap pre code .hljs-name, .tiptap pre code .hljs-selector-id, .tiptap pre code .hljs-selector-class { color: #007172; color: oklch(0.48 0.12 195); } [data-theme="dark"] .tiptap pre code .hljs-name, [data-theme="dark"] .tiptap pre code .hljs-selector-id, [data-theme="dark"] .tiptap pre code .hljs-selector-class { color: #39abab; color: oklch(0.68 0.1 195); } .tiptap pre code .hljs-attr, .tiptap pre code .hljs-attribute { color: #906a21; color: oklch(0.55 0.1 80); } [data-theme="dark"] .tiptap pre code .hljs-attr, [data-theme="dark"] .tiptap pre code .hljs-attribute { color: #c69e58; color: oklch(0.72 0.1 80); } .tiptap pre code .hljs-deletion { color: #b94642; color: oklch(0.55 0.15 25); } [data-theme="dark"] .tiptap pre code .hljs-deletion { color: #e97871; color: oklch(0.70 0.14 25); } .tiptap pre code .hljs-regexp, .tiptap pre code .hljs-link { color: #007e5e; color: oklch(0.52 0.12 170); } .tiptap pre code .hljs-meta, .tiptap pre code .hljs-meta .hljs-keyword, .tiptap pre code .hljs-meta .hljs-string { color: var(--color-text-muted); } .tiptap pre code .hljs-emphasis { font-style: italic; } .tiptap pre code .hljs-strong { font-weight: 700; } /* Code block language label */ .tiptap pre[data-language]::before { content: attr(data-language); position: absolute; top: 0.25rem; right: 0.5rem; font-size: 0.65rem; font-family: var(--font-mono); color: var(--color-text-faint); text-transform: uppercase; letter-spacing: 0.05em; pointer-events: none; } /* ============================================================ Table of Contents ============================================================ */ .toc-list { list-style: none; padding-left: 0; margin: 1em 0; border-left: 2px solid var(--color-border); padding-left: var(--space-md); } .toc-list ul { list-style: none; padding-left: var(--space-lg); margin: 0; } .toc-list li { margin: 0.25em 0; } .toc-list a { color: var(--color-text-muted); text-decoration: none; font-size: 0.9rem; transition: color var(--transition-fast); } .toc-list a:hover { color: var(--color-teal); text-decoration: underline; } /* ============================================================ Calendar — E2EE Collaborative Calendar ============================================================ */ /* --- Calendar tokens --- */ :root { --cal-cell-min: 120px; --cal-cell-min-tablet: 90px; --cal-cell-min-mobile: 60px; --cal-hour-height: 60px; --cal-gutter-width: 60px; --cal-now-color: #bd413f; --cal-now-color: oklch(0.55 0.16 25); /* Event palette — 8 hues keyed to oklch for both themes */ --cal-ev-red: #c75450; --cal-ev-red: oklch(0.56 0.14 25); --cal-ev-orange: #c47525; --cal-ev-orange: oklch(0.60 0.14 60); --cal-ev-gold: #a88a1a; --cal-ev-gold: oklch(0.62 0.12 90); --cal-ev-green: #3a8a4e; --cal-ev-green: oklch(0.55 0.12 150); --cal-ev-teal: #0f7e7f; --cal-ev-teal: oklch(0.52 0.10 195); --cal-ev-blue: #3d6ea5; --cal-ev-blue: oklch(0.52 0.10 250); --cal-ev-purple: #7c549e; --cal-ev-purple: oklch(0.50 0.12 310); --cal-ev-slate: #6a6560; --cal-ev-slate: oklch(0.50 0.01 75); } [data-theme="dark"] { --cal-now-color: #ce514d; --cal-now-color: oklch(0.60 0.16 25); --cal-ev-red: #d06b67; --cal-ev-red: oklch(0.62 0.14 25); --cal-ev-orange: #d08e45; --cal-ev-orange: oklch(0.66 0.12 60); --cal-ev-gold: #c0a230; --cal-ev-gold: oklch(0.70 0.12 90); --cal-ev-green: #4faa65; --cal-ev-green: oklch(0.65 0.12 150); --cal-ev-teal: #2fa0a0; --cal-ev-teal: oklch(0.62 0.10 195); --cal-ev-blue: #5f92c4; --cal-ev-blue: oklch(0.62 0.10 250); --cal-ev-purple: #9e78be; --cal-ev-purple: oklch(0.60 0.12 310); --cal-ev-slate: #8a857f; --cal-ev-slate: oklch(0.60 0.01 75); } /* ── App Layout ──────────────────────────────────────────────────────── */ .calendar-app { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; overscroll-behavior: none; /* prevent pull-to-refresh / rubber-band on mobile */ } .calendar-main { position: relative; flex: 1; display: flex; flex-direction: column; min-height: 0; /* allow flex children to shrink below content size */ } /* Calendar body: sidebar + grid wrapper */ .cal-body { flex: 1; display: flex; min-height: 0; overflow: hidden; } /* ── Mini Calendar Sidebar ──────────────────────────────────────────── */ .cal-sidebar { width: 200px; flex-shrink: 0; border-right: 1px solid var(--color-border); padding: var(--space-sm); overflow-y: auto; transition: width var(--transition-fast), padding var(--transition-fast), border var(--transition-fast); } .cal-sidebar-hidden { width: 0; padding: 0; border-right: none; overflow: hidden; } .cal-mini-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-xs); } .cal-mini-title { font-size: 0.75rem; font-weight: 600; color: var(--color-text); } .cal-mini-nav { background: none; border: none; color: var(--color-text-muted); cursor: pointer; font-size: 0.6rem; padding: 2px 4px; border-radius: var(--radius-sm); line-height: 1; } .cal-mini-nav:hover { background: var(--color-hover); color: var(--color-text); } .cal-mini-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; } .cal-mini-dow { font-size: 0.55rem; color: var(--color-text-muted); text-align: center; padding: 2px 0; font-weight: 600; } .cal-mini-day { display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 0.65rem; padding: 2px 0; border: none; background: none; color: var(--color-text); cursor: pointer; border-radius: var(--radius-sm); line-height: 1.2; position: relative; } .cal-mini-day:hover { background: var(--color-hover); } .cal-mini-other { color: var(--color-text-muted); opacity: 0.5; } .cal-mini-today { font-weight: 700; color: var(--color-accent); } .cal-mini-selected { background: var(--color-accent); color: var(--color-on-accent, #fff); } .cal-mini-selected:hover { background: var(--color-accent); opacity: 0.9; } .cal-mini-dot { width: 3px; height: 3px; border-radius: 50%; background: var(--color-accent); position: absolute; bottom: 1px; } .cal-mini-selected .cal-mini-dot { background: var(--color-on-accent, #fff); } /* Keyboard shortcuts reference */ .cal-sidebar-shortcuts { margin-top: var(--space-md); padding-top: var(--space-sm); border-top: 1px solid var(--color-border); } .cal-shortcuts-title { font-size: 0.6rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: var(--space-xs); } .cal-shortcut { font-size: 0.65rem; color: var(--color-text-muted); padding: 1px 0; display: flex; align-items: center; gap: var(--space-xs); } .cal-shortcut kbd { font-family: var(--font-mono, monospace); font-size: 0.6rem; padding: 0 3px; border: 1px solid var(--color-border); border-radius: 2px; background: var(--color-surface); min-width: 1.2em; text-align: center; } .cal-sidebar-toggle svg { display: block; } /* Hide sidebar on mobile */ @media (max-width: 767px) { .cal-sidebar { display: none; } } /* Calendar grid container — fills remaining space below toolbar. overflow: hidden here so each view child handles its own scroll. */ .calendar-app .calendar-grid { flex: 1; display: flex; flex-direction: column; min-height: 0; overflow: hidden; } /* ── Toolbar ─────────────────────────────────────────────────────────── */ .cal-toolbar { display: flex; align-items: center; padding: var(--space-sm) var(--space-md); padding-left: max(var(--space-md), env(safe-area-inset-left)); padding-right: max(var(--space-md), env(safe-area-inset-right)); gap: var(--space-md); border-bottom: 1px solid var(--color-border); background: var(--color-surface); flex-shrink: 0; } .cal-nav-group { display: flex; align-items: center; gap: var(--space-sm); } .cal-nav-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.3rem 0.65rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: transparent; color: var(--color-text-muted); font-family: var(--font-body); font-size: 0.8rem; cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); line-height: 1.3; min-height: 28px; } .cal-nav-btn:hover { background: var(--color-hover); color: var(--color-text); border-color: var(--color-border-strong); } .cal-nav-btn:active { transform: scale(0.98); } .cal-nav-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; } /* Search input */ .cal-search-wrapper { position: relative; display: flex; align-items: center; } .cal-search-input { width: 160px; padding: 0.3rem 1.6rem 0.3rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: transparent; color: var(--color-text); font-family: var(--font-body); font-size: 0.8rem; line-height: 1.3; min-height: 28px; transition: border-color var(--transition-fast), width var(--transition-fast); } .cal-search-input::placeholder { color: var(--color-text-muted); opacity: 0.7; } .cal-search-input:focus { outline: none; border-color: var(--color-accent); width: 220px; } .cal-search-clear { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); border: none; background: none; color: var(--color-text-muted); font-size: 1rem; cursor: pointer; padding: 0 4px; line-height: 1; } .cal-search-clear:hover { color: var(--color-text); } .cal-date-label { font-family: var(--font-display); font-size: 1.2rem; color: var(--color-text); white-space: nowrap; user-select: none; margin-left: var(--space-xs); } .cal-view-group { display: flex; align-items: center; gap: 2px; margin-left: auto; border: 1px solid var(--color-border); border-radius: var(--radius-sm); overflow: hidden; } .cal-view-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.3rem 0.7rem; border: none; background: transparent; color: var(--color-text-muted); font-family: var(--font-body); font-size: 0.75rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast); line-height: 1.3; min-height: 28px; } .cal-view-btn:hover { background: var(--color-hover); color: var(--color-text); } .cal-view-btn.active { background: var(--color-accent); color: var(--color-btn-primary-text); } .cal-view-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; } /* ── Month View ──────────────────────────────────────────────────────── */ .cal-month-grid { display: grid; grid-template-columns: repeat(7, 1fr); /* First row (day-of-week header) is compact; remaining rows share space equally */ grid-template-rows: auto; grid-auto-rows: 1fr; flex: 1; overflow: hidden; touch-action: pan-y; /* allow vertical touch gestures; we capture swipe at touchend */ } /* Week number variant: 8 columns (wk + 7 days) */ .cal-month-grid-weeknums { grid-template-columns: 28px repeat(7, 1fr); } .cal-week-num-header { position: sticky; top: 0; z-index: var(--z-component); padding: var(--space-xs) 2px; font-family: var(--font-display); font-size: 0.6rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); background: var(--color-surface); border-bottom: 1px solid var(--color-border-strong); text-align: center; user-select: none; } .cal-week-num { display: flex; align-items: center; justify-content: center; font-size: 0.62rem; font-weight: 500; color: var(--color-text-muted); border-bottom: 1px solid var(--color-border); user-select: none; opacity: 0.7; } .cal-month-header { display: contents; } .cal-month-header-cell { position: sticky; top: 0; z-index: var(--z-component); padding: var(--space-xs) var(--space-sm); font-family: var(--font-display); font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); background: var(--color-surface); border-bottom: 1px solid var(--color-border-strong); text-align: center; user-select: none; } .cal-day-cell { border-right: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border); padding: var(--space-xs); cursor: pointer; transition: background var(--transition-fast); overflow: hidden; position: relative; } /* Grid overflow clips the last column's right border naturally */ .cal-day-cell:hover { background: var(--color-hover); } .cal-day-number { display: inline-flex; align-items: center; justify-content: center; font-size: 0.78rem; font-weight: 600; color: var(--color-text); width: 1.6em; height: 1.6em; line-height: 1; margin-bottom: var(--space-xs); border-radius: 50%; user-select: none; } .cal-day-today .cal-day-number { background: var(--color-teal); color: #f7f5f1; color: oklch(0.97 0.005 75); } .cal-day-other-month { opacity: 0.38; } .cal-day-other-month:hover { opacity: 0.55; } .cal-event-pill { display: block; padding: 1px 5px; margin-bottom: 2px; border-radius: var(--radius-sm); font-size: 0.68rem; line-height: 1.4; font-family: var(--font-body); color: #f7f5f1; color: oklch(0.97 0.005 75); background: var(--pill-color, var(--cal-ev-teal)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: filter var(--transition-fast); } .cal-event-pill:hover { filter: brightness(1.1); } [data-theme="dark"] .cal-event-pill { color: #f7f5f1; color: oklch(0.97 0.005 75); } /* Multi-day event rendering */ .cal-event-pill.event-multi-start { border-radius: var(--radius-sm) 0 0 var(--radius-sm); margin-right: 0; } .cal-event-pill.event-multi-middle { border-radius: 0; margin-left: 0; margin-right: 0; } .cal-event-pill.event-multi-end { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; margin-left: 0; } /* Drag-and-drop event rescheduling */ .cal-event-pill.cal-dragging { opacity: 0.4; } .cal-day-cell.cal-drag-over { background: oklch(0.85 0.08 220 / 0.3); outline: 2px dashed oklch(0.6 0.1 220); outline-offset: -2px; } [data-theme="dark"] .cal-day-cell.cal-drag-over { background: oklch(0.3 0.06 220 / 0.4); outline-color: oklch(0.55 0.1 220); } /* Drop overlay for .ics file import */ .cal-drop-overlay { position: absolute; inset: 0; background: oklch(0.95 0.02 220 / 0.92); display: flex; align-items: center; justify-content: center; z-index: 100; border: 3px dashed oklch(0.6 0.1 220); border-radius: var(--radius-lg); pointer-events: none; } [data-theme="dark"] .cal-drop-overlay { background: oklch(0.15 0.02 220 / 0.92); border-color: oklch(0.5 0.1 220); } .cal-drop-overlay-inner { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; font-size: 1.1rem; font-weight: 600; color: oklch(0.4 0.08 220); } [data-theme="dark"] .cal-drop-overlay-inner { color: oklch(0.8 0.06 220); } .cal-drop-icon { font-size: 2.5rem; } .cal-more-link { display: block; padding: 1px 5px; font-size: 0.65rem; color: var(--color-text-muted); cursor: pointer; transition: color var(--transition-fast); user-select: none; } .cal-more-link:hover { color: var(--color-text); } /* ── Week View ───────────────────────────────────────────────────────── */ .cal-week-grid { display: grid; grid-template-columns: var(--cal-gutter-width) repeat(7, 1fr); grid-template-rows: auto auto 1fr; flex: 1; min-height: 0; overflow: hidden; } .cal-week-header { display: contents; } .cal-week-header-cell { padding: var(--space-xs) var(--space-sm); font-family: var(--font-display); font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); text-align: center; border-bottom: 1px solid var(--color-border); background: var(--color-surface); user-select: none; } .cal-week-header-cell.is-today { color: var(--color-teal); } .cal-week-day-name { display: block; font-size: 0.65rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; } .cal-week-header-gutter { grid-row: 1; grid-column: 1; border-bottom: 1px solid var(--color-border); background: var(--color-surface); } .cal-week-header-date { display: block; font-size: 1.3rem; font-family: var(--font-display); font-weight: 400; letter-spacing: normal; text-transform: none; line-height: 1.2; } .cal-week-header-cell.is-today .cal-week-header-date { display: inline-flex; align-items: center; justify-content: center; width: 1.6em; height: 1.6em; border-radius: 50%; background: var(--color-teal); color: #f7f5f1; color: oklch(0.97 0.005 75); } /* All-day row */ .cal-allday-bar { display: contents; } .cal-allday-gutter { grid-column: 1; padding: var(--space-xs); font-size: 0.6rem; color: var(--color-text-faint); text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--color-border-strong); background: var(--color-surface); display: flex; align-items: center; justify-content: center; } .cal-allday-cell { border-right: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border-strong); padding: var(--space-xs); min-height: 2rem; background: var(--color-bg); } .cal-allday-cell:last-child { border-right: none; } /* Time body — scrollable region */ .cal-week-body { grid-column: 1 / -1; display: grid; grid-template-columns: var(--cal-gutter-width) repeat(7, 1fr); overflow-y: auto; overscroll-behavior: contain; /* prevent scroll chaining to body */ -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--color-border) transparent; } .cal-time-gutter { width: var(--cal-gutter-width); } .cal-hour-label { height: var(--cal-hour-height); display: flex; align-items: flex-start; justify-content: flex-end; padding: 0 var(--space-sm) 0 0; font-size: 0.65rem; font-family: var(--font-mono); color: var(--color-text-faint); position: relative; top: -0.45em; user-select: none; } .cal-day-column { position: relative; border-right: 1px solid var(--color-border); } .cal-day-column:last-child { border-right: none; } .cal-hour-row { height: var(--cal-hour-height); border-bottom: 1px solid var(--color-border); } .cal-hour-row-half { height: calc(var(--cal-hour-height) / 2); border-bottom: 1px dashed var(--color-border); border-bottom-color: #d7d4cf66; border-bottom-color: oklch(0.87 0.008 75 / 0.4); } [data-theme="dark"] .cal-hour-row-half { border-bottom-color: #2b282566; border-bottom-color: oklch(0.28 0.008 75 / 0.4); } /* Event blocks — absolute positioned in day columns */ .cal-event-block { position: absolute; left: 2px; right: 2px; border-radius: var(--radius-sm); padding: 3px 6px; font-size: 0.7rem; font-family: var(--font-body); line-height: 1.3; color: #f7f5f1; color: oklch(0.97 0.005 75); background: var(--pill-color, var(--cal-ev-teal)); overflow: hidden; cursor: pointer; z-index: 1; transition: box-shadow var(--transition-fast), filter var(--transition-fast); border-left: 3px solid rgba(0, 0, 0, 0.15); } .cal-event-block:hover { box-shadow: var(--shadow-md); filter: brightness(1.08); z-index: 2; } .cal-event-block-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .cal-event-block-time { font-size: 0.6rem; opacity: 0.85; white-space: nowrap; } /* Current time indicator */ .cal-now-line { position: absolute; left: 0; right: 0; height: 2px; background: var(--cal-now-color); z-index: 3; pointer-events: none; } .cal-now-line::before { content: ''; position: absolute; left: -4px; top: -3px; width: 8px; height: 8px; border-radius: 50%; background: var(--cal-now-color); } /* ── Day View ────────────────────────────────────────────────────────── */ .cal-day-grid { display: grid; grid-template-columns: var(--cal-gutter-width) 1fr; grid-template-rows: auto auto 1fr; flex: 1; min-height: 0; overflow: hidden; } .cal-day-header { grid-column: 1 / -1; padding: var(--space-xs) var(--space-md); font-family: var(--font-display); font-size: 0.8rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 1px solid var(--color-border); background: var(--color-surface); user-select: none; } .cal-day-header-date { font-size: 1.4rem; font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--color-text); margin-left: var(--space-sm); } .cal-day-header.is-today .cal-day-header-date { display: inline-flex; align-items: center; justify-content: center; width: 1.6em; height: 1.6em; border-radius: 50%; background: var(--color-teal); color: #f7f5f1; color: oklch(0.97 0.005 75); } /* Day view all-day bar */ .cal-day-allday-gutter { grid-column: 1; padding: var(--space-xs); font-size: 0.6rem; color: var(--color-text-faint); text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--color-border-strong); background: var(--color-surface); display: flex; align-items: center; justify-content: center; } .cal-day-allday-cell { grid-column: 2; border-bottom: 1px solid var(--color-border-strong); padding: var(--space-xs); min-height: 2rem; background: var(--color-bg); } /* Day view scrollable body */ .cal-day-body { grid-column: 1 / -1; display: grid; grid-template-columns: var(--cal-gutter-width) 1fr; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--color-border) transparent; } /* Reuses .cal-time-gutter, .cal-hour-label, .cal-hour-row, .cal-hour-row-half, .cal-day-column, .cal-event-block, .cal-now-line from week view */ /* ── Agenda View ─────────────────────────────────────────────────────── */ .cal-agenda { flex: 1; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: var(--space-md) var(--space-lg); scrollbar-width: thin; scrollbar-color: var(--color-border) transparent; } .cal-date-group { margin-bottom: var(--space-md); } .cal-date-header { font-family: var(--font-display); font-size: 0.85rem; font-weight: 600; color: var(--color-text); padding-bottom: var(--space-xs); margin-bottom: var(--space-xs); margin-top: var(--space-md); border-bottom: 1px solid var(--color-border); user-select: none; } .cal-date-group:first-child .cal-date-header { margin-top: 0; } .cal-date-header-today { color: var(--color-teal); } .cal-agenda-item { display: flex; align-items: flex-start; gap: var(--space-sm); padding: var(--space-sm) var(--space-sm); border-radius: var(--radius-sm); cursor: pointer; transition: background var(--transition-fast); } .cal-agenda-item:hover { background: var(--color-hover); } .cal-agenda-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; margin-top: 0.35em; /* background set inline via style attr */ } .cal-agenda-time { flex-shrink: 0; width: 6.5em; font-size: 0.78rem; font-family: var(--font-mono); color: var(--color-text-muted); white-space: nowrap; } .cal-agenda-content { flex: 1; min-width: 0; } .cal-agenda-title { font-size: 0.88rem; font-weight: 500; color: var(--color-text); line-height: 1.3; } .cal-agenda-desc { font-size: 0.78rem; color: var(--color-text-muted); line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; } .cal-agenda-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-2xl) var(--space-md); color: var(--color-text-faint); font-size: 0.9rem; text-align: center; user-select: none; } .cal-agenda-empty-icon { font-size: 2rem; margin-bottom: var(--space-sm); opacity: 0.5; } /* ── Event Modal ─────────────────────────────────────────────────────── */ .event-modal { max-width: 480px; width: 90%; max-height: calc(100dvh - 2rem); overflow-y: auto; padding: var(--space-lg); background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); position: relative; -webkit-overflow-scrolling: touch; } .event-modal-title { font-family: var(--font-display); font-size: 1.2rem; margin: 0 0 var(--space-md); color: var(--color-text); padding-right: 2.5rem; } .event-modal-close { position: absolute; top: var(--space-sm); right: var(--space-sm); width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; background: transparent; color: var(--color-text-muted); border: none; border-radius: var(--radius-sm); font-size: 1.4rem; line-height: 1; cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast); } .event-modal-close:hover { background: var(--color-hover); color: var(--color-text); } .event-modal-field { display: flex; flex-direction: column; gap: var(--space-xs); margin-bottom: var(--space-md); } .event-modal-field label { font-size: 0.72rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; user-select: none; } .event-modal-field input[type="text"], .event-modal-field input[type="date"], .event-modal-field input[type="time"], .event-modal-field input[type="datetime-local"], .event-modal-field textarea, .event-modal-field select { width: 100%; padding: 0.5rem 0.7rem; font-family: var(--font-body); font-size: 0.85rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); outline: none; transition: border-color var(--transition-fast), box-shadow var(--transition-fast); } .event-modal-field input:focus, .event-modal-field textarea:focus, .event-modal-field select:focus { border-color: var(--color-teal); box-shadow: 0 0 0 2px var(--color-focus); } .event-modal-field textarea { resize: vertical; min-height: 3.5rem; line-height: 1.5; } .event-modal-checkbox { flex-direction: row; align-items: center; } .event-modal-checkbox input[type="checkbox"] { width: auto; margin: 0; } .event-modal-checkbox label { margin: 0; } .event-modal-row { display: flex; gap: var(--space-sm); } .event-modal-row > .event-modal-field { flex: 1; min-width: 0; } /* Color swatches */ .event-color-picker { display: flex; gap: var(--space-sm); flex-wrap: wrap; } .event-color-swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; transition: border-color var(--transition-fast), transform var(--transition-fast); padding: 0; } .event-color-swatch:hover { transform: scale(1.15); } .event-color-swatch.active { border-color: var(--color-text); box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-text-muted); } .event-color-swatch:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; } /* Modal actions */ .event-modal-actions { display: flex; gap: var(--space-sm); justify-content: flex-end; margin-top: var(--space-lg); padding-top: var(--space-md); border-top: 1px solid var(--color-border); } /* ── Dark Mode — calendar-specific adjustments ───────────────────────── */ [data-theme="dark"] .cal-event-block { border-left-color: rgba(255, 255, 255, 0.1); } [data-theme="dark"] .cal-event-pill, [data-theme="dark"] .cal-event-block { /* Slightly lower saturation in dark mode for comfort */ filter: saturate(0.9); } [data-theme="dark"] .cal-event-pill:hover { filter: saturate(0.9) brightness(1.12); } [data-theme="dark"] .cal-event-block:hover { filter: saturate(0.9) brightness(1.1); } /* ── Settings Popover ────────────────────────────────────────────────── */ .cal-settings-popover { position: fixed; z-index: 200; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius, 6px); padding: var(--space-sm) var(--space-md); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); min-width: 200px; } .cal-settings-title { font-size: 0.7rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: var(--space-sm); } .cal-settings-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); padding: var(--space-xs) 0; font-size: 0.8rem; color: var(--color-text); cursor: default; } .cal-settings-select { font-size: 0.75rem; padding: 2px 6px; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-bg); color: var(--color-text); cursor: pointer; } .cal-settings-select:focus { outline: 2px solid var(--color-focus); outline-offset: 1px; } /* ── Event Hover Preview ─────────────────────────────────────────────── */ .cal-event-preview { position: fixed; z-index: 210; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius, 6px); padding: var(--space-sm) var(--space-md); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); max-width: 250px; pointer-events: auto; } .cal-preview-title { font-weight: 600; font-size: 0.8rem; color: var(--color-text); margin-bottom: 2px; } .cal-preview-time { font-size: 0.72rem; color: var(--color-text-muted); margin-bottom: 4px; } .cal-preview-desc { font-size: 0.7rem; color: var(--color-text-faint); line-height: 1.4; white-space: pre-line; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; } /* ── Reminder rows (event modal) ─────────────────────────────────────── */ .event-reminder-rows { display: flex; flex-direction: column; gap: var(--space-xs); } .event-reminder-row { display: flex; align-items: center; gap: var(--space-xs); } .event-reminder-row .reminder-select { flex: 1; } .btn-remove-reminder { background: none; border: none; color: var(--color-text-secondary); font-size: 1.2rem; cursor: pointer; padding: 0 4px; line-height: 1; } .btn-remove-reminder:hover { color: var(--color-danger, #d94a4a); } .btn-add-reminder { background: none; border: 1px dashed var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); color: var(--color-text-secondary); cursor: pointer; font-size: 0.85rem; margin-top: var(--space-xs); } .btn-add-reminder:hover { border-color: var(--color-teal); color: var(--color-teal); } /* ── Subscription list (settings popover) ────────────────────────────── */ .cal-settings-divider { border: none; border-top: 1px solid var(--color-border); margin: var(--space-sm) 0; } .cal-sub-list { display: flex; flex-direction: column; gap: var(--space-xs); margin-bottom: var(--space-sm); } .cal-sub-empty { color: var(--color-text-secondary); font-size: 0.85rem; padding: var(--space-xs) 0; } .cal-sub-item { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) 0; } .cal-sub-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } .cal-sub-name { flex: 1; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .cal-sub-toggle { display: flex; align-items: center; gap: 4px; font-size: 0.8rem; color: var(--color-text-secondary); cursor: pointer; } .cal-sub-toggle-label { font-size: 0.75rem; } .cal-sub-sync, .cal-sub-delete { background: none; border: none; cursor: pointer; color: var(--color-text-secondary); font-size: 1rem; padding: 0 2px; } .cal-sub-sync:hover { color: var(--color-teal); } .cal-sub-delete:hover { color: var(--color-danger, #d94a4a); } .btn-add-subscription { background: none; border: 1px dashed var(--color-border); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); color: var(--color-text-secondary); cursor: pointer; font-size: 0.85rem; width: 100%; } .btn-add-subscription:hover { border-color: var(--color-teal); color: var(--color-teal); } /* ── Subscription modal ──────────────────────────────────────────────── */ .sub-modal { background: var(--color-surface); border-radius: var(--radius-lg); padding: var(--space-lg); width: min(440px, 90vw); max-height: 80vh; overflow-y: auto; box-shadow: var(--shadow-lg); } .sub-modal h2 { margin: 0 0 var(--space-md); font-size: 1.1rem; } /* ── External event overlay ──────────────────────────────────────────── */ .cal-event-external { opacity: 0.75; border-style: dashed !important; } /* ── Notification banner ─────────────────────────────────────────────── */ .cal-notif-banner { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-xs) var(--space-md); background: var(--color-surface-raised, var(--color-surface)); border: 1px solid var(--color-border); border-radius: var(--radius-sm); margin: var(--space-xs) var(--space-md); font-size: 0.85rem; } .cal-notif-banner .btn-sm { padding: 2px 10px; font-size: 0.8rem; } .cal-notif-row { display: flex; align-items: center; justify-content: space-between; padding: var(--space-xs) 0; font-size: 0.85rem; } .cal-notif-toggle-btn { padding: 2px 10px; font-size: 0.8rem; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-surface-raised, var(--color-surface)); color: var(--color-text); cursor: pointer; } .cal-notif-toggle-btn:hover:not(:disabled) { background: var(--color-teal); color: #fff; border-color: var(--color-teal); } .cal-notif-toggle-btn:disabled { opacity: 0.5; cursor: not-allowed; } /* ── Keyboard-focused event pill ─────────────────────────────────────── */ .cal-event-pill:focus-visible, .cal-event-block:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 1px; z-index: 5; } /* ── Print ───────────────────────────────────────────────────────────── */ @media print { .cal-toolbar, .cal-now-line { display: none !important; } .cal-day-cell { min-height: 80px !important; break-inside: avoid; } .cal-event-pill, .cal-event-block { -webkit-print-color-adjust: exact; print-color-adjust: exact; } } /* ── Responsive: Tablet (768px) ──────────────────────────────────────── */ @media (max-width: 768px) { .cal-toolbar { flex-wrap: wrap; padding: var(--space-xs) var(--space-sm); gap: var(--space-sm); } .cal-nav-group { order: 1; flex: 1 1 100%; } .cal-view-group { order: 2; margin-left: 0; flex: 1 1 100%; justify-content: center; } .cal-date-label { font-size: 1.05rem; } /* Month grid — smaller cells */ .cal-month-grid { grid-auto-rows: 1fr; } .cal-day-cell { padding: 2px; } .cal-day-number { font-size: 0.72rem; } .cal-event-pill { font-size: 0.62rem; padding: 0 3px; } /* Week/day — narrower gutter */ .cal-week-grid, .cal-week-body { grid-template-columns: 48px repeat(7, 1fr); } .cal-day-grid, .cal-day-body { grid-template-columns: 48px 1fr; } .cal-hour-label { font-size: 0.6rem; padding-right: var(--space-xs); } /* Event modal full-width */ .event-modal { max-width: 100%; width: 100%; border-radius: var(--radius-md); margin-bottom: var(--space-md); } .event-modal-row { flex-direction: column; gap: 0; } /* Hide week numbers on tablet */ .cal-week-num, .cal-week-num-header { display: none; } .cal-month-grid-weeknums { grid-template-columns: repeat(7, 1fr); } /* Shrink search input */ .cal-search-input { width: 120px; } .cal-search-input:focus { width: 160px; } /* Agenda — less padding */ .cal-agenda { padding: var(--space-sm) var(--space-md); } } /* ── Responsive: Mobile (480px) ──────────────────────────────────────── */ @media (max-width: 480px) { .cal-toolbar { padding: var(--space-xs); gap: var(--space-xs); } .cal-nav-btn { padding: 0.25rem 0.5rem; font-size: 0.72rem; min-height: 32px; min-width: 32px; } .cal-view-btn { padding: 0.25rem 0.5rem; font-size: 0.68rem; min-height: 32px; } .cal-date-label { font-size: 0.95rem; } /* Month grid — compact: no pills, just dots */ .cal-month-grid { grid-auto-rows: 1fr; } .cal-day-cell { padding: 1px; } .cal-month-header-cell { font-size: 0.6rem; padding: var(--space-xs) 2px; } /* Abbreviated day names handled by JS (S M T W T F S), but ensure cells don't overflow */ .cal-month-header-cell { overflow: hidden; text-overflow: ellipsis; } .cal-day-number { font-size: 0.68rem; width: 1.4em; height: 1.4em; } /* Hide event pills on very small screens — show dot indicator */ .cal-event-pill { width: 5px; height: 5px; border-radius: 50%; padding: 0; font-size: 0; line-height: 0; display: inline-block; margin: 0 1px 1px 0; vertical-align: top; } .cal-more-link { font-size: 0; width: 5px; height: 5px; border-radius: 50%; background: var(--color-text-faint); display: inline-block; padding: 0; margin: 0 1px 1px 0; } /* Week view — horizontal scroll */ .cal-week-grid { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 600px; } /* Day view — full width, narrow gutter */ .cal-day-grid, .cal-day-body { grid-template-columns: 40px 1fr; } .cal-hour-label { font-size: 0.55rem; } /* Agenda — full width, most comfortable mobile view */ .cal-agenda { padding: var(--space-xs) var(--space-sm); } .cal-agenda-time { width: 5em; font-size: 0.72rem; } .cal-agenda-title { font-size: 0.82rem; } .cal-agenda-desc { display: none; } /* Modal — full width, fills viewport, scrollable body */ .event-modal { padding: var(--space-md); padding-top: calc(var(--space-md) + env(safe-area-inset-top, 0)); padding-bottom: calc(var(--space-md) + env(safe-area-inset-bottom, 0)); border-radius: 0; max-height: 100dvh; min-height: 100dvh; width: 100%; max-width: 100%; margin: 0; } .event-modal h3 { font-size: 1.05rem; } .event-modal-field input, .event-modal-field textarea, .event-modal-field select { font-size: 16px; /* prevents iOS zoom on focus */ } .event-modal-actions { flex-wrap: wrap; } .event-modal-close { top: calc(env(safe-area-inset-top, 0) + var(--space-xs)); right: var(--space-xs); width: 44px; height: 44px; font-size: 1.6rem; } } /* ── Smooth theme transitions ────────────────────────────────────────── */ .cal-toolbar, .cal-month-header-cell, .cal-day-cell, .cal-week-header-cell, .cal-allday-cell, .cal-day-header, .event-modal { transition: background-color var(--transition-med), border-color var(--transition-med), color var(--transition-med); } /* ── Element Animation Keyframes (slides presenter) ──────────────── */ @keyframes atmos-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes atmos-fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes atmos-slide-in-left { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes atmos-slide-in-right { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes atmos-slide-in-up { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes atmos-slide-in-down { from { transform: translateY(-100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes atmos-slide-out-left { from { transform: translateX(0); opacity: 1; } to { transform: translateX(-100%); opacity: 0; } } @keyframes atmos-slide-out-right { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } } @keyframes atmos-slide-out-up { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-100%); opacity: 0; } } @keyframes atmos-slide-out-down { from { transform: translateY(0); opacity: 1; } to { transform: translateY(100%); opacity: 0; } } @keyframes atmos-zoom-in { from { transform: scale(0.5); opacity: 0; } to { transform: scale(1); opacity: 1; } } @keyframes atmos-zoom-out { from { transform: scale(1); opacity: 1; } to { transform: scale(0.5); opacity: 0; } } @keyframes atmos-bounce-in { 0% { transform: scale(0.3); opacity: 0; } 50% { transform: scale(1.05); } 70% { transform: scale(0.95); } 100% { transform: scale(1); opacity: 1; } } @keyframes atmos-spin-in { from { transform: rotate(-180deg) scale(0); opacity: 0; } to { transform: rotate(0) scale(1); opacity: 1; } } /* ── Data Bars (conditional formatting) ───────────────────────────── */ .cf-data-bar { position: absolute; bottom: 0; height: 100%; opacity: 0.3; pointer-events: none; transition: width 0.2s ease; } .cf-data-bar.cf-data-bar--negative { right: 50%; } .cf-data-bar.cf-data-bar--positive { left: 50%; } .cf-data-bar.cf-data-bar--all-positive { left: 0; } /* ── Icon Sets (conditional formatting) ───────────────────────────── */ .cf-icon-set { display: inline-block; width: 14px; height: 14px; margin-right: 4px; vertical-align: middle; } /* ── Layers Panel (diagrams) ──────────────────────────────────────── */ .layers-panel { position: absolute; right: 0; top: var(--topbar-h, 48px); bottom: 0; width: 220px; background: var(--color-surface); border-left: 1px solid var(--color-border); overflow-y: auto; z-index: 20; display: flex; flex-direction: column; padding: var(--space-xs); gap: var(--space-xs); } .layers-panel h3 { margin: 0; font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); } .layer-item { display: flex; align-items: center; gap: var(--space-xs); padding: 4px 6px; border-radius: var(--radius-sm, 4px); font-size: 0.82rem; cursor: pointer; user-select: none; } .layer-item:hover { background: var(--color-surface-alt); } .layer-item.layer-item--active { background: var(--color-teal-light); } .layer-item .layer-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .layer-item .layer-toggle { opacity: 0.5; cursor: pointer; font-size: 0.9rem; } .layer-item .layer-toggle:hover { opacity: 1; } .layer-item .layer-toggle--hidden { opacity: 0.25; } .layer-item .layer-toggle--locked { color: var(--color-accent); } .layers-panel .layers-add-btn { font-size: 0.78rem; padding: 4px 8px; border: 1px dashed var(--color-border); border-radius: var(--radius-sm, 4px); background: transparent; color: var(--color-text-muted); cursor: pointer; text-align: center; } .layers-panel .layers-add-btn:hover { border-color: var(--color-text-muted); color: var(--color-text); } /* ── Type Filter Bar (landing) ────────────────────────────────────── */ .type-filter-bar { display: flex; gap: var(--space-xs); padding: var(--space-xs) 0; overflow-x: auto; -webkit-overflow-scrolling: touch; } .type-filter-btn { display: inline-flex; align-items: center; gap: 4px; padding: 4px 12px; border: 1px solid var(--color-border); border-radius: 999px; background: transparent; color: var(--color-text-muted); font-size: 0.78rem; cursor: pointer; white-space: nowrap; transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); } .type-filter-btn:hover { border-color: var(--color-text-muted); color: var(--color-text); } .type-filter-btn.type-filter-btn--active { background: var(--color-accent); border-color: var(--color-accent); color: #fff; } .type-filter-btn .type-filter-count { font-size: 0.7rem; opacity: 0.7; } /* ── Shortcut Customization Panel ─────────────────────────────────── */ .shortcuts-settings-panel { max-width: 600px; margin: 0 auto; } .shortcut-row { display: flex; align-items: center; gap: var(--space-sm); padding: 6px 0; border-bottom: 1px solid var(--color-border); } .shortcut-row:last-child { border-bottom: none; } .shortcut-label { flex: 1; font-size: 0.85rem; } .shortcut-label .shortcut-desc { display: block; font-size: 0.75rem; color: var(--color-text-muted); } .shortcut-combo { display: inline-flex; align-items: center; gap: 2px; padding: 2px 8px; border: 1px solid var(--color-border); border-radius: var(--radius-sm, 4px); background: var(--color-surface); font-family: var(--font-mono, monospace); font-size: 0.78rem; min-width: 80px; text-align: center; cursor: pointer; } .shortcut-combo:hover { border-color: var(--color-accent); } .shortcut-combo.shortcut-combo--recording { border-color: var(--color-accent); background: var(--color-accent); color: #fff; } .shortcut-combo--conflict { border-color: #c33; color: #c33; } .shortcut-reset-btn { font-size: 0.72rem; padding: 2px 6px; border: none; background: transparent; color: var(--color-text-muted); cursor: pointer; } .shortcut-reset-btn:hover { color: var(--color-accent); } /* ── Slides Panel Tabs ────────────────────────────────────────── */ .slides-panel-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--color-border); margin-bottom: var(--space-xs); } .slides-panel-tab { flex: 1; padding: 6px 0; border: none; background: transparent; font-size: 0.78rem; font-weight: 500; color: var(--color-text-muted); cursor: pointer; border-bottom: 2px solid transparent; transition: color var(--transition-fast), border-color var(--transition-fast); } .slides-panel-tab:hover { color: var(--color-text); } .slides-panel-tab--active { color: var(--color-accent); border-bottom-color: var(--color-accent); } .slides-anim-list { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; max-height: 200px; } .anim-row { display: flex; align-items: center; gap: 4px; padding: 4px 6px; border-radius: var(--radius-sm, 4px); background: var(--color-surface); font-size: 0.8rem; } .anim-row:hover { background: var(--color-surface-alt); } .anim-effect { font-weight: 500; } .anim-remove { margin-left: auto; opacity: 0.5; } .anim-remove:hover { opacity: 1; color: var(--color-accent); } .slides-anim-controls { display: flex; gap: 4px; margin-top: var(--space-xs); flex-wrap: wrap; } .slides-anim-controls select { font-size: 0.78rem; flex: 1; min-width: 80px; } .slides-anim-hint { font-size: 0.78rem; color: var(--color-text-muted); margin: var(--space-xs) 0; } /* ── Slide Thumbnail Drag-to-Reorder ──────────────────────────── */ .slides-thumbnail.dragging { opacity: 0.4; } .slides-thumbnail.drag-over-top { border-top: 3px solid var(--color-accent); } .slides-thumbnail.drag-over-bottom { border-bottom: 3px solid var(--color-accent); } .slides-thumbnail { cursor: grab; transition: opacity 0.15s; } .slides-thumbnail:active { cursor: grabbing; } /* ── Presence / Who's Online Sidebar ─────────────────────────── */ .presence-sidebar { position: fixed; right: 0; top: var(--topbar-h, 48px); width: 240px; max-height: calc(100vh - var(--topbar-h, 48px)); background: var(--color-surface); border-left: 1px solid var(--color-border); overflow-y: auto; z-index: 30; padding: var(--space-sm); display: flex; flex-direction: column; gap: var(--space-xs); box-shadow: -2px 0 8px rgba(0,0,0,0.05); } .presence-sidebar h3 { margin: 0; font-size: 0.85rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; } .presence-user { display: flex; align-items: center; gap: var(--space-xs); padding: 6px 8px; border-radius: var(--radius-sm, 4px); } .presence-user:hover { background: var(--color-surface-alt); } .presence-avatar { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 600; font-size: 0.75rem; flex-shrink: 0; } .presence-info { flex: 1; min-width: 0; } .presence-name { font-size: 0.82rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .presence-status { font-size: 0.7rem; color: var(--color-text-muted); } .presence-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } .presence-dot--active { background: #4caf50; } .presence-dot--stale { background: #ff9800; } /* ── Content Search Results (landing) ─────────────────────────── */ .content-search-header { font-size: 0.8rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; padding: var(--space-xs) 0; border-top: 1px solid var(--color-border); margin-top: var(--space-sm); display: flex; align-items: center; gap: var(--space-xs); } .content-search-count { font-size: 0.7rem; background: var(--color-surface-alt); padding: 1px 6px; border-radius: 999px; } .content-search-list { display: flex; flex-direction: column; gap: 2px; } .content-search-item { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--radius-sm, 4px); text-decoration: none; color: var(--color-text); transition: background var(--transition-fast); } .content-search-item:hover { background: var(--color-surface-alt); } .content-search-name { font-size: 0.85rem; font-weight: 500; } .content-search-snippet { font-size: 0.78rem; color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .content-search-snippet mark { background: var(--color-teal-light); color: var(--color-text); border-radius: 2px; padding: 0 2px; } .content-search-meta { font-size: 0.7rem; color: var(--color-text-faint); } .content-search-header--forge { color: oklch(0.45 0.1 250); font-weight: 600; } .content-search-item--forge { border-left: 3px solid oklch(0.65 0.1 250); padding-left: 8px; } .content-search-badge { margin-left: 8px; padding: 1px 6px; border-radius: 3px; font-size: 0.65rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; vertical-align: 1px; } .content-search-badge--forge { background: oklch(0.92 0.04 250); color: oklch(0.45 0.1 250); } /* ── Batch Action Bar (landing multi-select) ──────────────────── */ .batch-action-bar { position: fixed; bottom: var(--space-md, 16px); left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: var(--space-xs); padding: 8px 16px; background: var(--color-text); color: var(--color-bg); border-radius: 999px; box-shadow: 0 4px 16px rgba(0,0,0,0.2); z-index: 100; font-size: 0.82rem; animation: atmos-fade-in 0.15s ease; } .batch-count { font-weight: 600; margin-right: var(--space-xs); } .batch-btn { border: none; background: rgba(255,255,255,0.15); color: inherit; padding: 4px 10px; border-radius: 999px; font-size: 0.78rem; cursor: pointer; white-space: nowrap; transition: background 0.15s; } .batch-btn:hover { background: rgba(255,255,255,0.25); } .batch-btn--danger:hover { background: rgba(220,50,50,0.6); } /* ── Footnote Footer ──────────────────────────────────────────── */ .footnote-footer { margin-top: 2rem; padding-top: 0; } .footnote-divider { border: none; border-top: 1px solid var(--color-border); margin: 0 0 0.75rem 0; width: 40%; } .footnote-list { margin: 0; padding-left: 1.5em; font-size: 0.82rem; color: var(--color-text-muted); line-height: 1.6; } .footnote-entry { margin-bottom: 4px; } .footnote-backref { color: var(--color-accent); text-decoration: none; font-weight: 600; cursor: pointer; } .footnote-backref:hover { text-decoration: underline; } .footnote-content { color: var(--color-text); } .footnote-marker { cursor: help; color: var(--color-accent); font-weight: 600; } .footnote-highlight { background: var(--color-teal-light); border-radius: 2px; transition: background 0.3s; } /* ── Suggestions Panel ────────────────────────────────────────── */ .suggestions-panel { padding: var(--space-sm); } .suggestions-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-xs); } .suggestions-count { font-size: 0.82rem; font-weight: 600; color: var(--color-text-muted); } .suggestions-bulk { display: flex; gap: 4px; } .suggestions-empty { font-size: 0.82rem; color: var(--color-text-muted); text-align: center; padding: var(--space-md) 0; } .suggestions-list { display: flex; flex-direction: column; gap: 6px; } .suggestion-item { padding: 8px 10px; border-radius: var(--radius-sm, 4px); border-left: 3px solid var(--color-border); background: var(--color-surface); } .suggestion-item--insert { border-left-color: #2ecc71; } .suggestion-item--delete { border-left-color: #e74c3c; } .suggestion-meta { font-size: 0.75rem; color: var(--color-text-muted); margin-bottom: 2px; } .suggestion-type { font-weight: 600; } .suggestion-item--insert .suggestion-type { color: #2ecc71; } .suggestion-item--delete .suggestion-type { color: #e74c3c; } .suggestion-preview { font-size: 0.82rem; margin-bottom: 4px; color: var(--color-text); } .suggestion-actions { display: flex; gap: 4px; } .suggestion-accept { background: #2ecc71; color: #fff; border: none; border-radius: 3px; padding: 2px 8px; font-size: 0.72rem; cursor: pointer; } .suggestion-accept:hover { background: #27ae60; } .suggestion-reject { background: #e74c3c; color: #fff; border: none; border-radius: 3px; padding: 2px 8px; font-size: 0.72rem; cursor: pointer; } .suggestion-reject:hover { background: #c0392b; } .suggestions-accept-all { background: #2ecc71; color: #fff; border: none; border-radius: 3px; padding: 3px 8px; font-size: 0.72rem; cursor: pointer; } .suggestions-reject-all { background: #e74c3c; color: #fff; border: none; border-radius: 3px; padding: 3px 8px; font-size: 0.72rem; cursor: pointer; } /* ── Form Response Analytics ──────────────────────────────────── */ .analytics-summary { display: flex; gap: var(--space-md); flex-wrap: wrap; padding: var(--space-sm) 0; } .analytics-stat { text-align: center; padding: var(--space-sm) var(--space-md); background: var(--color-surface); border-radius: var(--radius-sm, 4px); } .analytics-stat-value { font-size: 1.5rem; font-weight: 700; color: var(--color-text); display: block; } .analytics-stat-label { font-size: 0.75rem; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; } .analytics-chart { margin: var(--space-sm) 0; padding: var(--space-sm); background: var(--color-surface); border-radius: var(--radius-sm, 4px); } .analytics-chart h4 { margin: 0 0 var(--space-xs); font-size: 0.85rem; } /* ── Math Block (KaTeX) ───────────────────────────────────────── */ .math-block-wrapper { position: relative; margin: 1em 0; padding: 12px 16px; border: 1px solid var(--color-border); border-radius: var(--radius-sm, 4px); background: var(--color-surface); cursor: pointer; } .math-block-wrapper:hover { border-color: var(--color-text-muted); } .math-block-output { min-height: 1.5em; overflow-x: auto; } .math-block-output .katex-display { margin: 0.5em 0; } .math-placeholder { color: var(--color-text-faint); font-style: italic; font-size: 0.85rem; } .math-error { color: #c33; font-size: 0.8rem; font-family: var(--font-mono, monospace); } .math-block-toolbar { position: absolute; top: 4px; right: 4px; display: flex; gap: 4px; } .math-block-btn { padding: 2px 8px; border: 1px solid var(--color-border); border-radius: 3px; background: var(--color-bg); color: var(--color-text-muted); font-size: 0.72rem; cursor: pointer; } .math-block-btn:hover { background: var(--color-surface-alt); color: var(--color-text); } .math-block-editor { width: 100%; min-height: 60px; margin-top: 8px; padding: 8px; border: 1px solid var(--color-border); border-radius: 3px; background: var(--color-bg); color: var(--color-text); font-family: var(--font-mono, monospace); font-size: 0.85rem; resize: vertical; } /* TOC Block */ .toc-block-wrapper { position: relative; margin: 1em 0; padding: 16px 20px; border: 1px solid var(--color-border); border-radius: var(--radius-sm, 4px); background: var(--color-surface); } .toc-block-wrapper:hover { border-color: var(--color-text-muted); } .toc-block-header { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); margin-bottom: 8px; } .toc-block-content .toc-list { margin: 0; padding: 0; list-style: none; } .toc-block-content .toc-list ul { margin: 0; padding-left: 1.25em; list-style: none; } .toc-block-content .toc-item { margin: 2px 0; } .toc-block-content .toc-item a { color: var(--color-primary); text-decoration: none; font-size: 0.9rem; line-height: 1.6; border-bottom: 1px solid transparent; transition: border-color 0.15s; } .toc-block-content .toc-item a:hover { border-bottom-color: var(--color-primary); } .toc-block-content .toc-level-1 a { font-weight: 600; } .toc-block-content .toc-level-2 a { font-weight: 500; } .toc-block-empty { color: var(--color-text-faint); font-style: italic; font-size: 0.85rem; }