feat(ui): refresh dashboard and paper boat branding

This commit is contained in:
WangShen007 committed 2026-10-22 17:44:36 +08:00
1 parent 308332eb94
commit 1752a5b685
93 files changed
+11134 -7543

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 131 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#E3EADD"/><g transform="translate(9 18) scale(1.28)"><path d="M29 20 39 6 42 21Z" fill="#568B73"/><path d="M4 16 32 26 23 43H15Z" fill="#2E6A5C"/><path d="M35 26 60 16 49 43H27Z" fill="#8BB49C"/></g></svg>

After

Width:  |  Height:  |  Size: 305 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#E3EADD"/><path d="M18 25 47 34V77L18 66Z" fill="#2E6A5C"/><path d="M53 34 82 25V66L53 77Z" fill="#8BB49C"/><path d="M23 20 47 29V36L23 27Z" fill="#F8F4E9"/><path d="M53 29 77 20V27L53 36Z" fill="#FFFDF6"/></svg>

After

Width:  |  Height:  |  Size: 312 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#F2E6DC"/><path d="M19 36 31 24 47 24 50 33 53 24H69L81 36V50L50 78 19 50Z" fill="#B45132"/><path d="M50 33 69 24 81 36V50L50 78Z" fill="#D68C65"/></svg>

After

Width:  |  Height:  |  Size: 253 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#E3EADD"/><path d="M23 48H77V78H23Z" fill="#8BB49C"/><path d="M16 48 50 20 84 48Z" fill="#2E6A5C"/><path d="M50 20 84 48H50Z" fill="#568B73"/><path d="M43 58H57V78H43Z" fill="#F4F1EB"/></svg>

After

Width:  |  Height:  |  Size: 291 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#233E36"/><g transform="translate(9 18) scale(1.28)"><path d="M29 20 39 6 42 21Z" fill="#F4F1EB"/><path d="M4 16 32 26 23 43H15Z" fill="#DCE8DC"/><path d="M35 26 60 16 49 43H27Z" fill="#8BB49C"/></g></svg>

After

Width:  |  Height:  |  Size: 305 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#F2E8DC"/><path d="M51 15 77 43 51 72 25 43Z" fill="#D5AE68"/><path d="M51 15V72L25 43Z" fill="#B45132"/><path d="M51 72 48 81 55 87" fill="none" stroke="#8A6326" stroke-width="3" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 310 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#E8EBDC"/><path d="M25 76C15 40 36 19 78 22 80 60 59 81 25 76Z" fill="#8BB49C"/><path d="M25 76C15 40 36 19 78 22Z" fill="#2E6A5C"/></svg>

After

Width:  |  Height:  |  Size: 238 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#F1E8D9"/><path d="M20 31H80V71H20Z" fill="#D6B47C"/><path d="M20 71 50 45 80 71Z" fill="#ECD7AE"/><path d="M20 31 50 55 80 31Z" fill="#2E6A5C"/></svg>

After

Width:  |  Height:  |  Size: 251 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#F0E6D8"/><path d="M50 50 26 21 53 29Z" fill="#B45132"/><path d="M50 50 79 26 71 53Z" fill="#D5AE68"/><path d="M50 50 74 79 47 71Z" fill="#8BB49C"/><path d="M50 50 21 74 29 47Z" fill="#2E6A5C"/><circle cx="50" cy="50" r="4" fill="#F4F1EB"/></svg>

After

Width:  |  Height:  |  Size: 346 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="#E5ECE4"/><path d="M17 43 83 22 57 79 45 54Z" fill="#8BB49C"/><path d="M17 43 45 54 83 22Z" fill="#2E6A5C"/><path d="M45 54 57 79 55 48 83 22Z" fill="#568B73"/></svg>

After

Width:  |  Height:  |  Size: 266 B

