Files
hunjing/frontend/src/styles/globals.css
T
2026-08-21 16:00:13 +08:00

1170 lines
33 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";
@import "./features/cosmos.css";
@import "./features/chat.css";
@import "./features/characters.css";
@import "./features/memory.css";
@import "./features/time.css";
@import "./features/drive.css";
@import "./features/world.css";
@import "./features/evolution.css";
@import "./features/personality.css";
/*
* ============================================================
* 琉璃镜(Glazed Mirror)设计语言 — 三层 Token 架构
* ============================================================
*
* 三层的职责分离(per design-dna §1 token-architecture):
*
* Layer 0 — 原始色值(Raw Palette)
* --raw-* 前缀,不变的十六进制 / rgba 常量。
* 不直接用于生产,仅作为 Layer 1 的原料。
*
* Layer 1 — 语义 token(Semantic Tokens)
* --*-raw / --*-dim / --*-faint 等,按功能角色命名。
* 随亮 / 暗主题切换而变化,是组件引用层。
*
* Layer 2 — 组件 token(Component Tokens)
* 如 --btn-primary-bg / --card-surface / --pill-patina。
* 由 Layer 1 的语义 token 推导,业务组件直接使用。
*
* 色值命名规约:Descriptive name (hex) — 功能角色与约束(per finesse design-dna §1)。
*
* 目标:换主题只需改 Layer 0/Layer 1,无需逐组件调色。
* ============================================================
*/
@custom-variant dark (&:where(.dark, .dark *));
@theme inline {
/* ── 字体(Layer 1: 语义 font stack)──
* 优先使用系统字体,避免 CJK 网页字体(15MB+),
* 仅当系统无对应字体时才 fallback 到自托管/ CDN 网页字体。
* JetBrains Mono 已下载到 public/fonts/,通过 @font-face 自托管。 */
--font-serif:
"Source Han Serif SC", "Noto Serif CJK SC", "Songti SC", "STSong", serif;
--font-sans:
-apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei",
"Helvetica Neue", system-ui, sans-serif;
--font-mono: "JetBrains Mono", "SF Mono", ui-monospace, monospace;
/* Instrument Serif:英文展示衬线(Google Fonts 开源),仅 15KB */
--font-display-eng: "Instrument Serif", "Georgia", "Times New Roman", serif;
/* Space Grotesk:英文技术感无衬线(Google Fonts 开源),变量字体 22KB */
--font-sans-eng:
"Space Grotesk", "Inter", -apple-system, system-ui, sans-serif;
/* 霞鹜文楷:开源楷体中文,适合正文/文学场景 */
--font-kai: "LXGW WenKai", "Kaiti SC", "STKaiti", "KaiTi", serif;
/* 得意黑:开源现代圆体中文,适合标题/短标签 */
--font-round: "Smiley Sans", "PingFang SC", system-ui, sans-serif;
/* ── Layer 1: 语义色值 —— 运行时 CSS 变量映射 ── */
--color-surface: var(--surface);
--color-glass: var(--glass);
--color-glass-strong: var(--glass-strong);
--color-border-glass: var(--glass-border);
--color-fg: var(--fg);
--color-muted: var(--muted);
--color-jade: var(--jade);
--color-gold: var(--gold);
--color-cinnabar: var(--cinnabar);
--color-success: var(--success);
--color-info: var(--info);
--color-overlay-hover: var(--overlay-hover);
--color-overlay-active: var(--overlay-active);
--color-overlay-light: var(--overlay-light);
/* ── Layer 1: 铜镜鉴心语义色 ── */
--color-ink: var(--ink);
--color-night-bronze: var(--night-bronze);
--color-gilt: var(--gilt);
--color-patina: var(--patina);
--color-patina-bright: var(--patina-bright);
--color-fg-dim: var(--fg-dim);
--color-fg-faint: var(--fg-faint);
--color-rule: var(--rule);
--color-surface-hi: var(--surface-hi);
/* ── Layer 1: 铜镜复合色 — 晕染/描边/悬停态(高频使用) ── */
--color-patina-wash: var(--patina-wash);
--color-patina-dim: var(--patina-dim);
--color-gilt-dim: var(--gilt-dim);
--color-gilt-faint: var(--gilt-faint);
--color-cinnabar-wash: var(--cinnabar-wash);
--color-cinnabar-dim: var(--cinnabar-dim);
--color-glass: var(--glass);
--color-glass-border: var(--glass-border);
--color-overlay-hover: var(--overlay-hover);
--color-overlay-active: var(--overlay-active);
--color-bg: var(--bg);
/* ── Layer 2: 组件 token(业务组件直接引用)── */
/* Button */
--color-btn-primary-bg: var(--patina);
--color-btn-primary-text: var(--ink);
--color-btn-primary-border: var(--patina);
--color-btn-secondary-bg: var(--surface);
--color-btn-secondary-text: var(--fg);
--color-btn-secondary-border: var(--rule);
--color-btn-ghost-text: var(--muted);
--color-btn-danger-bg: var(--cinnabar);
--color-btn-danger-text: var(--ink);
--color-btn-danger-border: var(--cinnabar);
/* Pill / Badge */
--color-pill-patina-bg: var(--patina-wash);
--color-pill-patina-text: var(--patina);
--color-pill-patina-border: var(--patina-dim);
--color-pill-gilt-bg: var(--gilt-faint);
--color-pill-gilt-text: var(--gilt);
--color-pill-gilt-border: var(--gilt-dim);
--color-pill-cinnabar-bg: var(--cinnabar-wash);
--color-pill-cinnabar-text: var(--cinnabar);
--color-pill-cinnabar-border: var(--cinnabar-dim);
/* Panel / Card */
--color-panel-bg: var(--surface);
--color-panel-border: var(--rule);
--color-card-glass-bg: var(--glass);
--color-card-elevated-bg: var(--glass-strong);
/* Select / input */
--color-select-bg: var(--surface);
--color-select-border: var(--rule);
--color-select-text: var(--fg);
--color-input-bg: var(--input-bg);
--color-input-border: var(--rule);
/* Modal */
--color-modal-overlay: rgba(0, 0, 0, 0.5);
--color-modal-bg: var(--glass-strong);
--color-modal-border: var(--glass-border);
/* Tab */
--color-tab-active-text: var(--patina);
--color-tab-active-border: var(--patina);
--color-tab-inactive-text: var(--fg-faint);
--color-tab-hover-text: var(--fg-dim);
/* Toast */
--color-toast-success-bg: var(--success-wash);
--color-toast-success-text: var(--success);
--color-toast-success-border: var(--success-dim);
--color-toast-error-bg: var(--cinnabar-wash);
--color-toast-error-text: var(--cinnabar);
--color-toast-error-border: var(--cinnabar-dim);
--color-toast-warning-bg: var(--gilt-faint);
--color-toast-warning-text: var(--gilt);
--color-toast-warning-border: var(--gilt-dim);
--color-toast-info-bg: var(--patina-wash);
--color-toast-info-text: var(--patina);
--color-toast-info-border: var(--patina-dim);
/* ── 圆角缩放 ── */
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 24px;
/* ── 交互层级 ── */
--z-sticky: 20;
--z-header: 30;
--z-popover: 40;
--z-drawer: 50;
--z-modal: 60;
--z-toast: 70;
/* ── 动画曲线 ── */
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-out-quart: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
}
@layer base {
:where(a, button, input, select, textarea, [role="button"]):focus-visible {
outline: 2px solid var(--patina);
outline-offset: 2px;
}
/* ============================================================
* Layer 0: 原始色值(Raw Palette)—— 所有色值的原料
* 不随主题切换而变,仅作为 Layer 1 的参考来源。
* 实际使用时引用 Layer 1(:root / .dark 下的语义变量)。
* ============================================================ */
:root {
--raw-patina-light: #3f7d68;
--raw-patina-bright-light: #2f6450;
--raw-patina-dark: #6fa389;
--raw-patina-bright-dark: #84bb9d;
--raw-gilt-light: #8a6d28;
--raw-gilt-dark: #c9a24a;
--raw-cinnabar-light: #a8342a;
--raw-cinnabar-dark: #b8392e;
--raw-ink-light: #e7e1d0;
--raw-ink-dark: #0c0e0d;
}
/* ── Layer 1: 亮色 · 素绢底 ── */
:root {
color-scheme: light;
/* Layer 1: 语义色值 */
--bg: #ece8dc;
--surface: #f4f1e8;
--glass: rgba(255, 255, 255, 0.55);
--glass-strong: rgba(255, 255, 255, 0.72);
--glass-border: rgba(30, 40, 33, 0.1);
--fg: #1c2420;
--muted: #6b746e;
--jade: #3f7d72;
--gold: #9a7d3e;
--cinnabar: #a8392c;
--success: #4a8c6f; /* 碧玉 — Green Jadeite */
--success-dim: rgba(74, 140, 111, 0.3);
--success-wash: rgba(74, 140, 111, 0.08);
--info: #3f7d72; /* 复用铜绿 = jade */
--overlay-hover: rgba(0, 0, 0, 0.04);
--overlay-active: rgba(0, 0, 0, 0.08);
--overlay-light: rgba(255, 255, 255, 0.08);
--input-bg: rgba(255, 248, 235, 0.5);
--aurora-1: rgba(63, 125, 114, 0.22);
--aurora-2: rgba(154, 125, 62, 0.18);
--aurora-3: rgba(168, 57, 44, 0.1);
/* Layer 1: 铜镜鉴心语义色 */
--ink: #e7e1d0; /* 素绢暖纸底 */
--night-bronze: #ddd4c0; /* 夜铜暗面带铜温 */
--surface-hi: rgba(255, 255, 255, 0.74);
--gilt: #8a6d28; /* 鎏金 — 结构 / 发丝线 / 标签 */
--gilt-dim: rgba(138, 109, 40, 0.36);
--gilt-faint: rgba(138, 109, 40, 0.16);
--patina: #3f7d68; /* 铜绿锈 — 主色:在场 / 健康 / 记忆 */
--patina-bright: #2f6450;
--patina-dim: rgba(63, 125, 104, 0.3);
--patina-wash: rgba(63, 125, 104, 0.05);
--cinnabar-dim: rgba(168, 52, 42, 0.4);
--cinnabar-wash: rgba(168, 52, 42, 0.06);
--fg-dim: #5f594d; /* 次要正文 */
--fg-faint: #948f82; /* 极淡占位 / mono 副标 */
--rule: rgba(138, 109, 40, 0.22); /* 发丝线 */
/* Layer 1: 光照效果(镜面色泽) */
--sweep-gradient: linear-gradient(
130deg,
transparent 0%,
transparent 24%,
rgba(200, 170, 130, 0.06) 30%,
rgba(255, 248, 235, 0.18) 36%,
rgba(200, 170, 130, 0.1) 44%,
transparent 52%,
transparent 100%
);
--face-sheen: linear-gradient(
165deg,
rgba(255, 255, 255, 0.7),
rgba(255, 255, 255, 0.34) 42%,
rgba(120, 105, 75, 0.08)
);
--face-in-top: rgba(255, 255, 255, 0.7);
--face-in-bot: rgba(120, 100, 60, 0.1);
--shadow: 0 1px 2px rgba(60, 50, 30, 0.08);
/* 代码铭版(恒为深底,不随 .dark 切换) */
--code-ink: #0d1117;
--code-edge: rgba(201, 162, 74, 0.22);
--code-rule: rgba(201, 162, 74, 0.18);
--code-label: rgba(201, 162, 74, 0.62);
--code-label-dim: rgba(201, 162, 74, 0.5);
--code-label-hi: #d4b25a;
}
/* ── Layer 1: 暗色 · 墨夜底 ── */
.dark {
color-scheme: dark;
--bg: #0b0f0e;
--surface: #121817;
--glass: rgba(255, 255, 255, 0.045);
--glass-strong: rgba(255, 255, 255, 0.08);
--glass-border: rgba(255, 255, 255, 0.1);
--fg: #e6e2d6;
--muted: #8a9389;
--jade: #5fa192;
--gold: #c6a664;
--cinnabar: #b5402f;
--success: #6abf8e;
--success-dim: rgba(106, 191, 142, 0.3);
--success-wash: rgba(106, 191, 142, 0.08);
--info: #5fa192;
--overlay-hover: rgba(255, 255, 255, 0.05);
--overlay-active: rgba(255, 255, 255, 0.1);
--overlay-light: rgba(255, 255, 255, 0.03);
--input-bg: rgba(0, 0, 0, 0.3);
--aurora-1: rgba(95, 161, 146, 0.2);
--aurora-2: rgba(198, 166, 100, 0.16);
--aurora-3: rgba(42, 74, 71, 0.3);
/* Layer 1: 铜镜鉴心语义色(暗色) */
--ink: #0c0e0d;
--night-bronze: #14110d;
--surface-hi: rgba(255, 255, 255, 0.08);
--gilt: #c9a24a;
--gilt-dim: rgba(201, 162, 74, 0.32);
--gilt-faint: rgba(201, 162, 74, 0.14);
--patina: #6fa389;
--patina-bright: #84bb9d;
--patina-dim: rgba(111, 163, 137, 0.34);
--patina-wash: rgba(111, 163, 137, 0.06);
--cinnabar-dim: rgba(184, 57, 46, 0.4);
--cinnabar-wash: rgba(184, 57, 46, 0.08);
--fg-dim: #9b958a;
--fg-faint: #5e5a52;
--rule: rgba(201, 162, 74, 0.16);
/* Layer 1: 光照效果(暗色) */
--sweep-gradient: linear-gradient(
130deg,
transparent 0%,
transparent 28%,
rgba(201, 162, 74, 0.025) 34%,
rgba(255, 255, 255, 0.06) 40%,
rgba(201, 162, 74, 0.025) 48%,
transparent 55%,
transparent 100%
);
--face-sheen: linear-gradient(
165deg,
rgba(255, 255, 255, 0.09),
rgba(255, 255, 255, 0.02) 42%,
rgba(0, 0, 0, 0.18)
);
--face-in-top: rgba(255, 255, 255, 0.11);
--face-in-bot: rgba(0, 0, 0, 0.3);
--shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
/* ── iOS safe-area + 基础 HTML/BODY(Layer 2: 布局 token)── */
html,
body {
height: 100%;
}
body {
/* iOS safe-area 撑顶 */
padding-top: env(safe-area-inset-top, 0px);
padding-bottom: env(safe-area-inset-bottom, 0px);
padding-left: env(safe-area-inset-left, 0px);
padding-right: env(safe-area-inset-right, 0px);
background-color: var(--bg);
color: var(--fg);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
/*
* ============================================================
* 司命台 · 冷色系(Admin Slate)—— 与主域暖铜色温分化
*
* 在 .admin-shell 容器内切换为冷色调(铁青 / 墨灰 / 银线),
* 与主域琉璃镜的暖铜(素绢 + 鎏金)形成视觉区隔。
* 所有 Layer 1 语义色变量覆盖为冷系。
* ============================================================
*/
/* 亮色 · 司命冷灰 */
.admin-shell {
--bg: #eef0ec;
--surface: #f2f4f0;
--glass: rgba(225, 230, 225, 0.55);
--glass-strong: rgba(245, 247, 243, 0.72);
--glass-border: rgba(30, 35, 38, 0.1);
--fg: #1a1e1c;
--muted: #6b7170;
--ink: #e8eae4; /* 冷绢底 */
--night-bronze: #d6d9d2; /* 冷灰面带铁温 */
--gilt: #6a7b72; /* 铁青 — 结构/发丝线/标签 */
--gilt-dim: rgba(106, 123, 114, 0.32);
--gilt-faint: rgba(106, 123, 114, 0.14);
--patina: #3f7d68; /* 复用铜绿锈(一致的健康色) */
--patina-dim: rgba(63, 125, 104, 0.28);
--patina-wash: rgba(63, 125, 104, 0.05);
--fg-dim: #5a605c;
--fg-faint: #8a9089;
--rule: rgba(106, 123, 114, 0.18);
--overlay-hover: rgba(0, 0, 0, 0.03);
--overlay-active: rgba(0, 0, 0, 0.07);
--cinnabar-dim: rgba(180, 50, 40, 0.38);
--cinnabar-wash: rgba(180, 50, 40, 0.06);
--aurora-1: rgba(110, 140, 130, 0.18);
--aurora-2: rgba(180, 140, 100, 0.1);
--aurora-3: rgba(60, 80, 75, 0.12);
--shadow: 0 1px 2px rgba(40, 50, 45, 0.08);
/* Layer 2 组件 token 覆盖 */
--color-btn-primary-bg: var(--patina);
--color-btn-primary-text: var(--ink);
--color-btn-secondary-bg: var(--surface);
--color-btn-secondary-text: var(--fg);
}
/* 暗色 · 司命墨灰 */
.dark .admin-shell,
.admin-shell.dark {
--bg: #0a0e0d;
--surface: #121615;
--glass: rgba(255, 255, 255, 0.035);
--glass-strong: rgba(255, 255, 255, 0.07);
--glass-border: rgba(160, 175, 168, 0.08);
--fg: #e0e3de;
--muted: #7a8280;
--ink: #0a0e0d;
--night-bronze: #111514;
--gilt: #889c90; /* 铁青(暗色亮一些) */
--gilt-dim: rgba(136, 156, 144, 0.28);
--gilt-faint: rgba(136, 156, 144, 0.12);
--patina: #5fa192; /* 铜绿锈(暗色) */
--patina-dim: rgba(95, 161, 146, 0.3);
--patina-wash: rgba(95, 161, 146, 0.06);
--fg-dim: #8a908b;
--fg-faint: #555c58;
--rule: rgba(136, 156, 144, 0.14);
--overlay-hover: rgba(255, 255, 255, 0.04);
--overlay-active: rgba(255, 255, 255, 0.08);
--cinnabar-dim: rgba(190, 60, 50, 0.35);
--cinnabar-wash: rgba(190, 60, 50, 0.06);
--aurora-1: rgba(95, 161, 146, 0.15);
--aurora-2: rgba(160, 130, 80, 0.08);
--aurora-3: rgba(40, 60, 55, 0.2);
--shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
/*
* aurora 光晕:毛玻璃需要底层色彩才可见。
* 固定在视口、不可交互,铺三处雾化光斑(铜绿 / 铜金 / 墨青)。
*/
body::before {
content: "";
position: fixed;
inset: -10vmax;
z-index: -1;
background:
radial-gradient(
55vmax 55vmax at 12% 8%,
var(--aurora-1),
transparent 60%
),
radial-gradient(
48vmax 48vmax at 88% 16%,
var(--aurora-2),
transparent 60%
),
radial-gradient(
60vmax 60vmax at 50% 100%,
var(--aurora-3),
transparent 62%
);
filter: blur(30px);
pointer-events: none;
}
/* 细滚动条 */
* {
scrollbar-width: thin;
scrollbar-color: var(--glass-border) transparent;
}
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-thumb {
background-color: var(--glass-border);
border-radius: 9999px;
}
}
@layer utilities {
/* 琉璃面:标准毛玻璃层 */
.glass {
background-color: var(--glass);
backdrop-filter: blur(16px) saturate(140%);
-webkit-backdrop-filter: blur(16px) saturate(140%);
border: 1px solid var(--glass-border);
}
/* 琉璃面(强):浮层 / 抽屉 / 模态 */
.glass-strong {
background-color: var(--glass-strong);
backdrop-filter: blur(24px) saturate(160%);
-webkit-backdrop-filter: blur(24px) saturate(160%);
border: 1px solid var(--glass-border);
}
/* 铜镜镜面(mirror-face):抛光的当下——助手气泡 / 朱批卡的"被照见"感。
* 鎏金细描边 + 顶光内阴影 + 底铜阴,叠在琉璃底之上;比 .glass 多一层铜温。
*/
.mirror-face {
background-color: var(--glass);
background-image: var(--face-sheen);
backdrop-filter: blur(16px) saturate(140%);
-webkit-backdrop-filter: blur(16px) saturate(140%);
border: 1px solid var(--gilt-dim);
box-shadow:
inset 0 1px 0 var(--face-in-top),
inset 0 7px 22px -16px var(--face-in-top),
inset 0 -1px 0 var(--face-in-bot),
var(--shadow);
}
/*
* 镜面光泽(对话气泡):静镜 / 活镜二态。
* 静镜(默认)——已完成消息,光泽凝固于一处(opacity .42,仅静态反射);
* 活镜(.is-live)——流式生成中,光源流转漫反射(mirror-sweep 9s)。
* 把签名光泽从"常驻装饰"提为"状态指示器":只有正在生成的镜面才流转。
* 与登录卡 .animate-sweep 同源,但区分动静二态(登录卡维持永续动画不变)。
*/
.mirror-sweep {
position: relative;
overflow: hidden;
}
.mirror-sweep::before {
content: "";
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
background: var(--sweep-gradient);
background-size: 200% 200%;
background-position: 35% 35%;
opacity: 0.42;
}
.mirror-sweep.is-live::before {
background-position: 200% 200%;
opacity: 1;
animation: mirror-sweep 9s ease-in-out infinite;
}
/*
* 铜面颗粒(feTurbulence):与登录卡同源的金属肌理,杀死平坦矢量感。
* 叠在 .mirror-sweep 镜面之上;亮色 multiply、暗色 overlay,活镜态略强。
*/
.mirror-grain::after {
content: "";
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='7'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
opacity: 0.028;
mix-blend-mode: multiply;
}
.dark .mirror-grain::after {
opacity: 0.018;
mix-blend-mode: overlay;
}
.mirror-grain.is-live::after {
opacity: 0.05;
}
.dark .mirror-grain.is-live::after {
opacity: 0.035;
}
/*
* 朱漆面(vermilion):司命 / 朱批 / 告警的语义热色容器。
* 左缘 3px 朱漆 + 朱漆辐射底晕——全站唯一热色,仅用于待裁定 / 告警。
*/
.vermilion {
background-color: var(--glass);
background-image: radial-gradient(
120% 100% at 0% 0%,
var(--cinnabar-dim),
transparent 60%
);
border: 1px solid var(--cinnabar-dim);
border-left: 3px solid var(--cinnabar);
}
/*
* 朱砂浓度即风险等级(与 chat-redesign-preview 同源):
* L1 浅描(低风险,去朱晕)/ L2 朱块(.vermilion 基类,默认)/ L3 满朱晕染 + 辉光(高危)。
* 等级一眼可读,文字降为辅助。color-mix 随主题变量自动适配亮/暗。
*/
.vermilion-risk-l1 {
background-image: none;
background-color: var(--surface);
border-color: var(--rule);
border-left-color: var(--cinnabar);
}
.vermilion-risk-l3 {
background-image: radial-gradient(
120% 100% at 0% 0%,
color-mix(in srgb, var(--cinnabar) 22%, transparent),
transparent 55%
);
background-color: color-mix(in srgb, var(--cinnabar) 10%, transparent);
border-color: var(--cinnabar);
box-shadow: 0 0 28px -8px
color-mix(in srgb, var(--cinnabar) 35%, transparent);
}
/* 九枢星盘(Astrolabe)SVG 词法 —— 铜镜鉴心的"仪器"线宽与字体 */
.astrolabe-ring {
fill: none;
stroke: var(--gilt-dim);
stroke-width: 1;
}
.astrolabe-ring-fine {
stroke: var(--gilt-faint);
}
.astrolabe-ring-patina {
fill: none;
stroke: var(--patina-dim);
stroke-width: 1;
}
.astrolabe-tick {
stroke: var(--gilt);
stroke-width: 1;
opacity: 0.45;
}
.astrolabe-spoke {
stroke: var(--gilt);
stroke-width: 0.6;
stroke-dasharray: 1.5 3;
opacity: 0.4;
}
.astrolabe-pivot-label {
font-family: var(--font-serif);
font-size: 12.5px;
fill: var(--fg-dim);
transition: fill 0.15s;
}
.astrolabe-pivot-sub {
font-family: var(--font-mono);
font-size: 7px;
letter-spacing: 0.08em;
fill: var(--fg-faint);
}
.astrolabe-core-glyph {
font-family: var(--font-serif);
font-size: 20px;
font-weight: 700;
fill: var(--gilt);
}
.astrolabe-core-label {
font-family: var(--font-mono);
font-size: 7px;
letter-spacing: 0.2em;
fill: var(--fg-faint);
}
/*
* grain 纹理层:feTurbulence SVG 噪点覆盖。
* 杀死平坦矢量感的关键一层 —— 昂贵页面的秘密。
* 使用时用 <div className="grain" /> 置于布局顶层。
*/
.grain {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
opacity: 0.025;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) {
.grain {
opacity: 0.035;
}
}
/* 内容层提升(与 grain 配合) */
.content-layer {
position: relative;
z-index: 5;
}
/* 铜镜脉动环:VitrailPanel 在场指示等 */
.bg-surface-hi {
background-color: var(--surface-hi);
}
/* 镜面扫描光泽:登录卡上的斜向亮带滑移 */
.animate-sweep {
position: relative;
overflow: hidden;
}
.animate-sweep::before {
content: "";
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
background: var(--sweep-gradient);
background-size: 200% 200%;
background-position: 200% 200%;
animation: mirror-sweep 9s ease-in-out infinite;
}
@keyframes mirror-sweep {
0% {
background-position: 200% 200%;
}
40% {
background-position: 50% 50%;
}
60% {
background-position: 50% 50%;
}
100% {
background-position: -100% -100%;
}
}
/* 星盘慢旋转:九枢活的仪器,140s 一圈 */
.animate-slow-rot {
transform-origin: center;
animation: slow-rot 140s linear infinite;
}
@keyframes slow-rot {
to {
transform: rotate(360deg);
}
}
/*
* 通用 section 眉标:世界页 / 人物页 / 记忆页共用
* 设计稿 world-preview.html / time-preview.html
*/
.section-label {
font-family: var(--font-mono);
font-size: 12px;
letter-spacing: 0.1em;
color: var(--fg-faint);
margin-bottom: 14px;
display: flex;
align-items: center;
gap: 6px;
}
.section-label .sub {
font-size: 12px;
letter-spacing: 0.04em;
color: var(--fg-dim);
opacity: 0.75;
}
.section-label .glyph {
color: var(--gilt);
opacity: 0.8;
}
/* 人物 pill(世界页/时态页头部 + 设计稿 .char-pill) */
.char-pill {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12.5px;
color: var(--patina);
padding: 3px 11px 3px 4px;
border: 1px solid var(--patina-dim);
border-radius: 999px;
background: var(--patina-wash);
}
.char-pill .avatar-mini {
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--patina);
color: var(--ink);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-serif);
font-size: 11px;
font-weight: 600;
}
/*
* 侧栏背景:夜铜渐变底 + 铜绿晕染(6 处重复 -> 统一为 utility)
* 替代 AppShell / ChatShell / ChatContextRail / SessionSidebar 中的 inline gradient
*/
.bg-sidebar {
background: linear-gradient(
180deg,
color-mix(in srgb, var(--night-bronze) 92%, var(--patina) 4%),
var(--night-bronze)
);
}
/*
* 设置卡片(set-card):设置页的分组卡片布局。
* 设计稿 settings-preview.html §set-card
*/
.set-card {
border: 1px solid var(--rule);
border-radius: 10px;
background: var(--surface);
padding: 18px 20px;
}
.set-card-head {
display: flex;
align-items: baseline;
gap: 10px;
margin-bottom: 4px;
}
.set-card-title {
font-family: var(--font-serif);
font-size: 16px;
font-weight: 600;
color: var(--fg);
}
.set-card-eng {
font-family: var(--font-mono);
font-size: 11px;
color: var(--gilt);
}
.set-card-desc {
font-size: 12.5px;
color: var(--fg-dim);
margin-bottom: 16px;
line-height: 1.55;
}
.set-row {
display: flex;
align-items: center;
gap: 14px;
padding: 11px 0;
border-top: 1px solid var(--rule);
}
.set-row:first-of-type {
border-top: none;
padding-top: 4px;
}
.set-row .lab {
flex: 1;
}
.set-row .lab .t {
font-size: 13.5px;
color: var(--fg);
font-weight: 500;
}
.set-row .lab .h {
font-size: 11.5px;
color: var(--fg-faint);
margin-top: 1px;
}
.set-row .ctrl {
flex-shrink: 0;
}
.theme-pick {
display: flex;
gap: 8px;
}
.theme-opt {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
cursor: pointer;
background: none;
border: none;
font-family: inherit;
padding: 0;
}
.theme-opt .swatch {
width: 46px;
height: 30px;
border-radius: 6px;
border: 1.5px solid var(--rule);
transition: border-color 0.12s;
}
.theme-opt.sel .swatch {
border-color: var(--patina);
box-shadow: 0 0 0 2px var(--patina-wash);
}
.theme-opt .nm {
font-size: 11px;
color: var(--fg-dim);
}
.theme-opt.sel .nm {
color: var(--patina);
font-weight: 500;
}
.seg {
display: inline-flex;
border: 1px solid var(--rule);
border-radius: 7px;
overflow: hidden;
}
.seg button {
font-family: inherit;
font-size: 12.5px;
padding: 6px 14px;
background: transparent;
color: var(--fg-dim);
border: none;
cursor: pointer;
border-right: 1px solid var(--rule);
}
.seg button:last-child {
border-right: none;
}
.seg button.sel {
background: var(--patina-wash);
color: var(--patina);
font-weight: 500;
}
.toggle {
position: relative;
width: 38px;
height: 21px;
background: var(--rule);
border-radius: 999px;
cursor: pointer;
border: none;
padding: 0;
flex-shrink: 0;
transition: background 0.15s;
}
.toggle::after {
content: "";
position: absolute;
top: 2.5px;
left: 2.5px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--fg-dim);
transition:
transform 0.15s,
background 0.15s;
}
.toggle.on {
background: var(--patina-dim);
}
.toggle.on::after {
transform: translateX(17px);
background: var(--patina);
}
.save-hint {
font-size: 12px;
color: var(--patina);
display: inline-flex;
align-items: center;
gap: 6px;
}
.save-hint .dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--patina);
}
/* 铜镜徽标:LOGO 品牌图形基础 */
.logo-mark-ring {
fill: none;
stroke: var(--gilt);
stroke-width: 1.4;
opacity: 0.65;
}
.logo-mark-inner {
fill: none;
stroke: var(--patina-dim);
stroke-width: 0.8;
opacity: 0.45;
}
.logo-mark-char-ring {
fill: none;
stroke: var(--gilt-dim);
stroke-width: 0.5;
opacity: 0.35;
}
.logo-mark-char {
font-family: var(--font-serif);
font-size: 30px;
fill: var(--gilt);
font-weight: 700;
opacity: 0.8;
}
.logo-mark-dot {
fill: var(--gilt);
opacity: 0.35;
}
}
/* animate-pulse-ring:在场脉冲 —— 与铜镜呼吸脉动的视觉同构 */
@keyframes pulse-ring {
0% {
box-shadow: 0 0 0 0 rgba(111, 163, 137, 0.5);
}
70% {
box-shadow: 0 0 0 8px transparent;
}
100% {
box-shadow: 0 0 0 0 transparent;
}
}
.animate-pulse-ring {
animation: pulse-ring 2.6s cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
/* 六爻当爻流光:鎏金光泽沿爻象进度条漫移(设计稿 hex-shimmer)。
容器为虚线(阴爻·未达),fill 覆盖为阳爻;当爻态漫反射流光。 */
@keyframes hex-shimmer {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
.animate-hex-shimmer {
animation: hex-shimmer 2.4s linear infinite;
}
/* logo「镜启」彩蛋:触发时铜镜 gilt 辉光脉冲(设计稿 logoEggPulse 同源) */
@keyframes logo-egg-pulse {
0% {
transform: scale(1);
filter: drop-shadow(0 0 0 transparent);
}
40% {
transform: scale(1.2);
filter: drop-shadow(0 0 7px var(--gilt));
}
100% {
transform: scale(1);
filter: drop-shadow(0 0 0 transparent);
}
}
.logo-egg-pulse {
animation: logo-egg-pulse 1.4s ease;
}
/* 尊重减少动态偏好:关闭非必要动画 */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ============================================================
* 自托管字体:JetBrains Mono(已下载到 public/fonts/)
* 加载优先级:系统已安装 → 本地 woff2 → SF Mono → 通用等宽字体
* ============================================================ */
@font-face {
font-family: "JetBrains Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src:
local("JetBrains Mono"),
url("/fonts/JetBrainsMono-400.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-style: normal;
font-weight: 500;
font-display: swap;
src:
local("JetBrains Mono Medium"),
local("JetBrainsMono-Medium"),
url("/fonts/JetBrainsMono-500.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-style: normal;
font-weight: 600;
font-display: swap;
src:
local("JetBrains Mono SemiBold"),
local("JetBrainsMono-SemiBold"),
url("/fonts/JetBrainsMono-600.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-style: normal;
font-weight: 700;
font-display: swap;
src:
local("JetBrains Mono Bold"),
local("JetBrainsMono-Bold"),
url("/fonts/JetBrainsMono-700.woff2") format("woff2");
}
/* ============================================================
* 自托管字体:Instrument Serif(英文展示衬线,15KB)
* 用于 Hero 标题/英文 slogan 等展示场景
* ============================================================ */
@font-face {
font-family: "Instrument Serif";
font-style: normal;
font-weight: 400;
font-display: swap;
src:
local("Instrument Serif"),
url("/fonts/InstrumentSerif-400.woff2") format("woff2");
}
@font-face {
font-family: "Instrument Serif";
font-style: italic;
font-weight: 400;
font-display: swap;
src:
local("Instrument Serif Italic"),
local("InstrumentSerif-Italic"),
url("/fonts/InstrumentSerif-400i.woff2") format("woff2");
}
/* Space Grotesk:英文技术感无衬线(变量字体,支持 wght 300-700) */
@font-face {
font-family: "Space Grotesk";
font-style: normal;
font-weight: 400 700;
font-display: swap;
src:
local("Space Grotesk"),
url("/fonts/SpaceGrotesk-Variable.woff2") format("woff2");
}
/* ============================================================
* 自托管字体:霞鹜文楷(LXGW WenKai)— 开源的日系/中文楷体
* 用于正文 / 人物对话 / 文学场景
* ============================================================ */
@font-face {
font-family: "LXGW WenKai";
font-style: normal;
font-weight: 300;
font-display: swap;
src:
local("LXGW WenKai Light"),
url("/fonts/LXGWWenKai-Light.woff2") format("woff2");
}
@font-face {
font-family: "LXGW WenKai";
font-style: normal;
font-weight: 400;
font-display: swap;
src:
local("LXGW WenKai"),
local("LXGW WenKai Regular"),
url("/fonts/LXGWWenKai-Regular.woff2") format("woff2");
}
@font-face {
font-family: "LXGW WenKai";
font-style: normal;
font-weight: 500;
font-display: swap;
src:
local("LXGW WenKai Medium"),
url("/fonts/LXGWWenKai-Medium.woff2") format("woff2");
}
/* 得意黑(Smiley Sans)— 开源现代圆体中文,适合标题/标签 */
@font-face {
font-family: "Smiley Sans";
font-style: oblique;
font-weight: 400;
font-display: swap;
src:
local("Smiley Sans Oblique"),
url("/fonts/SmileySans-Oblique.ttf.woff2") format("woff2");
}