cc-haha/desktop/src/theme/globals.css
程序员阿江(Relakkes) 7d1e2a2ee4 Reduce sidebar control clutter in session navigation
The project filter and session search were competing for the same narrow vertical lane in the desktop sidebar. This change merges them into a single search surface, keeps project scoping available through an embedded trigger, and trims the surrounding control chrome so the sidebar reads like one cohesive tool instead of stacked widgets.

Constraint: Sidebar filtering behavior and existing project dropdown logic had to remain intact
Constraint: This commit must exclude unrelated in-progress desktop and server changes in the worktree
Rejected: Keep separate project and search controls with smaller spacing | still wastes vertical space and keeps the visual split
Rejected: Move project filtering into a second modal flow | adds friction to a frequent navigation task
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep project scoping embedded in the search lane unless session discovery changes materially
Tested: bun run test src/components/layout/ProjectFilter.test.tsx src/components/layout/Sidebar.test.tsx src/__tests__/pages.test.tsx; bun run lint; bun run build
Not-tested: Manual dark-theme screenshot pass after the final integrated layout change
2026-04-22 17:00:53 +08:00

645 lines
19 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@import "tailwindcss";
@plugin "@tailwindcss/typography";
/* ─── Self-hosted fonts (no Google CDN dependency) ────────────── */
/* Inter variable weight 400-600, latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400 600;
font-display: swap;
src: url('/fonts/inter-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400 600;
font-display: swap;
src: url('/fonts/inter-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Manrope variable weight 400-800, latin */
@font-face {
font-family: 'Manrope';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url('/fonts/manrope-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Manrope';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url('/fonts/manrope-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* JetBrains Mono weight 400, latin */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/jetbrains-mono-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/jetbrains-mono-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Material Symbols Outlined variable weight, use block to avoid showing raw text */
@font-face {
font-family: 'Material Symbols Outlined';
font-style: normal;
font-weight: 100 700;
font-display: block;
src: url('/fonts/material-symbols-outlined.woff2') format('woff2');
}
/* Code highlighting is handled by shiki/react-shiki (inline styles + CSS line numbers) */
/* ─── Shiki code viewer ───────────────────────────────────────── */
.code-viewer-area .line {
display: block;
padding: 0 12px;
}
.code-viewer-area .has-line-numbers .line {
padding-left: 12px;
}
.code-viewer-area .line:hover {
background: rgba(0, 0, 0, 0.03);
}
.code-viewer-area .line-numbers::before {
margin-right: 1.5ch;
}
.code-viewer-area .has-line-numbers {
--line-numbers-foreground: rgba(135, 115, 109, 0.5);
--line-numbers-width: 2.5ch;
--line-numbers-padding-left: 0;
--line-numbers-padding-right: 0;
--line-numbers-font-size: 11px;
}
/* ─── Tailwind Theme Override (matches prototype design system) ─── */
@theme {
--color-primary: #8F482F;
--color-primary-container: #AD5F45;
--color-primary-fixed: #FFDBD0;
--color-primary-fixed-dim: #FFB59D;
--color-on-primary: #FFFFFF;
--color-on-surface: #1B1C1A;
--color-on-surface-variant: #54433E;
--color-surface: #FAF9F5;
--color-surface-bright: #FAF9F5;
--color-surface-dim: #DBDAD6;
--color-surface-container: #EFEEEA;
--color-surface-container-low: #F4F4F0;
--color-surface-container-high: #E9E8E4;
--color-surface-container-highest: #E3E2DF;
--color-surface-container-lowest: #FFFFFF;
--color-surface-variant: #E3E2DF;
--color-background: #FAF9F5;
--color-outline: #87736D;
--color-outline-variant: #DAC1BA;
--color-secondary: #2D628F;
--color-secondary-container: #9ACBFE;
--color-tertiary: #4F6237;
--color-tertiary-container: #677B4E;
--color-error: #BA1A1A;
--color-error-container: #FFDAD6;
--color-on-error-container: #410002;
--color-inverse-surface: #2F312E;
--color-inverse-on-surface: #F2F1ED;
--color-inverse-primary: #FFB59D;
--color-success: #16A34A;
--color-warning: #CA8A04;
--font-headline: 'Manrope', sans-serif;
--font-body: 'Inter', sans-serif;
--font-label: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}
/* ─── Semantic Aliases (used by layout & infrastructure components) ── */
:root,
[data-theme="light"] {
color-scheme: light;
/* Layout dimensions */
--sidebar-width: 280px;
--sidebar-rail-width: 72px;
--titlebar-height: 40px;
--statusbar-height: 36px;
--motion-sidebar-duration: 280ms;
--motion-sidebar-easing: cubic-bezier(0.22, 1, 0.36, 1);
/* Surface aliases */
--color-surface-sidebar: var(--color-surface-container-low);
--color-surface-hover: var(--color-surface-container-high);
--color-surface-selected: var(--color-surface-container);
--color-sidebar-filter-bg: transparent;
--color-sidebar-filter-border: rgba(218, 193, 186, 0.92);
--color-sidebar-filter-icon-bg: transparent;
--color-sidebar-search-bg: rgba(255, 255, 255, 0.78);
--color-sidebar-search-border: rgba(218, 193, 186, 0.88);
--color-sidebar-item-hover: rgba(239, 238, 234, 0.82);
--color-sidebar-item-active: rgba(239, 238, 234, 0.94);
--color-sidebar-item-active-border: rgba(143, 72, 47, 0.12);
--sidebar-panel-bg-image: none;
/* Border aliases */
--color-border: var(--color-outline-variant);
--color-border-focus: var(--color-primary);
--color-border-separator: var(--color-outline-variant);
/* Text aliases */
--color-text-primary: var(--color-on-surface);
--color-text-secondary: var(--color-on-surface-variant);
--color-text-tertiary: var(--color-outline);
/* Info surface (for team status bar, notifications) */
--color-surface-info: var(--color-surface-container-low);
/* Brand & accents */
--color-brand: var(--color-primary);
--color-text-accent: var(--color-secondary);
/* Shadows */
--shadow-dropdown: 0 4px 20px rgba(27, 28, 26, 0.04), 0 12px 40px rgba(27, 28, 26, 0.08);
--shadow-sidebar-filter: none;
--shadow-focus-ring: 0 0 0 1px rgba(143, 72, 47, 0.16);
--shadow-error-ring: 0 0 0 1px rgba(186, 26, 26, 0.18);
--shadow-button-primary: 0 8px 24px rgba(143, 72, 47, 0.18);
/* Button colors */
--color-btn-primary-fg: var(--color-on-primary);
--gradient-btn-primary: linear-gradient(135deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(135deg, var(--color-primary-container), var(--color-primary));
/* User message bubble */
--color-surface-user-msg: var(--color-surface-container);
/* Glass / overlays */
--color-overlay-scrim: rgba(27, 28, 26, 0.48);
--color-surface-glass: rgba(255, 255, 255, 0.84);
--color-surface-glass-border: rgba(218, 193, 186, 0.22);
/* Code + diff */
--color-code-bg: #FDFCF9;
--color-code-fg: #24201E;
--color-code-comment: #5C6B7A;
--color-code-string: #437220;
--color-code-keyword: #B8533B;
--color-code-function: #1D5A8C;
--color-code-number: #1B7A6A;
--color-code-property: #7A3E20;
--color-code-type: #7E5520;
--color-code-parameter: #5C3D2E;
--color-code-punctuation: #5C504A;
--color-code-inserted: #1A7F37;
--color-code-deleted: #CF222E;
--color-diff-added-bg: #E8F5E2;
--color-diff-added-word: #B8E4A8;
--color-diff-added-gutter: #D4EDCA;
--color-diff-added-text: #1A7F37;
--color-diff-removed-bg: #FDECEA;
--color-diff-removed-word: #F5B8B4;
--color-diff-removed-gutter: #F9D4D0;
--color-diff-removed-text: #CF222E;
--color-diff-highlight-bg: #FFF5D6;
--color-diff-highlight-gutter: #FFECB3;
--color-diff-title-bg: #F4F4F0;
--color-diff-title-color: #87736D;
--color-diff-title-border: #DAC1BA;
/* Terminal */
--color-terminal-header: #2D2D2D;
--color-terminal-bg: #1E1E1E;
--color-terminal-border: #1A1A1A;
--color-terminal-fg: #D4D4D4;
--color-terminal-muted: #999999;
--color-terminal-accent: #28C840;
--color-terminal-danger: #FF5F57;
--color-terminal-warning: #FEBC2E;
/* Misc */
--color-window-close-hover: #E81123;
--color-selection-bg: rgba(255, 219, 208, 0.9);
--color-selection-fg: #390C00;
/* Radii */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
}
[data-theme="dark"] {
color-scheme: dark;
--color-primary: #FFB59F;
--color-primary-container: #FF6E40;
--color-primary-fixed: #FFD9CF;
--color-primary-fixed-dim: #FFB59F;
--color-on-primary: #2C120B;
--color-on-surface: #E5E2E1;
--color-on-surface-variant: #B7AAA5;
--color-surface: #131313;
--color-surface-bright: #201F1F;
--color-surface-dim: #0E0E0E;
--color-surface-container: #201F1F;
--color-surface-container-low: #1C1B1B;
--color-surface-container-high: #2A2929;
--color-surface-container-highest: #353534;
--color-surface-container-lowest: #0E0E0E;
--color-surface-variant: #252120;
--color-background: #0E0E0E;
--color-outline: #8D7F7A;
--color-outline-variant: #5A4138;
--color-secondary: #CDBDFF;
--color-secondary-container: #3A3050;
--color-tertiary: #00DAF3;
--color-tertiary-container: #003D44;
--color-error: #FFB4AB;
--color-error-container: #93000A;
--color-on-error-container: #FFDAD6;
--color-inverse-surface: #E5E2E1;
--color-inverse-on-surface: #1B1C1A;
--color-inverse-primary: #8F482F;
--color-success: #7EDB8B;
--color-warning: #F7C46C;
--color-surface-sidebar: #171615;
--color-surface-hover: var(--color-surface-container-highest);
--color-surface-selected: var(--color-surface-container);
--color-sidebar-filter-bg: rgba(255, 255, 255, 0.01);
--color-sidebar-filter-border: rgba(255, 255, 255, 0.08);
--color-sidebar-filter-icon-bg: transparent;
--color-sidebar-search-bg: rgba(255, 255, 255, 0.03);
--color-sidebar-search-border: rgba(255, 255, 255, 0.06);
--color-sidebar-item-hover: rgba(255, 255, 255, 0.04);
--color-sidebar-item-active: rgba(255, 255, 255, 0.06);
--color-sidebar-item-active-border: rgba(255, 181, 159, 0.14);
--sidebar-panel-bg-image:
radial-gradient(circle at top left, rgba(255, 181, 159, 0.045), transparent 34%),
linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0));
--color-border: rgba(90, 65, 56, 0.18);
--color-border-focus: rgba(255, 181, 159, 0.55);
--color-border-separator: rgba(90, 65, 56, 0.12);
--color-text-primary: var(--color-on-surface);
--color-text-secondary: var(--color-on-surface-variant);
--color-text-tertiary: #8F827D;
--color-surface-info: rgba(32, 31, 31, 0.88);
--color-brand: var(--color-primary);
--color-text-accent: var(--color-tertiary);
--shadow-dropdown: 0 16px 40px rgba(0, 0, 0, 0.42);
--shadow-sidebar-filter: none;
--shadow-focus-ring: 0 0 0 1px rgba(255, 181, 159, 0.32);
--shadow-error-ring: 0 0 0 1px rgba(255, 180, 171, 0.26);
--shadow-button-primary: 0 12px 24px rgba(255, 110, 64, 0.18);
--gradient-btn-primary: linear-gradient(135deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(135deg, var(--color-primary-container), var(--color-primary));
--color-surface-user-msg: rgba(32, 31, 31, 0.92);
--color-overlay-scrim: rgba(6, 6, 6, 0.56);
--color-surface-glass: rgba(32, 31, 31, 0.8);
--color-surface-glass-border: rgba(90, 65, 56, 0.18);
--color-code-bg: #0E0E0E;
--color-code-fg: #E5E2E1;
--color-code-comment: #8F8683;
--color-code-string: #88C988;
--color-code-keyword: #FF8F70;
--color-code-function: #00DAF3;
--color-code-number: #74E0F7;
--color-code-property: #FFC9B8;
--color-code-type: #CDBDFF;
--color-code-parameter: #E5E2E1;
--color-code-punctuation: #9B908C;
--color-code-inserted: #8EEA9A;
--color-code-deleted: #FFB59F;
--color-diff-added-bg: rgba(126, 219, 139, 0.12);
--color-diff-added-word: rgba(126, 219, 139, 0.22);
--color-diff-added-gutter: rgba(126, 219, 139, 0.18);
--color-diff-added-text: #8EEA9A;
--color-diff-removed-bg: rgba(255, 110, 64, 0.12);
--color-diff-removed-word: rgba(255, 110, 64, 0.24);
--color-diff-removed-gutter: rgba(255, 110, 64, 0.18);
--color-diff-removed-text: #FFB59F;
--color-diff-highlight-bg: rgba(205, 189, 255, 0.12);
--color-diff-highlight-gutter: rgba(205, 189, 255, 0.16);
--color-diff-title-bg: var(--color-surface-container-low);
--color-diff-title-color: var(--color-text-tertiary);
--color-diff-title-border: rgba(90, 65, 56, 0.15);
--color-terminal-header: #242323;
--color-terminal-bg: #121212;
--color-terminal-border: #1A1919;
--color-terminal-fg: #D7D2D0;
--color-terminal-muted: #8F8683;
--color-terminal-accent: #7EF18A;
--color-terminal-danger: #FF6D67;
--color-terminal-warning: #F8C55F;
--color-window-close-hover: #C63B44;
--color-selection-bg: rgba(255, 181, 159, 0.32);
--color-selection-fg: #FBE7E1;
}
/* ─── Material Symbols ─────────────────────────────────────────── */
.material-symbols-outlined {
font-family: 'Material Symbols Outlined';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
vertical-align: middle;
}
/* ─── Base styles ──────────────────────────────────────────────── */
* {
box-sizing: border-box;
}
html, body, #root {
height: 100%;
margin: 0;
padding: 0;
font-family: var(--font-body);
color: var(--color-on-surface);
background-color: var(--color-background);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
::selection {
background: var(--color-selection-bg);
color: var(--color-selection-fg);
}
/* Tauri drag region */
[data-tauri-drag-region] {
-webkit-app-region: drag;
}
button, input, textarea, select, a, [role="button"] {
-webkit-app-region: no-drag;
}
[draggable="true"] {
-webkit-app-region: no-drag;
}
.tab-bar-hit-area,
.tab-bar-hit-area * {
-webkit-app-region: no-drag;
}
/* Custom shadow from prototype */
.custom-shadow {
box-shadow: var(--shadow-dropdown);
}
.glass-panel {
background: var(--color-surface-glass);
border: 1px solid var(--color-surface-glass-border);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: var(--shadow-dropdown);
}
.glass-panel:focus-within {
box-shadow: var(--shadow-focus-ring), var(--shadow-dropdown);
}
.sidebar-shell {
width: var(--sidebar-width);
flex-shrink: 0;
overflow: hidden;
transition: width var(--motion-sidebar-duration) var(--motion-sidebar-easing);
will-change: width;
}
.sidebar-shell[data-state="closed"] {
width: var(--sidebar-rail-width);
}
.sidebar-panel {
width: var(--sidebar-width);
min-width: var(--sidebar-width);
background-image: var(--sidebar-panel-bg-image);
background-repeat: no-repeat;
transition:
background-color var(--motion-sidebar-duration) var(--motion-sidebar-easing),
border-color var(--motion-sidebar-duration) var(--motion-sidebar-easing);
}
.sidebar-panel[data-state="closed"] {
width: var(--sidebar-rail-width);
min-width: var(--sidebar-rail-width);
}
.sidebar-toggle-button {
color: color-mix(in srgb, var(--color-text-secondary) 72%, transparent);
background: transparent;
transition:
color 180ms ease,
background-color 180ms ease,
transform 180ms ease;
border: 0;
box-shadow: none;
}
.sidebar-toggle-button:hover {
color: color-mix(in srgb, var(--color-text-primary) 88%, transparent);
background: color-mix(in srgb, var(--color-surface-hover) 34%, transparent);
}
.sidebar-toggle-button:active {
transform: translateY(0.5px);
background: color-mix(in srgb, var(--color-surface-hover) 54%, transparent);
}
.sidebar-toggle-button--open {
color: color-mix(in srgb, var(--color-text-secondary) 68%, transparent);
}
.sidebar-toggle-button--open:hover {
color: color-mix(in srgb, var(--color-text-primary) 82%, transparent);
}
.sidebar-toggle-button--collapsed {
color: color-mix(in srgb, var(--color-text-primary) 78%, transparent);
}
.sidebar-toggle-button--collapsed:hover {
color: var(--color-text-primary);
}
.sidebar-toggle-button--collapsed:active {
}
.sidebar-toggle-icon {
overflow: visible;
}
.sidebar-toggle-chevron {
stroke: currentColor;
transition:
opacity 180ms ease,
transform 180ms ease;
vector-effect: non-scaling-stroke;
}
.sidebar-toggle-chevron {
opacity: 0.95;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 1.85;
transform-origin: 50% 50%;
}
.sidebar-toggle-icon--open .sidebar-toggle-chevron {
transform: translateX(-0.2px);
}
.sidebar-toggle-button--collapsed .sidebar-toggle-chevron {
stroke-width: 2;
transform: translateX(0.4px);
}
.sidebar-copy {
overflow: hidden;
white-space: nowrap;
transition:
max-width var(--motion-sidebar-duration) var(--motion-sidebar-easing),
opacity calc(var(--motion-sidebar-duration) - 40ms) ease,
transform var(--motion-sidebar-duration) var(--motion-sidebar-easing);
}
.sidebar-copy--visible {
max-width: 240px;
opacity: 1;
transform: translateX(0);
}
.sidebar-copy--hidden {
max-width: 0;
opacity: 0;
transform: translateX(-10px);
}
.sidebar-section {
overflow: hidden;
transition:
max-height var(--motion-sidebar-duration) var(--motion-sidebar-easing),
opacity calc(var(--motion-sidebar-duration) - 40ms) ease,
transform var(--motion-sidebar-duration) var(--motion-sidebar-easing);
}
.sidebar-section--visible {
max-height: 1200px;
opacity: 1;
transform: translateX(0);
}
.sidebar-section--hidden {
max-height: 0;
opacity: 0;
transform: translateX(-12px);
pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
.sidebar-shell,
.sidebar-panel,
.sidebar-copy,
.sidebar-section {
transition-duration: 0.01ms !important;
}
}
.markdown-prose .md-table-wrap table {
border-collapse: separate;
border-spacing: 0;
}
.markdown-prose .md-table-wrap tbody tr:last-child td {
border-bottom: 0;
}
.markdown-prose a code {
color: inherit;
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-outline); border-radius: 9999px; opacity: 0.3; }
::-webkit-scrollbar-thumb:hover { opacity: 0.6; }
/* Animations */
@keyframes shimmer {
0%, 100% { opacity: 0.4; }
50% { opacity: 1; }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.animate-shimmer { animation: shimmer 1.5s ease-in-out infinite; }
.animate-spin { animation: spin 1s linear infinite; }
.animate-pulse-dot { animation: pulse-dot 1.5s ease-in-out infinite; }
/* Progress bar */
@keyframes progress-fill {
from { width: 0%; }
}