This commit is contained in:
2026-09-12 14:15:26 +08:00
commit 9c06d3f4be
99 changed files with 41853 additions and 0 deletions

500
src/styles/02-palettes.css Normal file
View File

@@ -0,0 +1,500 @@
/* ===========================================================================
Palettes × Themes —— 收敛表达
Stage 4a.2:用「主题骨架 + palette 差异补丁」替代原 10 块字符级复制
设计思路:
所有 palette × theme 共享同一组 token 表达bg-hover / bg-active / 阴影
/ scrollbar / 边框等),但每个 palette 在每个 theme 下各自有自己的
视觉个性accent 色、带色相的 bg / fg
所以分两层:
1. 主题骨架(深 / 浅):定义所有「主题相关但 palette 无感」的 token。
主题骨架只装「公共部分」,不装任何 palette 个性。
2. palette 差异补丁:每块只覆盖该 palette 的 accent 系列 + 带色相的
bg/fg/text + markdown 配色 + toolbar-divider。其余 token 走主题骨架。
选择器特异性:
- [data-theme="dark"] (0,1,1)
- [data-theme-palette="X"][data-theme="Y"] (0,2,0)
后者更高,所以 palette 块能覆盖主题骨架。
=========================================================================== */
/* ---------- Dark Theme Skeleton ----------
暗色通用 token —— 5 个 palette 的暗色版共享这些。
palette 块只覆盖带色相部分accent + 自身 bg/fg/md-*)。
*/
[data-theme="dark"] {
/* 背景交互态:所有暗色 palette 都用白叠加 */
--bg-hover: rgba(255, 255, 255, 0.04);
--bg-active: rgba(255, 255, 255, 0.08);
/* 边框:所有暗色 palette 浅边用白叠加、强边用更深的白 */
--border-subtle: rgba(255, 255, 255, 0.04);
--border-strong: rgba(255, 255, 255, 0.12);
/* 滚动条 */
--scrollbar-thumb: rgba(255, 255, 255, 0.10);
--scrollbar-thumb-hover: rgba(255, 255, 255, 0.20);
/* 阴影:暗色下更深 */
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.15);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.32), 0 2px 4px rgba(0, 0, 0, 0.16);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.42), 0 4px 8px rgba(0, 0, 0, 0.25);
/* --shadow-glow 由 palette 设(带 accent-soft */
/* 语义色:所有暗色 palette 统一
audit fix (H4/H5)--danger 由 #ff6b6b → #d23636white-on-bg 对比从 2.2:1
提到 4.86:1AA 通过。btn-danger / error chip 都用这个 token统一收敛。 */
--danger: #d23636;
--btn-on-danger: #ffffff;
--warning: #ffb454;
--success: #5ad19a;
/* Markdown 通用(不带色相):所有暗色 palette 都用白叠加 */
--md-table-border: rgba(255, 255, 255, 0.08);
--md-table-stripe: rgba(255, 255, 255, 0.02);
--md-table-header-bg: rgba(255, 255, 255, 0.04);
--md-hr: rgba(255, 255, 255, 0.08);
/* --md-blockquote-* / --md-inline-code-bg / --md-code-bg / --md-link 由 palette 设 */
--md-heading: var(--fg-primary);
/* ── 文字版语义色 ───────────────────────────────────────────────
用途:状态栏 chip 字、AI 错误小字、表单 hint、设置卡 selected label
等 11-14px 的有色正文。装饰色warning / danger / success / accent
为图标、边框、圆点、单字符AI diff +/-)设计,直接套到正文字符上
会因高彩度小字"振动"看着累。这里取 60-65% 装饰色 + 35-40%
fg-primary 调和:色相仍可识别(暖橙 / 红 / 绿 / 蓝调),但 chroma
降到不会刺眼的程度。
比例选择:
dark 用 60% 装饰色 —— 深底 fg-primary 偏白,混出"暖白"效果。
light 用 70% 装饰色 —— 浅底 fg-primary 偏黑,需要更高的色比保证
文字可见度70% 仍比 100% 纯色温和一档。
边界borders / dots / icons / 单字符 +/- 继续用纯 *(不退色),
详见各组件 CSS 注释。 */
--warning-text: color-mix(in srgb, var(--warning) 60%, var(--fg-primary));
--danger-text: color-mix(in srgb, var(--danger) 60%, var(--fg-primary));
--accent-text: color-mix(in srgb, var(--accent) 65%, var(--fg-primary));
}
/* ---------- Light Theme Skeleton ---------- */
[data-theme="light"] {
--bg-hover: rgba(0, 0, 0, 0.04);
--bg-active: rgba(0, 0, 0, 0.07);
--border-subtle: rgba(0, 0, 0, 0.04);
--border-strong: rgba(0, 0, 0, 0.14);
--scrollbar-thumb: rgba(0, 0, 0, 0.14);
--scrollbar-thumb-hover: rgba(0, 0, 0, 0.26);
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.035), 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.035);
--shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.09), 0 4px 12px rgba(0, 0, 0, 0.05);
/* --shadow-glow 由 palette 设(带 accent-soft */
/* audit fix (H4/H5)light --danger 由 #e54848 → #c52424white-on-bg 对比从
3.93:1 提到 5.84:1AA 通过)。--warning / --success 本身对比足够,未动。 */
--danger: #c52424;
--btn-on-danger: #ffffff;
--warning: #d97706;
--success: #10b981;
--md-table-border: rgba(0, 0, 0, 0.08);
--md-table-stripe: rgba(0, 0, 0, 0.02);
--md-table-header-bg: rgba(0, 0, 0, 0.03);
--md-hr: rgba(0, 0, 0, 0.08);
--md-heading: var(--fg-primary);
/* 文字版语义色(与 dark 段对应注释。light 底 fg-primary 偏黑,
用 70% 装饰色让色相仍清晰,但比纯色温和:避免红字"扎眼"、橙字"泛酸"。 */
--warning-text: color-mix(in srgb, var(--warning) 70%, var(--fg-primary));
--danger-text: color-mix(in srgb, var(--danger) 70%, var(--fg-primary));
--accent-text: color-mix(in srgb, var(--accent) 70%, var(--fg-primary));
}
/* ===========================================================================
Palette overrides —— 每个块只覆盖该 palette 个性化的 token
=========================================================================== */
/* ---------- Default (Linear 风格:近黑中性底 + indigo) ----------
兜底body 上没有 data-theme-palette 时也应用 default兼容未挂属性场景。 */
body:not([data-theme-palette]),
[data-theme-palette="default"][data-theme="dark"] {
--bg-app: #08090a;
--bg-toolbar: rgba(8, 9, 10, 0.85);
--bg-sidebar: rgba(255, 255, 255, 0.022);
--bg-viewer: #08090a;
--bg-elevated: #16171a;
--bg-card: #101113;
--bg-card-hover: #191a1d;
--fg-primary: #f7f8f8;
--fg-secondary: #b0b6c0;
--fg-tertiary: #8e95a1;
--fg-muted: #6c7178;
--border-default: rgba(255, 255, 255, 0.06);
/* audit fix (H4/H5)--accent 由 #7883e0 → #4f5ec7white-on-bg 对比从 3.46:1
提到 5.6:1AA 通过)。其它 indigo 调色板都是浅 accent 配深色字(--btn-on-accent
= #1a232e已经满足 AA无需调。 */
--accent: #4f5ec7;
--btn-on-accent: #ffffff;
--accent-hover: #6473d3;
--accent-soft: rgba(79, 94, 199, 0.22);
--accent-soft-hover: rgba(79, 94, 199, 0.28);
--accent-selection: rgba(79, 94, 199, 0.50);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #101113;
--md-code-text: #e6e9f1;
--md-inline-code-bg: rgba(120, 131, 224, 0.20);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
/* indigo 在近黑底只有 4.2:1链接调亮一档2026-08 进一步提亮到 ~7:1 */
--md-link: #a3aaef;
--md-link-hover: #b8bef4;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(255, 255, 255, 0.08) 50%, transparent 100%);
}
[data-theme-palette="default"][data-theme="light"] {
--bg-app: #fbfbfc;
--bg-toolbar: rgba(255, 255, 255, 0.85);
--bg-sidebar: #f4f5f8;
--bg-viewer: #fbfbfc;
--bg-elevated: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #f7f8f9;
--fg-primary: #282a30;
--fg-secondary: #525968;
--fg-tertiary: #676e7d;
--fg-muted: #767b83;
--border-default: rgba(0, 0, 0, 0.07);
--accent: #5e6ad2;
--btn-on-accent: #ffffff;
--accent-hover: #4d58bd;
--accent-soft: rgba(94, 106, 210, 0.12);
--accent-soft-hover: rgba(94, 106, 210, 0.16);
--accent-selection: rgba(94, 106, 210, 0.28);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #f4f5f8;
--md-code-text: #282a30;
--md-inline-code-bg: rgba(94, 106, 210, 0.10);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
/* light 主题的 --md-link 用比 accent 更深的色modal 卡片底色浅(#eceefa / #e2eff5 / #e6f1ea / #faeae7
直接用 accent 只剩 3.5-4.0:1不达 WCAG AA4.5:1。这里给每个 light 调色板独立加深。 */
--md-link: #4244a8;
--md-link-hover: #2f3082;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(0, 0, 0, 0.08) 50%, transparent 100%);
}
/* ---------- Ocean (深海军 + 青绿) ---------- */
[data-theme-palette="ocean"][data-theme="dark"] {
--bg-app: #0b141d;
--bg-toolbar: rgba(11, 20, 29, 0.85);
--bg-sidebar: rgba(180, 210, 235, 0.04);
--bg-viewer: #0b141d;
--bg-elevated: #131e2a;
--bg-card: #16212e;
--bg-card-hover: #1c2837;
--fg-primary: #e3ecf3;
--fg-secondary: #c4d2dc;
--fg-tertiary: #96b1c6;
--fg-muted: #6c8090;
--border-default: rgba(180, 210, 235, 0.08);
--accent: #6cc5e6;
--btn-on-accent: #1a232e;
--accent-hover: #85d2ee;
--accent-soft: rgba(108, 197, 230, 0.20);
--accent-soft-hover: rgba(108, 197, 230, 0.26);
--accent-selection: rgba(108, 197, 230, 0.48);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #111923;
--md-code-text: #cbd6e0;
--md-inline-code-bg: rgba(108, 197, 230, 0.18);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #85d2ee;
--md-link-hover: #9cdcf2;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(180, 210, 235, 0.08) 50%, transparent 100%);
}
[data-theme-palette="ocean"][data-theme="light"] {
--bg-app: #eef4f8;
--bg-toolbar: rgba(255, 255, 255, 0.85);
--bg-sidebar: #e5eef5;
--bg-viewer: #eef4f8;
--bg-elevated: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #eef4f8;
--fg-primary: #0f1d2a;
--fg-secondary: #34465a;
--fg-tertiary: #4f697a;
--fg-muted: #6a7d8d;
--border-default: rgba(15, 40, 70, 0.08);
--accent: #0e7da8;
--btn-on-accent: #ffffff;
--accent-hover: #0a688d;
--accent-soft: rgba(14, 125, 168, 0.12);
--accent-soft-hover: rgba(14, 125, 168, 0.16);
--accent-selection: rgba(14, 125, 168, 0.30);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #e7eef4;
--md-code-text: #0f1d2a;
--md-inline-code-bg: rgba(14, 125, 168, 0.08);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #084060;
--md-link-hover: #05304a;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(15, 40, 70, 0.08) 50%, transparent 100%);
}
/* ---------- Forest (松黑 + 翠玉) ---------- */
[data-theme-palette="forest"][data-theme="dark"] {
--bg-app: #0e1410;
--bg-toolbar: rgba(14, 20, 16, 0.85);
--bg-sidebar: rgba(180, 210, 190, 0.04);
--bg-viewer: #0e1410;
--bg-elevated: #16201a;
--bg-card: #19251e;
--bg-card-hover: #1f2d26;
--fg-primary: #e6efe8;
--fg-secondary: #c4d4ca;
--fg-tertiary: #9eb3a4;
--fg-muted: #6c7d72;
--border-default: rgba(180, 210, 190, 0.08);
--accent: #76c78d;
--btn-on-accent: #1a232e;
--accent-hover: #8dd4a3;
--accent-soft: rgba(118, 199, 141, 0.20);
--accent-soft-hover: rgba(118, 199, 141, 0.26);
--accent-selection: rgba(118, 199, 141, 0.48);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #141c16;
--md-code-text: #cad7ce;
--md-inline-code-bg: rgba(118, 199, 141, 0.18);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #8dd4a3;
--md-link-hover: #a4e0b9;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(180, 210, 190, 0.08) 50%, transparent 100%);
}
[data-theme-palette="forest"][data-theme="light"] {
--bg-app: #f0f5f1;
--bg-toolbar: rgba(255, 255, 255, 0.85);
--bg-sidebar: #e6efe9;
--bg-viewer: #f0f5f1;
--bg-elevated: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #f0f5f1;
--fg-primary: #102018;
--fg-secondary: #34483c;
--fg-tertiary: #4f6356;
--fg-muted: #6d7e73;
--border-default: rgba(20, 55, 30, 0.08);
--accent: #2c8c52;
--btn-on-accent: #000000;
--accent-hover: #227544;
--accent-soft: rgba(44, 140, 82, 0.12);
--accent-soft-hover: rgba(44, 140, 82, 0.16);
--accent-selection: rgba(44, 140, 82, 0.30);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #e8efe9;
--md-code-text: #102018;
--md-inline-code-bg: rgba(44, 140, 82, 0.08);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #1a5a30;
--md-link-hover: #0f4220;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(20, 55, 30, 0.08) 50%, transparent 100%);
}
/* ---------- Lavender (茄紫 + 粉紫) ---------- */
[data-theme-palette="lavender"][data-theme="dark"] {
--bg-app: #14101a;
--bg-toolbar: rgba(20, 16, 26, 0.85);
--bg-sidebar: rgba(200, 180, 220, 0.04);
--bg-viewer: #14101a;
--bg-elevated: #1d1726;
--bg-card: #211a2c;
--bg-card-hover: #282034;
--fg-primary: #ece6f2;
--fg-secondary: #d0c5dc;
--fg-tertiary: #a99cc0;
--fg-muted: #76688c;
--border-default: rgba(200, 180, 220, 0.08);
--accent: #c89ce8;
--btn-on-accent: #1a232e;
--accent-hover: #d4abee;
--accent-soft: rgba(200, 156, 232, 0.20);
--accent-soft-hover: rgba(200, 156, 232, 0.26);
--accent-selection: rgba(200, 156, 232, 0.48);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #1a1423;
--md-code-text: #d3cce0;
--md-inline-code-bg: rgba(200, 156, 232, 0.18);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #d4abee;
--md-link-hover: #e0baf3;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(200, 180, 220, 0.08) 50%, transparent 100%);
}
[data-theme-palette="lavender"][data-theme="light"] {
--bg-app: #f5f0fa;
--bg-toolbar: rgba(255, 255, 255, 0.85);
--bg-sidebar: #ebe4f3;
--bg-viewer: #f5f0fa;
--bg-elevated: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #f5f0fa;
--fg-primary: #1a1228;
--fg-secondary: #3d3252;
--fg-tertiary: #5d4f7a;
--fg-muted: #6c5f86;
--border-default: rgba(60, 30, 90, 0.08);
--accent: #7c3aaf;
--btn-on-accent: #ffffff;
--accent-hover: #6a2f95;
--accent-soft: rgba(124, 58, 175, 0.12);
--accent-soft-hover: rgba(124, 58, 175, 0.16);
--accent-selection: rgba(124, 58, 175, 0.30);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #ebe2f2;
--md-code-text: #1a1228;
--md-inline-code-bg: rgba(124, 58, 175, 0.08);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #5e1f8a;
--md-link-hover: #421560;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(60, 30, 90, 0.08) 50%, transparent 100%);
}
/* ---------- Sunset (酒红 + 桃粉) ---------- */
[data-theme-palette="sunset"][data-theme="dark"] {
--bg-app: #1a0e14;
--bg-toolbar: rgba(26, 14, 20, 0.85);
--bg-sidebar: rgba(220, 170, 180, 0.04);
--bg-viewer: #1a0e14;
--bg-elevated: #261520;
--bg-card: #2c1a26;
--bg-card-hover: #34212e;
--fg-primary: #f4e6ea;
--fg-secondary: #d8c5cc;
--fg-tertiary: #b598a8;
--fg-muted: #806878;
--border-default: rgba(220, 170, 180, 0.08);
--accent: #ffa091;
--btn-on-accent: #1a232e;
--accent-hover: #ffb1a4;
--accent-soft: rgba(255, 160, 145, 0.20);
--accent-soft-hover: rgba(255, 160, 145, 0.26);
--accent-selection: rgba(255, 160, 145, 0.48);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #20131a;
--md-code-text: #dccdd2;
--md-inline-code-bg: rgba(255, 160, 145, 0.18);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #ffb1a4;
--md-link-hover: #ffc2b6;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(220, 170, 180, 0.08) 50%, transparent 100%);
}
[data-theme-palette="sunset"][data-theme="light"] {
--bg-app: #fbf2ee;
--bg-toolbar: rgba(255, 255, 255, 0.85);
--bg-sidebar: #f3e6e1;
--bg-viewer: #fbf2ee;
--bg-elevated: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #fbf2ee;
--fg-primary: #2a121a;
--fg-secondary: #48303a;
--fg-tertiary: #6b4d58;
--fg-muted: #7b636c;
--border-default: rgba(80, 30, 40, 0.08);
--accent: #d94f3a;
--btn-on-accent: #000000;
--accent-hover: #bf3f2d;
--accent-soft: rgba(217, 79, 58, 0.12);
--accent-soft-hover: rgba(217, 79, 58, 0.16);
--accent-selection: rgba(217, 79, 58, 0.30);
--shadow-glow: 0 0 0 3px var(--accent-soft);
--md-code-bg: #f1e3dd;
--md-code-text: #2a121a;
--md-inline-code-bg: rgba(217, 79, 58, 0.08);
--md-blockquote-border: var(--accent);
--md-blockquote-bg: var(--accent-soft);
--md-link: #8e1f10;
--md-link-hover: #621208;
--toolbar-divider: linear-gradient(90deg,
transparent 0%, rgba(80, 30, 40, 0.08) 50%, transparent 100%);
}