Compare commits
9 Commits
04cdf964af
...
d095531bb8
| Author | SHA1 | Date | |
|---|---|---|---|
| d095531bb8 | |||
| 05e8ea5e40 | |||
| b4030c386e | |||
| e34e2c965c | |||
| 9be775d346 | |||
| 9399d3f41e | |||
| 779140ef59 | |||
| 469e804e38 | |||
| 548455f127 |
84
.stylelintrc.cjs
Normal file
84
.stylelintrc.cjs
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Stylelint 配置 —— 颜色 Token 栏杆(规范见 doc/frontend/color_token_spec.md)
|
||||
*
|
||||
* 作用:拦住三类"绕过设计 Token"的写法,让规范从文字变成机制。
|
||||
* 规则1 color-no-hex → 禁止裸十六进制色号(如 #da7756)
|
||||
* 规则2 declaration-property-value-... → 禁止 rgb()/hsl() 字面色、禁止 var(--x, #hex) 兜底
|
||||
* 规则3 media-feature-name-disallowed-list → 禁止组件内新增 prefers-color-scheme 主题分支
|
||||
*
|
||||
* 基线策略(baseline):
|
||||
* - 颜色属性必须走 var(--token)。
|
||||
* - 下方 BASELINE_EXEMPT 列出的是"立规矩之前就存在违规"的存量文件,暂时豁免。
|
||||
* - 新文件不在名单里 → 从第一行起就受三条规则约束。
|
||||
* - 每当治理(清理)掉一个存量文件,就把它从 BASELINE_EXEMPT 删除,它从此受约束、不再回退。
|
||||
* - 设计上永久豁免:_tokens.scss(Token 定义源)、_virtual-monitor.scss(canvas 动画资产)。
|
||||
*/
|
||||
|
||||
// 颜色相关属性:这些属性的值必须用 token,不能写字面色
|
||||
const COLOR_PROPS =
|
||||
'/^(color|fill|stroke|background|background-color|border|border-color|border-top-color|border-right-color|border-bottom-color|border-left-color|box-shadow|outline|outline-color|text-decoration-color|caret-color|column-rule-color|stop-color)$/';
|
||||
|
||||
// 立规矩之前就存在硬编码颜色的存量文件(baseline 豁免,治理后逐个移除)
|
||||
const BASELINE_EXEMPT = [
|
||||
'static/src/admin/AdminDashboardApp.vue',
|
||||
'static/src/admin/ApiAdminApp.vue',
|
||||
'static/src/admin/CustomToolsApp.vue',
|
||||
'static/src/admin/CustomToolsGuideApp.vue',
|
||||
'static/src/admin/PolicyApp.vue',
|
||||
];
|
||||
|
||||
// 三条颜色规则(供默认与 override 复用)
|
||||
const COLOR_RULES = {
|
||||
// 规则1:禁止裸 hex
|
||||
'color-no-hex': [true, { message: '禁止裸 hex 色号,请使用设计 Token:var(--accent) 等(见 color_token_spec.md)' }],
|
||||
// 规则2:禁止 rgb()/hsl() 字面色 + 禁止 var() 兜底色
|
||||
'declaration-property-value-disallowed-list': [
|
||||
{
|
||||
[COLOR_PROPS]: ['/rgba?\\(/', '/hsla?\\(/', '/var\\(\\s*--[^,)]+,/'],
|
||||
},
|
||||
{
|
||||
message:
|
||||
'颜色属性禁止 rgb()/hsl() 字面色或 var(--x, #hex) 兜底,请直接用 var(--token)(见 color_token_spec.md)',
|
||||
},
|
||||
],
|
||||
// 规则3:禁止组件内手写 prefers-color-scheme 主题分支(主题切换只在 _tokens.scss 的 [data-theme] 完成)
|
||||
'media-feature-name-disallowed-list': [
|
||||
['prefers-color-scheme'],
|
||||
{ message: '禁止在组件内用 prefers-color-scheme 写主题分支,颜色随主题变化应通过 Token 自动完成' },
|
||||
],
|
||||
};
|
||||
|
||||
// 关闭三条规则(给存量豁免文件用)
|
||||
const COLOR_RULES_OFF = {
|
||||
'color-no-hex': null,
|
||||
'declaration-property-value-disallowed-list': null,
|
||||
'media-feature-name-disallowed-list': null,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// 设计上永久豁免:Token 定义源 + canvas 动画资产
|
||||
ignoreFiles: [
|
||||
'static/dist/**',
|
||||
'static/src/styles/base/_tokens.scss',
|
||||
'static/src/styles/components/chat/_virtual-monitor.scss',
|
||||
],
|
||||
// 顶层 rules 必填(stylelint 16 要求)。具体规则按文件类型在 overrides 中施加。
|
||||
rules: {},
|
||||
overrides: [
|
||||
{
|
||||
files: ['static/src/**/*.scss'],
|
||||
customSyntax: 'postcss-scss',
|
||||
rules: COLOR_RULES,
|
||||
},
|
||||
{
|
||||
files: ['static/src/**/*.vue'],
|
||||
customSyntax: 'postcss-html',
|
||||
rules: COLOR_RULES,
|
||||
},
|
||||
// baseline:存量文件暂时关闭三条规则(治理后从此数组移除该文件即可恢复约束)
|
||||
{
|
||||
files: BASELINE_EXEMPT,
|
||||
rules: COLOR_RULES_OFF,
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -141,16 +141,17 @@
|
||||
|
||||
> 适用范围:所有前端 UI(以 `static/src` Web 为主;`cli/src` 在视觉可类比处同样适用;以及未来新增的任何界面)。
|
||||
> 约束级别:写新 UI 或改动 UI 时**必须遵守**;遇到存量违规应在最小改动允许范围内顺手修正。
|
||||
> 配色基础设施:三模式 CSS 变量定义在 `static/src/styles/base/_tokens.scss`(`:root[data-theme='classic'|'light'|'dark']`),切换逻辑见 `static/src/utils/theme.ts`。
|
||||
> 配色基础设施:两层 token(原始层 + 语义层)定义在 `static/src/styles/base/_tokens.scss`(`:root[data-theme='classic'|'light'|'dark']` + 首屏回退 `:root:not([data-theme])`),切换逻辑见 `static/src/utils/theme.ts`;`.stylelintrc.cjs` 三条规则做防回退栏杆,`build` 含 `stylelint` 步骤。
|
||||
|
||||
1. **禁止边缘光晕**:不使用任何 glow / 外发光 / 彩色光晕效果(大范围彩色 `box-shadow` 扩散、`filter: drop-shadow` 光圈、`::before/::after` 模糊光晕等)。已有的要移除。允许的只是中性、克制的投影——沿用 `--claude-shadow` / `--theme-shadow-*` 既有 token,不自造发光阴影。
|
||||
1. **禁止边缘光晕**:不使用任何 glow / 外发光 / 彩色光晕效果(大范围彩色 `box-shadow` 扩散、`filter: drop-shadow` 光圈、`::before/::after` 模糊光晕等)。已有的要移除。允许的只是中性、克制的投影——沿用 `--shadow-*` 既有 token,不自造发光阴影。**仅在用户明确允许或要求时才可使用光晕效果。**
|
||||
2. **禁止原生浏览器组件**:不直接使用浏览器默认外观的 `<select>`、`<input type=checkbox/radio/range/date/color>`、`alert/confirm/prompt`、原生右键菜单、原生 tooltip 等,一律换成与项目风格统一的自定义组件(下拉 / 开关 / 单选 / 滑块 / 模态 / Toast)。
|
||||
3. **禁止圆角套娃**:不允许「圆角矩形套圆角矩形套圆角矩形」的多层嵌套卡片——典型垃圾审美,且极大占据有效显示面积。容器层级要扁平,优先用分隔线 / 留白 / 底色区分,不要多包一层带边框圆角的盒子。
|
||||
4. **图标外框对齐**:同一组图标按钮的外框(点击热区 / 容器)必须统一对齐,不能一会居中、一会左对齐、一会右对齐;同组固定相同尺寸与对齐方式。
|
||||
5. **图标视觉对齐而非理论对齐**:按图标视觉重心对齐而非几何边界盒;对重心偏移的图标(三角形 / 播放键 / 放大镜等)做微调,使其「看起来居中」。
|
||||
6. **颜色遵循三模式切换**:所有颜色走原生三模式(经典 `classic` / 明亮 `light` / 夜间 `dark`),禁止写死颜色字面量,一律用 CSS 变量(`--claude-*` / `--theme-*`)。新增颜色必须在三套主题里都补齐。
|
||||
6. **颜色遵循三模式切换 + 两层 Token**:所有颜色走原生三模式,禁止写死颜色字面量(裸 hex / `rgb()`/`hsl()` 字面色 / `var(--x, #hex)` 兜底),一律用**中性语义** CSS 变量(`--surface-*` / `--text-*` / `--border-*` / `--accent*` / `--state-*`)。三主题定位:**经典抄 Claude 亮色盘**(暖奶油 + 暖橙 primary `#cc785c`)、**浅色抄 ChatGPT 亮色盘**(冷白 + 灰 + 近黑 primary `#181818`)、**深色自研中性灰阶**。亮色表面靠灰阶拉层次(经典 `--surface-base #faf9f5` < `soft #f5f0e8` < `card #efe9de` < `muted #e8e0d2`),不许全塌成白。primary 克制(CTA-only),hover/选中/运行态走中性灰。半透明 tint 用 `color-mix(in srgb, var(--token) N%, transparent)` 派生。`--claude-*`/`--theme-*` 是过时别名,新代码勿用。新增颜色必须三主题(含首屏回退)补齐。
|
||||
7. **带文字容器固定高度**:所有含内部文字的选项 / 按钮 / 标签 / 容器固定高度,禁止因文字多少被撑大撑高;过长文字用省略号或内部滚动处理。
|
||||
8. **窗口设最大尺寸 + 内部滚动**:所有弹窗 / 面板 / 列表设置 `max-height` / `max-width`,超出由内部容器滚动,不顶大整个窗口;滚动条要么隐藏,要么做样式适配,不暴露原生粗滚动条。
|
||||
9. **实体面板禁止半透明**:实体 UI 容器(对话区 / 侧栏 / 下拉/二级菜单 / 抽屉 / 对话框本体 / 状态条 / tooltip / 输入栏)背景必须不透明,且不加 `backdrop-filter` 磨砂。唯一例外:遮罩层 scrim(`--overlay-scrim`,`position:fixed;inset:0`)和刻意玻璃质感装饰保留半透明。
|
||||
|
||||
## 6) Git 工作流(开发 + Review)
|
||||
|
||||
|
||||
13
CLAUDE.md
13
CLAUDE.md
@ -272,7 +272,7 @@ terminal.delete_conversation(conversation_id)
|
||||
> 适用范围:所有前端 UI(以 `static/src` Web 为主;`cli/src` 在视觉可类比处同样适用;以及未来新增的任何界面)。
|
||||
> 约束级别:写新 UI 或改动 UI 时**必须遵守**;遇到存量违规应在最小改动允许范围内顺手修正。
|
||||
|
||||
1. **禁止边缘光晕**:不使用任何 glow / 外发光 / 彩色光晕效果(大范围彩色 `box-shadow` 扩散、用 `filter: drop-shadow` 做光圈、`::before/::after` 模糊光晕等)。已有的要移除。允许的只是中性、克制的投影——沿用 `--claude-shadow` / `--theme-shadow-*` 这类已有 token,不要自造发光阴影。
|
||||
1. **禁止边缘光晕**:不使用任何 glow / 外发光 / 彩色光晕效果(大范围彩色 `box-shadow` 扩散、用 `filter: drop-shadow` 做光圈、`::before/::after` 模糊光晕等)。已有的要移除。允许的只是中性、克制的投影——沿用 `--claude-shadow` / `--theme-shadow-*` 这类已有 token,不要自造发光阴影。**仅在用户明确允许或要求时才可使用光晕效果。**
|
||||
|
||||
2. **禁止原生浏览器组件**:不直接使用浏览器默认外观的 `<select>`、`<input type=checkbox/radio/range/date/color>`、`alert/confirm/prompt`、原生右键菜单、原生 tooltip 等。一律替换为与项目风格统一的自定义组件(下拉、开关、单选、滑块、模态、Toast 等)。
|
||||
|
||||
@ -282,12 +282,21 @@ terminal.delete_conversation(conversation_id)
|
||||
|
||||
5. **图标视觉对齐而非理论对齐**:按图标的视觉重心对齐,而不是几何边界盒。对视觉重心偏移的图标(三角形 / 播放键 / 放大镜等)做微调(micro-nudge),让它「看起来居中」而非「数值上居中」。
|
||||
|
||||
6. **颜色遵循三模式切换**:所有颜色必须走原生三模式(经典 `classic` / 明亮 `light` / 夜间 `dark`)。禁止写死颜色字面量,一律使用 CSS 变量(`--claude-*` / `--theme-*`,定义在 `static/src/styles/base/_tokens.scss`,由 `:root[data-theme='classic'|'light'|'dark']` 提供;切换逻辑见 `static/src/utils/theme.ts`)。新增颜色必须在三套主题里都补齐。
|
||||
6. **颜色遵循三模式切换 + 两层 Token**:所有颜色必须走原生三模式(经典 `classic` / 明亮 `light` / 夜间 `dark`),禁止写死颜色字面量(含裸 hex、`rgb()`/`hsl()` 字面色、`var(--x, #hex)` 兜底),一律使用语义 CSS 变量。
|
||||
- **三主题定位**(填色基准):**经典 = 抄 Claude 官网亮色盘**(暖奶油色阶 + 暖橙 primary `#cc785c`);**浅色 = 抄 ChatGPT 亮色盘**(冷白 + 中性灰 + 近黑 primary `#181818`);**深色 = 自研中性灰阶**(浅灰/深灰/黑,不硬凑暖调)。
|
||||
- **两层结构**:token 定义在 `static/src/styles/base/_tokens.scss`,分原始层 + 语义层;组件只引用**中性语义名**(`--surface-*` / `--text-*` / `--border-*` / `--accent*` / `--state-*` 等)。`--claude-*` / `--theme-*` 是**过时兼容别名**,迁移完成后会删,新代码不要用。
|
||||
- **表面层次**(经典):画布 `--surface-base` `#faf9f5` < 侧栏 `--surface-soft` `#f5f0e8` < 卡片 `--surface-card` `#efe9de` < 嵌套 `--surface-muted` `#e8e0d2` < 纯白浮起 `--surface-raised`。亮色主题不许把所有表面塌成同一个白,必须靠暖/冷灰阶拉开层次。
|
||||
- **强调色克制**:primary(`--accent`)是 "CTA-only voltage",只点在主按钮/logo 等极少数处;hover / 选中 / 运行态一律走中性灰(跟各自主题表面色),不抢镜。
|
||||
- **派生色**:需要半透明 tint 时用 `color-mix(in srgb, var(--token) N%, transparent)` 从语义 token 派生,不写死 rgba。
|
||||
- **新增颜色**必须在 classic / light / dark 三套主题(及首屏回退 `:root:not([data-theme])`,与经典同值)都补齐。
|
||||
- **防回退栏杆**:`.stylelintrc.cjs` 用 `color-no-hex` / `declaration-property-value-disallowed-list` / `media-feature-name-disallowed-list` 三条规则拦截违规,`build` 脚本含 `stylelint` 步骤会拦下裸色。存量未清理文件在 `BASELINE_EXEMPT` 临时豁免,清理一个移除一个,不再回退。切换逻辑见 `static/src/utils/theme.ts`。
|
||||
|
||||
7. **带文字容器固定高度**:所有含内部文字的选项 / 按钮 / 标签 / 容器必须固定高度,禁止因文字多少被撑大撑高。文字过长用省略号或内部滚动处理,保持行高与块高稳定。
|
||||
|
||||
8. **窗口设最大尺寸 + 内部滚动**:所有弹窗 / 面板 / 列表必须设置 `max-height` / `max-width`,超出时由内部容器滚动,而不是把整个窗口顶大。滚动条要么隐藏,要么做样式适配(贴合整体设计,不暴露原生粗滚动条)。
|
||||
|
||||
9. **实体面板禁止半透明**:所有实体 UI 容器(对话区、侧栏、下拉/二级菜单、抽屉、对话框本体、状态条、tooltip 气泡、输入栏等)背景必须**不透明**,且不加 `backdrop-filter` 磨砂。背景一旦不透明,磨砂就失去意义,必须移除。**唯一例外**是遮罩层(弹窗背后压暗的 scrim,用 `--overlay-scrim`,`position:fixed;inset:0`)和刻意的玻璃质感装饰,这类保留半透明。
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- 所有用户操作在独立容器中执行,与宿主机隔离
|
||||
|
||||
@ -116,7 +116,7 @@ class MainTerminalToolsPolicyMixin:
|
||||
continue
|
||||
self.tool_category_states[key] = bool(value)
|
||||
|
||||
def apply_personalization_preferences(self, config: Optional[Dict[str, Any]] = None):
|
||||
def apply_personalization_preferences(self, config: Optional[Dict[str, Any]] = None, *, apply_default_model: bool = True):
|
||||
"""Apply persisted personalization settings that affect runtime behavior."""
|
||||
try:
|
||||
effective_config = config or load_personalization_config(self.data_dir)
|
||||
@ -176,7 +176,7 @@ class MainTerminalToolsPolicyMixin:
|
||||
|
||||
# 默认模型偏好(优先应用,再处理运行模式)
|
||||
preferred_model = effective_config.get("default_model")
|
||||
if isinstance(preferred_model, str) and preferred_model != self.model_key:
|
||||
if apply_default_model and isinstance(preferred_model, str) and preferred_model != self.model_key:
|
||||
try:
|
||||
self.set_model(preferred_model)
|
||||
except Exception as exc:
|
||||
|
||||
@ -91,6 +91,7 @@ DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = {
|
||||
"deep_compress_behavior": "continue", # 手动压缩行为:continue-注入并触发请求 / wait-仅插入等待用户
|
||||
"silent_tool_disable": True, # 禁用工具时不向模型插入提示(默认开启)
|
||||
"enhanced_tool_display": True, # 增强工具显示
|
||||
"compact_message_display": "full", # 简略消息显示:full-完整原始内容 / brief-一行概要
|
||||
"show_git_status_bar": True, # 是否显示输入栏上方 Git 状态栏
|
||||
"versioning_restore_mode": "overwrite", # 版本回溯模式固定为 overwrite
|
||||
"agents_md_auto_inject": False, # AGENTS.md 自动注入开关
|
||||
@ -414,6 +415,13 @@ def sanitize_personalization_payload(
|
||||
else:
|
||||
base["enhanced_tool_display"] = bool(base.get("enhanced_tool_display", True))
|
||||
|
||||
# 简略消息显示:full(完整原始内容)/ brief(一行概要)
|
||||
compact_msg = data.get("compact_message_display", base.get("compact_message_display"))
|
||||
if isinstance(compact_msg, str) and compact_msg.strip().lower() in ("full", "brief"):
|
||||
base["compact_message_display"] = compact_msg.strip().lower()
|
||||
else:
|
||||
base["compact_message_display"] = "full"
|
||||
|
||||
# Git 状态栏显示开关
|
||||
if "show_git_status_bar" in data:
|
||||
base["show_git_status_bar"] = bool(data.get("show_git_status_bar"))
|
||||
|
||||
2288
package-lock.json
generated
2288
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,8 +5,9 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite build --watch",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"build": "tsc --noEmit && stylelint \"static/src/**/*.{scss,vue}\" && vite build",
|
||||
"lint": "eslint \"static/src/**/*.{ts,tsx,js,vue}\" --max-warnings=0",
|
||||
"lint:css": "stylelint \"static/src/**/*.{scss,vue}\"",
|
||||
"format": "prettier --write \"static/src/**/*.{ts,tsx,js,vue,css}\"",
|
||||
"preview": "vite preview",
|
||||
"cli": "npm --prefix cli run dev",
|
||||
@ -47,8 +48,11 @@
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
"postcss-html": "^1.6.0",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.1.1",
|
||||
"sass": "^1.94.2",
|
||||
"stylelint": "^16.10.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vue-tsc": "^1.8.22"
|
||||
|
||||
82
scripts/color_map.py
Normal file
82
scripts/color_map.py
Normal file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
color_map.py —— 硬编码色值 → token 反查。
|
||||
解析 _tokens.scss 各主题真实值,对给定色值判定它等于哪个 token(A类)或无对应(B类)。
|
||||
|
||||
用法:
|
||||
python3 scripts/color_map.py <file> # 分析某文件里所有硬编码色的可映射性
|
||||
"""
|
||||
import sys, re, os
|
||||
from collections import defaultdict
|
||||
|
||||
TOK = "static/src/styles/base/_tokens.scss"
|
||||
|
||||
def norm(v):
|
||||
"""归一化色值:小写、去多余空格、#abc->#aabbcc、rgb 空格统一。"""
|
||||
v = v.strip().lower()
|
||||
v = re.sub(r'\s+', '', v)
|
||||
m = re.fullmatch(r'#([0-9a-f])([0-9a-f])([0-9a-f])', v)
|
||||
if m:
|
||||
v = '#' + ''.join(c*2 for c in m.groups())
|
||||
return v
|
||||
|
||||
def load_tokens():
|
||||
txt = open(TOK, encoding='utf-8').read()
|
||||
# semantic blocks only ([data-theme])
|
||||
themes = {}
|
||||
for m in re.finditer(r":root\[data-theme='([^']+)'\]\s*\{([^}]*)\}", txt):
|
||||
name, body = m.group(1), m.group(2)
|
||||
d = {}
|
||||
for dm in re.finditer(r'(--[a-z0-9-]+)\s*:\s*([^;]+);', body):
|
||||
d[norm(dm.group(2))] = dm.group(1)
|
||||
themes[name] = d
|
||||
return themes
|
||||
|
||||
def analyze(path, themes):
|
||||
text = open(path, encoding='utf-8').read()
|
||||
# only style content for vue
|
||||
if path.endswith('.vue'):
|
||||
style = '\n'.join(m.group(1) for m in re.finditer(r'<style[^>]*>(.*?)</style>', text, re.S|re.I))
|
||||
else:
|
||||
style = text
|
||||
style = re.sub(r'/\*.*?\*/', '', style, flags=re.S)
|
||||
style = re.sub(r'//[^\n]*', '', style)
|
||||
vals = re.findall(r'#[0-9a-fA-F]{3,8}\b|rgba?\([0-9 ,.%/]+\)|hsla?\([0-9 ,.%/]+\)', style)
|
||||
A = defaultdict(list) # value -> [(theme, token)]
|
||||
B = defaultdict(int) # value -> count (no match)
|
||||
counts = defaultdict(int)
|
||||
for raw in vals:
|
||||
n = norm(raw)
|
||||
counts[raw] += 1
|
||||
hits = []
|
||||
for tname, d in themes.items():
|
||||
if n in d:
|
||||
hits.append((tname, d[n]))
|
||||
if hits:
|
||||
A[raw] = hits
|
||||
else:
|
||||
B[raw] += 1
|
||||
return counts, A, B
|
||||
|
||||
def main():
|
||||
themes = load_tokens()
|
||||
path = sys.argv[1]
|
||||
counts, A, B = analyze(path, themes)
|
||||
print(f"=== {path} ===")
|
||||
print(f"硬编码色值种类: {len(counts)}, 总出现: {sum(counts.values())}")
|
||||
print(f"\n--- A类(有 token 对应, 可映射) ---")
|
||||
for v in sorted(A, key=lambda x:-counts[x]):
|
||||
# 取 classic 优先的 token 名
|
||||
toks = {t:tok for t,tok in A[v]}
|
||||
cls = toks.get('classic')
|
||||
shown = cls or list(toks.values())[0]
|
||||
themes_hit = ','.join(sorted(toks.keys()))
|
||||
print(f" {counts[v]:3d}× {v:32s} -> {shown:28s} (命中主题: {themes_hit})")
|
||||
print(f"\n--- B类(无 token 对应, 野色, 需决策) ---")
|
||||
for v in sorted(B, key=lambda x:-B[x]):
|
||||
print(f" {B[v]:3d}× {v}")
|
||||
if not B:
|
||||
print(" (无 — 此文件可全量安全迁移)")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
143
scripts/lint_check.py
Normal file
143
scripts/lint_check.py
Normal file
@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
lint_check.py —— Node 段错误环境下的 stylelint 替身验证器。
|
||||
|
||||
复刻 .stylelintrc.cjs 的三条颜色规则 + 基础语法完整性,用于在迁移每个文件后
|
||||
确认它已彻底清理干净(可安全从 BASELINE_EXEMPT 移除)。
|
||||
|
||||
用法:
|
||||
python3 scripts/lint_check.py <file1> [file2] ...
|
||||
python3 scripts/lint_check.py --all # 扫所有 .scss/.vue(排除永久豁免)
|
||||
|
||||
规则(与 stylelintrc 对齐):
|
||||
R1 color-no-hex : 禁止裸 #hex
|
||||
R2 literal-rgb-in-color : 颜色属性值禁止 rgb()/hsl() 字面色
|
||||
R3 var-fallback-in-color : 颜色属性值禁止 var(--x, <fallback>)
|
||||
R4 prefers-color-scheme : 禁止 @media prefers-color-scheme
|
||||
|
||||
注意: 只检查 <style> / scss 内容。.vue 文件只扫 <style> 块,跳过 <template>/<script>。
|
||||
"""
|
||||
import sys, re, os, glob
|
||||
|
||||
PERMANENT_IGNORE = {
|
||||
'static/src/styles/base/_tokens.scss',
|
||||
'static/src/styles/components/chat/_virtual-monitor.scss',
|
||||
}
|
||||
|
||||
COLOR_PROP = re.compile(
|
||||
r'^\s*(-?\w[\w-]*)?\s*('
|
||||
r'color|fill|stroke|background|background-color|border|border-color|'
|
||||
r'border-top-color|border-right-color|border-bottom-color|border-left-color|'
|
||||
r'box-shadow|outline|outline-color|text-decoration-color|caret-color|'
|
||||
r'column-rule-color|stop-color|text-shadow'
|
||||
r')\s*:', re.I)
|
||||
|
||||
HEX = re.compile(r'#[0-9a-fA-F]{3,8}\b')
|
||||
RGB = re.compile(r'\b(rgba?|hsla?)\s*\(')
|
||||
VARFALLBACK = re.compile(r'var\(\s*--[^,()]+,')
|
||||
|
||||
def extract_style_blocks(text, is_vue):
|
||||
"""返回 [(start_line, block_text)]。vue 只取 <style>,scss 取全文。"""
|
||||
if not is_vue:
|
||||
return [(1, text)]
|
||||
blocks = []
|
||||
for m in re.finditer(r'<style[^>]*>(.*?)</style>', text, re.S | re.I):
|
||||
start_line = text[:m.start(1)].count('\n') + 1
|
||||
blocks.append((start_line, m.group(1)))
|
||||
return blocks
|
||||
|
||||
def strip_comments(s):
|
||||
s = re.sub(r'/\*.*?\*/', lambda m: '\n' * m.group(0).count('\n'), s, flags=re.S)
|
||||
s = re.sub(r'//[^\n]*', '', s)
|
||||
return s
|
||||
|
||||
def check_text(block_text, base_line):
|
||||
errs = []
|
||||
clean = strip_comments(block_text)
|
||||
clean_lines = clean.splitlines()
|
||||
# R1 hex / R4 prefers-color-scheme —— 行级
|
||||
for i, line in enumerate(clean_lines):
|
||||
ln = base_line + i
|
||||
if 'prefers-color-scheme' in line:
|
||||
errs.append((ln, 'R4 prefers-color-scheme', line.strip()))
|
||||
if HEX.search(line):
|
||||
errs.append((ln, 'R1 no-hex', line.strip()))
|
||||
# R2/R3 —— 声明级(跨行)。按 ; { } 切成声明段,每段判断是否颜色属性,
|
||||
# 段内若含 rgb/hsl 字面色或 var(--x, fallback),把违规行号定位到该 token
|
||||
# 实际出现的那一行(声明可能跨多行,stylelint 报的是声明起始行;这里
|
||||
# 我们用 token 出现行,足够定位)。
|
||||
def line_of(char_idx):
|
||||
return base_line + clean.count('\n', 0, char_idx)
|
||||
pos = 0
|
||||
for m in re.finditer(r'[;{}]', clean):
|
||||
seg = clean[pos:m.start()]
|
||||
seg_start = pos
|
||||
pos = m.end()
|
||||
if not COLOR_PROP.search(seg):
|
||||
continue
|
||||
for vm in VARFALLBACK.finditer(seg):
|
||||
errs.append((line_of(seg_start + vm.start()), 'R3 var-fallback', seg.strip()[:80]))
|
||||
for rm in RGB.finditer(seg):
|
||||
errs.append((line_of(seg_start + rm.start()), 'R2 literal-rgb', seg.strip()[:80]))
|
||||
# 处理最后一段(无尾分隔符的残留,通常为空)
|
||||
seg = clean[pos:]
|
||||
if COLOR_PROP.search(seg):
|
||||
for vm in VARFALLBACK.finditer(seg):
|
||||
errs.append((line_of(pos + vm.start()), 'R3 var-fallback', seg.strip()[:80]))
|
||||
for rm in RGB.finditer(seg):
|
||||
errs.append((line_of(pos + rm.start()), 'R2 literal-rgb', seg.strip()[:80]))
|
||||
errs.sort(key=lambda e: e[0])
|
||||
return errs
|
||||
|
||||
def syntax_check(text, is_vue):
|
||||
"""大括号配对(针对 style 内容)。"""
|
||||
blocks = extract_style_blocks(text, is_vue)
|
||||
problems = []
|
||||
for base, bt in blocks:
|
||||
bt2 = strip_comments(bt)
|
||||
if bt2.count('{') != bt2.count('}'):
|
||||
problems.append(f" 大括号不配对 (block@L{base}): {{={bt2.count('{')} }}={bt2.count('}')}")
|
||||
return problems
|
||||
|
||||
def lint_file(path):
|
||||
text = open(path, encoding='utf-8').read()
|
||||
is_vue = path.endswith('.vue')
|
||||
all_errs = []
|
||||
for base, bt in extract_style_blocks(text, is_vue):
|
||||
all_errs.extend(check_text(bt, base))
|
||||
syn = syntax_check(text, is_vue)
|
||||
return all_errs, syn
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
if not args:
|
||||
print("用法: python3 scripts/lint_check.py <file...> | --all")
|
||||
sys.exit(2)
|
||||
if args == ['--all']:
|
||||
files = []
|
||||
for pat in ('static/src/**/*.scss', 'static/src/**/*.vue'):
|
||||
files += glob.glob(pat, recursive=True)
|
||||
files = [f for f in files if f.replace('\\', '/') not in PERMANENT_IGNORE]
|
||||
else:
|
||||
files = args
|
||||
total = 0
|
||||
for f in sorted(files):
|
||||
nf = f.replace('\\', '/')
|
||||
if nf in PERMANENT_IGNORE:
|
||||
print(f"SKIP (permanent ignore): {f}")
|
||||
continue
|
||||
errs, syn = lint_file(f)
|
||||
if errs or syn:
|
||||
print(f"\n✖ {f}")
|
||||
for ln, rule, txt in errs:
|
||||
print(f" L{ln:<5} {rule:22} | {txt[:80]}")
|
||||
for s in syn:
|
||||
print(s)
|
||||
total += len(errs) + len(syn)
|
||||
else:
|
||||
print(f"✔ {f}")
|
||||
print(f"\n总问题数: {total}")
|
||||
sys.exit(1 if total else 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
120
scripts/strip_fallback.py
Normal file
120
scripts/strip_fallback.py
Normal file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
strip_fallback.py —— 安全剥离 var(--DEFINED_TOKEN, fallback) 的 fallback。
|
||||
|
||||
仅当 token 在 _tokens.scss 中已定义时才剥离(此时 fallback 永不生效,剥离=零视觉变化)。
|
||||
未定义 token(fallback 是真实值)一律跳过。
|
||||
带 --write 才落盘,否则只 dry-run 报告。
|
||||
|
||||
安全校验:每个被改的位置,改动后只是去掉了 ", fallback",token 名和其余内容不变。
|
||||
"""
|
||||
import sys, re, glob, os
|
||||
|
||||
def load_defined():
|
||||
txt = open('static/src/styles/base/_tokens.scss', encoding='utf-8').read()
|
||||
return set(re.findall(r'(--[a-z0-9-]+)\s*:', txt))
|
||||
|
||||
def find_var_spans(s):
|
||||
"""返回所有 var(...) 的 (start, end, inner) ,支持嵌套,end 是右括号下一位。"""
|
||||
spans = []
|
||||
i = 0
|
||||
while True:
|
||||
m = re.search(r'var\(', s[i:])
|
||||
if not m:
|
||||
break
|
||||
start = i + m.start()
|
||||
# 从 'var(' 的左括号开始做括号匹配
|
||||
depth = 0
|
||||
j = start + 3 # points at '('
|
||||
assert s[j] == '('
|
||||
k = j
|
||||
while k < len(s):
|
||||
if s[k] == '(':
|
||||
depth += 1
|
||||
elif s[k] == ')':
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
break
|
||||
k += 1
|
||||
inner = s[j+1:k]
|
||||
spans.append((start, k+1, inner))
|
||||
i = k + 1
|
||||
return spans
|
||||
|
||||
def strip_one(s, defined):
|
||||
"""对字符串 s 处理最外层 var(),递归处理 inner。返回 (新串, 改动数)。"""
|
||||
spans = find_var_spans(s)
|
||||
if not spans:
|
||||
return s, 0
|
||||
out = []
|
||||
last = 0
|
||||
changes = 0
|
||||
for start, end, inner in spans:
|
||||
out.append(s[last:start])
|
||||
# 先递归处理 inner(处理嵌套 var)
|
||||
new_inner, c_inner = strip_one(inner, defined)
|
||||
changes += c_inner
|
||||
# 解析最外层 var(--tok, fallback?) —— 在顶层逗号处分割
|
||||
mtok = re.match(r'\s*(--[a-z0-9-]+)\s*', new_inner)
|
||||
if mtok:
|
||||
tok = mtok.group(1)
|
||||
rest = new_inner[mtok.end():]
|
||||
if rest.startswith(','):
|
||||
# 有 fallback。token 已定义 → 剥离
|
||||
if tok in defined:
|
||||
out.append(f'var({tok})')
|
||||
changes += 1
|
||||
else:
|
||||
out.append(f'var({new_inner})')
|
||||
else:
|
||||
out.append(f'var({new_inner})')
|
||||
else:
|
||||
out.append(f'var({new_inner})')
|
||||
last = end
|
||||
out.append(s[last:])
|
||||
return ''.join(out), changes
|
||||
|
||||
def process_file(path, defined, write):
|
||||
src = open(path, encoding='utf-8').read()
|
||||
new, ch = strip_one(src, defined)
|
||||
if ch and write:
|
||||
open(path, 'w', encoding='utf-8').write(new)
|
||||
return ch, src, new
|
||||
|
||||
def verify(src, new):
|
||||
"""校验:去掉所有空白后,new 必须是 src 删除若干 ', fallback' 的结果。
|
||||
粗校验:new 的非空白字符是 src 非空白字符的子序列,且行数不变。"""
|
||||
if src.count('\n') != new.count('\n'):
|
||||
return False, "行数变化"
|
||||
# 每行:new 行必须是 old 行的子序列(只删不增)
|
||||
for o, n in zip(src.splitlines(), new.splitlines()):
|
||||
oi = 0
|
||||
for ch in n:
|
||||
oi = o.find(ch, oi)
|
||||
if oi == -1:
|
||||
return False, f"非子序列: {o!r} -> {n!r}"
|
||||
oi += 1
|
||||
return True, "ok"
|
||||
|
||||
def main():
|
||||
write = '--write' in sys.argv
|
||||
args = [a for a in sys.argv[1:] if not a.startswith('--')]
|
||||
defined = load_defined()
|
||||
files = args or (glob.glob('static/src/**/*.scss', recursive=True) +
|
||||
glob.glob('static/src/**/*.vue', recursive=True))
|
||||
files = [f for f in files if '_tokens' not in f and '_virtual-monitor' not in f]
|
||||
total = 0
|
||||
for f in sorted(files):
|
||||
ch, src, new = process_file(f, defined, write=False)
|
||||
if not ch:
|
||||
continue
|
||||
ok, msg = verify(src, new)
|
||||
flag = "OK" if ok else f"FAIL({msg})"
|
||||
print(f"{ch:3d} strips [{flag}] {f}")
|
||||
if ok and write:
|
||||
open(f, 'w', encoding='utf-8').write(new)
|
||||
total += ch
|
||||
print(f"\n{'已写入' if write else 'DRY-RUN'} 总剥离: {total} 处")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -67,7 +67,29 @@ def _apply_workspace_personalization_preferences(terminal: WebTerminal, workspac
|
||||
"""Apply persisted workspace personalization after policy/workspace resolution."""
|
||||
try:
|
||||
config = load_personalization_config(workspace.data_dir)
|
||||
terminal.apply_personalization_preferences(config)
|
||||
session_model = None
|
||||
if has_request_context():
|
||||
raw_session_model = session.get("model_key")
|
||||
if isinstance(raw_session_model, str) and raw_session_model.strip():
|
||||
session_model = raw_session_model.strip()
|
||||
|
||||
# default_model 是“新会话初始偏好”,不能在每次 /api/status、任务创建、
|
||||
# 加载资源时覆盖用户已经在当前会话里手动切换的模型。
|
||||
if session_model and session_model != getattr(terminal, "model_key", None):
|
||||
try:
|
||||
terminal.set_model(session_model)
|
||||
except Exception as exc:
|
||||
debug_log(f"[Personalization] 恢复会话模型失败: {session_model} ({exc})")
|
||||
|
||||
apply_default_model = not bool(session_model) and not bool(
|
||||
getattr(terminal, "_workspace_default_model_applied", False)
|
||||
)
|
||||
terminal.apply_personalization_preferences(config, apply_default_model=apply_default_model)
|
||||
if apply_default_model:
|
||||
try:
|
||||
terminal._workspace_default_model_applied = True
|
||||
except Exception:
|
||||
pass
|
||||
if has_request_context():
|
||||
session["run_mode"] = getattr(terminal, "run_mode", session.get("run_mode"))
|
||||
session["thinking_mode"] = getattr(terminal, "thinking_mode", session.get("thinking_mode"))
|
||||
|
||||
@ -123,6 +123,7 @@
|
||||
:class="{
|
||||
'chat-container--immersive': workspaceCollapsed,
|
||||
'chat-container--mobile': isMobileViewport,
|
||||
'chat-container--app-shell': isAppShell,
|
||||
'chat-container--monitor': chatDisplayMode === 'monitor',
|
||||
'has-title-ribbon': titleRibbonVisible
|
||||
}"
|
||||
@ -370,11 +371,6 @@
|
||||
@reset-context="resetGitChangesContext"
|
||||
/>
|
||||
</transition>
|
||||
<div
|
||||
v-if="!isMobileViewport && rightCollapsed && !gitChangesPanelOpen"
|
||||
class="resize-handle"
|
||||
@mousedown="startResize('right', $event)"
|
||||
></div>
|
||||
</div>
|
||||
<transition name="desktop-approval-fade">
|
||||
<div v-if="!isMobileViewport && !rightCollapsed" class="desktop-approval-overlay">
|
||||
@ -818,7 +814,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { defineAsyncComponent, onMounted, ref } from 'vue';
|
||||
import appOptions from './app';
|
||||
import VideoPicker from './components/overlay/VideoPicker.vue';
|
||||
import { useTutorialStore } from './stores/tutorial';
|
||||
@ -832,10 +828,23 @@ const PathAuthorizationDialog = defineAsyncComponent(
|
||||
const tutorialStore = useTutorialStore();
|
||||
|
||||
const mobilePanelIcon = new URL('../icons/align-left.svg', import.meta.url).href;
|
||||
const isAppShell =
|
||||
typeof window !== 'undefined' &&
|
||||
(new URLSearchParams(window.location.search).has('app_shell') ||
|
||||
Boolean((window as any)?.AndroidThemeBridge));
|
||||
const detectAppShell = () => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const ua = window.navigator?.userAgent || '';
|
||||
return (
|
||||
params.has('app_shell') ||
|
||||
Boolean((window as any)?.AndroidThemeBridge) ||
|
||||
/;\s*wv\)/i.test(ua)
|
||||
);
|
||||
};
|
||||
const isAppShell = ref(detectAppShell());
|
||||
onMounted(() => {
|
||||
isAppShell.value = detectAppShell();
|
||||
window.setTimeout(() => {
|
||||
isAppShell.value = detectAppShell();
|
||||
}, 300);
|
||||
});
|
||||
const mobileMenuIcons = {
|
||||
workspace: new URL('../icons/folder.svg', import.meta.url).href,
|
||||
personal: new URL('../icons/user.svg', import.meta.url).href,
|
||||
|
||||
@ -651,7 +651,7 @@ button {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
padding: 10px 14px;
|
||||
background: var(--claude-highlight, #f3d2a8);
|
||||
background: var(--claude-highlight);
|
||||
color: #2a2013;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
|
||||
@ -612,7 +612,7 @@ watch(secondaryVerified, async (val) => {
|
||||
color: var(--muted);
|
||||
}
|
||||
.status.error {
|
||||
color: #dc2626;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
.editor-only {
|
||||
max-width: 1080px;
|
||||
@ -708,7 +708,7 @@ watch(secondaryVerified, async (val) => {
|
||||
color: var(--muted);
|
||||
}
|
||||
.error {
|
||||
color: #dc2626;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
.empty {
|
||||
color: var(--muted);
|
||||
@ -729,8 +729,8 @@ watch(secondaryVerified, async (val) => {
|
||||
.primary {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--claude-accent, #da7756) 0%,
|
||||
var(--claude-accent-strong, #bd5d3a) 100%
|
||||
var(--claude-accent) 0%,
|
||||
var(--claude-accent-strong) 100%
|
||||
);
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
||||
@ -54,8 +54,8 @@ onMounted(() => {
|
||||
--border: #e3d8c8;
|
||||
--ink: #1a120b;
|
||||
--muted: #6f635a;
|
||||
--accent: var(--claude-accent, #da7756);
|
||||
--accent-strong: var(--claude-accent-strong, #bd5d3a);
|
||||
--accent: var(--claude-accent);
|
||||
--accent-strong: var(--claude-accent-strong);
|
||||
--shadow: 0 16px 40px rgba(47, 32, 21, 0.12);
|
||||
|
||||
max-width: 1080px;
|
||||
@ -114,7 +114,7 @@ onMounted(() => {
|
||||
color: var(--muted);
|
||||
}
|
||||
.status.error {
|
||||
color: #d64545;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
.markdown :global(h1),
|
||||
.markdown :global(h2),
|
||||
|
||||
@ -1367,8 +1367,8 @@ button:disabled {
|
||||
gap: 12px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid var(--theme-control-border, rgba(118, 103, 84, 0.25));
|
||||
background: var(--theme-surface-muted, rgba(255, 255, 255, 0.85));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
background: var(--theme-surface-muted);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
@ -1381,8 +1381,8 @@ button:disabled {
|
||||
}
|
||||
|
||||
.toggle-row:hover {
|
||||
border-color: var(--theme-control-border-strong, rgba(118, 103, 84, 0.35));
|
||||
background: var(--theme-surface-soft, rgba(255, 255, 255, 0.92));
|
||||
border-color: var(--theme-control-border-strong);
|
||||
background: var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.toggle-row input {
|
||||
@ -1410,7 +1410,7 @@ button:disabled {
|
||||
|
||||
.fancy-path {
|
||||
fill: none;
|
||||
stroke: var(--claude-text-secondary, #7f7766);
|
||||
stroke: var(--claude-text-secondary);
|
||||
stroke-width: 5;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
@ -1423,13 +1423,13 @@ button:disabled {
|
||||
}
|
||||
|
||||
.toggle-row input:checked + .fancy-check .fancy-path {
|
||||
stroke: var(--claude-accent, #da7756);
|
||||
stroke: var(--claude-accent);
|
||||
stroke-dasharray: 70.5096664428711 9999999;
|
||||
stroke-dashoffset: -262.2723388671875;
|
||||
}
|
||||
|
||||
.toggle-row span {
|
||||
color: var(--claude-text, #3d3929);
|
||||
color: var(--claude-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
||||
@ -139,7 +139,7 @@ export const computed = {
|
||||
return !this.isMobileViewport && this.chatDisplayMode === 'chat';
|
||||
},
|
||||
chatContainerStyle() {
|
||||
const minHeight = 80;
|
||||
const minHeight = 90;
|
||||
const raw = Number(this.composerReservedHeight || 0);
|
||||
const height = Number.isFinite(raw) ? Math.max(minHeight, Math.round(raw)) : minHeight;
|
||||
const growth = Math.max(0, height - minHeight);
|
||||
|
||||
@ -1191,6 +1191,7 @@ export const uiMethods = {
|
||||
}
|
||||
this.messages = [];
|
||||
this.currentConversationId = null;
|
||||
this.resetTokenStatistics?.();
|
||||
this.currentConversationTitle = '新对话';
|
||||
this.titleReady = true;
|
||||
this.suppressTitleTyping = false;
|
||||
|
||||
@ -28,8 +28,8 @@ body {
|
||||
padding: 30px;
|
||||
border-radius: 18px;
|
||||
background: var(--theme-surface-soft);
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
box-shadow: var(--theme-shadow-mid, var(--claude-shadow));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
box-shadow: var(--theme-shadow-mid);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ body {
|
||||
min-height: 46px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
background: var(--theme-surface-strong);
|
||||
color: var(--claude-text);
|
||||
padding: 11px 12px;
|
||||
@ -86,7 +86,7 @@ body {
|
||||
font-size: 0.95rem;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(135deg, var(--claude-accent), var(--claude-accent-strong));
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
transition:
|
||||
transform 0.15s ease,
|
||||
filter 0.15s ease;
|
||||
@ -117,7 +117,7 @@ body {
|
||||
.auth-error {
|
||||
min-height: 1.2em;
|
||||
margin-top: 12px;
|
||||
color: #e85b57;
|
||||
color: var(--state-danger);
|
||||
font-size: 0.86rem;
|
||||
}
|
||||
|
||||
|
||||
@ -634,7 +634,11 @@ const blockDisplayMode = computed(() => {
|
||||
return personalization.experiments.blockDisplayMode || 'stacked';
|
||||
});
|
||||
const compactMessageDisplay = computed(() => {
|
||||
return personalization.experiments.compactMessageDisplay || 'full';
|
||||
return (
|
||||
personalization.form.compact_message_display ||
|
||||
personalization.experiments.compactMessageDisplay ||
|
||||
'full'
|
||||
);
|
||||
});
|
||||
const stackedBlocksEnabled = computed(() => {
|
||||
// 堆叠模式和极简模式都使用堆叠布局
|
||||
@ -790,6 +794,7 @@ const {
|
||||
});
|
||||
const rootEl = scrollRef;
|
||||
const thinkingRefs = new Map<string, HTMLElement | null>();
|
||||
let scrollbarResizeObserver: ResizeObserver | null = null;
|
||||
let bounceTraceCount = 0;
|
||||
const BOUNCE_TRACE_MAX = 240;
|
||||
const bounceTraceLastTsByKey = new Map<string, number>();
|
||||
@ -1005,6 +1010,13 @@ function attachBounceListener() {
|
||||
}
|
||||
}
|
||||
|
||||
function updateChatScrollbarWidth() {
|
||||
const el = scrollRef.value;
|
||||
if (!el) return;
|
||||
const scrollbarWidth = Math.max(0, el.offsetWidth - el.clientWidth);
|
||||
el.style.setProperty('--chat-scrollbar-width', `${scrollbarWidth}px`);
|
||||
}
|
||||
|
||||
watch(
|
||||
[isAtBottom, isNearBottom, escapedFromLock],
|
||||
([atBottom, nearBottom, escaped]) => {
|
||||
@ -1459,6 +1471,11 @@ function compactBriefLabel(msg: any): string {
|
||||
|
||||
onMounted(() => {
|
||||
attachBounceListener();
|
||||
updateChatScrollbarWidth();
|
||||
if (typeof ResizeObserver !== 'undefined' && scrollRef.value) {
|
||||
scrollbarResizeObserver = new ResizeObserver(updateChatScrollbarWidth);
|
||||
scrollbarResizeObserver.observe(scrollRef.value);
|
||||
}
|
||||
console.warn('[SCROLL_BOUNCE_TRACE]', 'mounted', {
|
||||
hasScrollRef: !!scrollRef.value
|
||||
});
|
||||
@ -1469,10 +1486,23 @@ onMounted(() => {
|
||||
|
||||
watch(scrollRef, () => {
|
||||
attachBounceListener();
|
||||
updateChatScrollbarWidth();
|
||||
if (scrollbarResizeObserver) {
|
||||
scrollbarResizeObserver.disconnect();
|
||||
scrollbarResizeObserver = null;
|
||||
}
|
||||
if (typeof ResizeObserver !== 'undefined' && scrollRef.value) {
|
||||
scrollbarResizeObserver = new ResizeObserver(updateChatScrollbarWidth);
|
||||
scrollbarResizeObserver.observe(scrollRef.value);
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
detachBounceListener();
|
||||
if (scrollbarResizeObserver) {
|
||||
scrollbarResizeObserver.disconnect();
|
||||
scrollbarResizeObserver = null;
|
||||
}
|
||||
if (timerHandle !== null) {
|
||||
clearInterval(timerHandle);
|
||||
timerHandle = null;
|
||||
|
||||
@ -541,12 +541,15 @@ watch(
|
||||
|
||||
<style scoped>
|
||||
.minimal-blocks-container {
|
||||
--chat-content-x: 0px;
|
||||
margin: 16px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 摘要组 */
|
||||
.summary-group {
|
||||
margin: 16px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sub-agent-system-group {
|
||||
@ -567,7 +570,8 @@ watch(
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: start;
|
||||
column-gap: 8px;
|
||||
padding: 0 6px 0 6px;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
@ -633,14 +637,15 @@ watch(
|
||||
grid-template-rows: 0fr;
|
||||
transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
margin-top: 8px;
|
||||
padding: 0 6px 0 6px;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 桌面端与正式文本输出左边距保持一致(text-content: 0 20px 0 15px) */
|
||||
/* 桌面端与正式文本输出左右内边距保持一致 */
|
||||
@media (min-width: 769px) {
|
||||
.summary-line-text,
|
||||
.steps-container {
|
||||
padding: 0 20px 0 15px;
|
||||
padding: 0 var(--chat-content-x);
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,6 +731,28 @@ watch(
|
||||
display: block;
|
||||
/* 让第一行文字中心和 SVG 中心对齐:向上移动半个行高减去半个字高 */
|
||||
margin-top: calc((1em - 1.7em) / 2);
|
||||
/* 滚动条样式(参考 git 状态侧边栏文件列表,滚动槽透明贴合灰色底色) */
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent)
|
||||
transparent;
|
||||
}
|
||||
|
||||
.thinking-content::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.thinking-content::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
border-radius: 999px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.thinking-content::-webkit-scrollbar-thumb {
|
||||
background: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent);
|
||||
border-radius: 999px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
/* 工具内容 */
|
||||
@ -802,7 +829,7 @@ watch(
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.text-output {
|
||||
margin: 16px -9px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1089,7 +1089,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.tool-result-meta {
|
||||
margin-bottom: 12px;
|
||||
padding: 8px 12px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
background: var(--hover-bg);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
@ -1106,10 +1106,47 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.tool-result-content.scrollable {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
background: color-mix(in srgb, transparent 99%, var(--text-primary));
|
||||
}
|
||||
|
||||
/* 结构化显示滚动条样式(参考 git 状态侧边栏文件列表,滚动槽透明贴合灰色底色) */
|
||||
.tool-result-content.scrollable,
|
||||
.tool-result-diff.scrollable,
|
||||
.code-block pre,
|
||||
.output-block pre {
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent)
|
||||
transparent;
|
||||
}
|
||||
|
||||
.tool-result-content.scrollable::-webkit-scrollbar,
|
||||
.tool-result-diff.scrollable::-webkit-scrollbar,
|
||||
.code-block pre::-webkit-scrollbar,
|
||||
.output-block pre::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.tool-result-content.scrollable::-webkit-scrollbar-track,
|
||||
.tool-result-diff.scrollable::-webkit-scrollbar-track,
|
||||
.code-block pre::-webkit-scrollbar-track,
|
||||
.output-block pre::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
border-radius: 999px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.tool-result-content.scrollable::-webkit-scrollbar-thumb,
|
||||
.tool-result-diff.scrollable::-webkit-scrollbar-thumb,
|
||||
.code-block pre::-webkit-scrollbar-thumb,
|
||||
.output-block pre::-webkit-scrollbar-thumb {
|
||||
background: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent);
|
||||
border-radius: 999px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.tool-result-content pre {
|
||||
@ -1128,7 +1165,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
}
|
||||
|
||||
.tool-result-empty {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
color: var(--text-secondary);
|
||||
font-style: italic;
|
||||
padding: 8px;
|
||||
}
|
||||
@ -1141,15 +1178,15 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.search-result-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 6px;
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
background: color-mix(in srgb, transparent 99%, var(--text-primary));
|
||||
}
|
||||
|
||||
/* 暗色模式下的搜索结果 */
|
||||
:root[data-theme='dark'] .search-result-item {
|
||||
background: #2a2a2a;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: var(--badge-bg);
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.search-result-title {
|
||||
@ -1160,20 +1197,20 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
|
||||
.search-result-url {
|
||||
font-size: 12px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .search-result-url {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.search-result-url a {
|
||||
color: #0066cc;
|
||||
color: var(--state-info);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .search-result-url a {
|
||||
color: #6b9fff;
|
||||
color: var(--state-info);
|
||||
}
|
||||
|
||||
.search-result-url a:hover {
|
||||
@ -1191,10 +1228,10 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.tool-result-diff.scrollable {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
background: color-mix(in srgb, transparent 99%, var(--text-primary));
|
||||
}
|
||||
|
||||
.diff-line {
|
||||
@ -1225,13 +1262,13 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
}
|
||||
|
||||
.diff-remove {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
color: #c00;
|
||||
background: var(--diff-del-bg);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.diff-add {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
color: #0a0;
|
||||
background: var(--diff-add-bg);
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.diff-separator {
|
||||
@ -1249,7 +1286,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.diff-operation {
|
||||
font-weight: 600;
|
||||
margin: 8px 0 4px;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* 图片 */
|
||||
@ -1262,7 +1299,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
/* 代码块 */
|
||||
@ -1281,8 +1318,8 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.output-block pre {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background: var(--hover-bg);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 6px;
|
||||
overflow-x: auto;
|
||||
font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
|
||||
@ -1295,17 +1332,17 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
/* 暗色模式:run_python 代码/输出统一白字,去除任何描边/阴影观感 */
|
||||
:root[data-theme='dark'] .code-block pre,
|
||||
:root[data-theme='dark'] .output-block pre {
|
||||
color: #ffffff !important;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
color: var(--text-primary) !important;
|
||||
background: var(--hover-bg);
|
||||
border-color: var(--border-strong);
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .code-block pre code,
|
||||
:root[data-theme='dark'] .output-block pre code {
|
||||
color: #ffffff !important;
|
||||
color: var(--text-primary) !important;
|
||||
text-shadow: none !important;
|
||||
-webkit-text-fill-color: #ffffff;
|
||||
-webkit-text-fill-color: var(--text-primary);
|
||||
}
|
||||
|
||||
.output-block {
|
||||
@ -1326,18 +1363,18 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
}
|
||||
|
||||
.memory-add {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
color: #0a0;
|
||||
background: var(--diff-add-bg);
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.memory-update {
|
||||
background: rgba(255, 165, 0, 0.1);
|
||||
color: #f90;
|
||||
background: color-mix(in srgb, var(--state-warning) 10%, transparent);
|
||||
color: var(--state-warning);
|
||||
}
|
||||
|
||||
.memory-delete {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
color: #c00;
|
||||
background: var(--diff-del-bg);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
/* 待办事项 */
|
||||
@ -1361,8 +1398,8 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
/* 彩蛋 */
|
||||
.easter-egg-content {
|
||||
padding: 12px;
|
||||
background: linear-gradient(135deg, rgba(255, 215, 0, 0.1), rgba(255, 105, 180, 0.1));
|
||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||
background: linear-gradient(135deg, color-mix(in srgb, var(--decorative-gold) 10%, transparent), color-mix(in srgb, var(--decorative-pink) 10%, transparent));
|
||||
border: 1px solid color-mix(in srgb, var(--decorative-gold) 30%, transparent);
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
@ -1371,7 +1408,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
/* 搜索匹配项 */
|
||||
.search-match-separator {
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
color: var(--text-tertiary);
|
||||
margin: 12px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
@ -1379,23 +1416,23 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.search-match-item {
|
||||
margin-bottom: 12px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
background: var(--hover-bg);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .search-match-item {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.search-match-line {
|
||||
font-size: 11px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .search-match-line {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.search-match-item pre {
|
||||
@ -1407,7 +1444,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
/* 提取片段 */
|
||||
.segment-separator {
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
color: var(--text-tertiary);
|
||||
margin: 12px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
@ -1415,23 +1452,23 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
.segment-item {
|
||||
margin-bottom: 12px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
background: var(--hover-bg);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .segment-item {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.segment-range {
|
||||
font-size: 11px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .segment-range {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.segment-item pre {
|
||||
@ -1443,7 +1480,7 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
/* 个性化管理 */
|
||||
.personalization-message {
|
||||
padding: 12px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
background: var(--hover-bg);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
@ -1451,17 +1488,17 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .personalization-message {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.personalization-config-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .personalization-config-title {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.personalization-config-list {
|
||||
@ -1474,30 +1511,30 @@ function renderEasterEgg(result: any, args: any): string {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
background: var(--hover-bg);
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .config-item {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.config-label {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .config-label {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.config-value {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
color: var(--text-primary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .config-value {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -130,8 +130,8 @@
|
||||
class="floating-project-status__stats"
|
||||
@click.stop="$emit('open-git-changes-panel')"
|
||||
>
|
||||
<span class="floating-project-status__add">+{{ projectGitSummaryForRender.additions }}</span>
|
||||
<span class="floating-project-status__del">-{{ projectGitSummaryForRender.deletions }}</span>
|
||||
<span class="floating-project-status__add">+<RollingNumber :value="projectGitSummaryForRender.additions" /></span>
|
||||
<span class="floating-project-status__del">-<RollingNumber :value="projectGitSummaryForRender.deletions" /></span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
@ -185,15 +185,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<button
|
||||
type="button"
|
||||
class="stadium-btn add-btn"
|
||||
data-tutorial="quick-menu-open"
|
||||
@click.stop="$emit('toggle-quick-menu')"
|
||||
:disabled="!isConnected"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<div class="stadium-input-rich">
|
||||
<EditorContent
|
||||
:editor="editor"
|
||||
@ -203,6 +194,17 @@
|
||||
@focusout="onInputBlur"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-actions">
|
||||
<button
|
||||
type="button"
|
||||
class="stadium-btn add-btn"
|
||||
data-tutorial="quick-menu-open"
|
||||
@click.stop="$emit('toggle-quick-menu')"
|
||||
:disabled="!isConnected"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="stadium-btn send-btn"
|
||||
@ -366,6 +368,7 @@ import Mention from '@tiptap/extension-mention';
|
||||
import Placeholder from '@tiptap/extension-placeholder';
|
||||
import { TextSelection } from 'prosemirror-state';
|
||||
import QuickMenu from '@/components/input/QuickMenu.vue';
|
||||
import RollingNumber from '@/components/input/RollingNumber.vue';
|
||||
import { useInputStore } from '@/stores/input';
|
||||
import { usePersonalizationStore } from '@/stores/personalization';
|
||||
|
||||
@ -1512,7 +1515,7 @@ const emitComposerHeight = () => {
|
||||
}
|
||||
const baseline = baselineComposerVisualHeight.value || visualHeight;
|
||||
const growth = Math.max(0, visualHeight - baseline);
|
||||
const baseReservedHeight = 80;
|
||||
const baseReservedHeight = 90;
|
||||
const reservedHeight = Math.ceil(baseReservedHeight + growth);
|
||||
emit('composer-height-change', {
|
||||
reservedHeight,
|
||||
@ -1527,6 +1530,9 @@ const adjustTextareaSize = () => {
|
||||
return;
|
||||
}
|
||||
const target = root;
|
||||
const previousScrollTop = target.scrollTop;
|
||||
const selectionShouldStayVisible =
|
||||
document.activeElement === target || target.contains(document.activeElement);
|
||||
target.style.height = 'auto';
|
||||
const computedStyle = window.getComputedStyle(target);
|
||||
const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20;
|
||||
@ -1536,11 +1542,58 @@ const adjustTextareaSize = () => {
|
||||
const multiline = targetHeight > lineHeight * 1.4;
|
||||
applyLineMetrics(lines, multiline);
|
||||
target.style.height = `${targetHeight}px`;
|
||||
keepEditorSelectionVisible(target, {
|
||||
previousScrollTop,
|
||||
selectionShouldStayVisible,
|
||||
padding: Math.max(4, lineHeight * 0.3)
|
||||
});
|
||||
nextTick(() => {
|
||||
emitComposerHeight();
|
||||
});
|
||||
};
|
||||
|
||||
const keepEditorSelectionVisible = (
|
||||
target: HTMLElement,
|
||||
options: { previousScrollTop: number; selectionShouldStayVisible: boolean; padding: number }
|
||||
) => {
|
||||
const maxScrollTop = Math.max(0, target.scrollHeight - target.clientHeight);
|
||||
if (maxScrollTop <= 0) {
|
||||
target.scrollTop = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.selectionShouldStayVisible) {
|
||||
target.scrollTop = Math.min(maxScrollTop, Math.max(0, options.previousScrollTop));
|
||||
return;
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const instance = editor.value;
|
||||
if (!instance) {
|
||||
target.scrollTop = Math.min(maxScrollTop, Math.max(0, options.previousScrollTop));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const caretRect = instance.view.coordsAtPos(instance.state.selection.head);
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
const padding = options.padding;
|
||||
const currentMaxScrollTop = Math.max(0, target.scrollHeight - target.clientHeight);
|
||||
let nextScrollTop = target.scrollTop;
|
||||
|
||||
if (caretRect.bottom > targetRect.bottom - padding) {
|
||||
nextScrollTop += caretRect.bottom - targetRect.bottom + padding;
|
||||
} else if (caretRect.top < targetRect.top + padding) {
|
||||
nextScrollTop -= targetRect.top + padding - caretRect.top;
|
||||
}
|
||||
|
||||
target.scrollTop = Math.min(currentMaxScrollTop, Math.max(0, nextScrollTop));
|
||||
} catch {
|
||||
target.scrollTop = Math.min(maxScrollTop, Math.max(0, options.previousScrollTop));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onInput = (event: Event) => {
|
||||
const target = event.target as HTMLTextAreaElement;
|
||||
if (!props.isConnected || props.inputLocked) {
|
||||
@ -1638,9 +1691,9 @@ const contextUsagePercentLabel = computed(() => `${Math.round(contextUsagePercen
|
||||
|
||||
const contextUsageColor = computed(() => {
|
||||
const percent = contextUsagePercent.value;
|
||||
if (percent < 40) return '#16a34a';
|
||||
if (percent <= 80) return '#f59e0b';
|
||||
return '#ef4444';
|
||||
if (percent < 40) return 'var(--state-success)';
|
||||
if (percent <= 80) return 'var(--state-warning)';
|
||||
return 'var(--state-danger)';
|
||||
});
|
||||
|
||||
const formatCompactTokens = (value: number) => {
|
||||
@ -1815,7 +1868,7 @@ onBeforeUnmount(() => {
|
||||
<style scoped>
|
||||
.floating-project-status {
|
||||
position: absolute;
|
||||
left: calc(5% - 7px);
|
||||
left: 5%;
|
||||
bottom: calc(100% + 6px);
|
||||
z-index: auto;
|
||||
width: 90%;
|
||||
@ -1828,7 +1881,7 @@ onBeforeUnmount(() => {
|
||||
padding: 4px 10px 4px 4px;
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 14px;
|
||||
background: var(--theme-surface-muted);
|
||||
background: var(--theme-surface-soft);
|
||||
box-shadow: none;
|
||||
pointer-events: auto;
|
||||
}
|
||||
@ -1884,8 +1937,8 @@ onBeforeUnmount(() => {
|
||||
.floating-project-status__button--active,
|
||||
.floating-project-status__notice--button:hover,
|
||||
.floating-project-status__submenu button:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
background: var(--theme-tab-active);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.floating-project-status__button--project {
|
||||
@ -1925,15 +1978,19 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.floating-project-status__stats:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
background: var(--theme-tab-active);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.floating-project-status__add {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: var(--git-diff-add-text);
|
||||
}
|
||||
|
||||
.floating-project-status__del {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: var(--git-diff-del-text);
|
||||
}
|
||||
|
||||
@ -1951,7 +2008,7 @@ onBeforeUnmount(() => {
|
||||
padding: 6px;
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 14px;
|
||||
background: var(--theme-surface-muted);
|
||||
background: var(--theme-surface-soft);
|
||||
box-shadow: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -1978,8 +2035,8 @@ onBeforeUnmount(() => {
|
||||
:global(body[data-theme='dark'] .floating-project-status),
|
||||
:global(html[data-theme='dark'] .floating-project-status__submenu),
|
||||
:global(body[data-theme='dark'] .floating-project-status__submenu) {
|
||||
background: #2a2a2a !important;
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
background: var(--badge-bg) !important;
|
||||
border-color: var(--border-card-strong);
|
||||
}
|
||||
|
||||
:global(html[data-theme='dark'] .floating-project-status__button:hover),
|
||||
@ -1990,7 +2047,7 @@ onBeforeUnmount(() => {
|
||||
:global(body[data-theme='dark'] .floating-project-status__stats:hover),
|
||||
:global(html[data-theme='dark'] .floating-project-status__submenu button:hover),
|
||||
:global(body[data-theme='dark'] .floating-project-status__submenu button:hover) {
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.floating-status-motion-enter-active,
|
||||
@ -2027,9 +2084,9 @@ onBeforeUnmount(() => {
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
color: var(--claude-text-secondary, #7f7766);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 92%, var(--claude-text-tertiary, #a59a86) 8%);
|
||||
border: 1px solid var(--theme-chip-border, rgba(118, 103, 84, 0.2));
|
||||
color: var(--claude-text-secondary);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 92%, var(--claude-text-tertiary) 8%);
|
||||
border: 1px solid var(--theme-chip-border);
|
||||
user-select: none;
|
||||
transition: gap 0.2s ease, padding 0.2s ease;
|
||||
}
|
||||
@ -2057,32 +2114,32 @@ onBeforeUnmount(() => {
|
||||
opacity: 0;
|
||||
}
|
||||
.goal-mode-banner--running {
|
||||
color: var(--claude-accent, #da7756);
|
||||
border-color: var(--claude-accent, #da7756);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 82%, var(--claude-accent, #da7756) 18%);
|
||||
color: var(--claude-accent);
|
||||
border-color: var(--claude-accent);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 82%, var(--claude-accent) 18%);
|
||||
}
|
||||
.goal-mode-banner--done {
|
||||
color: var(--claude-success, #76b086);
|
||||
border-color: var(--claude-success, #76b086);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 82%, var(--claude-success, #76b086) 18%);
|
||||
color: var(--claude-success);
|
||||
border-color: var(--claude-success);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 82%, var(--claude-success) 18%);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-mode-banner,
|
||||
:global(body[data-theme='dark']) .goal-mode-banner {
|
||||
color: var(--claude-text-secondary, #a0a0a0);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 82%, var(--claude-text-tertiary, #707070) 18%);
|
||||
border-color: var(--theme-control-border-strong, rgba(255, 255, 255, 0.12));
|
||||
color: var(--claude-text-secondary);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 82%, var(--claude-text-tertiary) 18%);
|
||||
border-color: var(--theme-control-border-strong);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-mode-banner--running,
|
||||
:global(body[data-theme='dark']) .goal-mode-banner--running {
|
||||
color: #e5e7eb;
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 72%, var(--claude-accent, #606060) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-accent, #606060) 70%, white 30%);
|
||||
color: var(--text-primary);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 72%, var(--claude-accent) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-accent) 70%, white 30%);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-mode-banner--done,
|
||||
:global(body[data-theme='dark']) .goal-mode-banner--done {
|
||||
color: #d1fae5;
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 72%, var(--claude-success, #10b981) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-success, #10b981) 70%, white 30%);
|
||||
color: color-mix(in srgb, var(--state-success) 30%, white);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 72%, var(--claude-success) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-success) 70%, white 30%);
|
||||
}
|
||||
.goal-mode-banner--clickable {
|
||||
cursor: pointer;
|
||||
@ -2091,14 +2148,14 @@ onBeforeUnmount(() => {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--claude-text-tertiary, #a59a86);
|
||||
background: var(--claude-text-tertiary);
|
||||
}
|
||||
.goal-mode-banner--running .goal-mode-banner__dot {
|
||||
background: var(--claude-accent, #da7756);
|
||||
background: var(--claude-accent);
|
||||
animation: goal-banner-pulse 1.4s ease-in-out infinite;
|
||||
}
|
||||
.goal-mode-banner--done .goal-mode-banner__dot {
|
||||
background: var(--claude-success, #76b086);
|
||||
background: var(--claude-success);
|
||||
}
|
||||
@keyframes goal-banner-pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
@ -2129,7 +2186,7 @@ onBeforeUnmount(() => {
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--border-color, #2a2f3a);
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.image-thumbnail {
|
||||
@ -2144,7 +2201,7 @@ onBeforeUnmount(() => {
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: none;
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
@ -2152,7 +2209,7 @@ onBeforeUnmount(() => {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
padding: 2px 4px;
|
||||
text-shadow: 0 0 3px rgba(0, 0, 0, 0.8);
|
||||
text-shadow: 0 0 3px var(--text-shadow-legible);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
@ -2161,6 +2218,6 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.image-remove-btn-hover:hover {
|
||||
color: #ef4444;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -240,14 +240,14 @@ const goalCompleted = computed(() => String(props.goalProgress?.status || '').to
|
||||
.submenu-desc {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary, #7f8792);
|
||||
color: var(--text-secondary);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.menu-entry.goal-entry-active {
|
||||
color: var(--claude-accent, #da7756);
|
||||
color: var(--claude-accent);
|
||||
}
|
||||
.menu-entry.goal-entry-active .entry-arrow {
|
||||
color: var(--claude-accent, #da7756);
|
||||
color: var(--claude-accent);
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
273
static/src/components/input/RollingNumber.vue
Normal file
273
static/src/components/input/RollingNumber.vue
Normal file
@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<!--
|
||||
数字滚筒(直达式):每一位是一个固定高度的窗口,内部只放「旧值 / 新值」两格。
|
||||
一次变化只滚一步,不路过中间数字。
|
||||
- 值变大:旧在上、新在下,带子上移 → 下面的数字顶上来。
|
||||
- 值变小:新在上、旧在下,带子先停在下格再回滚 → 上面的数字压下来。
|
||||
各位用 transition-delay 错开,高位先动,间隔很短。
|
||||
-->
|
||||
<span class="rolling-number">
|
||||
<TransitionGroup name="rn-place" tag="span" class="rolling-number__track">
|
||||
<span
|
||||
v-for="item in renderPlaces"
|
||||
:key="item.place"
|
||||
class="rolling-number__digit"
|
||||
>
|
||||
<span
|
||||
class="rolling-number__strip"
|
||||
:class="{ 'is-animating': item.state.animate }"
|
||||
:style="{ '--rn-offset': item.state.offset, transitionDelay: item.state.delay + 'ms' }"
|
||||
>
|
||||
<span class="rolling-number__cell">{{ item.state.top }}</span>
|
||||
<span class="rolling-number__cell">{{ item.state.bottom }}</span>
|
||||
</span>
|
||||
</span>
|
||||
</TransitionGroup>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, reactive, nextTick, watch, onBeforeUnmount } from 'vue';
|
||||
|
||||
const props = defineProps<{ value: number }>();
|
||||
|
||||
// 相邻位的启动错开(ms),高位先动,整体间隔很短。
|
||||
const STEP = 38;
|
||||
// 单位滚动时长,需与下方 css transition 时长保持一致。
|
||||
const DUR = 360;
|
||||
|
||||
type PlaceState = {
|
||||
top: number; // 上格数字
|
||||
bottom: number; // 下格数字
|
||||
offset: number; // 当前停靠格:0=显示上格,1=显示下格
|
||||
animate: boolean; // 是否启用过渡(false 时为瞬时落位)
|
||||
delay: number; // transition-delay,实现高→低位错开
|
||||
};
|
||||
|
||||
// place:位权,0=个位,越大位权越高。
|
||||
const order = ref<number[]>([]); // 渲染顺序(高位在前)
|
||||
const states = new Map<number, PlaceState>(); // place => 该位的滚动状态(reactive)
|
||||
let booted = false;
|
||||
let gen = 0; // 代次,防止过期定时器回写
|
||||
const normalizeTimers = new Set<number>();
|
||||
const removeTimers = new Map<number, number>();
|
||||
|
||||
function digitsOf(v: number): Map<number, number> {
|
||||
const s = Math.max(0, Math.trunc(Number(v) || 0)).toString();
|
||||
const len = s.length;
|
||||
const m = new Map<number, number>();
|
||||
for (let i = 0; i < len; i++) m.set(len - 1 - i, Number(s[i]));
|
||||
return m;
|
||||
}
|
||||
|
||||
const renderPlaces = computed(() =>
|
||||
order.value
|
||||
.map((p) => ({ place: p, state: states.get(p) as PlaceState }))
|
||||
.filter((x) => !!x.state)
|
||||
);
|
||||
|
||||
function setOrderDesc(places: Iterable<number>) {
|
||||
order.value = [...new Set(places)].sort((a, b) => b - a);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
async (val) => {
|
||||
const target = digitsOf(val);
|
||||
const myGen = ++gen;
|
||||
|
||||
// 首次直接落位,不滚动。
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
states.clear();
|
||||
for (const [p, d] of target) {
|
||||
states.set(p, reactive({ top: d, bottom: d, offset: 0, animate: false, delay: 0 }));
|
||||
}
|
||||
setOrderDesc(target.keys());
|
||||
return;
|
||||
}
|
||||
|
||||
const union = new Set<number>([...states.keys(), ...target.keys()]);
|
||||
const maxPlace = Math.max(...union, 0);
|
||||
|
||||
const ups: PlaceState[] = [];
|
||||
const downs: PlaceState[] = [];
|
||||
|
||||
// 目标里仍存在的位,撤销其待删除计时。
|
||||
for (const p of target.keys()) {
|
||||
const t = removeTimers.get(p);
|
||||
if (t) {
|
||||
window.clearTimeout(t);
|
||||
removeTimers.delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
for (const place of union) {
|
||||
const delay = (maxPlace - place) * STEP;
|
||||
const nv = target.get(place);
|
||||
if (nv === undefined) continue; // 该位被移除,下面统一处理淡出
|
||||
|
||||
const existing = states.get(place);
|
||||
if (!existing) {
|
||||
// 新增高位:直接出现(配合 TransitionGroup 淡入),不滚动。
|
||||
states.set(place, reactive({ top: nv, bottom: nv, offset: 0, animate: false, delay }));
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.delay = delay;
|
||||
const ov = existing.top; // 当前显示值
|
||||
if (ov === nv) {
|
||||
existing.bottom = nv;
|
||||
existing.offset = 0;
|
||||
existing.animate = false;
|
||||
continue;
|
||||
}
|
||||
if (ov < nv) {
|
||||
// 增加:上格=旧,下格=新,offset 0 → 1(下面顶上来)
|
||||
existing.animate = false;
|
||||
existing.top = ov;
|
||||
existing.bottom = nv;
|
||||
existing.offset = 0;
|
||||
ups.push(existing);
|
||||
} else {
|
||||
// 减少:上格=新,下格=旧,offset 1 → 0(上面压下来)
|
||||
existing.animate = false;
|
||||
existing.top = nv;
|
||||
existing.bottom = ov;
|
||||
existing.offset = 1;
|
||||
downs.push(existing);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新渲染顺序(纳入新增位,触发移除位的淡出)。
|
||||
setOrderDesc(target.keys());
|
||||
|
||||
// 移除位:淡出动画跑完后再清理状态。
|
||||
for (const place of [...states.keys()]) {
|
||||
if (!target.has(place) && !removeTimers.has(place)) {
|
||||
const t = window.setTimeout(() => {
|
||||
removeTimers.delete(place);
|
||||
states.delete(place);
|
||||
}, 260);
|
||||
removeTimers.set(place, t);
|
||||
}
|
||||
}
|
||||
|
||||
// 等起始态渲染并绘制后,再统一开启过渡并滚到目标格。
|
||||
await nextTick();
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (myGen !== gen) return;
|
||||
for (const s of ups) {
|
||||
s.animate = true;
|
||||
s.offset = 1;
|
||||
}
|
||||
for (const s of downs) {
|
||||
s.animate = true;
|
||||
s.offset = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 最慢一位滚完后归一化:落到 top=新值、offset=0、关闭过渡(瞬时,无闪烁)。
|
||||
const settle = maxPlace * STEP + DUR + 80;
|
||||
const norm = window.setTimeout(() => {
|
||||
normalizeTimers.delete(norm);
|
||||
if (myGen !== gen) return;
|
||||
for (const [p, d] of target) {
|
||||
const s = states.get(p);
|
||||
if (s) {
|
||||
s.animate = false;
|
||||
s.top = d;
|
||||
s.bottom = d;
|
||||
s.offset = 0;
|
||||
}
|
||||
}
|
||||
}, settle);
|
||||
normalizeTimers.add(norm);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
normalizeTimers.forEach((t) => window.clearTimeout(t));
|
||||
normalizeTimers.clear();
|
||||
removeTimers.forEach((t) => window.clearTimeout(t));
|
||||
removeTimers.clear();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.rolling-number {
|
||||
display: inline-flex;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.rolling-number__track {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.rolling-number__digit {
|
||||
--rn-h: 1.2em;
|
||||
display: inline-block;
|
||||
height: var(--rn-h);
|
||||
line-height: var(--rn-h);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rolling-number__strip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transform: translateY(calc(var(--rn-offset, 0) * var(--rn-h) * -1));
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.rolling-number__strip.is-animating {
|
||||
transition: transform 360ms cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
}
|
||||
|
||||
.rolling-number__cell {
|
||||
height: var(--rn-h);
|
||||
line-height: var(--rn-h);
|
||||
text-align: center;
|
||||
font-variant-numeric: inherit;
|
||||
}
|
||||
|
||||
/* 位数增减时整位的进出:新增位淡入下沉,消失位淡出上移 */
|
||||
.rn-place-enter-active,
|
||||
.rn-place-leave-active {
|
||||
transition: opacity 220ms ease, transform 220ms ease;
|
||||
}
|
||||
|
||||
.rn-place-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(45%);
|
||||
}
|
||||
|
||||
.rn-place-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-45%);
|
||||
}
|
||||
|
||||
/* 让消失位脱离布局,其余位平滑左移而非瞬跳 */
|
||||
.rn-place-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.rn-place-move {
|
||||
transition: transform 220ms ease;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.rolling-number__strip.is-animating {
|
||||
transition: none;
|
||||
}
|
||||
.rn-place-enter-active,
|
||||
.rn-place-leave-active,
|
||||
.rn-place-move {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -177,7 +177,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
.review-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: var(--theme-overlay-scrim, rgba(18, 19, 22, 0.4));
|
||||
background: var(--theme-overlay-scrim);
|
||||
backdrop-filter: blur(8px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -248,7 +248,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
color: var(--claude-text-secondary);
|
||||
padding: 0 10px;
|
||||
border-radius: 8px;
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
max-width: 280px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
@ -273,7 +273,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
}
|
||||
|
||||
.icon-close-btn:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
|
||||
.conversation-item:hover:not(:disabled),
|
||||
.conversation-item.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
/* 选中态:左侧强调条提示,不靠彩色光晕 */
|
||||
@ -418,7 +418,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
background: var(--theme-chip-bg, rgba(118, 103, 84, 0.12));
|
||||
background: var(--theme-chip-bg);
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
@ -463,7 +463,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
}
|
||||
|
||||
.load-more-btn:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -496,7 +496,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
}
|
||||
|
||||
.preview-line:nth-child(odd) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.04));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
@ -529,7 +529,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
}
|
||||
|
||||
.placeholder.error .text-main {
|
||||
color: var(--claude-warning, #d99845);
|
||||
color: var(--claude-warning);
|
||||
}
|
||||
|
||||
/* ===== 底部操作栏 ===== */
|
||||
@ -568,7 +568,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
width: 38px;
|
||||
height: 22px;
|
||||
border-radius: 999px;
|
||||
background: var(--theme-switch-track, #d7d1c5);
|
||||
background: var(--theme-switch-track);
|
||||
position: relative;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
@ -579,7 +579,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background: var(--theme-surface-strong, #ffffff);
|
||||
background: var(--theme-surface-strong);
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
transition: transform 0.2s ease;
|
||||
@ -608,7 +608,7 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
background: var(--claude-accent);
|
||||
color: #fffaf0;
|
||||
color: var(--on-accent);
|
||||
transition:
|
||||
background 140ms ease,
|
||||
color 140ms ease;
|
||||
@ -628,12 +628,6 @@ const formatUpdatedAt = (value: string | number) => {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* 暗色模式下主按钮文字保持白色(accent 在暗色为灰,文字仍需高对比) */
|
||||
:global(:root[data-theme='dark']) .primary-btn,
|
||||
:global(body[data-theme='dark']) .primary-btn {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* ===== 窄屏:上下堆叠 ===== */
|
||||
@media (max-width: 860px) {
|
||||
.review-body {
|
||||
|
||||
@ -167,52 +167,52 @@ const stoppedReasonLabel = computed(() => {
|
||||
font-size: 12px;
|
||||
padding: 2px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--theme-chip-border, rgba(118, 103, 84, 0.2));
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 92%, var(--claude-text-tertiary, #a59a86) 8%);
|
||||
color: var(--claude-text-secondary, #7f7766);
|
||||
border: 1px solid var(--theme-chip-border);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 92%, var(--claude-text-tertiary) 8%);
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
.goal-progress-status.is-running {
|
||||
color: var(--claude-accent, #da7756);
|
||||
border-color: var(--claude-accent, #da7756);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 82%, var(--claude-accent, #da7756) 18%);
|
||||
color: var(--claude-accent);
|
||||
border-color: var(--claude-accent);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 82%, var(--claude-accent) 18%);
|
||||
}
|
||||
.goal-progress-status.is-done {
|
||||
color: var(--claude-success, #76b086);
|
||||
border-color: var(--claude-success, #76b086);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 82%, var(--claude-success, #76b086) 18%);
|
||||
color: var(--claude-success);
|
||||
border-color: var(--claude-success);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 82%, var(--claude-success) 18%);
|
||||
}
|
||||
.goal-progress-status.is-stopped {
|
||||
color: var(--claude-warning, #d99845);
|
||||
border-color: var(--claude-warning, #d99845);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft, #fffaf0) 82%, var(--claude-warning, #d99845) 18%);
|
||||
color: var(--claude-warning);
|
||||
border-color: var(--claude-warning);
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 82%, var(--claude-warning) 18%);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-progress-status,
|
||||
:global(body[data-theme='dark']) .goal-progress-status {
|
||||
color: var(--claude-text-secondary, #a0a0a0);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 82%, var(--claude-text-tertiary, #707070) 18%);
|
||||
border-color: var(--theme-control-border-strong, rgba(255, 255, 255, 0.12));
|
||||
color: var(--claude-text-secondary);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 82%, var(--claude-text-tertiary) 18%);
|
||||
border-color: var(--theme-control-border-strong);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-progress-status.is-running,
|
||||
:global(body[data-theme='dark']) .goal-progress-status.is-running {
|
||||
color: #e5e7eb;
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 72%, var(--claude-accent, #606060) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-accent, #606060) 70%, white 30%);
|
||||
color: var(--text-primary);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 72%, var(--claude-accent) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-accent) 70%, white 30%);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-progress-status.is-done,
|
||||
:global(body[data-theme='dark']) .goal-progress-status.is-done {
|
||||
color: #d1fae5;
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 72%, var(--claude-success, #10b981) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-success, #10b981) 70%, white 30%);
|
||||
color: color-mix(in srgb, var(--state-success) 30%, white);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 72%, var(--claude-success) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-success) 70%, white 30%);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .goal-progress-status.is-stopped,
|
||||
:global(body[data-theme='dark']) .goal-progress-status.is-stopped {
|
||||
color: #ffedd5;
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 72%, var(--claude-warning, #f59e0b) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-warning, #f59e0b) 70%, white 30%);
|
||||
color: color-mix(in srgb, var(--state-warning) 30%, white);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 72%, var(--claude-warning) 28%);
|
||||
border-color: color-mix(in srgb, var(--claude-warning) 70%, white 30%);
|
||||
}
|
||||
.goal-progress-goal {
|
||||
font-size: 13px;
|
||||
color: var(--claude-text-secondary, #7f7766);
|
||||
color: var(--claude-text-secondary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -228,37 +228,37 @@ const stoppedReasonLabel = computed(() => {
|
||||
text-align: center;
|
||||
padding: 10px 6px;
|
||||
border-radius: 10px;
|
||||
background: var(--theme-surface-muted, rgba(255, 255, 255, 0.85));
|
||||
border: 1px solid var(--theme-control-border, rgba(118, 103, 84, 0.25));
|
||||
background: var(--theme-surface-muted);
|
||||
border: 1px solid var(--theme-control-border);
|
||||
}
|
||||
.goal-metric__value {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--claude-text, #3d3929);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
.goal-metric__label {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
color: var(--claude-text-tertiary, #a59a86);
|
||||
color: var(--claude-text-tertiary);
|
||||
}
|
||||
.goal-progress-reason {
|
||||
font-size: 13px;
|
||||
color: var(--claude-warning, #d99845);
|
||||
color: var(--claude-warning);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.goal-progress-summary {
|
||||
border-top: 1px solid var(--theme-control-border, rgba(118, 103, 84, 0.25));
|
||||
border-top: 1px solid var(--theme-control-border);
|
||||
padding-top: 10px;
|
||||
}
|
||||
.goal-progress-summary__title {
|
||||
font-size: 12px;
|
||||
color: var(--claude-text-tertiary, #a59a86);
|
||||
color: var(--claude-text-tertiary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.goal-progress-summary__body {
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--claude-text, #3d3929);
|
||||
color: var(--claude-text);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
max-height: 240px;
|
||||
|
||||
@ -184,7 +184,7 @@ const handleOverlayClose = () => {
|
||||
|
||||
.host-workspace-dialog__error {
|
||||
font-size: 13px;
|
||||
color: #ef4444;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.host-workspace-dialog__actions {
|
||||
@ -210,7 +210,7 @@ const handleOverlayClose = () => {
|
||||
.host-workspace-dialog__btn.primary {
|
||||
background: var(--claude-accent);
|
||||
border-color: var(--claude-accent-strong);
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.host-workspace-dialog__btn:disabled {
|
||||
|
||||
@ -300,12 +300,12 @@ const submitRename = (item: WorkspaceItem) => {
|
||||
justify-self: flex-start;
|
||||
background: var(--claude-accent);
|
||||
border-color: var(--claude-accent-strong);
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.host-workspace-dialog__btn.danger {
|
||||
color: #ef4444;
|
||||
border-color: color-mix(in srgb, #ef4444 45%, var(--theme-control-border-strong));
|
||||
color: var(--state-danger);
|
||||
border-color: color-mix(in srgb, var(--state-danger) 45%, var(--theme-control-border-strong));
|
||||
}
|
||||
|
||||
.workspace-manage-list {
|
||||
@ -375,7 +375,7 @@ const submitRename = (item: WorkspaceItem) => {
|
||||
|
||||
.host-workspace-dialog__error {
|
||||
font-size: 13px;
|
||||
color: #ef4444;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
|
||||
@ -134,7 +134,7 @@ onMounted(() => {
|
||||
.image-picker-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
background: var(--overlay-scrim);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -143,20 +143,20 @@ onMounted(() => {
|
||||
.image-picker-panel {
|
||||
width: min(980px, 92vw);
|
||||
max-height: 88vh;
|
||||
background: #0f1116;
|
||||
color: #e8ecf2;
|
||||
border: 1px solid #2a2f3a;
|
||||
background: var(--surface-panel);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0 16px 40px var(--shadow-color);
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #1f2430;
|
||||
border-bottom: 1px solid var(--border-default);
|
||||
}
|
||||
.header-left {
|
||||
display: flex;
|
||||
@ -167,11 +167,11 @@ onMounted(() => {
|
||||
font-weight: 600;
|
||||
}
|
||||
.local-btn {
|
||||
border: 1px solid #2f3645;
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 4px 10px;
|
||||
border-radius: 8px;
|
||||
background: #1b202c;
|
||||
color: #c5ccda;
|
||||
background: var(--surface-raised);
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -181,7 +181,7 @@ onMounted(() => {
|
||||
}
|
||||
.close-btn {
|
||||
background: transparent;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
@ -197,9 +197,9 @@ onMounted(() => {
|
||||
gap: 12px;
|
||||
}
|
||||
.card {
|
||||
border: 1px solid #1f2430;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
background: #151922;
|
||||
background: var(--surface-card);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
@ -209,49 +209,49 @@ onMounted(() => {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
object-fit: cover;
|
||||
background: #0c0f14;
|
||||
background: var(--surface-base);
|
||||
}
|
||||
.card .name {
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
color: #c5ccda;
|
||||
color: var(--text-secondary);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.card.selected {
|
||||
border-color: #4ca6ff;
|
||||
box-shadow: 0 0 0 2px rgba(76, 166, 255, 0.2);
|
||||
border-color: var(--state-info);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--state-info) 20%, transparent);
|
||||
}
|
||||
.loading,
|
||||
.empty {
|
||||
padding: 40px 0;
|
||||
text-align: center;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid #1f2430;
|
||||
border-top: 1px solid var(--border-default);
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.btn {
|
||||
border: 1px solid #2f3645;
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
background: #1b202c;
|
||||
color: #e8ecf2;
|
||||
background: var(--surface-raised);
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn.primary {
|
||||
background: #4ca6ff;
|
||||
border-color: #4ca6ff;
|
||||
color: #0d1117;
|
||||
background: var(--state-info);
|
||||
border-color: var(--state-info);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
@ -259,7 +259,7 @@ onMounted(() => {
|
||||
}
|
||||
.count {
|
||||
font-size: 13px;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.grid {
|
||||
|
||||
@ -47,23 +47,23 @@ const emitSkip = () => emit('skip');
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
background: var(--theme-overlay-scrim, rgba(15, 23, 42, 0.45));
|
||||
background: var(--theme-overlay-scrim);
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
.new-user-tutorial-dialog {
|
||||
width: min(520px, calc(100vw - 32px));
|
||||
border-radius: 18px;
|
||||
border: 1px solid var(--theme-control-border-strong, rgba(148, 163, 184, 0.35));
|
||||
background: var(--theme-surface-card, #ffffff);
|
||||
box-shadow: var(--theme-shadow-strong, 0 24px 64px rgba(15, 23, 42, 0.26));
|
||||
border: 1px solid var(--theme-control-border-strong);
|
||||
background: var(--theme-surface-card);
|
||||
box-shadow: var(--theme-shadow-strong);
|
||||
padding: 22px 22px 18px;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--theme-text-muted, #64748b);
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
h3 {
|
||||
@ -73,7 +73,7 @@ h3 {
|
||||
|
||||
.desc {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted, #64748b);
|
||||
color: var(--text-tertiary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ h3 {
|
||||
button {
|
||||
min-height: 38px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--theme-control-border, rgba(148, 163, 184, 0.3));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
padding: 0 15px;
|
||||
font-weight: 700;
|
||||
font-size: 13px;
|
||||
@ -101,12 +101,12 @@ button {
|
||||
.primary {
|
||||
border: none;
|
||||
background: linear-gradient(135deg, var(--claude-accent), var(--claude-accent-strong));
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.ghost {
|
||||
background: var(--theme-surface-soft, rgba(248, 250, 252, 0.9));
|
||||
color: var(--claude-text, inherit);
|
||||
background: var(--theme-surface-soft);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
button:hover:not(:disabled) {
|
||||
|
||||
@ -50,7 +50,7 @@ defineEmits<{
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.overlay-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.35); display: flex; align-items: center; justify-content: center; z-index: 1000; }
|
||||
.overlay-backdrop { position: fixed; inset: 0; background: var(--overlay-scrim); display: flex; align-items: center; justify-content: center; z-index: 1000; }
|
||||
.overlay-card { width: min(680px, 92vw); background: var(--theme-surface-soft); border: 1px solid var(--theme-control-border); border-radius: 12px; padding: 12px; }
|
||||
.overlay-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
|
||||
.overlay-header h3 { margin: 0; font-size: 16px; }
|
||||
|
||||
@ -192,12 +192,12 @@ function submit() {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.traffic-dot--close { background: #ff5f57; }
|
||||
.traffic-dot--close { background: var(--mac-close); }
|
||||
|
||||
.user-question-window-title {
|
||||
text-align: center;
|
||||
@ -266,7 +266,7 @@ function submit() {
|
||||
}
|
||||
|
||||
.user-question-nav button:hover:not(:disabled) {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.055));
|
||||
background: var(--hover-bg);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ function submit() {
|
||||
}
|
||||
|
||||
.user-question-option:hover {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.055));
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.user-question-option.active {
|
||||
@ -408,18 +408,18 @@ function submit() {
|
||||
}
|
||||
|
||||
.user-question-btn.ghost:hover {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.055));
|
||||
background: var(--hover-bg);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
.user-question-btn.primary {
|
||||
background: var(--claude-accent);
|
||||
border-color: var(--claude-accent-strong);
|
||||
color: #fffaf0;
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.user-question-btn.primary:hover:not(:disabled) {
|
||||
background: var(--claude-button-hover, var(--claude-accent-strong));
|
||||
background: var(--claude-button-hover);
|
||||
}
|
||||
|
||||
.user-question-btn:disabled {
|
||||
|
||||
@ -318,7 +318,7 @@ const formatTime = (value: string) => {
|
||||
width: 38px;
|
||||
height: 22px;
|
||||
border-radius: 999px;
|
||||
background: var(--theme-switch-track, #d7d1c5);
|
||||
background: var(--theme-switch-track);
|
||||
position: relative;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
@ -329,7 +329,7 @@ const formatTime = (value: string) => {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background: var(--theme-surface-strong, #ffffff);
|
||||
background: var(--theme-surface-strong);
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
transition: transform 0.2s ease;
|
||||
@ -386,7 +386,7 @@ const formatTime = (value: string) => {
|
||||
}
|
||||
|
||||
.scope-select-button:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.scope-select.disabled .scope-select-button,
|
||||
@ -435,7 +435,7 @@ const formatTime = (value: string) => {
|
||||
padding: 6px;
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 12px;
|
||||
background: var(--theme-surface-strong, #fff);
|
||||
background: var(--theme-surface-strong);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -461,7 +461,7 @@ const formatTime = (value: string) => {
|
||||
}
|
||||
|
||||
.scope-menu-option:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.scope-menu-option.disabled,
|
||||
@ -492,7 +492,7 @@ const formatTime = (value: string) => {
|
||||
}
|
||||
|
||||
.refresh-btn:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.refresh-btn:disabled {
|
||||
@ -516,7 +516,7 @@ const formatTime = (value: string) => {
|
||||
}
|
||||
|
||||
.icon-close-btn:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.05));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -572,7 +572,7 @@ const formatTime = (value: string) => {
|
||||
|
||||
.checkpoint-item:hover,
|
||||
.checkpoint-item.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.checkpoint-item.active {
|
||||
@ -622,11 +622,11 @@ const formatTime = (value: string) => {
|
||||
|
||||
/* diff 红绿增删色:通用语义色,保留固定值,三模式下含义一致 */
|
||||
.plus {
|
||||
color: #16a34a;
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.minus {
|
||||
color: #dc2626;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.files {
|
||||
@ -671,11 +671,11 @@ const formatTime = (value: string) => {
|
||||
}
|
||||
|
||||
.file-row:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.04));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.file-row.expanded {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.status {
|
||||
@ -719,7 +719,7 @@ const formatTime = (value: string) => {
|
||||
|
||||
.workspace-mismatch-tip {
|
||||
margin-right: auto;
|
||||
color: var(--claude-warning, #d99845);
|
||||
color: var(--claude-warning);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@ -732,7 +732,7 @@ const formatTime = (value: string) => {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
background: var(--claude-accent);
|
||||
color: #fffaf0;
|
||||
color: var(--on-accent);
|
||||
cursor: pointer;
|
||||
transition: background 140ms ease;
|
||||
}
|
||||
@ -746,12 +746,6 @@ const formatTime = (value: string) => {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* 暗色下主按钮文字保持高对比 */
|
||||
:global(:root[data-theme='dark']) .confirm-btn,
|
||||
:global(body[data-theme='dark']) .confirm-btn {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* ===== diff 展示:与文件编辑差异保持一致 ===== */
|
||||
.tool-result-diff {
|
||||
margin-top: 10px;
|
||||
@ -765,7 +759,7 @@ const formatTime = (value: string) => {
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
background: var(--theme-surface-soft, transparent);
|
||||
background: var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.diff-line {
|
||||
@ -777,13 +771,13 @@ const formatTime = (value: string) => {
|
||||
|
||||
/* diff 增删色:通用语义色,保留固定值 */
|
||||
.diff-remove {
|
||||
background: rgba(220, 38, 38, 0.12);
|
||||
color: #dc2626;
|
||||
background: var(--diff-del-bg);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.diff-add {
|
||||
background: rgba(22, 163, 74, 0.12);
|
||||
color: #16a34a;
|
||||
background: var(--diff-add-bg);
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.diff-context {
|
||||
|
||||
@ -139,7 +139,7 @@ onMounted(() => {
|
||||
.image-picker-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
background: var(--overlay-scrim);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -148,20 +148,20 @@ onMounted(() => {
|
||||
.image-picker-panel {
|
||||
width: min(780px, 92vw);
|
||||
max-height: 88vh;
|
||||
background: #0f1116;
|
||||
color: #e8ecf2;
|
||||
border: 1px solid #2a2f3a;
|
||||
background: var(--surface-panel);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0 16px 40px var(--shadow-color);
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #1f2430;
|
||||
border-bottom: 1px solid var(--border-default);
|
||||
}
|
||||
.header-left {
|
||||
display: flex;
|
||||
@ -172,11 +172,11 @@ onMounted(() => {
|
||||
font-weight: 600;
|
||||
}
|
||||
.local-btn {
|
||||
border: 1px solid #2f3645;
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 4px 10px;
|
||||
border-radius: 8px;
|
||||
background: #1b202c;
|
||||
color: #c5ccda;
|
||||
background: var(--surface-raised);
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -186,7 +186,7 @@ onMounted(() => {
|
||||
}
|
||||
.close-btn {
|
||||
background: transparent;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
@ -202,9 +202,9 @@ onMounted(() => {
|
||||
gap: 12px;
|
||||
}
|
||||
.card {
|
||||
border: 1px solid #1f2430;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
background: #151922;
|
||||
background: var(--surface-card);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
@ -214,61 +214,61 @@ onMounted(() => {
|
||||
.video-thumb {
|
||||
height: 110px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, rgba(76, 166, 255, 0.12), rgba(76, 166, 255, 0.05));
|
||||
border: 1px solid #243144;
|
||||
background: linear-gradient(135deg, color-mix(in srgb, var(--state-info) 12%, transparent), color-mix(in srgb, var(--state-info) 5%, transparent));
|
||||
border: 1px solid var(--border-strong);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #d9e6ff;
|
||||
color: var(--text-primary);
|
||||
gap: 6px;
|
||||
font-size: 28px;
|
||||
}
|
||||
.video-thumb .ext {
|
||||
font-size: 12px;
|
||||
color: #9fb7d8;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.card .name {
|
||||
padding: 8px 2px 0;
|
||||
font-size: 12px;
|
||||
color: #c5ccda;
|
||||
color: var(--text-secondary);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.card.selected {
|
||||
border-color: #4ca6ff;
|
||||
box-shadow: 0 0 0 2px rgba(76, 166, 255, 0.2);
|
||||
border-color: var(--state-info);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--state-info) 20%, transparent);
|
||||
}
|
||||
.loading,
|
||||
.empty {
|
||||
padding: 40px 0;
|
||||
text-align: center;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid #1f2430;
|
||||
border-top: 1px solid var(--border-default);
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.btn {
|
||||
border: 1px solid #2f3645;
|
||||
border: 1px solid var(--border-strong);
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
background: #1b202c;
|
||||
color: #e8ecf2;
|
||||
background: var(--surface-raised);
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn.primary {
|
||||
background: #4ca6ff;
|
||||
border-color: #4ca6ff;
|
||||
color: #0d1117;
|
||||
background: var(--state-info);
|
||||
border-color: var(--state-info);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
@ -276,7 +276,7 @@ onMounted(() => {
|
||||
}
|
||||
.count {
|
||||
font-size: 13px;
|
||||
color: #9aa3b5;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.grid {
|
||||
|
||||
@ -250,9 +250,9 @@ const parseFinalMessage = (text: string) => {
|
||||
.auto-approval-block {
|
||||
margin-top: 12px;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--theme-control-border, var(--border-color, #2a2f3a));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
border-radius: 8px;
|
||||
background: var(--theme-surface-muted, var(--panel-bg, rgba(0, 0, 0, 0.12)));
|
||||
background: var(--theme-surface-muted);
|
||||
}
|
||||
|
||||
.auto-approval-block__title {
|
||||
@ -281,11 +281,11 @@ const parseFinalMessage = (text: string) => {
|
||||
}
|
||||
|
||||
.auto-approval-block__decision--approved {
|
||||
color: #22c55e;
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.auto-approval-block__decision--rejected {
|
||||
color: #ef4444;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.auto-approval-block__reason {
|
||||
@ -294,8 +294,8 @@ const parseFinalMessage = (text: string) => {
|
||||
}
|
||||
|
||||
.tool-approval-panel.is-goal-approval-mode .auto-approval-block {
|
||||
background: var(--theme-surface-card, var(--theme-surface-soft));
|
||||
border-color: var(--theme-control-border, var(--claude-border));
|
||||
background: var(--theme-surface-card);
|
||||
border-color: var(--theme-control-border);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -310,12 +310,12 @@ const parseFinalMessage = (text: string) => {
|
||||
|
||||
:global(:root[data-theme='dark']) .auto-approval-block,
|
||||
:global(body[data-theme='dark']) .auto-approval-block {
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #141414) 86%, white 4%);
|
||||
border-color: var(--theme-control-border-strong, rgba(255, 255, 255, 0.12));
|
||||
color: var(--claude-text, #ffffff);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 86%, white 4%);
|
||||
border-color: var(--theme-control-border-strong);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
:global(:root[data-theme='dark']) .auto-approval-block__content,
|
||||
:global(body[data-theme='dark']) .auto-approval-block__content {
|
||||
color: var(--claude-text-secondary, #a0a0a0);
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -93,7 +93,7 @@ function confirmSelection() {
|
||||
.exp-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(33, 24, 14, 0.55);
|
||||
background: var(--overlay-scrim);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -102,11 +102,11 @@ function confirmSelection() {
|
||||
}
|
||||
.exp-card {
|
||||
width: min(1100px, 96vw);
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
background: var(--surface-soft);
|
||||
border-radius: 18px;
|
||||
padding: 24px 28px;
|
||||
box-shadow: none;
|
||||
border: 1px solid rgba(118, 103, 84, 0.25);
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
.exp-header {
|
||||
display: flex;
|
||||
@ -117,17 +117,17 @@ function confirmSelection() {
|
||||
}
|
||||
.title {
|
||||
font-size: 22px;
|
||||
color: #3d3929;
|
||||
color: var(--text-primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
color: #7f7766;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.confirm-btn {
|
||||
border: none;
|
||||
background: #da7756;
|
||||
color: #fff;
|
||||
background: var(--accent);
|
||||
color: var(--on-accent);
|
||||
border-radius: 12px;
|
||||
padding: 10px 18px;
|
||||
font-weight: 600;
|
||||
@ -139,20 +139,20 @@ function confirmSelection() {
|
||||
gap: 16px;
|
||||
}
|
||||
.mode-card {
|
||||
border: 1px solid rgba(118, 103, 84, 0.25);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 14px;
|
||||
padding: 16px 14px;
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease;
|
||||
box-shadow: none;
|
||||
background: #fff;
|
||||
background: var(--surface-raised);
|
||||
}
|
||||
.mode-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: none;
|
||||
}
|
||||
.mode-card.active {
|
||||
border-color: #da7756;
|
||||
border-color: var(--accent);
|
||||
box-shadow: none;
|
||||
}
|
||||
.badge {
|
||||
@ -160,8 +160,8 @@ function confirmSelection() {
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
color: #bd5d3a;
|
||||
background: rgba(218, 119, 86, 0.14);
|
||||
color: var(--accent-strong);
|
||||
background: var(--highlight);
|
||||
padding: 4px 10px;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 8px;
|
||||
@ -170,12 +170,12 @@ function confirmSelection() {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 14px;
|
||||
background: rgba(218, 119, 86, 0.12);
|
||||
background: var(--highlight);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
color: #bd5d3a;
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
.icon svg {
|
||||
width: 30px;
|
||||
@ -184,12 +184,12 @@ function confirmSelection() {
|
||||
.mode-card h3 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 17px;
|
||||
color: #3d3929;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.mode-card p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #7f7766;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1779,7 +1779,9 @@ const blockDisplayLabel = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const currentCompactMessageDisplay = computed(() => experiments.value.compactMessageDisplay);
|
||||
const currentCompactMessageDisplay = computed(
|
||||
() => form.value.compact_message_display || 'full'
|
||||
);
|
||||
|
||||
const compactMessageDisplayLabel = computed(() => {
|
||||
return (
|
||||
@ -2351,29 +2353,29 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
|
||||
<style scoped>
|
||||
.settings-redesign-card {
|
||||
--settings-floating-menu-bg: #ffffff;
|
||||
--settings-floating-menu-hover: rgba(0, 0, 0, 0.055);
|
||||
--settings-floating-menu-bg: color-mix(in srgb, var(--surface-soft) 90%, var(--surface-raised));
|
||||
--settings-floating-menu-hover: var(--hover-bg);
|
||||
--settings-floating-menu-shadow: none;
|
||||
--settings-tab-hover-bg: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
--settings-tab-active-bg: var(--theme-tab-active, rgba(0, 0, 0, 0.078));
|
||||
--settings-tab-hover-bg: var(--theme-tab-active);
|
||||
--settings-tab-active-bg: var(--theme-tab-active);
|
||||
position: relative;
|
||||
width: min(70vw, calc(100vw - 24px));
|
||||
height: min(80vh, calc(100vh - 24px));
|
||||
padding: 30px 42px 24px;
|
||||
border-radius: 32px;
|
||||
overflow: visible;
|
||||
background: var(--theme-surface-soft, var(--claude-panel));
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
background: var(--theme-surface-soft);
|
||||
border: 1px solid var(--theme-control-border);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:global(html[data-theme='dark']) .settings-redesign-card,
|
||||
:global(body[data-theme='dark']) .settings-redesign-card {
|
||||
--settings-floating-menu-bg: #1a1a1a;
|
||||
--settings-floating-menu-hover: rgba(255, 255, 255, 0.08);
|
||||
--settings-floating-menu-bg: var(--surface-panel);
|
||||
--settings-floating-menu-hover: var(--hover-bg);
|
||||
--settings-floating-menu-shadow: none;
|
||||
--settings-tab-hover-bg: rgba(255, 255, 255, 0.078);
|
||||
--settings-tab-active-bg: rgba(255, 255, 255, 0.078);
|
||||
--settings-tab-hover-bg: var(--hover-bg);
|
||||
--settings-tab-active-bg: var(--hover-bg);
|
||||
}
|
||||
|
||||
.settings-close-button {
|
||||
@ -2393,7 +2395,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.settings-close-button:hover {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.06));
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.settings-close-button svg {
|
||||
@ -2420,7 +2422,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
margin-top: 68px;
|
||||
height: calc(100% - 68px);
|
||||
padding-right: 28px;
|
||||
border-right: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border-right: 1px solid var(--theme-control-border);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
@ -2507,7 +2509,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
|
||||
.settings-redesign-title-line {
|
||||
height: 1px;
|
||||
background: var(--theme-control-border, var(--claude-border));
|
||||
background: var(--theme-control-border);
|
||||
margin: 22px 0 8px;
|
||||
flex: 0 0 1px;
|
||||
}
|
||||
@ -2549,7 +2551,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.settings-action-row,
|
||||
.settings-toggle-row {
|
||||
min-height: 64px;
|
||||
border-bottom: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border-bottom: 1px solid var(--theme-control-border);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
@ -2614,7 +2616,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.settings-select-button:hover {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.055));
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.settings-select-button .select-chevron {
|
||||
@ -2649,7 +2651,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
padding: 6px;
|
||||
border-radius: 20px;
|
||||
background: var(--settings-floating-menu-bg);
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
box-shadow: var(--settings-floating-menu-shadow);
|
||||
opacity: 1;
|
||||
backdrop-filter: none;
|
||||
@ -2662,23 +2664,23 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.settings-floating-menu.dark {
|
||||
background: #1a1a1a !important;
|
||||
background: var(--surface-panel) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.settings-floating-menu.dark .settings-menu-option:hover {
|
||||
background: rgba(255, 255, 255, 0.08) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
}
|
||||
|
||||
:global(html[data-theme='dark']) :global(.settings-floating-menu),
|
||||
:global(body[data-theme='dark']) :global(.settings-floating-menu) {
|
||||
background: #1a1a1a !important;
|
||||
background: var(--surface-panel) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:global(html[data-theme='dark']) :global(.settings-menu-option:hover),
|
||||
:global(body[data-theme='dark']) :global(.settings-menu-option:hover) {
|
||||
background: rgba(255, 255, 255, 0.08) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
}
|
||||
|
||||
.settings-menu-option {
|
||||
@ -2757,7 +2759,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.settings-number-input,
|
||||
.settings-compression-grid input {
|
||||
height: 38px;
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
border-radius: 12px;
|
||||
background: transparent;
|
||||
color: var(--claude-text);
|
||||
@ -2779,7 +2781,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.settings-section-divider__label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--claude-text-secondary, #7f7766);
|
||||
color: var(--claude-text-secondary);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.settings-section-divider::after {
|
||||
@ -2787,7 +2789,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
margin-left: 10px;
|
||||
background: var(--theme-control-border, var(--claude-border));
|
||||
background: var(--theme-control-border);
|
||||
}
|
||||
|
||||
.settings-input-row > input {
|
||||
@ -2834,7 +2836,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.settings-add-row button,
|
||||
.settings-secondary-button,
|
||||
.settings-primary-button {
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
color: var(--claude-text);
|
||||
@ -2848,18 +2850,18 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.settings-number-row button:hover,
|
||||
.settings-add-row button:hover,
|
||||
.settings-secondary-button:hover {
|
||||
background: var(--theme-hover-bg, rgba(0, 0, 0, 0.055));
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.settings-chip-row button.active,
|
||||
.settings-primary-button {
|
||||
border-color: var(--claude-accent);
|
||||
background: var(--claude-accent);
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.settings-secondary-button.danger {
|
||||
color: var(--claude-warning, #c85f45);
|
||||
color: var(--claude-warning);
|
||||
}
|
||||
|
||||
.settings-inline-actions {
|
||||
@ -2880,7 +2882,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.settings-mini-status.warning {
|
||||
color: var(--claude-warning, #c85f45);
|
||||
color: var(--claude-warning);
|
||||
}
|
||||
|
||||
.settings-add-row,
|
||||
@ -2907,7 +2909,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
|
||||
.settings-consideration-list li {
|
||||
min-height: 34px;
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
border-radius: 12px;
|
||||
padding: 0 8px;
|
||||
display: grid;
|
||||
@ -2980,7 +2982,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.settings-group-block {
|
||||
border-bottom: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border-bottom: 1px solid var(--theme-control-border);
|
||||
padding: 14px 0 16px;
|
||||
}
|
||||
|
||||
@ -3099,7 +3101,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
.usage-summary-item {
|
||||
padding: 12px 14px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@ -3132,7 +3134,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
}
|
||||
|
||||
.usage-summary-refresh {
|
||||
border: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border: 1px solid var(--theme-control-border);
|
||||
border-radius: 999px;
|
||||
padding: 7px 14px;
|
||||
background: transparent;
|
||||
@ -3170,7 +3172,7 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => {
|
||||
padding-right: 0;
|
||||
padding-bottom: 12px;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border-bottom: 1px solid var(--theme-control-border);
|
||||
flex-direction: row;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
@ -21,6 +21,7 @@ interface PersonalForm {
|
||||
skill_strict_run_command_background_enabled: boolean;
|
||||
silent_tool_disable: boolean;
|
||||
enhanced_tool_display: boolean;
|
||||
compact_message_display: CompactMessageDisplay;
|
||||
show_git_status_bar: boolean;
|
||||
enhanced_tool_display_categories: string[];
|
||||
enabled_skills: string[];
|
||||
@ -116,6 +117,7 @@ const defaultForm = (): PersonalForm => ({
|
||||
skill_strict_run_command_background_enabled: false,
|
||||
silent_tool_disable: false,
|
||||
enhanced_tool_display: true,
|
||||
compact_message_display: 'full',
|
||||
show_git_status_bar: true,
|
||||
enhanced_tool_display_categories: [],
|
||||
enabled_skills: [],
|
||||
@ -295,6 +297,7 @@ export const usePersonalizationStore = defineStore('personalization', {
|
||||
!!data.skill_strict_run_command_background_enabled,
|
||||
silent_tool_disable: !!data.silent_tool_disable,
|
||||
enhanced_tool_display: data.enhanced_tool_display !== false,
|
||||
compact_message_display: data.compact_message_display === 'brief' ? 'brief' : 'full',
|
||||
show_git_status_bar: data.show_git_status_bar !== false,
|
||||
enhanced_tool_display_categories: Array.isArray(data.enhanced_tool_display_categories)
|
||||
? data.enhanced_tool_display_categories.filter((item: unknown) => typeof item === 'string')
|
||||
@ -381,6 +384,18 @@ export const usePersonalizationStore = defineStore('personalization', {
|
||||
if (this.form.default_hide_workspace) {
|
||||
useUiStore().setWorkspaceCollapsed(true);
|
||||
}
|
||||
// 简略消息显示:以配置文件为准,同步到旧版 localStorage 镜像供 ChatArea 读取。
|
||||
// 一次性迁移:后端仍为默认 full,但本地缓存遗留 brief(旧版纯前端记录)时,回写到配置文件。
|
||||
const cachedCompact = this.experiments.compactMessageDisplay;
|
||||
if (this.form.compact_message_display === 'full' && cachedCompact === 'brief') {
|
||||
this.form = { ...this.form, compact_message_display: 'brief' };
|
||||
void this.persistCompactMessageDisplay('brief');
|
||||
}
|
||||
this.experiments = {
|
||||
...this.experiments,
|
||||
compactMessageDisplay: this.form.compact_message_display
|
||||
};
|
||||
this.persistExperiments();
|
||||
this.clearFeedback();
|
||||
},
|
||||
applyTheme(theme: 'classic' | 'light' | 'dark') {
|
||||
@ -791,11 +806,35 @@ export const usePersonalizationStore = defineStore('personalization', {
|
||||
this.persistExperiments();
|
||||
},
|
||||
setCompactMessageDisplay(mode: CompactMessageDisplay) {
|
||||
const target: CompactMessageDisplay = mode === 'brief' ? 'brief' : 'full';
|
||||
this.form = {
|
||||
...this.form,
|
||||
compact_message_display: target
|
||||
};
|
||||
// 同步旧版 localStorage 镜像,保持兼容并避免迁移逻辑回写旧值
|
||||
this.experiments = {
|
||||
...this.experiments,
|
||||
compactMessageDisplay: mode
|
||||
compactMessageDisplay: target
|
||||
};
|
||||
this.persistExperiments();
|
||||
this.clearFeedback();
|
||||
// 持久化到后端配置文件(即时保存,参照主题/默认隐藏工作区)
|
||||
void this.persistCompactMessageDisplay(target);
|
||||
},
|
||||
async persistCompactMessageDisplay(mode: CompactMessageDisplay) {
|
||||
try {
|
||||
const resp = await fetch('/api/personalization', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ compact_message_display: mode })
|
||||
});
|
||||
const result = await resp.json();
|
||||
if (!resp.ok || !result.success) {
|
||||
console.warn('保存简略消息显示失败:', result?.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('保存简略消息显示失败:', error);
|
||||
}
|
||||
},
|
||||
setCommunicationStyle(style: 'default' | 'human_like') {
|
||||
this.form = {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
html,
|
||||
body {
|
||||
height: var(--app-viewport, 100vh);
|
||||
height: var(--app-viewport);
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@ -1,186 +1,318 @@
|
||||
/* CSS variables + shared design tokens */
|
||||
/* 设计 Token —— 两层结构:语义层(按主题取值)+ 兼容别名层 */
|
||||
/* 规范见 doc/frontend/color_token_spec.md。本文件为结构重构产物,值与重构前逐一致(零视觉变化)。 */
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
/* 主题无关的布局变量 */
|
||||
--app-viewport: 100vh;
|
||||
--app-bottom-inset: env(safe-area-inset-bottom, 0px);
|
||||
--claude-bg: #eeece2;
|
||||
--claude-panel: rgba(255, 255, 255, 0.82);
|
||||
--claude-left-rail: #f7f3ea;
|
||||
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
||||
--claude-border: rgba(118, 103, 84, 0.25);
|
||||
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
||||
--claude-text: #3d3929;
|
||||
--claude-text-secondary: #7f7766;
|
||||
--claude-text-tertiary: #a59a86;
|
||||
--claude-muted: rgba(121, 109, 94, 0.4);
|
||||
--claude-accent: #da7756;
|
||||
--claude-accent-strong: #bd5d3a;
|
||||
--claude-deep: #f2a93b;
|
||||
--claude-deep-strong: #d07a14;
|
||||
--claude-highlight: rgba(218, 119, 86, 0.14);
|
||||
--claude-button-hover: #c76541;
|
||||
--claude-button-active: #a95331;
|
||||
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||
--claude-success: #16a34a;
|
||||
--claude-warning: #d99845;
|
||||
--claude-danger: #dc2626;
|
||||
--git-diff-add-text: #00e000;
|
||||
--git-diff-del-text: #ff1a1a;
|
||||
/* Theme-neutral surfaces */
|
||||
--theme-surface-card: #fffaf4;
|
||||
--theme-surface-strong: #ffffff;
|
||||
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
||||
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
||||
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||
--theme-control-border: rgba(118, 103, 84, 0.25);
|
||||
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
||||
--theme-switch-track: #d7d1c5;
|
||||
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
||||
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
||||
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
||||
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
||||
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
||||
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
||||
|
||||
/* 装饰色(主题无关,固定品牌色):macOS 风格窗口关闭红绿灯 */
|
||||
--mac-close: #ff5f57;
|
||||
--mac-close-hover: #ff3b30;
|
||||
--mac-close-border: #e0443e;
|
||||
/* 媒体上的文字可读性阴影(主题无关,需固定强暗影压住任意底图) */
|
||||
--text-shadow-legible: rgba(0, 0, 0, 0.8);
|
||||
/* 彩蛋装饰色(主题无关,固定festive色) */
|
||||
--decorative-gold: #ffd700;
|
||||
--decorative-pink: #ff69b4;
|
||||
/* 玻璃质感/实验视觉装饰光斑(主题无关,固定品牌渐变色,刻意不随主题变) */
|
||||
--glass-tint-blue: rgba(104, 147, 255, 0.2);
|
||||
--glass-tint-blue-soft: rgba(128, 183, 255, 0.18);
|
||||
--glass-tint-blue-mid: rgba(140, 180, 255, 0.35);
|
||||
--glass-tint-amber: rgba(255, 200, 150, 0.22);
|
||||
--glass-base-deep: rgba(28, 27, 41, 0.95);
|
||||
--glass-shadow-deep: rgba(24, 20, 37, 0.45);
|
||||
/* 进度环未完成轨道(主题无关,固定中性灰) */
|
||||
--progress-track: rgba(127, 135, 146, 0.28);
|
||||
/* 拖拽预览浮层投影(主题无关,固定黑投影) */
|
||||
--drag-preview-shadow: rgba(0, 0, 0, 0.35);
|
||||
|
||||
/* === 兼容别名(旧 token 名 → 新语义 token),迁移完成后删除 === */
|
||||
--claude-bg: var(--surface-base);
|
||||
--claude-panel: var(--surface-panel);
|
||||
--claude-left-rail: var(--surface-rail);
|
||||
--claude-sidebar: var(--surface-sidebar);
|
||||
--theme-surface-card: var(--surface-card);
|
||||
--theme-surface-strong: var(--surface-raised);
|
||||
--theme-surface-soft: var(--surface-soft);
|
||||
--theme-surface-muted: var(--surface-muted);
|
||||
--claude-text: var(--text-primary);
|
||||
--claude-text-secondary: var(--text-secondary);
|
||||
--claude-text-tertiary: var(--text-tertiary);
|
||||
--claude-muted: var(--text-muted);
|
||||
--claude-border: var(--border-default);
|
||||
--claude-border-strong: var(--border-strong);
|
||||
--theme-card-border-strong: var(--border-card-strong);
|
||||
--theme-chip-border: var(--chip-border);
|
||||
--claude-accent: var(--accent);
|
||||
--claude-accent-strong: var(--accent-strong);
|
||||
--claude-button-hover: var(--accent-hover);
|
||||
--claude-button-active: var(--accent-active);
|
||||
--claude-deep: var(--accent-deep);
|
||||
--claude-deep-strong: var(--accent-deep-strong);
|
||||
--claude-success: var(--state-success);
|
||||
--claude-warning: var(--state-warning);
|
||||
--claude-danger: var(--state-danger);
|
||||
--claude-highlight: var(--highlight);
|
||||
--theme-tab-active: var(--tab-active);
|
||||
--theme-chip-bg: var(--chip-bg);
|
||||
--theme-badge-bg: var(--badge-bg);
|
||||
--theme-switch-track: var(--switch-track);
|
||||
--claude-shadow: var(--shadow-card);
|
||||
--theme-shadow-soft: var(--shadow-soft);
|
||||
--theme-shadow-mid: var(--shadow-mid);
|
||||
--theme-shadow-strong: var(--shadow-strong);
|
||||
--theme-overlay-scrim: var(--overlay-scrim);
|
||||
--theme-mobile-menu: var(--mobile-menu);
|
||||
--theme-mobile-menu-shadow: var(--mobile-menu-shadow);
|
||||
--git-diff-add-text: var(--diff-add-text);
|
||||
--git-diff-del-text: var(--diff-del-text);
|
||||
/* 合并项:下列旧名与上面某新名同值,统一指向合并后的语义 token */
|
||||
--theme-control-border: var(--border-default);
|
||||
--theme-control-border-strong: var(--border-strong);
|
||||
}
|
||||
|
||||
:root[data-theme='classic'] {
|
||||
color-scheme: light;
|
||||
--claude-bg: #eeece2;
|
||||
--claude-panel: rgba(255, 255, 255, 0.82);
|
||||
--claude-left-rail: #f7f3ea;
|
||||
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
||||
--claude-border: rgba(118, 103, 84, 0.25);
|
||||
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
||||
--claude-text: #3d3929;
|
||||
--claude-text-secondary: #7f7766;
|
||||
--claude-text-tertiary: #a59a86;
|
||||
--claude-muted: rgba(121, 109, 94, 0.4);
|
||||
--claude-accent: #da7756;
|
||||
--claude-accent-strong: #bd5d3a;
|
||||
--claude-deep: #f2a93b;
|
||||
--claude-deep-strong: #d07a14;
|
||||
--claude-highlight: rgba(218, 119, 86, 0.14);
|
||||
--claude-button-hover: #c76541;
|
||||
--claude-button-active: #a95331;
|
||||
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||
--claude-success: #16a34a;
|
||||
--claude-warning: #d99845;
|
||||
--claude-danger: #dc2626;
|
||||
--git-diff-add-text: #00e000;
|
||||
--git-diff-del-text: #ff1a1a;
|
||||
--theme-surface-card: #fffaf4;
|
||||
--theme-surface-strong: #ffffff;
|
||||
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
||||
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
||||
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||
--theme-control-border: rgba(118, 103, 84, 0.25);
|
||||
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
||||
--theme-switch-track: #d7d1c5;
|
||||
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
||||
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
||||
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
||||
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
||||
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
||||
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
||||
/* Surface 表面层级 —— Claude 亮色暖奶油盘(canvas<soft<card<cream-strong,raised纯白浮起) */
|
||||
--surface-base: #faf9f5;
|
||||
--surface-panel: #faf9f5;
|
||||
--surface-rail: #f5f0e8;
|
||||
--surface-sidebar: #f5f0e8;
|
||||
--surface-card: #efe9de;
|
||||
--surface-raised: #ffffff;
|
||||
--surface-soft: #f5f0e8;
|
||||
--surface-muted: #e8e0d2;
|
||||
/* Text 文字 —— Claude */
|
||||
--text-primary: #141413;
|
||||
--text-secondary: #3d3d3a;
|
||||
--text-tertiary: #6c6a64;
|
||||
--text-muted: rgba(108, 106, 100, 0.55);
|
||||
/* Border 边框 —— Claude hairline */
|
||||
--border-default: #e6dfd8;
|
||||
--border-strong: #d8cfc4;
|
||||
--border-card-strong: #e6dfd8;
|
||||
--chip-border: #ebe6df;
|
||||
/* Accent 强调 —— Claude primary,克制 CTA-only */
|
||||
--accent: #cc785c;
|
||||
--accent-strong: #a9583e;
|
||||
--accent-hover: #bd6a4f;
|
||||
--accent-active: #a9583e;
|
||||
--accent-deep: #6c6a64;
|
||||
--accent-deep-strong: #3d3d3a;
|
||||
--on-accent: #ffffff;
|
||||
/* State 状态 —— Claude semantic */
|
||||
--state-success: #5db872;
|
||||
--state-warning: #d4a017;
|
||||
--state-danger: #c64545;
|
||||
--state-danger-strong: #a83838;
|
||||
--status-offline: #c64545;
|
||||
--state-info: #5db8a6;
|
||||
/* Highlight / 交互态 —— 中性暖灰(不带橙) */
|
||||
--highlight: rgba(20, 20, 19, 0.05);
|
||||
--tab-active: rgba(20, 20, 19, 0.07);
|
||||
--chip-bg: #f5f0e8;
|
||||
--badge-bg: #efe9de;
|
||||
--switch-track: #d8cfc4;
|
||||
--hover-bg: rgba(20, 20, 19, 0.05);
|
||||
--pulse-ring: rgba(0, 0, 0, 0.1);
|
||||
/* Shadow 阴影 */
|
||||
--shadow-card: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||
--shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||
--shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||
--shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||
--shadow-color: rgba(0, 0, 0, 0.1);
|
||||
/* Overlay / 移动端 */
|
||||
--overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||
--mobile-menu: #f5f0e8;
|
||||
--mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||
/* 专用色 */
|
||||
--diff-add-text: #00e000;
|
||||
--diff-del-text: #ff1a1a;
|
||||
--diff-add-bg: rgba(22, 163, 74, 0.12);
|
||||
--diff-del-bg: rgba(220, 38, 38, 0.12);
|
||||
}
|
||||
|
||||
:root[data-theme='light'] {
|
||||
color-scheme: light;
|
||||
/* 类似 ChatGPT 的明亮配色:白底黑字,优雅浅灰 */
|
||||
--claude-bg: #ffffff;
|
||||
--claude-panel: #ffffff;
|
||||
--claude-left-rail: #f9f9f9;
|
||||
--claude-sidebar: #ffffff;
|
||||
--claude-border: rgba(0, 0, 0, 0.08);
|
||||
--claude-border-strong: rgba(0, 0, 0, 0.12);
|
||||
--claude-text: #0d0d0d;
|
||||
--claude-text-secondary: #676767;
|
||||
--claude-text-tertiary: #8e8e8e;
|
||||
--claude-muted: rgba(0, 0, 0, 0.3);
|
||||
--claude-accent: #acacac;
|
||||
--claude-accent-strong: #8e8e8e;
|
||||
--claude-deep: #c4c4c4;
|
||||
--claude-deep-strong: #acacac;
|
||||
--claude-highlight: rgba(0, 0, 0, 0.05);
|
||||
--claude-button-hover: #d1d1d1;
|
||||
--claude-button-active: #acacac;
|
||||
--claude-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
--claude-success: #10b981;
|
||||
--claude-warning: #f59e0b;
|
||||
--claude-danger: #dc2626;
|
||||
--git-diff-add-text: #00e000;
|
||||
--git-diff-del-text: #ff1a1a;
|
||||
--theme-surface-card: #ffffff;
|
||||
--theme-surface-strong: #ffffff;
|
||||
--theme-surface-soft: #ffffff;
|
||||
--theme-surface-muted: #fafafa;
|
||||
--theme-overlay-scrim: rgba(0, 0, 0, 0.5);
|
||||
--theme-shadow-strong: 0 2px 4px rgba(0, 0, 0, 0.08);
|
||||
--theme-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
--theme-shadow-mid: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||
--theme-control-border: rgba(0, 0, 0, 0.08);
|
||||
--theme-control-border-strong: rgba(0, 0, 0, 0.12);
|
||||
--theme-switch-track: #ececec;
|
||||
--theme-chip-bg: #f5f5f5;
|
||||
--theme-chip-border: rgba(0, 0, 0, 0.08);
|
||||
--theme-badge-bg: #f5f5f5;
|
||||
--theme-tab-active: rgba(0, 0, 0, 0.05);
|
||||
--theme-mobile-menu: rgba(255, 255, 255, 0.95);
|
||||
--theme-mobile-menu-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
--theme-card-border-strong: rgba(0, 0, 0, 0.1);
|
||||
/* Surface 表面层级 —— ChatGPT 亮色冷白盘 */
|
||||
--surface-base: #ffffff;
|
||||
--surface-panel: #ffffff;
|
||||
--surface-rail: #f9f9f9;
|
||||
--surface-sidebar: #f9f9f9;
|
||||
--surface-card: #ffffff;
|
||||
--surface-raised: #ffffff;
|
||||
--surface-soft: #f9f9f9;
|
||||
--surface-muted: #f3f3f3;
|
||||
/* Text 文字 —— ChatGPT */
|
||||
--text-primary: #0d0d0d;
|
||||
--text-secondary: #5d5d5d;
|
||||
--text-tertiary: #8f8f8f;
|
||||
--text-muted: rgba(13, 13, 13, 0.35);
|
||||
/* Border 边框 —— ChatGPT hairline */
|
||||
--border-default: rgba(13, 13, 13, 0.1);
|
||||
--border-strong: rgba(13, 13, 13, 0.15);
|
||||
--border-card-strong: rgba(13, 13, 13, 0.1);
|
||||
--chip-border: rgba(13, 13, 13, 0.05);
|
||||
/* Accent 强调 —— ChatGPT primary(近黑,克制 CTA-only) */
|
||||
--accent: #181818;
|
||||
--accent-strong: #181818;
|
||||
--accent-hover: #303030;
|
||||
--accent-active: #414141;
|
||||
--accent-deep: #5d5d5d;
|
||||
--accent-deep-strong: #414141;
|
||||
--on-accent: #ffffff;
|
||||
/* State 状态 —— ChatGPT semantic */
|
||||
--state-success: #00a240;
|
||||
--state-warning: #e25507;
|
||||
--state-danger: #e02e2a;
|
||||
--state-danger-strong: #911e1b;
|
||||
--status-offline: #e02e2a;
|
||||
--state-info: #0285ff;
|
||||
/* Highlight / 交互态 —— 中性冷灰 */
|
||||
--highlight: rgba(13, 13, 13, 0.05);
|
||||
--tab-active: rgba(13, 13, 13, 0.05);
|
||||
--chip-bg: #f3f3f3;
|
||||
--badge-bg: #f3f3f3;
|
||||
--switch-track: #ececec;
|
||||
--hover-bg: rgba(13, 13, 13, 0.05);
|
||||
--pulse-ring: rgba(0, 0, 0, 0.1);
|
||||
/* Shadow 阴影 */
|
||||
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
--shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
--shadow-mid: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||
--shadow-strong: 0 2px 4px rgba(0, 0, 0, 0.08);
|
||||
--shadow-color: rgba(0, 0, 0, 0.1);
|
||||
/* Overlay / 移动端 */
|
||||
--overlay-scrim: rgba(0, 0, 0, 0.5);
|
||||
--mobile-menu: #ffffff;
|
||||
--mobile-menu-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
/* 专用色 */
|
||||
--diff-add-text: #00e000;
|
||||
--diff-del-text: #ff1a1a;
|
||||
--diff-add-bg: rgba(22, 163, 74, 0.12);
|
||||
--diff-del-bg: rgba(220, 38, 38, 0.12);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
color-scheme: dark;
|
||||
/* 暗色主题:灰黑色底色,白色文字 */
|
||||
--claude-bg: #1a1a1a;
|
||||
--claude-panel: #1a1a1a;
|
||||
--claude-left-rail: #181818;
|
||||
--claude-sidebar: #181818;
|
||||
--claude-border: rgba(255, 255, 255, 0.08);
|
||||
--claude-border-strong: rgba(255, 255, 255, 0.12);
|
||||
--claude-text: #ffffff;
|
||||
--claude-text-secondary: #a0a0a0;
|
||||
--claude-text-tertiary: #707070;
|
||||
--claude-muted: rgba(255, 255, 255, 0.3);
|
||||
--claude-accent: #606060;
|
||||
--claude-accent-strong: #505050;
|
||||
--claude-deep: #808080;
|
||||
--claude-deep-strong: #606060;
|
||||
--claude-highlight: rgba(255, 255, 255, 0.05);
|
||||
--claude-button-hover: #707070;
|
||||
--claude-button-active: #505050;
|
||||
--claude-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
--claude-success: #10b981;
|
||||
--claude-warning: #f59e0b;
|
||||
--claude-danger: #dc2626;
|
||||
--git-diff-add-text: #00e000;
|
||||
--git-diff-del-text: #ff1a1a;
|
||||
--theme-surface-card: #0a0a0a;
|
||||
--theme-surface-strong: #1a1a1a;
|
||||
--theme-surface-soft: #0f0f0f;
|
||||
--theme-surface-muted: #141414;
|
||||
--theme-overlay-scrim: rgba(0, 0, 0, 0.8);
|
||||
--theme-shadow-strong: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||
--theme-shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
--theme-shadow-mid: 0 3px 8px rgba(0, 0, 0, 0.5);
|
||||
--theme-control-border: rgba(255, 255, 255, 0.08);
|
||||
--theme-control-border-strong: rgba(255, 255, 255, 0.12);
|
||||
--theme-switch-track: #2a2a2a;
|
||||
--theme-chip-bg: #2a2a2a;
|
||||
--theme-chip-border: rgba(255, 255, 255, 0.08);
|
||||
--theme-badge-bg: #2a2a2a;
|
||||
--theme-tab-active: rgba(255, 255, 255, 0.05);
|
||||
--theme-mobile-menu: rgba(10, 10, 10, 0.95);
|
||||
--theme-mobile-menu-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||
--theme-card-border-strong: rgba(255, 255, 255, 0.1);
|
||||
/* Surface 表面层级 */
|
||||
--surface-base: #1a1a1a;
|
||||
--surface-panel: #1a1a1a;
|
||||
--surface-rail: #181818;
|
||||
--surface-sidebar: #181818;
|
||||
--surface-card: #0a0a0a;
|
||||
--surface-raised: #1a1a1a;
|
||||
--surface-soft: #0f0f0f;
|
||||
--surface-muted: #141414;
|
||||
/* Text 文字 */
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #a0a0a0;
|
||||
--text-tertiary: #707070;
|
||||
--text-muted: rgba(255, 255, 255, 0.3);
|
||||
/* Border 边框 */
|
||||
--border-default: rgba(255, 255, 255, 0.08);
|
||||
--border-strong: rgba(255, 255, 255, 0.12);
|
||||
--border-card-strong: rgba(255, 255, 255, 0.1);
|
||||
--chip-border: rgba(255, 255, 255, 0.08);
|
||||
/* Accent 强调(含运行模式 deep) */
|
||||
--accent: #606060;
|
||||
--accent-strong: #505050;
|
||||
--accent-hover: #707070;
|
||||
--accent-active: #505050;
|
||||
--accent-deep: #808080;
|
||||
--accent-deep-strong: #606060;
|
||||
--on-accent: #ffffff;
|
||||
/* State 状态 */
|
||||
--state-success: #10b981;
|
||||
--state-warning: #f59e0b;
|
||||
--state-danger: #dc2626;
|
||||
--state-danger-strong: #b91c1c;
|
||||
--status-offline: #e34d4d;
|
||||
--state-info: #60a5fa;
|
||||
/* Highlight / 交互态 */
|
||||
--highlight: rgba(255, 255, 255, 0.05);
|
||||
--tab-active: rgba(255, 255, 255, 0.05);
|
||||
--chip-bg: #2a2a2a;
|
||||
--badge-bg: #2a2a2a;
|
||||
--switch-track: #2a2a2a;
|
||||
--hover-bg: rgba(255, 255, 255, 0.06);
|
||||
--pulse-ring: rgba(255, 255, 255, 0.1);
|
||||
/* Shadow 阴影 */
|
||||
--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
--shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
--shadow-mid: 0 3px 8px rgba(0, 0, 0, 0.5);
|
||||
--shadow-strong: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||
--shadow-color: rgba(0, 0, 0, 0.4);
|
||||
/* Overlay / 移动端 */
|
||||
--overlay-scrim: rgba(0, 0, 0, 0.8);
|
||||
--mobile-menu: rgba(10, 10, 10, 0.95);
|
||||
--mobile-menu-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||
/* 专用色 */
|
||||
--diff-add-text: #00e000;
|
||||
--diff-del-text: #ff1a1a;
|
||||
--diff-add-bg: rgba(22, 163, 74, 0.12);
|
||||
--diff-del-bg: rgba(220, 38, 38, 0.12);
|
||||
}
|
||||
|
||||
/* 首屏(JS 设置 data-theme 之前)回退到 classic 取值 */
|
||||
:root:not([data-theme]) {
|
||||
/* Surface 表面层级 —— 同 classic(Claude 亮色暖奶油盘) */
|
||||
--surface-base: #faf9f5;
|
||||
--surface-panel: #faf9f5;
|
||||
--surface-rail: #f5f0e8;
|
||||
--surface-sidebar: #f5f0e8;
|
||||
--surface-card: #efe9de;
|
||||
--surface-raised: #ffffff;
|
||||
--surface-soft: #f5f0e8;
|
||||
--surface-muted: #e8e0d2;
|
||||
/* Text 文字 */
|
||||
--text-primary: #141413;
|
||||
--text-secondary: #3d3d3a;
|
||||
--text-tertiary: #6c6a64;
|
||||
--text-muted: rgba(108, 106, 100, 0.55);
|
||||
/* Border 边框 */
|
||||
--border-default: #e6dfd8;
|
||||
--border-strong: #d8cfc4;
|
||||
--border-card-strong: #e6dfd8;
|
||||
--chip-border: #ebe6df;
|
||||
/* Accent 强调 */
|
||||
--accent: #cc785c;
|
||||
--accent-strong: #a9583e;
|
||||
--accent-hover: #bd6a4f;
|
||||
--accent-active: #a9583e;
|
||||
--accent-deep: #6c6a64;
|
||||
--accent-deep-strong: #3d3d3a;
|
||||
--on-accent: #ffffff;
|
||||
/* State 状态 */
|
||||
--state-success: #5db872;
|
||||
--state-warning: #d4a017;
|
||||
--state-danger: #c64545;
|
||||
--state-danger-strong: #a83838;
|
||||
--status-offline: #c64545;
|
||||
--state-info: #5db8a6;
|
||||
/* Highlight / 交互态 —— 中性暖灰 */
|
||||
--highlight: rgba(20, 20, 19, 0.05);
|
||||
--tab-active: rgba(20, 20, 19, 0.07);
|
||||
--chip-bg: #f5f0e8;
|
||||
--badge-bg: #efe9de;
|
||||
--switch-track: #d8cfc4;
|
||||
--hover-bg: rgba(20, 20, 19, 0.05);
|
||||
--pulse-ring: rgba(0, 0, 0, 0.1);
|
||||
/* Shadow 阴影 */
|
||||
--shadow-card: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||
--shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||
--shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||
--shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||
--shadow-color: rgba(0, 0, 0, 0.1);
|
||||
/* Overlay / 移动端 */
|
||||
--overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||
--mobile-menu: #f5f0e8;
|
||||
--mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||
/* 专用色 */
|
||||
--diff-add-text: #00e000;
|
||||
--diff-del-text: #ff1a1a;
|
||||
--diff-add-bg: rgba(22, 163, 74, 0.12);
|
||||
--diff-del-bg: rgba(220, 38, 38, 0.12);
|
||||
}
|
||||
|
||||
@ -1,7 +1,16 @@
|
||||
/* 聊天容器整体布局,保证聊天区可见并支持上下滚动 */
|
||||
.chat-container {
|
||||
--chat-surface-color: var(--theme-surface-strong, #ffffff);
|
||||
--composer-base-height: calc(80px + var(--app-bottom-inset, 0px));
|
||||
--chat-surface-color: var(--surface-panel);
|
||||
--chat-rail-max: 900px;
|
||||
--chat-rail-fluid: 94%;
|
||||
--chat-scrollbar-width: 8px;
|
||||
--chat-rail-width: min(var(--chat-rail-max), var(--chat-rail-fluid));
|
||||
--chat-message-rail-width: min(
|
||||
var(--chat-rail-max),
|
||||
calc(var(--chat-rail-fluid) + (var(--chat-scrollbar-width) * 0.94))
|
||||
);
|
||||
--chat-content-x: 0px;
|
||||
--composer-base-height: calc(90px + var(--app-bottom-inset));
|
||||
--composer-reserved-height: var(--composer-base-height);
|
||||
--composer-growth-height: 0px;
|
||||
flex: 1;
|
||||
@ -9,7 +18,7 @@
|
||||
flex-direction: column;
|
||||
background: var(--chat-surface-color);
|
||||
min-width: 0;
|
||||
height: var(--app-viewport, 100vh);
|
||||
height: var(--app-viewport);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
backdrop-filter: blur(6px);
|
||||
@ -23,7 +32,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #0f172a;
|
||||
color: var(--text-primary);
|
||||
background: var(--chat-surface-color); /* 与对话区域保持一致且不透明 */
|
||||
box-shadow: none;
|
||||
pointer-events: auto;
|
||||
@ -65,8 +74,8 @@
|
||||
letter-spacing: 0.02em;
|
||||
font-family: 'Iowan Old Style', ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
|
||||
max-width: 60%;
|
||||
color: #0f172a;
|
||||
text-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
|
||||
color: var(--text-primary);
|
||||
text-shadow: 0 1px 6px var(--shadow-color);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@ -98,7 +107,9 @@
|
||||
}
|
||||
|
||||
.messages-flow {
|
||||
width: min(960px, 100%);
|
||||
position: relative;
|
||||
left: calc(var(--chat-scrollbar-width) / 2);
|
||||
width: var(--chat-message-rail-width);
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -134,7 +145,7 @@
|
||||
.messages-area::-webkit-scrollbar-thumb,
|
||||
.sidebar::-webkit-scrollbar-thumb,
|
||||
.conversation-list::-webkit-scrollbar-thumb {
|
||||
background: rgba(121, 109, 94, 0.4);
|
||||
background: var(--text-muted);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@ -161,21 +172,24 @@
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
.chat-container--immersive .messages-flow {
|
||||
width: min(900px, 100%);
|
||||
}
|
||||
|
||||
.chat-container--immersive .scroll-lock-toggle {
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
.chat-container--mobile {
|
||||
--chat-rail-fluid: 100%;
|
||||
padding-top: 52px;
|
||||
}
|
||||
|
||||
.chat-container--mobile.chat-container--app-shell {
|
||||
--chat-scrollbar-width: 0px !important;
|
||||
--chat-message-rail-width: var(--chat-rail-width) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.chat-container {
|
||||
--composer-base-height: calc(80px + var(--app-bottom-inset, 0px));
|
||||
--chat-rail-fluid: 100%;
|
||||
--composer-base-height: calc(90px + var(--app-bottom-inset));
|
||||
--composer-reserved-height: var(--composer-base-height);
|
||||
}
|
||||
|
||||
@ -205,6 +219,7 @@
|
||||
/* 额外的手机端样式,不依赖 mobile 类 */
|
||||
@media (max-width: 768px) {
|
||||
.messages-flow {
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
@ -220,7 +235,7 @@
|
||||
border: none;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
color: #0f172a;
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
line-height: 1.35;
|
||||
@ -230,7 +245,7 @@
|
||||
}
|
||||
|
||||
.conversation-ribbon__selector:hover {
|
||||
color: #111827;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.conversation-ribbon__selector:disabled {
|
||||
@ -239,7 +254,7 @@
|
||||
}
|
||||
|
||||
.conversation-ribbon__selector.open {
|
||||
color: #111827;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.selector-label {
|
||||
@ -258,7 +273,7 @@
|
||||
|
||||
.selector-mode {
|
||||
font-weight: 500;
|
||||
color: rgba(15, 23, 42, 0.8);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.selector-caret {
|
||||
@ -276,9 +291,8 @@
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
border-radius: 14px;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
background: var(--surface-soft);
|
||||
box-shadow: none;
|
||||
backdrop-filter: blur(8px);
|
||||
pointer-events: auto;
|
||||
width: min(640px, calc(100vw - 32px));
|
||||
max-width: calc(100vw - 32px);
|
||||
@ -339,7 +353,7 @@
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(15, 23, 42, 0.65);
|
||||
color: var(--text-secondary);
|
||||
padding: 2px 12px;
|
||||
}
|
||||
|
||||
@ -354,11 +368,11 @@
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
color: #0f172a;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.dropdown-item:hover:not(.disabled) {
|
||||
background: #f6f7fb;
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.dropdown-item.disabled {
|
||||
@ -374,13 +388,13 @@
|
||||
.item-desc {
|
||||
grid-column: 1 / 2;
|
||||
font-size: 12px;
|
||||
color: rgba(15, 23, 42, 0.65);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.item-check {
|
||||
align-self: center;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.header-menu-enter-active,
|
||||
@ -402,7 +416,7 @@
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--claude-border);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
background: var(--surface-soft);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -499,7 +513,7 @@
|
||||
}
|
||||
|
||||
.user-message .message-text {
|
||||
background: #f5f5f5;
|
||||
background: var(--chip-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
@ -529,7 +543,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
width: min(760px, 92%);
|
||||
width: 100%;
|
||||
margin: 2px auto;
|
||||
color: var(--claude-text-secondary);
|
||||
user-select: none;
|
||||
@ -540,7 +554,7 @@
|
||||
content: '';
|
||||
flex: 1 1 auto;
|
||||
height: 0;
|
||||
border-top: 1px solid var(--theme-control-border, var(--claude-border));
|
||||
border-top: 1px solid var(--theme-control-border);
|
||||
}
|
||||
|
||||
.user-message.user-message--brief .compact-brief-text {
|
||||
@ -552,17 +566,12 @@
|
||||
}
|
||||
|
||||
.user-message .message-text .user-skill-link {
|
||||
color: #2563eb;
|
||||
color: var(--state-info);
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
margin: 0 0.25em;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .user-message .message-text .user-skill-link,
|
||||
body[data-theme='dark'] .user-message .message-text .user-skill-link {
|
||||
color: #60a5fa;
|
||||
}
|
||||
|
||||
.assistant-message .message-text {
|
||||
background: var(--claude-highlight);
|
||||
border-left: 4px solid var(--claude-accent);
|
||||
@ -583,7 +592,7 @@ body[data-theme='dark'] .user-message .message-text .user-skill-link {
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--border-color, #2a2f3a);
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.user-message .message-text.user-bubble-text .image-thumbnail {
|
||||
@ -651,7 +660,7 @@ body[data-theme='dark'] .user-message .message-text .user-skill-link {
|
||||
}
|
||||
|
||||
.collapsible-block {
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
background: transparent;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
@ -667,7 +676,7 @@ body[data-theme='dark'] .user-message .message-text .user-skill-link {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
user-select: none;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
background: transparent;
|
||||
transition: background-color 0.2s ease;
|
||||
position: relative;
|
||||
min-height: 36px;
|
||||
@ -1184,12 +1193,17 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
}
|
||||
|
||||
.text-output .text-content {
|
||||
padding: 0 20px 0 15px;
|
||||
padding: 0 var(--chat-content-x);
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.text-output .text-content .code-block-wrapper {
|
||||
margin-right: calc(var(--chat-content-x) * -1);
|
||||
margin-left: calc(var(--chat-content-x) * -1);
|
||||
}
|
||||
|
||||
.text-output pre {
|
||||
font-family:
|
||||
'JetBrains Mono', 'SF Mono', 'Fira Code', 'Consolas', 'Menlo', 'Monaco', 'Courier New',
|
||||
@ -1229,9 +1243,9 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
.text-output .text-content .md-table-scroll,
|
||||
.text-output .text-content [data-md-table-scroll='1'] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 16px 0;
|
||||
width: auto;
|
||||
max-width: none;
|
||||
margin: 16px calc(var(--chat-content-x) * -1);
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
@ -1253,21 +1267,21 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
|
||||
.text-output .text-content .md-table-scroll::-webkit-scrollbar-track,
|
||||
.text-output .text-content [data-md-table-scroll='1']::-webkit-scrollbar-track {
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #d1d5db) 70%, transparent);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 70%, transparent);
|
||||
border-radius: 999px;
|
||||
margin: 0 8px 6px;
|
||||
}
|
||||
|
||||
.text-output .text-content .md-table-scroll::-webkit-scrollbar-thumb,
|
||||
.text-output .text-content [data-md-table-scroll='1']::-webkit-scrollbar-thumb {
|
||||
background: color-mix(in srgb, var(--claude-text-secondary, #6b7280) 55%, transparent);
|
||||
background: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.text-output .text-content .md-table-scroll,
|
||||
.text-output .text-content [data-md-table-scroll='1'] {
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary, #6b7280) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted, #d1d5db) 70%, transparent);
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted) 70%, transparent);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
@ -1290,7 +1304,7 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
}
|
||||
|
||||
.text-output .text-content hr {
|
||||
margin: 32px 0;
|
||||
margin: 32px calc(var(--chat-content-x) * -1);
|
||||
border: none;
|
||||
border-top: 1px solid var(--claude-border);
|
||||
}
|
||||
@ -1299,8 +1313,8 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
margin: 12px 0;
|
||||
padding: 10px 14px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(59, 130, 246, 0.08));
|
||||
border-left: 4px solid rgba(79, 70, 229, 0.6);
|
||||
background: linear-gradient(135deg, color-mix(in srgb, var(--state-info) 8%, transparent), color-mix(in srgb, var(--state-info) 8%, transparent));
|
||||
border-left: 4px solid var(--state-info);
|
||||
color: var(--claude-text);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
@ -1336,8 +1350,8 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
|
||||
.append-block.append-error,
|
||||
.append-placeholder.append-error {
|
||||
background: rgba(255, 244, 242, 0.85);
|
||||
border-left-color: rgba(216, 90, 66, 0.38);
|
||||
background: color-mix(in srgb, var(--state-danger) 8%, var(--surface-soft));
|
||||
border-left-color: color-mix(in srgb, var(--state-danger) 40%, transparent);
|
||||
}
|
||||
|
||||
.append-header {
|
||||
@ -1352,14 +1366,14 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
margin: 16px 0;
|
||||
background: var(--theme-surface-strong, #ffffff);
|
||||
background: var(--theme-surface-strong);
|
||||
min-height: 80px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.code-block-header {
|
||||
min-height: 44px;
|
||||
background: var(--theme-surface-strong, #ffffff);
|
||||
background: var(--theme-surface-strong);
|
||||
padding: 0 12px 0 18px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -1404,7 +1418,7 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
}
|
||||
|
||||
.copy-code-btn:hover {
|
||||
background-color: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background-color: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -1414,7 +1428,7 @@ show-html:not([data-rendered='1'])[ratio='3:4'] {
|
||||
}
|
||||
|
||||
.code-block-wrapper pre {
|
||||
background: var(--theme-surface-strong, #ffffff) !important;
|
||||
background: var(--theme-surface-strong) !important;
|
||||
padding: 24px 28px 28px !important;
|
||||
margin: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
@ -47,10 +47,10 @@
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
// 动画 - 使用主题色的脉冲效果
|
||||
// 动画 - 使用主题色的脉冲效果(颜色走 --pulse-ring,随主题自动适配)
|
||||
@keyframes drag-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 0 0 var(--claude-highlight);
|
||||
box-shadow: 0 0 0 0 var(--pulse-ring);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 12px transparent;
|
||||
@ -82,15 +82,6 @@
|
||||
.drag-upload-hint {
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@keyframes drag-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 12px transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 经典色主题(classic) - 提示文字改为黑色
|
||||
@ -111,13 +102,4 @@
|
||||
.drag-upload-icon {
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@keyframes drag-pulse {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 12px transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
.stadium-input-wrapper {
|
||||
position: relative;
|
||||
width: min(900px, 94%);
|
||||
width: var(--chat-rail-width, min(900px, 94%));
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
--runtime-queue-divider: rgba(15, 23, 42, 0.12);
|
||||
--runtime-queue-border: rgba(15, 23, 42, 0.12);
|
||||
position: absolute;
|
||||
left: calc(50% - 7px);
|
||||
left: 50%;
|
||||
bottom: calc(100% - 2px);
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
@ -113,8 +113,8 @@
|
||||
}
|
||||
|
||||
.runtime-queue-item__action--danger:hover {
|
||||
color: #b91c1c;
|
||||
background: rgba(185, 28, 28, 0.12);
|
||||
color: var(--state-danger-strong);
|
||||
background: color-mix(in srgb, var(--state-danger) 12%, transparent);
|
||||
}
|
||||
|
||||
.runtime-queue-item + .runtime-queue-item::before {
|
||||
@ -137,7 +137,7 @@
|
||||
--skill-slash-motion-easing: cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
--skill-slash-visible-rows: 5;
|
||||
position: absolute;
|
||||
left: calc(50% - 7px);
|
||||
left: 50%;
|
||||
bottom: calc(100% - 2px);
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
@ -153,7 +153,7 @@
|
||||
border: 1px solid var(--claude-border);
|
||||
border-top-left-radius: var(--skill-slash-radius);
|
||||
border-top-right-radius: var(--skill-slash-radius);
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
background: var(--surface-soft);
|
||||
box-shadow: none;
|
||||
pointer-events: auto;
|
||||
scrollbar-width: none;
|
||||
@ -227,8 +227,8 @@
|
||||
|
||||
.skill-slash-item:hover,
|
||||
.skill-slash-item--active {
|
||||
background: rgba(118, 103, 84, 0.12);
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
background: var(--hover-bg);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.skill-slash-item--disabled,
|
||||
@ -246,7 +246,7 @@
|
||||
.skill-slash-item__name {
|
||||
flex: 0 0 auto;
|
||||
max-width: 210px;
|
||||
color: #2563eb;
|
||||
color: var(--accent);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
@ -277,7 +277,7 @@
|
||||
|
||||
body[data-theme='dark'] {
|
||||
.runtime-queue-list {
|
||||
--runtime-queue-bg: #2a2a2a;
|
||||
--runtime-queue-bg: var(--badge-bg);
|
||||
--runtime-queue-divider: rgba(255, 255, 255, 0.12);
|
||||
--runtime-queue-border: rgba(255, 255, 255, 0.12);
|
||||
background: transparent;
|
||||
@ -294,23 +294,34 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.skill-slash-menu {
|
||||
background: #2a2a2a;
|
||||
background: var(--badge-bg);
|
||||
border-color: var(--claude-border);
|
||||
}
|
||||
|
||||
.skill-slash-item__name {
|
||||
color: #60a5fa;
|
||||
color: var(--state-info);
|
||||
}
|
||||
|
||||
.skill-slash-item:hover,
|
||||
.skill-slash-item--active {
|
||||
background: rgba(255, 255, 255, 0.078);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
|
||||
background: var(--hover-bg);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.stadium-input-editor .skill-md-link,
|
||||
.stadium-input-highlight .skill-md-link {
|
||||
color: #60a5fa;
|
||||
color: var(--state-info);
|
||||
}
|
||||
}
|
||||
|
||||
body[data-theme='light'] {
|
||||
.skill-slash-item__name {
|
||||
color: var(--state-info);
|
||||
}
|
||||
|
||||
.stadium-input-editor .skill-md-link,
|
||||
.stadium-input-highlight .skill-md-link {
|
||||
color: var(--state-info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,7 +376,7 @@ body[data-theme='dark'] {
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background:
|
||||
conic-gradient(var(--context-ring-color) var(--context-progress), rgba(127, 135, 146, 0.28) 0);
|
||||
conic-gradient(var(--context-ring-color) var(--context-progress), var(--progress-track) 0);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -511,7 +522,7 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.permission-switcher__item-label--warn {
|
||||
color: #d97706;
|
||||
color: var(--state-warning);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@ -540,15 +551,14 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.stadium-shell {
|
||||
--stadium-radius: 24px;
|
||||
--stadium-radius: 18px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
min-height: calc(var(--stadium-radius) * 2.1);
|
||||
padding: 12px 18px;
|
||||
padding: 10px;
|
||||
border-radius: var(--stadium-radius);
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--border-default);
|
||||
background: var(--surface-raised);
|
||||
box-shadow: none;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
@ -558,22 +568,19 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.stadium-shell.is-multiline {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
min-height: calc(var(--stadium-radius) * 2.7);
|
||||
border-color: rgba(15, 23, 42, 0.2);
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.stadium-shell.is-focused,
|
||||
.stadium-shell.has-text {
|
||||
border-color: rgba(15, 23, 42, 0.12);
|
||||
border-color: var(--border-default);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.stadium-shell.is-multiline.is-focused,
|
||||
.stadium-shell.is-multiline.has-text {
|
||||
border-color: rgba(15, 23, 42, 0.2);
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@ -586,16 +593,24 @@ body[data-theme='dark'] {
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.stadium-input-rich {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
padding: 2px 0 0 6px;
|
||||
}
|
||||
|
||||
.stadium-input-rich .stadium-input {
|
||||
@ -603,7 +618,7 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.stadium-input-editor .skill-md-link {
|
||||
color: #2563eb;
|
||||
color: var(--accent);
|
||||
font-weight: inherit;
|
||||
border-radius: 4px;
|
||||
padding: 0 1px;
|
||||
@ -624,7 +639,7 @@ body[data-theme='dark'] {
|
||||
gap: 6px;
|
||||
padding: 0 4px 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary, #7f8792);
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@ -638,7 +653,7 @@ body[data-theme='dark'] {
|
||||
.image-remove-btn {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-secondary, #7f8792);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0 4px;
|
||||
font-size: 12px;
|
||||
@ -646,7 +661,7 @@ body[data-theme='dark'] {
|
||||
transition: color 0.15s ease, transform 0.15s ease;
|
||||
}
|
||||
.image-remove-btn:hover {
|
||||
color: #d14b4b;
|
||||
color: var(--state-danger);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
@ -713,19 +728,19 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.stadium-btn {
|
||||
flex: 0 0 36px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex: 0 0 28px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
border-radius: 7px;
|
||||
background: transparent;
|
||||
color: var(--claude-text);
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s ease, transform 0.2s ease, margin-top 0.2s ease;
|
||||
transition: background 140ms ease, color 140ms ease;
|
||||
}
|
||||
|
||||
.stadium-btn:disabled {
|
||||
@ -734,21 +749,20 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.stadium-btn:hover:not(:disabled) {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
font-size: 22px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.stadium-btn.send-btn {
|
||||
background: var(--claude-accent);
|
||||
color: #fffaf0;
|
||||
box-shadow: 0 10px 20px rgba(189, 93, 58, 0.28);
|
||||
color: var(--on-accent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.stadium-btn.send-btn:hover:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
background: var(--claude-button-hover);
|
||||
}
|
||||
|
||||
@ -765,31 +779,26 @@ body[data-theme='dark'] {
|
||||
.stadium-btn.send-btn .send-icon {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 6px solid transparent;
|
||||
border-bottom: 6px solid transparent;
|
||||
border-left: 10px solid #fffaf0;
|
||||
margin-left: 5px;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 9px solid var(--on-accent);
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.stadium-btn.send-btn .stop-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 2px;
|
||||
background-color: #fffaf0;
|
||||
background-color: var(--on-accent);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.stadium-btn.send-btn:disabled .send-icon {
|
||||
border-left-color: rgba(255, 255, 255, 0.4);
|
||||
border-left-color: color-mix(in srgb, var(--on-accent) 40%, transparent);
|
||||
}
|
||||
|
||||
.stadium-btn.send-btn:disabled .stop-icon {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.stadium-shell.is-multiline .stadium-btn {
|
||||
align-self: flex-end;
|
||||
margin-top: 0;
|
||||
background-color: color-mix(in srgb, var(--on-accent) 40%, transparent);
|
||||
}
|
||||
|
||||
.file-input-hidden {
|
||||
@ -805,7 +814,7 @@ body[data-theme='dark'] {
|
||||
gap: 6px;
|
||||
width: 230px;
|
||||
padding: 12px;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
background: var(--surface-soft);
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 18px;
|
||||
box-shadow: none;
|
||||
@ -838,11 +847,11 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.menu-entry:hover:not(:disabled) {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.menu-entry.active {
|
||||
background: rgba(118, 103, 84, 0.12);
|
||||
background: var(--chip-bg);
|
||||
color: var(--claude-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
@ -866,7 +875,7 @@ body[data-theme='dark'] {
|
||||
padding: 12px;
|
||||
border-radius: 18px;
|
||||
border: 1px solid var(--claude-border);
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
background: var(--surface-soft);
|
||||
box-shadow: none;
|
||||
z-index: 31;
|
||||
}
|
||||
@ -898,12 +907,12 @@ body[data-theme='dark'] {
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
gap: 10px;
|
||||
padding-bottom: 140px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
.blank-hero-text {
|
||||
font-size: 32px;
|
||||
color: #2f3a4a;
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
max-width: min(88vw, 680px);
|
||||
@ -919,8 +928,8 @@ body[data-theme='dark'] {
|
||||
|
||||
.composer-container {
|
||||
position: relative;
|
||||
height: var(--composer-base-height, calc(80px + var(--app-bottom-inset, 0px)));
|
||||
flex: 0 0 var(--composer-base-height, calc(80px + var(--app-bottom-inset, 0px)));
|
||||
height: var(--composer-base-height, calc(90px + var(--app-bottom-inset)));
|
||||
flex: 0 0 var(--composer-base-height, calc(90px + var(--app-bottom-inset)));
|
||||
transition: transform 0.3s ease;
|
||||
z-index: 2;
|
||||
}
|
||||
@ -933,6 +942,10 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.input-area {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.blank-hero-text {
|
||||
font-size: 28px;
|
||||
}
|
||||
@ -944,7 +957,7 @@ body[data-theme='dark'] {
|
||||
transform: translateY(calc(-32vh + var(--composer-growth-height, 0px)));
|
||||
}
|
||||
.blank-hero-overlay {
|
||||
padding-bottom: 120px;
|
||||
padding-bottom: 136px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1015,10 +1028,6 @@ body[data-theme='dark'] {
|
||||
@media (max-height: 900px) {
|
||||
.input-area {
|
||||
bottom: 12px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
.stadium-shell {
|
||||
width: min(900px, 98%);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1026,7 +1035,7 @@ body[data-theme='dark'] {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: calc(100% + 12px);
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
background: var(--surface-soft);
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 12px;
|
||||
box-shadow: none;
|
||||
@ -1045,7 +1054,7 @@ body[data-theme='dark'] {
|
||||
right: 20px;
|
||||
border-width: 10px 10px 0 10px;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.96) transparent transparent transparent;
|
||||
border-color: var(--surface-soft) transparent transparent transparent;
|
||||
filter: drop-shadow(0 3px 4px rgba(61, 57, 41, 0.12));
|
||||
}
|
||||
|
||||
@ -1065,7 +1074,7 @@ body[data-theme='dark'] {
|
||||
.tool-menu .tool-menu-status,
|
||||
.tool-menu .tool-menu-empty {
|
||||
font-size: 13px;
|
||||
color: rgba(61, 57, 41, 0.78);
|
||||
color: var(--text-secondary);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@ -1081,9 +1090,9 @@ body[data-theme='dark'] {
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 10px;
|
||||
border: 1px solid rgba(118, 103, 84, 0.14);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
background: var(--surface-soft);
|
||||
font-size: 13px;
|
||||
aspect-ratio: 1 / 1;
|
||||
min-height: 0;
|
||||
@ -1127,19 +1136,19 @@ body[data-theme='dark'] {
|
||||
.menu-btn {
|
||||
width: 100%;
|
||||
padding: 8px 14px;
|
||||
border: 1px solid rgba(118, 103, 84, 0.14);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
text-align: left;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
background: var(--surface-soft);
|
||||
color: var(--claude-text);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-btn:not(:disabled):hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
background: var(--surface-soft);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
@ -1149,21 +1158,21 @@ body[data-theme='dark'] {
|
||||
}
|
||||
|
||||
.menu-btn.compress-entry {
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
background: var(--surface-soft);
|
||||
color: var(--claude-success);
|
||||
}
|
||||
|
||||
.menu-btn.compress-entry:not(:disabled):hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
background: var(--surface-soft);
|
||||
}
|
||||
|
||||
.menu-btn.clear-entry {
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
color: #bf422b;
|
||||
background: var(--surface-soft);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.menu-btn.clear-entry:not(:disabled):hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
background: var(--surface-soft);
|
||||
}
|
||||
|
||||
.settings-menu-enter-active,
|
||||
@ -1198,7 +1207,7 @@ body[data-theme='dark'] {
|
||||
|
||||
.mobile-panel-sheet--approval .approval-btn--approve {
|
||||
background: var(--claude-accent);
|
||||
color: #fff;
|
||||
color: var(--on-accent);
|
||||
border-color: var(--claude-accent);
|
||||
}
|
||||
|
||||
@ -1253,10 +1262,10 @@ body[data-theme='dark'] {
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0 5px;
|
||||
border: 1.5px solid var(--theme-surface-strong, #fff);
|
||||
border: 1.5px solid var(--theme-surface-strong);
|
||||
border-radius: 999px;
|
||||
background: #ff5f57;
|
||||
color: #fff;
|
||||
background: var(--mac-close);
|
||||
color: var(--on-accent);
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,10 @@
|
||||
|
||||
.workspace-panel--collapsed {
|
||||
pointer-events: none;
|
||||
flex-basis: 0;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.workspace-panel--collapsed > * {
|
||||
@ -135,7 +139,6 @@
|
||||
.mode-indicator {
|
||||
--mode-indicator-color-1: var(--claude-accent);
|
||||
--mode-indicator-color-2: var(--claude-accent-strong);
|
||||
--mode-indicator-shadow: rgba(189, 93, 58, 0.25);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
@ -147,8 +150,8 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, var(--mode-indicator-color-1), var(--mode-indicator-color-2));
|
||||
color: #fffef8;
|
||||
box-shadow: 0 8px 20px var(--mode-indicator-shadow);
|
||||
color: var(--on-accent);
|
||||
box-shadow: none;
|
||||
transition:
|
||||
background 0.35s ease,
|
||||
box-shadow 0.35s ease,
|
||||
@ -160,27 +163,22 @@
|
||||
}
|
||||
|
||||
.mode-indicator:focus-visible {
|
||||
box-shadow:
|
||||
0 0 0 2px rgba(255, 255, 255, 0.8),
|
||||
0 8px 20px var(--mode-indicator-shadow);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--on-accent) 80%, transparent);
|
||||
}
|
||||
|
||||
.mode-indicator.fast {
|
||||
--mode-indicator-color-1: #ffe08c;
|
||||
--mode-indicator-color-2: #f7b23c;
|
||||
--mode-indicator-shadow: rgba(247, 178, 60, 0.35);
|
||||
--mode-indicator-color-1: var(--accent-deep);
|
||||
--mode-indicator-color-2: var(--accent-deep-strong);
|
||||
}
|
||||
|
||||
.mode-indicator.thinking {
|
||||
--mode-indicator-color-1: var(--claude-accent);
|
||||
--mode-indicator-color-2: var(--claude-accent-strong);
|
||||
--mode-indicator-shadow: rgba(189, 93, 58, 0.3);
|
||||
}
|
||||
|
||||
.mode-indicator.deep {
|
||||
--mode-indicator-color-1: var(--claude-deep);
|
||||
--mode-indicator-color-2: var(--claude-deep-strong);
|
||||
--mode-indicator-shadow: rgba(208, 122, 20, 0.35);
|
||||
}
|
||||
|
||||
.mode-indicator .icon {
|
||||
@ -192,7 +190,7 @@
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
background: #e34d4d;
|
||||
background: var(--status-offline);
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
@ -205,7 +203,7 @@
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: #e34d4d;
|
||||
background: var(--status-offline);
|
||||
animation: statusPulse 2.4s ease-out infinite;
|
||||
}
|
||||
|
||||
@ -266,8 +264,8 @@
|
||||
}
|
||||
|
||||
.sidebar-manage-btn {
|
||||
border: 1px solid rgba(118, 103, 84, 0.25);
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
border: 1px solid var(--border-default);
|
||||
background: var(--surface-soft);
|
||||
color: var(--claude-text);
|
||||
padding: 4px 10px;
|
||||
border-radius: 6px;
|
||||
@ -279,16 +277,16 @@
|
||||
}
|
||||
|
||||
.sidebar-manage-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-color: rgba(118, 103, 84, 0.45);
|
||||
background: var(--surface-soft);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
|
||||
.sidebar-view-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(118, 103, 84, 0.3);
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
border: 1px solid var(--border-strong);
|
||||
background: var(--surface-soft);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -299,7 +297,7 @@
|
||||
}
|
||||
|
||||
.sidebar-view-toggle:hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
background: var(--surface-soft);
|
||||
}
|
||||
|
||||
.sidebar-panel-card-wrapper {
|
||||
@ -349,8 +347,8 @@
|
||||
top: 0;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 1px solid rgba(118, 103, 84, 0.2);
|
||||
background: var(--surface-soft);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 8px;
|
||||
padding: 6px 8px;
|
||||
box-shadow: none;
|
||||
@ -367,7 +365,7 @@
|
||||
}
|
||||
|
||||
.panel-menu button.active {
|
||||
background: rgba(108, 92, 231, 0.1);
|
||||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
@ -455,7 +453,7 @@
|
||||
}
|
||||
|
||||
.sub-agent-card {
|
||||
border: 1px solid rgba(118, 103, 84, 0.2);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
padding: 12px 14px;
|
||||
background: color-mix(in srgb, var(--claude-left-rail) 88%, var(--theme-surface-strong) 12%);
|
||||
@ -465,17 +463,17 @@
|
||||
box-shadow 0.2s ease;
|
||||
|
||||
[data-theme='dark'] & {
|
||||
background: rgba(30, 30, 30, 0.6);
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
background: color-mix(in srgb, var(--surface-base) 60%, transparent);
|
||||
border-color: var(--border-card-strong);
|
||||
}
|
||||
}
|
||||
|
||||
.sub-agent-card:hover {
|
||||
border-color: #6c5ce7;
|
||||
border-color: var(--accent);
|
||||
box-shadow: none;
|
||||
|
||||
[data-theme='dark'] & {
|
||||
border-color: #8b7ce7;
|
||||
border-color: var(--accent-hover);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
@ -494,18 +492,18 @@
|
||||
}
|
||||
|
||||
.sub-agent-status.running {
|
||||
color: #0984e3;
|
||||
color: var(--state-info);
|
||||
}
|
||||
|
||||
.sub-agent-status.completed {
|
||||
color: #00b894;
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.sub-agent-status.failed,
|
||||
.sub-agent-status.timeout,
|
||||
.sub-agent-status.terminated,
|
||||
.sub-agent-status.cancelled {
|
||||
color: #d63031;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.sub-agent-summary {
|
||||
@ -537,8 +535,8 @@
|
||||
text-align: center;
|
||||
|
||||
[data-theme='dark'] & {
|
||||
background: rgba(20, 20, 20, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
background: color-mix(in srgb, var(--surface-base) 90%, transparent);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
}
|
||||
|
||||
@ -674,14 +672,14 @@
|
||||
|
||||
&.default {
|
||||
color: var(--claude-deep-strong);
|
||||
border-color: rgba(208, 122, 20, 0.35);
|
||||
background: rgba(242, 169, 59, 0.14);
|
||||
border-color: color-mix(in srgb, var(--accent-deep-strong) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--accent-deep) 14%, transparent);
|
||||
}
|
||||
|
||||
&.current {
|
||||
color: #2f6f4e;
|
||||
border-color: rgba(47, 111, 78, 0.35);
|
||||
background: rgba(118, 176, 134, 0.18);
|
||||
color: var(--state-success);
|
||||
border-color: color-mix(in srgb, var(--state-success) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--state-success) 18%, transparent);
|
||||
}
|
||||
|
||||
&.running {
|
||||
@ -693,38 +691,38 @@
|
||||
|
||||
[data-theme='dark'] .host-workspace-header-box {
|
||||
background: var(--claude-left-rail);
|
||||
border-color: rgba(160, 160, 160, 0.45);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
|
||||
[data-theme='dark'] .host-workspace-card {
|
||||
background: color-mix(in srgb, var(--claude-left-rail) 88%, var(--theme-surface-strong) 12%);
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: #222222;
|
||||
background: var(--badge-bg);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #242424;
|
||||
background: color-mix(in srgb, var(--badge-bg) 100%, white 4%);
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme='dark'] .host-workspace-badge {
|
||||
&.default {
|
||||
color: #f7c56f;
|
||||
border-color: rgba(247, 197, 111, 0.35);
|
||||
background: rgba(247, 197, 111, 0.16);
|
||||
color: var(--accent-deep);
|
||||
border-color: color-mix(in srgb, var(--accent-deep) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--accent-deep) 16%, transparent);
|
||||
}
|
||||
|
||||
&.current {
|
||||
color: #8edbb4;
|
||||
border-color: rgba(142, 219, 180, 0.34);
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: var(--state-success);
|
||||
border-color: color-mix(in srgb, var(--state-success) 34%, transparent);
|
||||
background: color-mix(in srgb, var(--state-success) 20%, transparent);
|
||||
}
|
||||
|
||||
&.running {
|
||||
color: #f7c56f;
|
||||
border-color: rgba(247, 197, 111, 0.35);
|
||||
background: rgba(247, 197, 111, 0.16);
|
||||
color: var(--accent-deep);
|
||||
border-color: color-mix(in srgb, var(--accent-deep) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--accent-deep) 16%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,7 +742,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid rgba(118, 103, 84, 0.18);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
color: var(--claude-text);
|
||||
@ -752,8 +750,8 @@
|
||||
}
|
||||
|
||||
.todo-task.done {
|
||||
background: rgba(92, 190, 125, 0.08);
|
||||
border-color: rgba(92, 190, 125, 0.3);
|
||||
background: color-mix(in srgb, var(--state-success) 8%, transparent);
|
||||
border-color: color-mix(in srgb, var(--state-success) 30%, transparent);
|
||||
}
|
||||
|
||||
.todo-task-title {
|
||||
@ -853,14 +851,13 @@
|
||||
|
||||
.context-menu {
|
||||
position: fixed;
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(15, 23, 42, 0.08);
|
||||
background: var(--surface-raised);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 8px;
|
||||
box-shadow: none;
|
||||
z-index: 3000;
|
||||
min-width: 180px;
|
||||
padding: 6px 0;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.context-menu button {
|
||||
@ -870,17 +867,17 @@
|
||||
border: none;
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
color: #1f2933;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.context-menu button:hover {
|
||||
background: rgba(59, 130, 246, 0.12);
|
||||
background: color-mix(in srgb, var(--state-info) 12%, transparent);
|
||||
}
|
||||
|
||||
.context-menu button:disabled {
|
||||
color: #9ca3af;
|
||||
color: var(--text-tertiary);
|
||||
cursor: not-allowed;
|
||||
background: transparent;
|
||||
}
|
||||
@ -901,7 +898,7 @@
|
||||
}
|
||||
|
||||
.sidebar-manage-btn:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
@ -922,7 +919,7 @@
|
||||
}
|
||||
|
||||
.sidebar-view-toggle:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.panel-menu {
|
||||
@ -957,5 +954,5 @@
|
||||
|
||||
.panel-menu button:hover,
|
||||
.panel-menu button.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
background: var(--claude-panel);
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 26px;
|
||||
box-shadow: 0 24px 42px rgba(61, 57, 41, 0.18);
|
||||
box-shadow: 0 24px 42px var(--shadow-color);
|
||||
transition: transform 0.35s ease, opacity 0.35s ease;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
@ -170,18 +170,18 @@
|
||||
left: 12px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 1px solid #e0443e;
|
||||
border: 1px solid var(--mac-close-border);
|
||||
border-radius: 50%;
|
||||
background: #ff5f56;
|
||||
background: var(--mac-close);
|
||||
display: block;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease, transform 0.2s ease;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 2px 4px var(--shadow-color);
|
||||
}
|
||||
|
||||
.token-close-btn:hover {
|
||||
background: #ff3b30;
|
||||
background: var(--mac-close-hover);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
background: rgba(125, 109, 94, 0.15);
|
||||
background: var(--badge-bg);
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
@ -340,7 +340,7 @@
|
||||
border-radius: 12px;
|
||||
background: var(--claude-bg);
|
||||
border: 1px solid var(--claude-border-strong);
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 12px 30px var(--shadow-color);
|
||||
z-index: 2000;
|
||||
max-width: 320px;
|
||||
color: var(--claude-text);
|
||||
@ -388,8 +388,8 @@
|
||||
padding: 12px 14px;
|
||||
border-radius: 14px;
|
||||
background: var(--claude-bg);
|
||||
border: 1px solid var(--claude-border-strong, rgba(118,103,84,0.35));
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
|
||||
border: 1px solid var(--claude-border-strong);
|
||||
box-shadow: 0 12px 30px var(--shadow-color);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@
|
||||
}
|
||||
|
||||
.app-toast--error::before {
|
||||
background: #d45f5f;
|
||||
background: var(--state-danger);
|
||||
}
|
||||
|
||||
.app-toast-body {
|
||||
@ -444,17 +444,17 @@
|
||||
|
||||
|
||||
.status-pill--running {
|
||||
background: rgba(118, 176, 134, 0.18);
|
||||
background: color-mix(in srgb, var(--state-success) 22%, transparent);
|
||||
color: var(--claude-success);
|
||||
}
|
||||
|
||||
.status-pill--stopped {
|
||||
background: rgba(217, 152, 69, 0.2);
|
||||
background: color-mix(in srgb, var(--state-warning) 22%, transparent);
|
||||
color: var(--claude-warning);
|
||||
}
|
||||
|
||||
.status-pill--host {
|
||||
background: rgba(125, 109, 94, 0.12);
|
||||
background: var(--badge-bg);
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
@ -584,9 +584,9 @@
|
||||
|
||||
.search-result-item {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid rgba(118, 103, 84, 0.16);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
background: var(--surface-soft);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
height: 32px;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
background: var(--hover-bg);
|
||||
color: var(--claude-text);
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
@ -56,7 +56,7 @@
|
||||
height: 32px;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
background: var(--hover-bg);
|
||||
color: var(--claude-text);
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
@ -66,7 +66,7 @@
|
||||
flex: 0 0 auto;
|
||||
min-width: 340px;
|
||||
max-width: min(600px, 52vw);
|
||||
height: var(--app-viewport, 100vh);
|
||||
height: var(--app-viewport);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--claude-left-rail);
|
||||
@ -139,9 +139,9 @@
|
||||
}
|
||||
|
||||
.git-changes-panel__close:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.git-changes-panel__body {
|
||||
@ -149,14 +149,14 @@
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding: 12px;
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary, #6b7280) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted, #d1d5db) 70%, transparent);
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted) 70%, transparent);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.git-changes-panel * {
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary, #6b7280) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted, #d1d5db) 70%, transparent);
|
||||
scrollbar-color: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent)
|
||||
color-mix(in srgb, var(--theme-surface-muted) 70%, transparent);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
@ -168,14 +168,14 @@
|
||||
|
||||
.git-changes-panel::-webkit-scrollbar-track,
|
||||
.git-changes-panel ::-webkit-scrollbar-track {
|
||||
background: color-mix(in srgb, var(--theme-surface-muted, #d1d5db) 70%, transparent);
|
||||
background: color-mix(in srgb, var(--theme-surface-muted) 70%, transparent);
|
||||
border-radius: 999px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.git-changes-panel::-webkit-scrollbar-thumb,
|
||||
.git-changes-panel ::-webkit-scrollbar-thumb {
|
||||
background: color-mix(in srgb, var(--claude-text-secondary, #6b7280) 55%, transparent);
|
||||
background: color-mix(in srgb, var(--claude-text-secondary) 55%, transparent);
|
||||
border-radius: 999px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: padding-box;
|
||||
@ -189,7 +189,7 @@
|
||||
}
|
||||
|
||||
.git-changes-panel__empty--error {
|
||||
color: var(--theme-danger, #c00);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.git-change-file {
|
||||
@ -238,9 +238,9 @@
|
||||
|
||||
.git-change-file__open-btn:hover,
|
||||
.git-change-file__open-btn.open {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.git-change-file__open-btn:disabled {
|
||||
@ -322,8 +322,8 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.git-change-file__open-option:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
background: var(--theme-tab-active);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.git-change-file__open-empty {
|
||||
@ -354,9 +354,9 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.git-change-file__reset:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.git-change-file__diff {
|
||||
@ -402,9 +402,9 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.git-change-file__fold:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
box-shadow: 0 1px 2px rgba(61, 57, 41, 0.08);
|
||||
box-shadow: 0 1px 2px var(--shadow-color);
|
||||
}
|
||||
|
||||
.git-change-file__fold-icon {
|
||||
@ -471,13 +471,13 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.git-change-line--add {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
color: #0a0;
|
||||
background: var(--diff-add-bg);
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.git-change-line--delete {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
color: #c00;
|
||||
background: var(--diff-del-bg);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.git-changes-panel-slide-enter-active,
|
||||
@ -514,8 +514,8 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
box-shadow: 0 12px 28px rgba(61, 57, 41, 0.08);
|
||||
background: var(--surface-soft);
|
||||
box-shadow: 0 12px 28px var(--shadow-color);
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
@ -541,7 +541,7 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
.file-content {
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
background: #ffffff;
|
||||
background: var(--surface-raised);
|
||||
}
|
||||
|
||||
.file-content pre {
|
||||
@ -553,7 +553,7 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #1f2227;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tool-approval-panel .approval-panel-body {
|
||||
@ -621,10 +621,10 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
line-height: 1.5;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
background: color-mix(in srgb, transparent 99%, var(--text-primary));
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
@ -685,13 +685,13 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.tool-approval-panel .diff-remove {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
color: #c00;
|
||||
background: var(--diff-del-bg);
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.tool-approval-panel .diff-add {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
color: #0a0;
|
||||
background: var(--diff-add-bg);
|
||||
color: var(--state-success);
|
||||
}
|
||||
|
||||
.approval-actions {
|
||||
@ -719,8 +719,8 @@ body[data-theme='dark'] .git-change-file__open-icon {
|
||||
}
|
||||
|
||||
.approval-btn--switch {
|
||||
color: #fff;
|
||||
background: #dc2626;
|
||||
color: var(--on-accent);
|
||||
background: var(--state-danger);
|
||||
}
|
||||
|
||||
.approval-btn--reject {
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
top: 0;
|
||||
z-index: 120;
|
||||
width: var(--conversation-expanded-width);
|
||||
height: var(--app-viewport, 100vh) !important;
|
||||
min-height: var(--app-viewport, 100vh) !important;
|
||||
height: var(--app-viewport) !important;
|
||||
min-height: var(--app-viewport) !important;
|
||||
overflow: hidden;
|
||||
background: var(--claude-left-rail);
|
||||
border-right: 0;
|
||||
@ -97,13 +97,13 @@
|
||||
|
||||
.conversation-sidebar.collapsed .sidebar-nav-row:hover .sidebar-nav-icon,
|
||||
.conversation-sidebar.collapsed .sidebar-nav-row:focus-visible .sidebar-nav-icon {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.conversation-sidebar:not(.collapsed) .sidebar-nav-row:hover,
|
||||
.conversation-sidebar:not(.collapsed) .sidebar-nav-row:focus-visible,
|
||||
.conversation-sidebar:not(.collapsed) .sidebar-nav-row.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
|
||||
.conversation-sidebar:not(.collapsed) .workspace-control-btn.active:hover,
|
||||
.conversation-sidebar:not(.collapsed) .workspace-control-btn.active:focus-visible {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.sidebar-nav-label,
|
||||
@ -178,7 +178,7 @@
|
||||
|
||||
.search-input-wrap:hover,
|
||||
.search-input-wrap:focus-within {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.search-inline-icon {
|
||||
@ -257,7 +257,7 @@
|
||||
|
||||
.conversation-sidebar .running-task-item:hover,
|
||||
.conversation-sidebar .running-task-item.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.conversation-sidebar .running-task-workspace {
|
||||
@ -294,7 +294,7 @@
|
||||
[data-theme='dark'] .conversation-sidebar .running-task-item.active,
|
||||
body[data-theme='dark'] .conversation-sidebar .running-task-item:hover,
|
||||
body[data-theme='dark'] .conversation-sidebar .running-task-item.active {
|
||||
background: #222222;
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-item {
|
||||
@ -360,7 +360,7 @@ body[data-theme='dark'] .conversation-sidebar .running-task-item.active {
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-item.duplicate-source-mask:hover::after {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
:root[data-theme='dark']
|
||||
@ -369,7 +369,7 @@ body[data-theme='dark'] .conversation-sidebar .running-task-item.active {
|
||||
body[data-theme='dark']
|
||||
.conversation-sidebar
|
||||
.conversation-item.duplicate-source-mask:hover::after {
|
||||
background: rgba(255, 255, 255, 0.078);
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-item.duplicate-source-mask > * {
|
||||
@ -407,18 +407,18 @@ body[data-theme='dark']
|
||||
.conversation-sidebar .conversation-item:focus-within,
|
||||
.conversation-sidebar .conversation-item.active:hover,
|
||||
.conversation-sidebar .conversation-item.active:focus-within {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055)) !important;
|
||||
background: var(--theme-tab-active) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-item.active {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055)) !important;
|
||||
background: var(--theme-tab-active) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .conversation-sidebar .conversation-item.active,
|
||||
body[data-theme='dark'] .conversation-sidebar .conversation-item.active {
|
||||
background: rgba(255, 255, 255, 0.078) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
@ -430,7 +430,7 @@ body[data-theme='dark'] .conversation-sidebar .conversation-item:hover,
|
||||
body[data-theme='dark'] .conversation-sidebar .conversation-item:focus-within,
|
||||
body[data-theme='dark'] .conversation-sidebar .conversation-item.active:hover,
|
||||
body[data-theme='dark'] .conversation-sidebar .conversation-item.active:focus-within {
|
||||
background: rgba(255, 255, 255, 0.078) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
@ -543,7 +543,7 @@ body[data-theme='dark'] .conversation-sidebar .conversation-item.active:focus-wi
|
||||
padding: 6px;
|
||||
border: 1px solid var(--claude-border);
|
||||
border-radius: 14px;
|
||||
background: var(--theme-surface-strong, #fff);
|
||||
background: var(--theme-surface-strong);
|
||||
box-shadow: none;
|
||||
opacity: 0;
|
||||
transform: translateY(-4px) scale(0.98);
|
||||
@ -579,11 +579,11 @@ body[data-theme='dark'] .conversation-sidebar .conversation-item.active:focus-wi
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-actions-menu button:hover {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
}
|
||||
|
||||
.conversation-sidebar .conversation-actions-menu button.danger {
|
||||
color: #d6483b;
|
||||
color: var(--state-danger);
|
||||
}
|
||||
|
||||
.conversation-personal-entry {
|
||||
@ -626,7 +626,7 @@ body[data-theme='dark'] .conversation-sidebar .conversation-item.active:focus-wi
|
||||
}
|
||||
|
||||
.load-more-btn:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||
background: var(--theme-tab-active);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
@ -716,19 +716,19 @@ body[data-theme='dark'] .conversation-sidebar .conversation-item.active:focus-wi
|
||||
|
||||
.conversation-sidebar.collapsed .personal-page-btn:hover .sidebar-nav-icon,
|
||||
.conversation-sidebar.collapsed .personal-page-btn:focus-visible .sidebar-nav-icon {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055)) !important;
|
||||
background: var(--theme-tab-active) !important;
|
||||
}
|
||||
|
||||
.conversation-sidebar:not(.collapsed) .personal-page-btn:hover,
|
||||
.conversation-sidebar:not(.collapsed) .personal-page-btn:focus-visible {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055)) !important;
|
||||
background: var(--theme-tab-active) !important;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .conversation-sidebar:not(.collapsed) .personal-page-btn:hover,
|
||||
:root[data-theme='dark'] .conversation-sidebar:not(.collapsed) .personal-page-btn:focus-visible,
|
||||
body[data-theme='dark'] .conversation-sidebar:not(.collapsed) .personal-page-btn:hover,
|
||||
body[data-theme='dark'] .conversation-sidebar:not(.collapsed) .personal-page-btn:focus-visible {
|
||||
background: rgba(255, 255, 255, 0.078) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
}
|
||||
|
||||
.conversation-sidebar .load-more-btn {
|
||||
@ -739,10 +739,10 @@ body[data-theme='dark'] .conversation-sidebar:not(.collapsed) .personal-page-btn
|
||||
}
|
||||
|
||||
.conversation-sidebar .load-more-btn:hover:not(:disabled) {
|
||||
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055)) !important;
|
||||
background: var(--theme-tab-active) !important;
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] .conversation-sidebar .load-more-btn:hover:not(:disabled),
|
||||
body[data-theme='dark'] .conversation-sidebar .load-more-btn:hover:not(:disabled) {
|
||||
background: rgba(255, 255, 255, 0.078) !important;
|
||||
background: var(--hover-bg) !important;
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: var(--app-viewport, 100vh);
|
||||
height: var(--app-viewport);
|
||||
align-items: stretch;
|
||||
background: var(--claude-bg);
|
||||
color: var(--claude-text);
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: var(--app-viewport, 100vh);
|
||||
min-height: var(--app-viewport);
|
||||
background: var(--claude-bg);
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
top: 0;
|
||||
height: 100%;
|
||||
z-index: 1000;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 2px 0 10px var(--shadow-color);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user