diff --git a/src/App.tsx b/src/App.tsx index f544cdf..5166c70 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,7 +30,7 @@ import AccountManagementPage from './pages/AccountManagementPage' import BackupPage from './pages/BackupPage' import { useAppStore } from './stores/appStore' -import { useThemeStore, type ThemeMode } from './stores/themeStore' +import { themes, useThemeStore, type ThemeId, type ThemeMode } from './stores/themeStore' import * as configService from './services/config' import * as cloudControl from './services/cloudControl' import { Download, X, Shield } from 'lucide-react' @@ -74,7 +74,7 @@ function App() { setLocked } = useAppStore() - const { themeMode, setThemeMode } = useThemeStore() + const { currentTheme, themeMode, setTheme, setThemeMode } = useThemeStore() const isAgreementWindow = location.pathname === '/agreement-window' const isOnboardingWindow = location.pathname === '/onboarding-window' const isVideoPlayerWindow = location.pathname === '/video-player-window' @@ -149,11 +149,12 @@ function App() { } }, [isOnboardingWindow, isNotificationWindow, isAnnualReportWindow, isDualReportWindow]) - // 应用主题模式 (light / dark / system) + // 应用主题 (accent color + light/dark mode) useEffect(() => { const mq = window.matchMedia('(prefers-color-scheme: dark)') const applyMode = (mode: ThemeMode, systemDark?: boolean) => { const effectiveMode = mode === 'system' ? (systemDark ?? mq.matches ? 'dark' : 'light') : mode + document.documentElement.setAttribute('data-theme', currentTheme) document.documentElement.setAttribute('data-mode', effectiveMode) } @@ -167,13 +168,19 @@ function App() { } mq.addEventListener('change', handler) return () => mq.removeEventListener('change', handler) - }, [themeMode, isOnboardingWindow, isNotificationWindow, isAnnualReportWindow, isDualReportWindow]) + }, [currentTheme, themeMode, isOnboardingWindow, isNotificationWindow, isAnnualReportWindow, isDualReportWindow]) // 读取已保存的主题设置 useEffect(() => { const loadTheme = async () => { try { - const savedThemeMode = await configService.getTheme() + const [savedThemeId, savedThemeMode] = await Promise.all([ + configService.getThemeId(), + configService.getTheme() + ]) + if (savedThemeId && themes.some((theme) => theme.id === savedThemeId)) { + setTheme(savedThemeId as ThemeId) + } if (savedThemeMode === 'light' || savedThemeMode === 'dark' || savedThemeMode === 'system') { setThemeMode(savedThemeMode) } @@ -184,20 +191,23 @@ function App() { } } loadTheme() - }, [setThemeMode]) + }, [setTheme, setThemeMode]) // 保存主题设置 useEffect(() => { if (!themeHydrated) return const saveTheme = async () => { try { - await configService.setTheme(themeMode) + await Promise.all([ + configService.setThemeId(currentTheme), + configService.setTheme(themeMode) + ]) } catch (e) { console.error('保存主题配置失败:', e) } } saveTheme() - }, [themeMode, themeHydrated]) + }, [currentTheme, themeMode, themeHydrated]) // 检查是否已同意协议 useEffect(() => { diff --git a/src/components/Sidebar.scss b/src/components/Sidebar.scss index d082bd4..0c1d31e 100644 --- a/src/components/Sidebar.scss +++ b/src/components/Sidebar.scss @@ -1,13 +1,14 @@ -// ChatGPT-style sidebar +// Redesigned sidebar — premium feel with left accent bar, refined spacing .sidebar { width: var(--sidebar-width, 260px); background: var(--bg-sidebar, var(--bg-secondary)); display: flex; flex-direction: column; - padding: 8px 0; - transition: width 0.2s ease; + padding: 0; + transition: width 0.2s cubic-bezier(0.4, 0, 0.2, 1); flex-shrink: 0; overflow: hidden; + border-right: 1px solid var(--border-color); &.collapsed { width: 68px; @@ -23,21 +24,37 @@ .user-meta { display: none; } + + .user-menu-caret { + display: none; + } } - .nav-menu, - .sidebar-footer { + .nav-menu { padding: 0 8px; } + .sidebar-footer { + padding: 0 8px; + padding-top: 8px; + } + .nav-label { display: none; } + .nav-badge:not(.icon-badge) { + display: none; + } + .nav-item { justify-content: center; padding: 10px; gap: 0; + + &::before { + display: none; + } } } } @@ -47,18 +64,19 @@ flex: 1; display: flex; flex-direction: column; - gap: 2px; - padding: 0 12px; + gap: 1px; + padding: 12px 10px; overflow-y: auto; overflow-x: hidden; } .nav-item { + position: relative; display: flex; align-items: center; gap: 12px; - padding: 10px 12px; - border-radius: 8px; + padding: 9px 14px; + border-radius: 10px; color: var(--text-secondary); text-decoration: none; transition: background 0.15s ease, color 0.15s ease; @@ -68,6 +86,21 @@ cursor: pointer; font-family: inherit; font-size: 14px; + margin: 1px 0; + + // Left accent bar for active state + &::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%) scaleY(0); + width: 3px; + height: 16px; + border-radius: 0 2px 2px 0; + background: var(--primary); + transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1); + } &:hover { background: var(--bg-hover); @@ -78,6 +111,14 @@ background: var(--bg-hover); color: var(--text-primary); font-weight: 600; + + &::before { + transform: translateY(-50%) scaleY(1); + } + + .nav-icon { + color: var(--primary); + } } } @@ -88,6 +129,7 @@ width: 20px; height: 20px; flex-shrink: 0; + transition: color 0.15s ease; } .nav-icon-with-badge { @@ -129,19 +171,19 @@ // ---- Footer ---- .sidebar-footer { - padding: 0 12px; + padding: 4px 10px; border-top: 1px solid var(--border-color); padding-top: 8px; margin-top: 4px; display: flex; flex-direction: column; - gap: 2px; + gap: 1px; } // ---- User card ---- .sidebar-user-card-wrap { position: relative; - margin: 0 12px 8px; + margin: 0 10px 10px; --sidebar-user-menu-width: 172px; } @@ -153,7 +195,7 @@ width: max(100%, var(--sidebar-user-menu-width)); z-index: 12; border: 1px solid var(--border-color); - border-radius: 10px; + border-radius: 12px; background: var(--bg-secondary-solid, var(--bg-secondary)); display: flex; flex-direction: column; @@ -203,7 +245,7 @@ .sidebar-user-card { width: 100%; - padding: 10px; + padding: 10px 12px; border-radius: 10px; background: transparent; display: flex; @@ -223,8 +265,8 @@ } .user-avatar { - width: 32px; - height: 32px; + width: 34px; + height: 34px; border-radius: 50%; overflow: hidden; background: var(--primary); @@ -232,6 +274,7 @@ align-items: center; justify-content: center; flex-shrink: 0; + box-shadow: 0 0 0 2px var(--bg-sidebar, var(--bg-secondary)); img { width: 100%; diff --git a/src/pages/AnnualReportPage.scss b/src/pages/AnnualReportPage.scss index 396441c..bdee64f 100644 --- a/src/pages/AnnualReportPage.scss +++ b/src/pages/AnnualReportPage.scss @@ -7,6 +7,7 @@ min-height: 100%; text-align: center; padding: 40px 24px; + animation: reportFadeIn 0.35s ease-out; } .annual-report-page.report-route-transitioning > :not(.report-launch-overlay) { @@ -20,40 +21,43 @@ } .page-title { - font-size: 32px; + font-size: 28px; font-weight: 700; color: var(--text-primary); - margin: 0 0 12px; + margin: 0 0 10px; + letter-spacing: -0.5px; } .page-desc { font-size: 15px; color: var(--text-secondary); - margin: 0 0 48px; + margin: 0 0 40px; + line-height: 1.7; } .page-desc.load-summary { - margin: 0 0 28px; + margin: 0 0 24px; } .page-desc.load-summary.complete { color: var(--text-secondary); } +// ---- Load telemetry ---- .load-telemetry { - width: min(760px, 100%); - padding: 12px 14px; - margin: 0 0 28px; - border-radius: 12px; - border: 1px solid color-mix(in srgb, var(--border-color) 80%, transparent); - background: color-mix(in srgb, var(--card-bg) 92%, transparent); + width: min(620px, 100%); + padding: 12px 16px; + margin: 0 0 24px; + border-radius: 10px; + border: 1px solid var(--border-color); + background: var(--card-bg); text-align: left; font-size: 13px; color: var(--text-secondary); line-height: 1.5; p { - margin: 4px 0; + margin: 3px 0; } .label { @@ -62,31 +66,32 @@ } .load-telemetry.loading { - border-color: color-mix(in srgb, var(--primary) 30%, var(--border-color)); + border-color: color-mix(in srgb, var(--primary) 25%, var(--border-color)); } .load-telemetry.complete { - border-color: color-mix(in srgb, var(--primary) 40%, var(--border-color)); + border-color: color-mix(in srgb, var(--primary) 35%, var(--border-color)); } .load-telemetry.compact { margin: 12px 0 0; - width: min(560px, 100%); + width: min(500px, 100%); } +// ---- Report sections ---- .report-sections { display: flex; flex-direction: column; - gap: 32px; - width: min(760px, 100%); + gap: 20px; + width: min(620px, 100%); } .report-section { width: 100%; background: var(--card-bg); border: 1px solid var(--border-color); - border-radius: 20px; - padding: 28px; + border-radius: 16px; + padding: 24px; text-align: left; } @@ -95,57 +100,57 @@ align-items: flex-start; justify-content: space-between; gap: 16px; - margin-bottom: 20px; + margin-bottom: 16px; } .section-title { margin: 0; - font-size: 20px; + font-size: 17px; font-weight: 700; color: var(--text-primary); } .section-desc { - margin: 8px 0 0; - font-size: 14px; + margin: 6px 0 0; + font-size: 13px; color: var(--text-tertiary); } .section-badge { display: inline-flex; align-items: center; - gap: 6px; - padding: 6px 10px; + gap: 5px; + padding: 4px 10px; border-radius: 999px; - background: color-mix(in srgb, var(--primary) 12%, transparent); + background: var(--primary-light); color: var(--primary); - border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent); font-size: 12px; font-weight: 600; white-space: nowrap; } .section-hint { - margin: 12px 0 0; + margin: 10px 0 0; font-size: 12px; color: var(--text-tertiary); } +// ---- Year cards ---- .year-grid-with-status { display: flex; align-items: flex-start; justify-content: space-between; - gap: 16px; - margin-bottom: 24px; + gap: 12px; + margin-bottom: 20px; } .year-grid { display: flex; flex-wrap: wrap; - gap: 16px; + gap: 10px; justify-content: center; max-width: 600px; - margin-bottom: 48px; + margin-bottom: 40px; } .report-section .year-grid { @@ -169,7 +174,7 @@ } .year-load-status.complete { - color: color-mix(in srgb, var(--primary) 80%, var(--text-secondary)); + color: var(--primary); } .dot-ellipsis { @@ -187,32 +192,33 @@ } .year-card { - width: 120px; - height: 100px; + width: 88px; + height: 64px; display: flex; flex-direction: column; align-items: center; justify-content: center; - background: var(--card-bg); - border: 2px solid var(--border-color); - border-radius: 16px; + background: transparent; + border: 1px solid var(--border-color); + border-radius: 10px; cursor: pointer; - transition: all 0.2s; + transition: all 0.15s ease; + gap: 2px; &:hover { - border-color: var(--primary); - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + border-color: var(--text-tertiary); + background: var(--bg-hover); } &.disabled { pointer-events: none; - opacity: 0.72; + opacity: 0.6; } &.selected { border-color: var(--primary); background: var(--primary-light); + box-shadow: 0 0 0 1px var(--primary); .year-number { color: var(--primary); @@ -220,45 +226,41 @@ } .year-number { - font-size: 32px; + font-size: 22px; font-weight: 700; color: var(--text-primary); line-height: 1; } .year-label { - font-size: 14px; + font-size: 11px; color: var(--text-tertiary); - margin-top: 4px; } } +// ---- Generate button ---- .generate-btn { display: flex; align-items: center; - gap: 10px; - padding: 16px 40px; - background: linear-gradient(135deg, var(--primary) 0%, color-mix(in srgb, var(--primary) 80%, #000) 100%); + justify-content: center; + gap: 8px; + width: 100%; + padding: 12px 24px; + background: var(--primary); border: none; - border-radius: 50px; - color: #fff; - font-size: 16px; + border-radius: 10px; + color: var(--on-primary); + font-size: 15px; font-weight: 600; cursor: pointer; - transition: all 0.2s; - box-shadow: 0 4px 16px color-mix(in srgb, var(--primary) 30%, transparent); + transition: opacity 0.15s ease; &:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 8px 24px color-mix(in srgb, var(--primary) 40%, transparent); - } - - &:active:not(:disabled) { - transform: translateY(0); + opacity: 0.9; } &:disabled { - opacity: 0.6; + opacity: 0.5; cursor: not-allowed; } @@ -267,13 +269,18 @@ } &.secondary { - background: var(--card-bg); + background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); - box-shadow: none; + + &:hover:not(:disabled) { + background: var(--bg-hover); + opacity: 1; + } } } +// ---- Launch overlay ---- .report-launch-overlay { position: fixed; inset: 0; @@ -281,9 +288,9 @@ display: flex; align-items: center; justify-content: center; - background: color-mix(in srgb, var(--bg-primary) 78%, transparent); + background: color-mix(in srgb, var(--bg-primary) 80%, transparent); backdrop-filter: blur(8px); - animation: report-launch-overlay-in 420ms ease-out both; + animation: report-launch-overlay-in 350ms ease-out both; } .launch-core { @@ -293,13 +300,13 @@ gap: 10px; text-align: center; color: var(--text-primary); - animation: report-launch-core-in 420ms cubic-bezier(0.2, 0.8, 0.2, 1) both; + animation: report-launch-core-in 350ms cubic-bezier(0.2, 0.8, 0.2, 1) both; } .launch-title { margin: 4px 0 0; - font-size: 18px; - font-weight: 650; + font-size: 17px; + font-weight: 600; } .launch-subtitle { @@ -312,6 +319,7 @@ animation: spin 1s linear infinite; } +// ---- Animations ---- @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } @@ -329,27 +337,34 @@ } to { opacity: 0; - filter: blur(8px); + filter: blur(6px); transform: scale(0.985); } } @keyframes report-launch-overlay-in { - from { - opacity: 0; - } - to { - opacity: 1; - } + from { opacity: 0; } + to { opacity: 1; } } @keyframes report-launch-core-in { from { opacity: 0; - transform: translateY(18px) scale(0.96); + transform: translateY(14px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } } + +@keyframes reportFadeIn { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/pages/ChatAnalyticsHubPage.scss b/src/pages/ChatAnalyticsHubPage.scss index f6621a7..e84a14d 100644 --- a/src/pages/ChatAnalyticsHubPage.scss +++ b/src/pages/ChatAnalyticsHubPage.scss @@ -7,68 +7,79 @@ } .analytics-hub-inner { - width: min(720px, 100%); - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - animation: analyticsHubFadeIn 0.4s ease-out; + width: min(560px, 100%); + animation: analyticsHubFadeIn 0.35s ease-out; +} + +// ---- Hero ---- +.analytics-hub-hero { + margin-bottom: 40px; } .analytics-hub-title { font-size: 28px; font-weight: 700; color: var(--text-primary); - margin: 0 0 12px; + margin: 0 0 10px; letter-spacing: -0.5px; } .analytics-hub-desc { - max-width: 520px; - margin: 0 0 36px; + margin: 0; color: var(--text-secondary); font-size: 15px; line-height: 1.7; } -.analytics-hub-grid { - width: 100%; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 16px; -} - -.analytics-hub-card { +// ---- Perspectives list ---- +.analytics-hub-perspectives { display: flex; flex-direction: column; - align-items: flex-start; - text-align: left; - gap: 16px; - padding: 24px; - border: 1px solid var(--border-color); + gap: 4px; +} + +.analytics-hub-perspectives-label { + font-size: 12px; + font-weight: 600; + color: var(--text-tertiary); + text-transform: uppercase; + letter-spacing: 0.05em; + padding: 0 4px; + margin-bottom: 8px; +} + +.analytics-hub-row { + display: flex; + align-items: center; + gap: 14px; + padding: 14px 16px; + border: none; border-radius: 12px; - background: var(--card-bg); + background: transparent; color: var(--text-primary); cursor: pointer; - transition: background 0.15s ease, border-color 0.15s ease; + text-align: left; + transition: background 0.15s ease; + width: 100%; &:hover { background: var(--bg-hover); - border-color: var(--text-tertiary); - .analytics-hub-card-arrow { + .analytics-hub-row-arrow { transform: translateX(3px); + color: var(--text-secondary); } } } -.analytics-hub-card-icon { - width: 44px; - height: 44px; - border-radius: 10px; +.analytics-hub-row-icon { + width: 40px; + height: 40px; + border-radius: 50%; display: flex; align-items: center; justify-content: center; + flex-shrink: 0; background: var(--primary-light); color: var(--primary); @@ -78,53 +89,39 @@ } } -[data-mode="dark"] .analytics-hub-card-icon--group { +[data-mode="dark"] .analytics-hub-row-icon--group { background: rgba(96, 165, 250, 0.12); color: #60a5fa; } -.analytics-hub-card-body { - display: flex; - flex-direction: column; - gap: 8px; - width: 100%; +.analytics-hub-row-body { + flex: 1; + min-width: 0; } -.analytics-hub-card-header { - display: flex; - align-items: center; - justify-content: space-between; - - h2 { - margin: 0; - font-size: 18px; - font-weight: 600; - line-height: 1.2; - } +.analytics-hub-row-title { + font-size: 15px; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 2px; } -.analytics-hub-card-arrow { - color: var(--text-tertiary); - transition: transform 0.15s ease; -} - -.analytics-hub-card-body p { - margin: 0; - color: var(--text-secondary); +.analytics-hub-row-desc { font-size: 13px; - line-height: 1.6; + color: var(--text-tertiary); + line-height: 1.5; } -@media (max-width: 640px) { - .analytics-hub-grid { - grid-template-columns: 1fr; - } +.analytics-hub-row-arrow { + color: var(--text-tertiary); + flex-shrink: 0; + transition: transform 0.15s ease, color 0.15s ease; } @keyframes analyticsHubFadeIn { from { opacity: 0; - transform: translateY(10px); + transform: translateY(8px); } to { opacity: 1; diff --git a/src/pages/ChatAnalyticsHubPage.tsx b/src/pages/ChatAnalyticsHubPage.tsx index 3e21c73..4bc514e 100644 --- a/src/pages/ChatAnalyticsHubPage.tsx +++ b/src/pages/ChatAnalyticsHubPage.tsx @@ -8,44 +8,44 @@ function ChatAnalyticsHubPage() { return (
-