+16 -12
View File
@@ -29,21 +29,30 @@ html, body {
body {
line-height: 1.6;
font-family: var(--font-sans);
font-size: 15px;
font-size: 14px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Display headings */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-display);
font-weight: var(--font-weight-bold);
/* Headings — 墨与瓷 sets them in the serif face; the smallest two stay sans
because they sit inside dense UI where a serif reads as a mistake. */
h1, h2, h3, h4 {
font-family: var(--font-serif);
font-weight: 600;
letter-spacing: var(--tracking-display);
color: var(--text);
line-height: 1.2;
}
h5, h6 {
font-family: var(--font-sans);
font-weight: 600;
letter-spacing: 0;
color: var(--text);
line-height: 1.3;
}
/* Inputs inherit font */
input, textarea, select, button {
font-family: var(--font-sans);
@@ -56,13 +65,8 @@ input::placeholder, textarea::placeholder {
/* Text selection */
::selection {
background: #C9F24E;
color: #0B0C10;
}
[data-theme="light"] ::selection {
background: #4C7A0B;
color: #ffffff;
background: var(--vermilion);
color: var(--seal-fg);
}
/* Scrollbars */
+1 -6
View File
@@ -1,6 +1 @@
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="20" y="20" width="80" height="80" rx="22" fill="#C9F24E"/>
<circle cx="42" cy="60" r="6" fill="#0B0C10"/>
<circle cx="60" cy="60" r="6" fill="#0B0C10"/>
<circle cx="78" cy="60" r="6" fill="#0B0C10"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 48" fill="none"><path d="M29 20 39 6 42 21Z" fill="#568B73"/><path d="M4 16 32 26 23 43H15Z" fill="#2E6A5C"/><path d="M35 26 60 16 49 43H27Z" fill="#8BB49C"/></svg>

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 221 B

+82 -17
View File
@@ -14,41 +14,106 @@
body {
min-height: 100vh;
color: var(--text-color);
background: var(--background-color);
background: var(--paper);
line-height: 1.6;
font-family: var(--font-family);
font-size: var(--text-base);
text-rendering: optimizeLegibility;
font-family: var(--font-sans);
font-size: 14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'ss01', 'cv11';
transition: background-color var(--t-med), color var(--t-med);
}
/* Paper grain — the texture that keeps the warm surfaces from looking flat */
body::after {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
opacity: var(--grain-opacity);
mix-blend-mode: var(--grain-blend);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
::selection {
background: var(--vermilion);
color: var(--seal-fg);
}
/* Typography */
h1, h2, h3, h4, h5, h6 {
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
line-height: 1.2;
}
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }
h5 { font-size: var(--text-lg); }
h6 { font-size: var(--text-base); }
h1 {
font-size: var(--text-4xl);
}
h2 {
font-size: var(--text-3xl);
}
h3 {
font-size: var(--text-2xl);
}
h4 {
font-size: var(--text-xl);
}
h5 {
font-size: var(--text-lg);
}
h6 {
font-size: var(--text-base);
}
/* Links */
a {
color: var(--primary-color);
color: inherit;
text-decoration: none;
transition: var(--transition-fast);
}
a:hover {
opacity: 0.8;
/* Scrollbars — hairlines, not gutters */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-thumb {
background: var(--line-2);
border-radius: 10px;
border: 3px solid transparent;
background-clip: padding-box;
}
::-webkit-scrollbar-track {
background: transparent;
}
/* Focus Styles */
:focus-visible {
outline: 2px solid var(--primary-color);
outline-offset: 2px;
}
outline: none;
box-shadow: var(--ring);
border-radius: var(--radius-sm);
}
/* Helpers shared by every surface */
.num {
font-family: var(--font-num);
font-variant-numeric: lining-nums tabular-nums;
font-optical-sizing: auto;
}
.mono {
font-family: var(--font-mono);
font-size: 0.92em;
letter-spacing: -0.01em;
}
.serif {
font-family: var(--font-serif);
}
.muted {
color: var(--muted);
}
File diff suppressed because it is too large. Load diff
+266 -203
View File
@@ -1,49 +1,135 @@
/* ChatterMate Design Tokens — dark-first, lime accent */
:root {
/* ReplyPier Design Tokens — 墨与瓷 (ink & porcelain)
*
* Light = 瓷 (porcelain, default), Dark = 夜墨 (night ink).
* One accent with meaning: 朱 vermilion = brand + needs attention.
* 青 celadon = AI, 金 brass = ratings, 黛 indigo = info. Primary action = ink.
*
* The lower half of :root maps the legacy token names onto this palette so the
* existing components keep working without a per-file rewrite.
*/
:root,
[data-theme='light'] {
/* ── Surfaces ─────────────────────────────────────── */
--paper: #f4f1eb; /* app background */
--paper-2: #ece8e0; /* sidebar, recessed wells */
--surface: #fffefb; /* cards, panels */
--surface-2: #f9f7f2; /* subtle fills inside cards */
--surface-sunk: #efebe4; /* inputs on surface, tracks */
/* ── Ink scale ────────────────────────────────────── */
--ink: #16171a;
--ink-2: #33343a;
--ink-muted: #6a665f; /* AA 5.0:1 on paper */
--ink-faint: #9a958c; /* decorative / placeholder only */
/* ── Hairlines ────────────────────────────────────── */
--line: rgba(22, 23, 26, 0.08);
--line-2: rgba(22, 23, 26, 0.14);
--line-3: rgba(22, 23, 26, 0.22);
/* ── Meaningful colour ────────────────────────────── */
--vermilion: #b23a22; /* 朱 — brand, waiting, unread, destructive */
--celadon: #2e6a5c; /* 青 — AI, online, success */
--brass: #8a6326; /* 金 — ratings, premium */
--indigo: #3a4b7c; /* 黛 — info, links */
--vermilion-soft: color-mix(in srgb, var(--vermilion) 8%, transparent);
--vermilion-line: color-mix(in srgb, var(--vermilion) 26%, transparent);
--celadon-soft: color-mix(in srgb, var(--celadon) 8%, transparent);
--celadon-line: color-mix(in srgb, var(--celadon) 24%, transparent);
--brass-soft: color-mix(in srgb, var(--brass) 10%, transparent);
--brass-line: color-mix(in srgb, var(--brass) 28%, transparent);
--indigo-soft: color-mix(in srgb, var(--indigo) 8%, transparent);
--indigo-line: color-mix(in srgb, var(--indigo) 24%, transparent);
/* ── Actions ──────────────────────────────────────── */
--primary-bg: var(--ink);
--primary-fg: #f7f4ee;
--primary-hover: #2a2b30;
--seal-fg: #fbf6ee;
/* ── Message bubbles ──────────────────────────────── */
--bubble-visitor: var(--surface);
--bubble-ai: color-mix(in srgb, var(--celadon) 6%, var(--surface));
--bubble-human: var(--ink);
--bubble-human-fg: #f3efe7;
/* ── Elevation — paper-like, low and warm ─────────── */
--elev-1: 0 1px 0 rgba(22, 23, 26, 0.03), 0 1px 2px rgba(22, 23, 26, 0.05);
--elev-2: 0 1px 0 rgba(22, 23, 26, 0.03), 0 10px 30px -12px rgba(40, 30, 15, 0.14);
--elev-3: 0 30px 80px -24px rgba(40, 30, 15, 0.28);
--ring: 0 0 0 3px color-mix(in srgb, var(--ink) 12%, transparent);
/* ── Type ─────────────────────────────────────────── */
--font-serif: 'Noto Serif SC', 'Songti SC', 'STSong', serif;
--font-num: 'Fraunces', 'Noto Serif SC', Georgia, serif;
--font-sans-cn: 'Hanken Grotesk', 'PingFang SC', 'Hiragino Sans GB', 'Noto Sans SC',
'Microsoft YaHei', sans-serif;
--font-mono-cn: 'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;
/* ── Motion ───────────────────────────────────────── */
--ease: cubic-bezier(0.2, 0.7, 0.1, 1);
--t-fast: 0.16s var(--ease);
--t-med: 0.28s var(--ease);
/* ── Chart series (validated categorical pair, both modes) ── */
--viz-1: #00876c; /* AI */
--viz-2: #b5650c; /* 人工 */
--viz-grid: rgba(22, 23, 26, 0.07);
--viz-axis: #8b867d;
/* ── Grain overlay ────────────────────────────────── */
--grain-opacity: 0.045;
--grain-blend: multiply;
color-scheme: light;
/* ══════════════════════════════════════════════════════
Legacy token layer — same names, 墨与瓷 values.
══════════════════════════════════════════════════════ */
/* Surfaces */
--bg: #0B0C10;
--bg2: #0E0F14;
--surface: #13151C;
--topbar: rgba(11,12,16,.8);
--bg: var(--paper);
--bg2: var(--surface);
--topbar: color-mix(in srgb, var(--paper) 88%, transparent);
--bg-elevated: var(--surface);
--bg-deep: var(--paper-2);
--scrim: rgba(22, 23, 26, 0.4);
--header-gradient: linear-gradient(180deg, var(--paper), var(--paper));
/* Accent */
--accent-ink: #C9F24E; /* accent for text / borders / icons (darkens in light mode) */
--accent-solid: #C9F24E; /* accent for FILLED surfaces (stays lime in both themes) */
--on-accent-solid: #0B0C10; /* text/icon on --accent-solid (dark in both themes) */
--c-lime: #C9F24E;
--c-teal: #5FE3D6;
--c-purple: #9D8CFF;
--c-coral: #FF8A73;
/* Accent — the single primary action colour is ink */
--accent-ink: var(--ink);
--accent-solid: var(--ink);
--on-accent-solid: var(--primary-fg);
--c-lime: var(--vermilion);
--c-teal: var(--celadon);
--c-purple: var(--indigo);
--c-coral: var(--vermilion);
/* Contrast inks — text/icon placed on top of a fill */
--on-accent: #0B0C10; /* on lime accent */
--on-light: #0B0C10; /* on any light fill */
--on-dark: #F5F6F8; /* on any dark/coloured fill (theme-invariant) */
/* Elevated surfaces / header gradient */
--bg-elevated: #101119;
--bg-deep: #0A0B0E;
--header-gradient: linear-gradient(180deg, var(--bg-elevated), var(--bg));
--scrim: rgba(6,7,10,.72);
/* Contrast inks */
--on-accent: var(--primary-fg);
--on-light: var(--ink);
--on-dark: #f5f6f8;
/* Mode pills (agent editor) */
--mode-ai-bg: #3B82F6;
--mode-ai-fg: #FFFFFF;
--mode-wf-bg: #9D8CFF;
--mode-wf-fg: #0B0C10;
--mode-ai-bg: var(--celadon);
--mode-ai-fg: #f2faf6;
--mode-wf-bg: var(--indigo);
--mode-wf-fg: #f4f6fb;
--pill-idle-bg: var(--o05);
--pill-idle-fg: var(--muted);
/* Extended status / chart palette */
--c-danger: #FF6B6B;
--c-warn: #E6A23C;
--c-info: #8FB8FF;
--c-positive: #7CE38B;
--c-neutral: #8A93A3;
--c-online: #8FEDE3; /* online label text */
--c-pro: #C5BDFF; /* PRO badge text */
/* Status / chart palette */
--c-danger: var(--vermilion);
--c-warn: var(--brass);
--c-info: var(--indigo);
--c-positive: var(--celadon);
--c-neutral: var(--ink-muted);
--c-online: var(--celadon);
--c-pro: var(--brass);
/* Theme-aware tints (derived from base palette, auto-adjust per theme) */
/* Theme-aware tints */
--accent-bg-06: color-mix(in srgb, var(--accent-ink) 6%, transparent);
--accent-bg-08: color-mix(in srgb, var(--accent-ink) 8%, transparent);
--accent-bg-12: color-mix(in srgb, var(--accent-ink) 12%, transparent);
@@ -51,72 +137,73 @@
--teal-bg-10: color-mix(in srgb, var(--c-teal) 10%, transparent);
--teal-bg: color-mix(in srgb, var(--c-teal) 12%, transparent);
--teal-border: color-mix(in srgb, var(--c-teal) 22%, transparent);
--purple-bg: color-mix(in srgb, var(--c-purple) 15%, transparent);
--purple-border: color-mix(in srgb, var(--c-purple) 28%, transparent);
--purple-bg: color-mix(in srgb, var(--c-purple) 12%, transparent);
--purple-border: color-mix(in srgb, var(--c-purple) 26%, transparent);
--coral-bg: color-mix(in srgb, var(--c-coral) 12%, transparent);
--coral-border: color-mix(in srgb, var(--c-coral) 30%, transparent);
/* Controls */
--toggle-knob: #FFFFFF;
--toggle-knob: #ffffff;
--toggle-track-off: var(--o12);
--toggle-on-teal: var(--c-teal);
--toggle-on-accent: var(--accent-ink);
/* Inbox message bubbles */
--bubble-customer-bg: var(--o05);
--bubble-customer-bg: var(--surface-2);
--bubble-customer-fg: var(--text2);
--bubble-ai-bg: var(--teal-bg-10);
--bubble-ai-border: var(--teal-border);
--bubble-ai-bg: var(--bubble-ai);
--bubble-ai-border: var(--celadon-line);
--bubble-ai-fg: var(--text2);
--bubble-agent-bg: var(--accent-ink);
--bubble-agent-fg: var(--on-accent);
--bubble-agent-bg: var(--bubble-human);
--bubble-agent-fg: var(--bubble-human-fg);
/* Brand gradients / avatars */
--grad-purple-teal: linear-gradient(135deg, var(--c-purple), var(--c-teal));
--grad-lime-teal: linear-gradient(135deg, var(--accent-ink), var(--c-teal));
--grad-generate: linear-gradient(135deg, var(--c-purple), #7C6AE6);
--grad-purple-teal: linear-gradient(135deg, var(--indigo), var(--celadon));
--grad-lime-teal: linear-gradient(135deg, var(--ink), var(--celadon));
--grad-generate: linear-gradient(135deg, var(--indigo), color-mix(in srgb, var(--indigo) 70%, var(--ink)));
/* Text scale */
--text: #F5F6F8;
--text2: #E7EAF0;
--text3: #C7CCD6;
--muted: #9CA3B0;
/* Small text on every surface (down to #1A1C23) must reach WCAG AA 4.5:1. */
--muted2: #868D9C;
--faint: #7F8696;
--code: #D7DBE3;
--text: var(--ink);
--text2: var(--ink-2);
--text3: color-mix(in srgb, var(--ink) 82%, var(--paper));
--muted: var(--ink-muted);
--muted2: color-mix(in srgb, var(--ink-muted) 82%, var(--paper));
--faint: var(--ink-faint);
--code: var(--ink-2);
/* White-opacity tokens — borders, dividers, overlays */
--o03: rgba(255,255,255,.03);
--o04: rgba(255,255,255,.04);
--o05: rgba(255,255,255,.05);
--o06: rgba(255,255,255,.06);
--o07: rgba(255,255,255,.07);
--o08: rgba(255,255,255,.08);
--o10: rgba(255,255,255,.1);
--o12: rgba(255,255,255,.12);
--o14: rgba(255,255,255,.14);
--o16: rgba(255,255,255,.16);
--o20: rgba(255,255,255,.2);
--o25: rgba(255,255,255,.25);
--o30: rgba(255,255,255,.3);
/* White-opacity tokens → ink-opacity tokens (they are borders/overlays) */
--o03: color-mix(in srgb, var(--ink) 3%, transparent);
--o04: color-mix(in srgb, var(--ink) 4%, transparent);
--o05: color-mix(in srgb, var(--ink) 5%, transparent);
--o06: color-mix(in srgb, var(--ink) 6%, transparent);
--o07: color-mix(in srgb, var(--ink) 7.5%, transparent);
--o08: color-mix(in srgb, var(--ink) 8%, transparent);
--o10: color-mix(in srgb, var(--ink) 10%, transparent);
--o12: color-mix(in srgb, var(--ink) 12%, transparent);
--o14: color-mix(in srgb, var(--ink) 14%, transparent);
--o16: color-mix(in srgb, var(--ink) 16%, transparent);
--o20: color-mix(in srgb, var(--ink) 20%, transparent);
--o25: color-mix(in srgb, var(--ink) 25%, transparent);
--o30: color-mix(in srgb, var(--ink) 30%, transparent);
/* Semantic */
--success-color: #0f9d6e;
--error-color: #DC2626;
--error-dark: #b91c1c;
--warning-color: #D97706;
--info-color: #2563EB;
--success-bg: rgba(15,157,110,.1);
--error-bg: rgba(220,38,38,.1);
--warning-bg: rgba(217,119,6,.1);
--info-bg: rgba(37,99,235,.1);
--success-color: var(--celadon);
--error-color: var(--vermilion);
--error-dark: #8f2c18;
--warning-color: var(--brass);
--info-color: var(--indigo);
--success-bg: var(--celadon-soft);
--error-bg: var(--vermilion-soft);
--warning-bg: var(--brass-soft);
--info-bg: var(--indigo-soft);
/* Fonts */
--font-family: 'Instrument Sans', system-ui, -apple-system, sans-serif;
--font-sans: 'Instrument Sans', system-ui, -apple-system, sans-serif;
--font-display: 'Space Grotesk', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--font-family: var(--font-sans-cn);
--font-sans: var(--font-sans-cn);
/* Legacy alias: 121 call sites use it for headings *and* small labels, so it
stays sans. Titles that should be serif use --font-serif explicitly. */
--font-display: var(--font-sans-cn);
--font-mono: var(--font-mono-cn);
/* Font weights */
--font-weight-normal: 400;
@@ -125,7 +212,7 @@
--font-weight-bold: 700;
/* Letter spacing */
--tracking-display: -0.02em;
--tracking-display: 0.02em;
--tracking-tight: -0.01em;
--tracking-wide: 0.04em;
@@ -149,34 +236,35 @@
--space-3xl: 4rem;
/* Border radius */
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 16px;
--radius-sm: 7px;
--radius-md: 10px;
--radius-lg: 14px;
--radius-full: 9999px;
/* Design-spec radii */
--radius-chip: 10px;
--radius-btn: 11px;
--radius-input: 12px;
--radius-card: 18px;
--radius-chip: 8px;
--radius-btn: 10px;
--radius-input: 10px;
--radius-card: 14px;
--radius-card-lg: 20px;
--radius-pill: 999px;
--radius-xl: 20px;
/* Transitions */
--transition-fast: 0.18s cubic-bezier(0.4,0,0.2,1);
--transition-normal: 0.25s cubic-bezier(0.4,0,0.2,1);
--transition-slow: 0.4s cubic-bezier(0.4,0,0.2,1);
--transition-fast: var(--t-fast);
--transition-normal: var(--t-med);
--transition-slow: 0.4s var(--ease);
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0,0,0,.15);
--shadow-md: 0 4px 12px rgba(0,0,0,.2);
--shadow-lg: 0 20px 50px rgba(0,0,0,.5);
--shadow-sm: var(--elev-1);
--shadow-md: var(--elev-2);
--shadow-lg: var(--elev-3);
/* Focus ring */
--ring-focus: 0 0 0 3px rgba(201,242,78,.15);
--ring-focus: var(--ring);
/* Icon filters (for SVG img elements on dark bg) */
--icon-filter: brightness(0) invert(1);
--icon-opacity: 0.5;
/* Icon filters (for SVG img elements) */
--icon-filter: brightness(1);
--icon-opacity: 0.55;
--icon-active-opacity: 0.9;
/* Mobile app shell */
@@ -187,15 +275,14 @@
/* Overlay stacking order — every fixed overlay must use one of these */
--z-topbar: 50;
--z-bottom-nav: 900;
--z-drawer: 1000; /* notification drawer, sidebar overlay */
--z-fullscreen-page: 1050; /* mobile chat-info "Details" page */
--z-prompt: 1090; /* push/install prompts */
--z-sheet: 1100; /* More bottom sheet */
--z-support-chat: 1150; /* hosted support chat drawer (read from JS) */
--z-drawer: 1000;
--z-fullscreen-page: 1050;
--z-prompt: 1090;
--z-sheet: 1100;
--z-support-chat: 1150;
--z-modal: 2000;
/* Breakpoints — keep in sync with useBreakpoint.ts (JS can't read these
at media-query time: --breakpoint-sm = MOBILE, --breakpoint-md = TABLET) */
/* Breakpoints — keep in sync with useBreakpoint.ts */
--breakpoint-xs: 480px;
--breakpoint-sm: 768px;
--breakpoint-md: 1024px;
@@ -206,7 +293,7 @@
/* Legacy aliases (keep for component compatibility) */
--primary-color: var(--accent-ink);
--primary-dark: #b3d943;
--primary-dark: var(--ink-2);
--background-color: var(--bg);
--background-base: var(--surface);
--background-soft: var(--bg2);
@@ -221,120 +308,96 @@
--text-muted: var(--muted);
--text-placeholder: var(--faint);
--code-bg: var(--surface);
--primary-soft: rgba(201,242,78,.1);
--primary-soft: var(--accent-bg-08);
/* Legacy aliases used by the agent editor (resolve via flipping tokens) */
/* Legacy aliases used by the agent editor */
--accent-color: var(--accent-ink);
--background-alt: var(--bg2);
--background-muted: var(--o05);
--radius-xl: 20px;
--success: var(--success-color);
--success-dark: var(--success-color);
--success-light: color-mix(in srgb, var(--success-color) 14%, transparent);
--success-color-soft: color-mix(in srgb, var(--success-color) 12%, transparent);
--success-dark: var(--celadon);
--success-light: var(--success-bg);
--success-color-soft: var(--success-bg);
--warning: var(--warning-color);
--warning-light: color-mix(in srgb, var(--warning-color) 14%, transparent);
--error-light: var(--coral-bg);
--error-soft: var(--coral-bg);
--error-color-soft: var(--coral-bg);
--warning-light: var(--warning-bg);
--error-light: var(--error-bg);
--error-soft: var(--error-bg);
--error-color-soft: var(--error-bg);
--primary-color-filter: none;
}
/* Light theme override */
[data-theme="light"] {
--bg: #EEF0F4;
--bg2: #FFFFFF;
--surface: #FFFFFF;
--topbar: rgba(255,255,255,.85);
/* ── 夜墨 ─────────────────────────────────────────────── */
[data-theme='dark'] {
--paper: #121211;
--paper-2: #0c0c0b;
--surface: #1a1917;
--surface-2: #201f1c;
--surface-sunk: #151413;
/* Accent and status inks are used as text on white and on their own pale
tints: darkened until they reach WCAG AA 4.5:1 on both. */
--accent-ink: #44700A;
--c-lime: #44700A;
--c-teal: #097171;
--c-purple: #6454BF;
--c-coral: #AC4829;
--warning-color: #9C5604;
--ink: #ede7dc;
--ink-2: #cfc8bc;
--ink-muted: #a09a8f;
--ink-faint: #6f6a62;
--text: #171A21;
--text2: #222732;
--text3: #3C424E;
--muted: #5C6473;
/* Small text on every surface (down to #EEF0F4) must reach WCAG AA 4.5:1. */
--muted2: #626977;
--faint: #646B79;
--code: #3C424E;
--line: rgba(237, 231, 220, 0.08);
--line-2: rgba(237, 231, 220, 0.14);
--line-3: rgba(237, 231, 220, 0.22);
--o03: rgba(17,21,30,.03);
--o04: rgba(17,21,30,.04);
--o05: rgba(17,21,30,.05);
--o06: rgba(17,21,30,.06);
--o07: rgba(17,21,30,.075);
--o08: rgba(17,21,30,.08);
--o10: rgba(17,21,30,.09);
--o12: rgba(17,21,30,.1);
--o14: rgba(17,21,30,.11);
--o16: rgba(17,21,30,.12);
--o20: rgba(17,21,30,.14);
--o25: rgba(17,21,30,.18);
--o30: rgba(17,21,30,.2);
--vermilion: #e2603f;
--celadon: #74b9a6;
--brass: #d3aa62;
--indigo: #9aabdd;
/* Icon filters for light theme — SVGs are already dark, no inversion needed */
--icon-filter: brightness(1);
--icon-opacity: 0.6;
--icon-active-opacity: 0.85;
--primary-bg: #ede7dc;
--primary-fg: #121211;
--primary-hover: #ffffff;
--seal-fg: #fff7ee;
--shadow-sm: 0 1px 2px rgba(17,21,30,.05);
--shadow-md: 0 4px 12px rgba(17,21,30,.08);
--shadow-lg: 0 20px 50px rgba(17,21,30,.15);
--bubble-ai: color-mix(in srgb, var(--celadon) 9%, var(--surface));
--bubble-human: #ede7dc;
--bubble-human-fg: #151413;
--ring-focus: 0 0 0 3px rgba(76,122,11,.2);
--primary-soft: rgba(76,122,11,.08);
--elev-1: 0 1px 0 rgba(0, 0, 0, 0.3);
--elev-2: 0 1px 0 rgba(255, 255, 255, 0.02) inset, 0 14px 34px -14px rgba(0, 0, 0, 0.7);
--elev-3: 0 30px 90px -20px rgba(0, 0, 0, 0.85);
--ring: 0 0 0 3px color-mix(in srgb, var(--ink) 18%, transparent);
/* Contrast inks — accent is dark-olive in light, so text on it must be white */
--on-accent: #FFFFFF;
--on-light: #0B0C10;
--on-dark: #F5F6F8;
--viz-1: #1e9e80;
--viz-2: #b97c1c;
--viz-grid: rgba(237, 231, 220, 0.07);
--viz-axis: #8d887f;
/* Elevated surfaces / scrim (gradients & tints referencing base tokens auto-recompute) */
--bg-elevated: #FFFFFF;
--bg-deep: #F4F6FA;
--scrim: rgba(17,21,30,.4);
--grain-opacity: 0.06;
--grain-blend: screen;
/* Mode pills — darker fills need light text in light theme */
--mode-ai-bg: #2563EB;
--mode-ai-fg: #FFFFFF;
--mode-wf-bg: #6D5BD0;
--mode-wf-fg: #FFFFFF;
color-scheme: dark;
/* Extended status / chart palette tuned for light bg: each reaches WCAG AA
4.5:1 as text on white and on its own pale tint. */
--c-danger: #B33F3F;
--c-warn: #8F5E18;
--c-info: #225BD8;
--c-positive: #187742;
--c-neutral: #606773;
--c-online: #097171;
--c-pro: #6454BF;
/* Legacy overrides that cannot derive from the base palette */
--on-accent: var(--primary-fg);
--on-light: #121211;
--on-dark: #f5f6f8;
/* Generate gradient — darker end stop for light */
--grad-generate: linear-gradient(135deg, var(--c-purple), #5B49C9);
--mode-ai-bg: var(--celadon);
--mode-ai-fg: #10201c;
--mode-wf-bg: var(--indigo);
--mode-wf-fg: #12151d;
/* Legacy aliases */
--primary-color: var(--accent-ink);
--primary-dark: #3d6209;
--background-color: var(--bg);
--background-base: var(--surface);
--toggle-knob: #121211;
--grad-purple-teal: linear-gradient(135deg, var(--indigo), var(--celadon));
--grad-lime-teal: linear-gradient(135deg, var(--ink), var(--celadon));
--grad-generate: linear-gradient(135deg, var(--indigo), color-mix(in srgb, var(--indigo) 70%, #ffffff));
--text3: color-mix(in srgb, var(--ink) 82%, var(--paper));
--muted2: color-mix(in srgb, var(--ink-muted) 82%, var(--paper));
--error-dark: #f08a72;
--background-soft: var(--bg2);
--background-mute: var(--o08);
--hover-bg: var(--o05);
--border-color: var(--o10);
--border-color-hover: var(--o16);
--text-primary: var(--text);
--text-secondary: var(--text3);
--text-color: var(--text);
--text-heading: var(--text);
--text-muted: var(--muted);
--text-placeholder: var(--faint);
--code-bg: var(--surface);
--header-gradient: linear-gradient(180deg, var(--paper), var(--paper));
--icon-filter: brightness(0) invert(1);
--icon-opacity: 0.5;
--icon-active-opacity: 0.9;
--primary-dark: var(--ink-2);
--success-dark: var(--celadon);
}