聊天分析

-

- 选择你要进入的分析视角。私聊分析适合查看好友聊天统计,群聊分析则用于查看群成员活跃度。 -

+
+

聊天分析

+

+ 选择你要进入的分析视角,深入了解关系网络、活跃时段与消息趋势。 +

+
+ +
+
视角
-
diff --git a/src/pages/DualReportPage.scss b/src/pages/DualReportPage.scss index 802f0bb..61944a0 100644 --- a/src/pages/DualReportPage.scss +++ b/src/pages/DualReportPage.scss @@ -1,6 +1,7 @@ .dual-report-page { padding: 32px 28px; color: var(--text-primary); + animation: dualFadeIn 0.35s ease-out; } .dual-report-page.loading { @@ -22,25 +23,26 @@ h1 { margin: 0; - font-size: 24px; + font-size: 22px; font-weight: 700; + letter-spacing: -0.3px; } p { - margin: 8px 0 0; + margin: 6px 0 0; color: var(--text-secondary); + font-size: 14px; } } .year-badge { display: inline-flex; align-items: center; - gap: 6px; - padding: 6px 10px; + gap: 5px; + padding: 4px 10px; border-radius: 999px; - background: color-mix(in srgb, var(--primary) 12%, transparent); + background: var(--primary-light); color: var(--primary); - border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent); font-size: 12px; font-weight: 600; white-space: nowrap; @@ -50,11 +52,12 @@ display: flex; align-items: center; gap: 8px; - padding: 10px 12px; + padding: 9px 12px; background: var(--card-bg); border: 1px solid var(--border-color); - border-radius: 12px; - margin-bottom: 20px; + border-radius: 10px; + margin-bottom: 16px; + color: var(--text-tertiary); input { flex: 1; @@ -69,7 +72,7 @@ .ranking-list { display: flex; flex-direction: column; - gap: 12px; + gap: 4px; } .ranking-item { @@ -77,42 +80,41 @@ grid-template-columns: auto auto 1fr auto; align-items: center; gap: 12px; - padding: 12px 16px; - background: var(--card-bg); - border: 1px solid var(--border-color); - border-radius: 14px; + padding: 10px 14px; + background: transparent; + border: none; + border-radius: 10px; text-align: left; cursor: pointer; - transition: all 0.2s; + transition: background 0.15s ease; + width: 100%; &:hover { - border-color: var(--primary); - box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); - transform: translateY(-1px); + background: var(--bg-hover); } } .rank-badge { - width: 28px; - height: 28px; + width: 26px; + height: 26px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; - background: var(--border-color); + background: var(--bg-tertiary); color: var(--text-secondary); font-size: 12px; font-weight: 700; &.top { - background: color-mix(in srgb, var(--primary) 18%, transparent); - color: var(--primary); + background: var(--primary); + color: var(--on-primary); } } .avatar { - width: 40px; - height: 40px; + width: 36px; + height: 36px; border-radius: 50%; overflow: hidden; background: var(--primary-light); @@ -121,6 +123,7 @@ justify-content: center; color: var(--primary); font-weight: 700; + font-size: 14px; img { width: 100%; @@ -132,11 +135,11 @@ .info { display: flex; flex-direction: column; - gap: 2px; - min-width: 0; // 允许 flex 子项缩小,配合 ellipsis + gap: 1px; + min-width: 0; .name { - font-size: 15px; + font-size: 14px; font-weight: 600; color: var(--text-primary); white-space: nowrap; @@ -146,29 +149,29 @@ .sub { font-size: 12px; - color: var(--text-secondary); // 从 tertiary 改为 secondary 以增强对比度 + color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - opacity: 0.8; } } .meta { text-align: right; font-size: 12px; - color: var(--text-secondary); // 改为 secondary + color: var(--text-secondary); flex-shrink: 0; .count { - font-size: 14px; + font-size: 13px; font-weight: 700; - color: var(--primary); // 使用主题色更醒目 - margin-bottom: 2px; + color: var(--primary); + margin-bottom: 1px; } .hint { - opacity: 0.7; + color: var(--text-tertiary); + font-size: 11px; } } @@ -176,6 +179,7 @@ text-align: center; color: var(--text-tertiary); padding: 40px 0; + font-size: 14px; } .spin { @@ -183,11 +187,17 @@ } @keyframes spin { - from { - transform: rotate(0deg); - } + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} +@keyframes dualFadeIn { + from { + opacity: 0; + transform: translateY(8px); + } to { - transform: rotate(360deg); + opacity: 1; + transform: translateY(0); } } \ No newline at end of file diff --git a/src/styles/main.scss b/src/styles/main.scss index 8b19126..5d0b7d4 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -1,6 +1,5 @@ // WeFlow — ChatGPT-inspired design token system -// Only light/dark/system modes. No per-theme variants. -// All legacy variable names preserved for backward compatibility. +// Accent colors per theme, backgrounds unified across themes. @use './chat-patterns.scss'; // ============================================= @@ -8,7 +7,7 @@ // ============================================= :root, [data-mode="light"] { - // ---- Accent / Brand ---- + // ---- Accent / Brand (default = ChatGPT green) ---- --primary: #10a37f; --primary-rgb: 16, 163, 127; --primary-hover: #0d8a6c; @@ -18,7 +17,7 @@ --danger: #ef4444; --warning: #f59e0b; - // ---- Backgrounds ---- + // ---- Backgrounds (same for all themes) ---- --bg-primary: #ffffff; --bg-secondary: #f9f9f9; --bg-secondary-solid: #f9f9f9; @@ -56,7 +55,6 @@ // Dark mode // ============================================= [data-mode="dark"] { - // ---- Accent / Brand ---- --primary: #10a37f; --primary-rgb: 16, 163, 127; --primary-hover: #1ab893; @@ -66,7 +64,6 @@ --danger: #f87171; --warning: #fbbf24; - // ---- Backgrounds ---- --bg-primary: #212121; --bg-secondary: #2f2f2f; --bg-secondary-solid: #2f2f2f; @@ -75,27 +72,137 @@ --bg-sidebar: #171717; --bg-gradient: linear-gradient(180deg, #212121 0%, #1a1a1a 100%); - // ---- Text ---- --text-primary: #ececec; --text-secondary: #b4b4b4; --text-tertiary: #676767; - // ---- Borders ---- --border-color: rgba(255, 255, 255, 0.08); - // ---- Shadows ---- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3); --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4); - // ---- Cards ---- --card-bg: #2f2f2f; --card-inner-bg: #353535; --sent-card-bg: var(--primary); - - // ---- On-primary foreground ---- --on-primary: #ffffff; +} - --primary-gradient: linear-gradient(135deg, #10a37f 0%, #1ab893 100%); +// ============================================= +// Accent color themes (override --primary only) +// Backgrounds/text stay the same — like ChatGPT's accent system. +// ============================================= + +// 云上舞白 — warm brown +[data-theme="cloud-dancer"] { + --primary: #8B7355; + --primary-rgb: 139, 115, 85; + --primary-hover: #7A6548; + --primary-light: rgba(139, 115, 85, 0.1); + --primary-gradient: linear-gradient(135deg, #8B7355 0%, #A68B5B 100%); +} +[data-theme="cloud-dancer"][data-mode="dark"] { + --primary: #C9A86C; + --primary-rgb: 201, 168, 108; + --primary-hover: #D9B87C; + --primary-light: rgba(201, 168, 108, 0.15); + --primary-gradient: linear-gradient(135deg, #8B7355 0%, #C9A86C 100%); +} + +// 繁花如梦 — rose pink +[data-theme="blossom-dream"] { + --primary: #D4849A; + --primary-rgb: 212, 132, 154; + --primary-hover: #C4748A; + --primary-light: rgba(212, 132, 154, 0.12); + --primary-gradient: linear-gradient(135deg, #D4849A 0%, #E8A8B8 100%); +} +[data-theme="blossom-dream"][data-mode="dark"] { + --primary: #D19EBB; + --primary-rgb: 209, 158, 187; + --primary-hover: #DDB0C8; + --primary-light: rgba(209, 158, 187, 0.15); + --primary-gradient: linear-gradient(135deg, #D19EBB 0%, #A878A8 100%); +} + +// 刚玉蓝 — steel blue +[data-theme="corundum-blue"] { + --primary: #4A6670; + --primary-rgb: 74, 102, 112; + --primary-hover: #3D565E; + --primary-light: rgba(74, 102, 112, 0.1); + --primary-gradient: linear-gradient(135deg, #4A6670 0%, #5A7A86 100%); +} +[data-theme="corundum-blue"][data-mode="dark"] { + --primary: #6A9AAA; + --primary-rgb: 106, 154, 170; + --primary-hover: #7AAABA; + --primary-light: rgba(106, 154, 170, 0.15); + --primary-gradient: linear-gradient(135deg, #4A6670 0%, #6A9AAA 100%); +} + +// 冰猕猴桃汁绿 — kiwi green +[data-theme="kiwi-green"] { + --primary: #7A9A5C; + --primary-rgb: 122, 154, 92; + --primary-hover: #6A8A4C; + --primary-light: rgba(122, 154, 92, 0.1); + --primary-gradient: linear-gradient(135deg, #7A9A5C 0%, #8AAA6C 100%); +} +[data-theme="kiwi-green"][data-mode="dark"] { + --primary: #9ABA7C; + --primary-rgb: 154, 186, 124; + --primary-hover: #AACA8C; + --primary-light: rgba(154, 186, 124, 0.15); + --primary-gradient: linear-gradient(135deg, #7A9A5C 0%, #9ABA7C 100%); +} + +// 辛辣红 — spicy red +[data-theme="spicy-red"] { + --primary: #8B4049; + --primary-rgb: 139, 64, 73; + --primary-hover: #7A3540; + --primary-light: rgba(139, 64, 73, 0.1); + --primary-gradient: linear-gradient(135deg, #8B4049 0%, #A05058 100%); +} +[data-theme="spicy-red"][data-mode="dark"] { + --primary: #C06068; + --primary-rgb: 192, 96, 104; + --primary-hover: #D07078; + --primary-light: rgba(192, 96, 104, 0.15); + --primary-gradient: linear-gradient(135deg, #8B4049 0%, #C06068 100%); +} + +// 明水鸭色 — teal +[data-theme="teal-water"] { + --primary: #5A8A8A; + --primary-rgb: 90, 138, 138; + --primary-hover: #4A7A7A; + --primary-light: rgba(90, 138, 138, 0.1); + --primary-gradient: linear-gradient(135deg, #5A8A8A 0%, #6A9A9A 100%); +} +[data-theme="teal-water"][data-mode="dark"] { + --primary: #7ABAAA; + --primary-rgb: 122, 186, 170; + --primary-hover: #8ACABA; + --primary-light: rgba(122, 186, 170, 0.15); + --primary-gradient: linear-gradient(135deg, #5A8A8A 0%, #7ABAAA 100%); +} + +// Geist — monochrome +[data-theme="geist"] { + --primary: #444444; + --primary-rgb: 68, 68, 68; + --primary-hover: #333333; + --primary-light: rgba(68, 68, 68, 0.08); + --primary-gradient: linear-gradient(135deg, #444444 0%, #666666 100%); +} +[data-theme="geist"][data-mode="dark"] { + --primary: #ededed; + --primary-rgb: 237, 237, 237; + --primary-hover: #d5d5d5; + --primary-light: rgba(237, 237, 237, 0.1); + --primary-gradient: linear-gradient(135deg, #ededed 0%, #cccccc 100%); + --on-primary: #111111; } // =============================================