DESIGN.md · diff
git:20260924.1295c06 to git:20260924.8d24bd3
1 added, 1 removed. Audit B to B.
---
name: OMK Studio
description: Studio 当前实现的设计基线与已确认改进方向;品牌紫、选中底、悬停与按下三档、状态色、页级字号、两档圆角、间距阶梯与响应式断点已接入运行时。
colors:
primary: "#7753ff"
primary-hover: "#6745eb"
action-ink: "#5a3cdb"
selection-fill: "#f2eeff"
text: "#192236"
text-secondary: "#657085"
text-muted: "#5f6b7f"
navigation-hover-text: "#293348"
canvas: "#f7f8fb"
surface: "#ffffff"
border: "#e2e6ee"
navigation-selected: "#f2eeff"
surface-hover: "#f4f6fa"
surface-press: "#eaeef6"
tone-success-ink: "#14795a"
tone-warning-ink: "#a1560b"
tone-error-ink: "#b42318"
tone-neutral-ink: "#5f6b7f"
typography:
body:
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif'
page-title:
fontSize: "20px"
lineHeight: "28px"
reader-body:
fontSize: "16px"
lineHeight: "1.85"
page-description:
fontSize: "12px"
lineHeight: "20px"
session-title:
fontSize: "14px"
fontWeight: 500
rounded:
control: "6px"
container: "8px"
spacing:
hairline: "2px"
micro: "4px"
compact: "8px"
small: "12px"
regular: "16px"
content-inline: "20px"
section: "24px"
major: "32px"
components:
navigation-item:
textColor: "{colors.text-secondary}"
rounded: "{rounded.control}"
padding: "7px 10px"
navigation-item-hover:
textColor: "{colors.navigation-hover-text}"
backgroundColor: "{colors.surface-hover}"
navigation-item-pressed:
textColor: "{colors.navigation-hover-text}"
backgroundColor: "{colors.surface-press}"
navigation-item-selected:
textColor: "{colors.text}"
backgroundColor: "{colors.navigation-selected}"
table-container:
backgroundColor: "{colors.surface}"
rounded: "{rounded.container}"
---
# OMK Studio 设计基线
## Overview
**设计主旨:让知识与证据清楚可读、可核对。**
Studio 是知识工作的全屏操作界面,服务于真实工作观测、知识维护与受控测量。内容、来源和结论之间的关系优先于装饰;界面不能以视觉上的“成功”替代领域中尚未成立的判断。产品定位以 [PRODUCT.md](./PRODUCT.md) 为准。
本文件只覆盖 Studio,不定义官网、文档站或第三方插件的视觉。正文以中文维护;英文节名用于兼容 DESIGN.md 的工具格式。执行边界与验收要求以根 [AGENTS.md](./AGENTS.md) 和 [Studio 领域规则](./src/studio/AGENTS.md) 为准,本文件不扩大它们的授权。
### 基线的使用方式
- **已确认约束与方向**:品牌、导航归属、全屏布局、表格可达性和证据语义,后续设计必须遵守。配色里**品牌紫、选中底与四支状态 ink 已接入运行时**(见「已应用的配色」),其余角色仍是方向,不代表源码已经采用。
- **当前可复用基础**:frontmatter 提取自现有主题与 CSS,作为本版相应角色的默认值;已接入的取值由 `test/architecture/studio-color-tokens.test.ts` 与主题、样式钉成同源,未接入的角色仍是提案。
- **待收敛项**:以“待收敛”标注的差异仅用于识别现状,不作为新页面的默认模板。重设计提案先单独讨论、给出可评审的构图,验证后再更新本文件。
提取依据是 [StudioTheme](./src/studio/web/components/layout/theme.tsx)、[studio.css](./src/studio/web/app/studio.css) 与 [StudioShell](./src/studio/web/components/layout/shell.tsx)。本版是源码基线,不声称完成所有页面的计算样式、对比度或响应式验收。
设计改进由 [Issue #1060](https://github.com/lizhiyao/oh-my-knowledge/issues/1060) 跟踪。当前阶段交付规范与设计方案;本文件合并不表示视觉改造已经实现,也不关闭该 Issue。静态稿采用合成数据,不能代替真实组件、交互和可访问性验收。
Issue #1060 期间的代表页原型、组件状态矩阵与对比度/布局取证脚本已随该 Issue 关闭退场,仓库内不再保留:已确认的规范取值全部接入运行时并回写到本文件(仍是提案的少数几项记在「仍然没有收敛的」与 Shapes 一节),验收证据从第七批起改在真实 Studio 页面上量(见「已应用的配色」各批记录),逐批结论与取舍同时记在 [Issue #1060](https://github.com/lizhiyao/oh-my-knowledge/issues/1060) 的收口评论里。本文件是当前实现基线与未收敛项的唯一正文;下一轮视觉改进需要可评审构图时重新建稿,并对着真实页面取证。
## Colors
### 品牌与基础表面
| Token | 角色与适用范围 |
|---|---|
| `primary` | 品牌紫填充值:主按钮、通用键盘焦点轮廓、分区导航当前项下边框 |
| `action-ink` | 正文链接与品牌色小字专用;不与 `primary` 合并,理由见「已应用的配色」 |
| `primary-hover` | 正文、弹层中普通链接的悬停色;不替代具备专属状态的组件规则 |
| `text` | 主文字和当前导航文字 |
| `text-secondary` | 辅助说明、默认导航文字与品牌文字 |
| `canvas`/`surface` | 应用背景与侧栏、表格等内容表面 |
| `border` | 结构分隔线与内容容器边界 |
| `navigation-hover-text` | 非当前一级导航与列表行的悬停/按下文字 |
| `surface-hover`/`surface-press` | 可点表面的鼠标位置档与按下档,比选中底更中性;按下比悬停深一档 |
| `navigation-selected` | 当前一级导航的背景块 |
品牌名称为 **OMK Studio**。品牌链接的 hover、focus、active 状态保持文字颜色稳定,键盘焦点通过轮廓提示。
项目文档与 Issue 中,配色统一称为“Studio 品牌紫”,通过色值和用途描述,不以外部参考品牌命名。
一级导航、分区导航与侧栏使用墨色层级;正文链接使用品牌色层级。当前导航不参与非当前项的悬停加深。一级导航用背景块标识当前位置,不能复制分区导航的下边框样式。
### 已应用的配色
以下取值已进入运行时:`src/studio/web/app/studio.css` 的 `:root` 定义语义 token,`StudioTheme` 的主色与之同源,三者由 `test/architecture/studio-color-tokens.test.ts` 锁住。
| 角色 | 取值 | token | 使用边界 |
|---|---|---|---|
| 主操作填充 | `#7753FF` | `--studio-action` | Studio 品牌紫;主按钮纯色,不将导航正文一并染紫;焦点环、分区导航下边框、受管强调色同用此值 |
| 正文链接与品牌色文字 | `#5A3CDB` | `--studio-action-ink` | 链接与品牌色小字专用 |
| 选中背景 | `#F2EEFF` | `--studio-selection-fill` | 一级导航当前项,配深墨色文字与 2px 指示条 |
| 悬停背景 | `#F4F6FA` | `--studio-surface-hover` | 非当前导航项、分区链接、侧栏项目摘要与折叠/工具入口的鼠标位置反馈;比选中底更浅,读者据此区分「鼠标在这」和「你在这」 |
| 按下背景 | `#EAEEF6` | `--studio-surface-press` | 与悬停档同一批表面,只加深底色、不改文字层级;当前项不参与,避免选中感在按下瞬间消失 |
| 导航与主文字 | `#192236` | 现有 `colorText` | 延续墨色层级,不因配色更新改变信息优先级 |
| 状态 ink | `#14795A` `#A1560B` `#B42318` `#5F6B7F` | `--tone-*-ink` | 成功/警告/错误/中性文字;浅底 fill 沿用既有变量关系 |
| 次要文字 | `#657085` | `--studio-ink-secondary` | 14px 及以上的辅助文字;同时写入 `StudioTheme.colorTextSecondary`,Ant Design 组件与本仓库样式共用一个值 |
| 弱文字 | `#5F6B7F` | `--studio-ink-muted` | 12px 及以下小字、落在着色表面上的文字;对应 `colorTextTertiary` |
| 状态浅底 | `#E6F4EE` `#FDF1E3` `#FBEAE8` | `colorSuccessBg` 等 | 必须显式给出:antd 会从基色派生浅底,基色换深后派生出的灰绿/土黄反而不达标 |
| 悬停深色 | `#6745EB` | `--studio-action-hover` → `colorLinkHover`、`Button.colorPrimaryHover` | 正文与弹层链接的悬停文字(实测 5.45:1 落在应用底色、5.55:1 落在卡片底),以及主按钮悬停底色(白字实测 5.79:1)。必须在主题层给出:样式里那条低优先级默认值压不过 antd 注入的 `a:hover`,不覆写时悬停取派生浅紫 `#AA90F5`,实测只有 2.42:1 |
| 页签选中文字 | `#5A3CDB`(墨条仍用 `#7753FF`) | `components.Tabs.itemSelectedColor` | antd 默认把 `colorPrimary` 当选中文字色,压在应用底色上实测 4.43:1,不达小字 4.5:1 |
品牌紫之所以拆成填充与文字两个值,是量出来的:`#7753FF` 对纯白 4.70:1 达标,对应用底色 `#F7F8FB` 只有 4.43:1、对选中底 `#F2EEFF` 只有 4.13:1,都低于小字要求的 4.5:1,而 AA 的大字豁免要 24px,正文与元信息够不到。文字改用 `#5A3CDB` 后,在上述三种表面上分别为 6.77、6.37、5.94:1。状态 ink 同理:基线的 `#1F9D63`、`#D97706`、`#8893A5` 在白底只有 3.46、3.19、3.10,作为 12px 状态文字全部不达标。
主紫与白色按 sRGB 相对亮度计算的对比度约为 4.70:1;该数值只说明此配色组合,不代表生成图片或全部组件已经通过无障碍验收。浅紫不作为普通字号白字按钮的底色。
### 仍是提案的配色
字体、间距、页面密度与多栏结构已在 #1060 第三~九批接入运行时(见下方各批记录),本节剩下的提案只到图标字形与加载画法这一层;不从生成图片反推精确 token。
**已收口**:一级导航当前项、观测会话列表、候选列表与评测侧栏四处的选中底色此前分别是浅紫、浅蓝与灰蓝,现统一到 `--studio-selection-fill`,选中指示条统一到 2px 品牌紫;「运行中」行的蓝色指示条是另一个角色(表达活动性,不是选中),收成 `--studio-running-indicator` 但保持原值。
**第二批已收口**:上一批留下的未达项已经修完,且修在正确的层。真实页面(`http://127.0.0.1:7799`,1440×900,逐文字节点量计算样式)现在量不出未达项——观测列表 235 个节点、对话详情 196 个、评测 24 个、知识 27 个、Agent 22 个,均为 0 组未达(这组数字的目录口径见下文更正,本批已换成全隔离重测)。做法是把 `colorLink`、`colorTextSecondary`/`Tertiary` 与 `colorSuccess`/`Warning`/`Error` 在 `StudioTheme` 层与 token 对齐,并把 12 处硬编码 `#8893a5` 与人类气泡的发送者标签收进 `--studio-ink-muted`,不是逐个组件加 CSS 覆写。
这里有一个反直觉的坑值得记下:把基色换深后,Ant Design 会**从基色派生** Tag/Alert 的浅底,结果落在灰绿 `#adb8b2`、土黄 `#e0d9ca` 上,12px 文字实测只有 2.63 与 3.88:1,比换色前更差。所以 `colorSuccessBg` 等浅底与边框必须一起显式给出,这条已锁进门禁。
一个必须记下的接线细节:`components` 要与 `token` **平级**放在 `theme` 下。放进 `token` 对象里会被当成一个无效 token 名,不报错也不生效——第一次尝试就是这么静默失败的,是复量才抓出来。
**第五批已收口(悬停档与圆角)**:「鼠标在这」和「你在这」不再共用一个底色。侧栏折叠按钮、分区导航链接、项目摘要、工具入口四处悬停原本直接写死旧的选中底 `#EEF0F6`,观测会话行又另用第三个值 `#F0F1F8`;现在统一走 `--studio-navigation-hover-fill`(`#F4F6FA`,第六批改名为 `--studio-surface-hover`,比选中底 `#F2EEFF` 更浅、不带紫味)。`#EEF0F6` 只保留给人类消息气泡(`--studio-message-human-fill`),它本就是另一个角色;运行中行的 `#E2EDFF` 表达活动性,不参与归并。圆角则把已有两档钉成 `--studio-radius-control`(6px)与 `--studio-radius-container`(8px),21 处硬编码像素全部替换,样式里不再出现未走 token 的圆角值(`50%` 的圆形品牌标记除外)。
这一批真正的收获是**把量测补到了悬停态**。前四批扫的都是静置的计算样式,而悬停文字色一直不由我们的规则决定:样式里 `.studio-content :where(a:hover)` 是域规则刻意留的低优先级默认值(`:where()` 让自带悬停设计的组件能压过它),但 antd 注入的 `:where(.css-hash) a:hover` 特异性更高,于是悬停文字取它从 `colorLink` 派生的浅紫 `#AA90F5`——压在刚统一出来的悬停底上实测 **2.42:1**;主按钮同理,白字 14px 落在派生的 `#9D7DFF` 上只有 **3.08:1**,静置时是 4.70:1。两个值都不达小字 4.5:1,而前四批的扫描一次也抓不到,因为鼠标从没被真正放上去过。修在主题层:`colorLinkHover` 与 `Button.colorPrimaryHover` 给出同一个深色 `#6745EB`(链接悬停实测 5.45:1 落在应用底色、5.55:1 落在卡片底,主按钮白字 5.79:1),不改那条默认值的优先级,也不动 Input/Select 的悬停边框(1px 描边按非文本 3:1 判,派生值本来就够)。会话行另加一条自己的悬停文字色,把列表行留在墨色层级,不让它继承链接的品牌紫。
**第六批已收口(按下档与选中态不参与悬停档)**:把上一批量到的「按下与悬停同色」补上了第三档。`--studio-surface-press:#EAEEF6` 接到一级导航非当前项、工具入口、侧栏项目摘要、侧栏工作区行与观测会话行,只加深底色、文字层级不变;真实页面逐表面量到 静置透明 → 悬停 `#F4F6FA` → 按下 `#EAEEF6`。同时把这一档改名成 `--studio-surface-hover`——它早就同时用于导航与列表行,名字里的 navigation 不准确。改名时量出一个真回归:侧栏工作区行在被选中时(浅紫底 `#F2EEFF`)悬停会换成更浅的中性底,选中感在鼠标经过的一瞬间消失,违反「当前项不参与非当前项的悬停加深」。一级导航本来用 `:not([aria-current])` 做对了,现在同一口径推广到 `:not(.selected)`,量到选中行三档都保持 `#F2EEFF`。候选列表行本来没有任何悬停反馈(域规则要求可点表面必须有视觉变化),一并补上两档;该表面在隔离工作区里没有数据,到现在也只有门禁这一条证据,不能算在线量过。
**第七批已收口(真产物在线验收与三处修复)**:第一次拿真跑出来的 `omk eval` 产物做在线复核(离线 echo 执行器+`--no-judge`,零 API 调用,五个数据目录全部隔离),量出三处 SSR 层看不到的缺口,全部修完。侧栏运行标识在选中浅紫底上取 `--studio-ink-secondary` 实测 **4.38:1**,差 0.12 就够小字的 4.5:1;换成 `--studio-ink-muted` 后 4.74:1,用的是「12px 及以下小字、落在着色表面上」这条既有角色,不是新配色。等宽片段被列宽裁掉时没有完整内容出口——antd 的自动 `title` 只覆盖纯字符串单元格,包了组件的单元格就不给;出口改由 `Code` 自己给,一处覆盖所有用到它的列,量到「截断且无出口」从 1 处降到 0。
表头吸顶这条前后试了三次,值得单独记下:在样式里给 `th` 写 `position:sticky`,计算值是对的、真实页面上却不吸。逐层清 `overflow` 才量清原因——卡片的 `overflow:hidden`(为圆角裁切)与 antd 的 `.ant-table-content{overflow-x:auto}`(为横向滚动)都会把自身变成滚动容器,把 sticky 的锚点从滚动面板截到卡片内部;而 `overflow-y:clip` 与 `auto` 配对时按规范退成 `hidden`,同样截锚点。最终走 antd 的 `sticky` 属性:它把表头拆成独立的 `.ant-table-sticky-holder` 一层,天然出得了横向滚动容器,卡片的裁切则换成 `overflow:clip`——保留圆角裁切又不建立滚动容器。在线判据不是计算值而是「把表头顶到面板上沿之上时它是否停在那里」,并配一组对照(临时把吸顶层改回 `position:static`):报告页 8 张表里 5 张量到吸住(吸住时 `0`,同一位置改 static 后 `-60`/`-1004`),横向滚动仍在表体这一层(417/268px 可滚且滚得动),页面级横向溢出 0;圆角与卡片外观未变。剩下 3 张在另一页签的折叠区里,切页签后点标题没能展开(手风琴一次只开一个),只有同组件同属性的结构证据,不算在线量过。
**第八批已收口(间距归档与省略出口)**:把现网 80 条一次性间距按「就近归档、同距向上」收进阶梯,阶梯之外只留两个具名档位——`--studio-space-1`(2px 发丝档)与 `--studio-collapsed-rail-offset`(折叠栏避让量,是布局偏移不是间距)。门禁随之收紧成「`padding`/`margin`/`gap` 里不许出现任何字面 px」。代价用同一会话内的 A/B 量:把归档前的 76 条字面量注回页面再量一遍,1273 个可比元素里 253 个尺寸真的变了(侧栏导航行 36→38px、侧栏头部 50→54px、折叠按钮 30→34px),其余只是被顶下去;三条硬判据(页面级横向溢出、被裁单元格、可点表面容得下标签)前后逐项一致,都是 0。第一版曾用「两次运行分别截图对量」,被运行时注入的 `<style>` 节点把下标整体错位,报出 94/358 个假变化,已改成同会话注回旧值才敢报数。
同一批里修掉一个被全局 `nowrap` 掩盖的可达性缺口:6 个身份列被硬切成 `custom-executor-eef2…` 这样,既没有省略号也没有完整内容出口。这里有一条实测教训值得留着——先给 `.ant-table-cell` 全局加 `overflow:hidden;text-overflow:ellipsis`,结果被裁单元格不再贡献固有宽度,整张表从「比容器宽、可横向滚」塌成容器宽,长标识反而只能逐个悬停;配 `tableLayout:fixed` 也救不回来,列会被拉伸填满、同样没有横向滚动。改回按列给 antd 的 `ellipsis`(省略号与自动 title 一起给)后,隐含的 fixed 布局让当前这份产物的 4 张表都不再需要横向滚动(所有列同屏可见),被裁的 6 个单元格全部带省略号与完整内容出口(`noEllipsis`/`noExit` 都是 0);表头与表体拆层后逐列对齐量过,8 张表 0 列错位。列宽之和真超过容器时仍会横向滚(横向滚动那一层没被改坏)。
**仍然没有收敛的**:
- 真实数据下仍存在 **11px** 文字(侧栏项目计数、评测侧栏副标),比规范假设的最小 12px 低一档;换到 `--studio-ink-muted` 后对比度达标,但字号本身是否该抬,属排版规范决定。
- 配色、字号、圆角、边界色、间距阶梯与响应式断点(1280/1024/860)都已接入运行时,由 `test/architecture/studio-type-scale.test.ts` 与 `studio-color-tokens.test.ts` 钉住。**仍未收敛的是图标字形与加载画法**:现网自绘的两枚图标(侧栏收起/展开、设置与帮助)已按本文件网格对齐到 16px/描边 1.5px/round 端点,其余图标来自 Ant Design 内置,是否整体换成自绘线性字形属实现决策;四处加载指示(按钮 spinner、标签前 spinner、输入内嵌条、行级骨架)仍是四种语言,是否统一成一套同样属规范决定。
- 交互态的量测进度:悬停档与按下档都已在真实页面上用派发鼠标事件量过(70 个控件按判据零未达;注入旧浅紫会报出 11 个未达,证明扫描不是空跑)。键盘焦点也已用 Tab 逐元素量过并**修完**:此前 `summary` 与侧栏按钮吃到本仓库的 2px 品牌紫环(4.7:1),而品牌链接与四个一级导航项吃 antd `genFocusOutline` 的派生浅紫 `#DECDFF`,对表面只有 1.27~1.45:1,不达焦点指示器要求的 3:1。现在全应用统一 2px 实色 `#7753FF`,最低一档 4.13:1(那条是压在选中底上的导航项),低于 3:1 的 0 处。修法刻意走样式特异性而不是主题:焦点环颜色是 antd 别名 `colorPrimaryBorder`,它被 slider/date-picker/notification 等 47 处共用,改它等于顺手改一批无关控件的观感。
- 覆盖面限制要说清:报告详情与评测列表在隔离工作区里没有数据可渲染,改用「真实组件 SSR + antd 运行时派生样式 + 真实 `studio.css`」在 1440×900 上量:报告详情 161 个节点、列表 43 个节点,各 0 组未达。**这一层量出了在线量不到的真问题**——页签选中文字用主色压在应用底色上只有 4.43:1。第七批改用真实 `omk eval` 产物在运行中的页面上量,报告详情页已不再依赖这一层兜底。
- 上一批那句「在线量的是有数据的隔离工作区」要说得更准:当时只把 `--observations-dir` 指到合成数据,`agents`/`reports` 等目录仍走默认(项目级与本机等),所以那组节点数(235/196/24/27/22)混了本机真实数据。本批把五个目录全部隔离后重测,节点数为观测 225、评测 23、知识 28、Agent 22,合计 298 个文字节点、0 组未达;结论方向未变,但**换成全隔离口径后数字才叫可复现**。
- 仍未量到的部分:候选核对的三栏整页(只有决定头与列表行两枚片段被覆盖,7 个节点)、需要真实评测产物才会出现的空态/错误态组合,以及数据丰富页面上的全部悬停控件;报告详情页已有真实产物可看(第七批),但样本只有 2 个用例,长表与分页要更大样本才验得到。输入框的焦点仍走 Ant Design 的边框+浅紫外阴影(`outline: 3px none`),按非文本 3:1 判达标,但它是同一页上的第三种焦点画法——要不要连它一起收成 2px 实色环,属观感决定,留给你。
- 报告页的**结果摘要投影没有做,前置比原先写的更硬**:`EvaluationReportSchema.summaries` 是无类型 `JsonValue`,内容由调用方决定,本仓库没有生产者。把外部可写的 JSON 直接投给展示层,等于渲染一个没有契约的形状——既定不出「哪些键该显示」,也写不出有意义的缺值分支。两条出路需要定一个:① 先给 `summaries` 定一份带版本的类型化 schema(公开契约变更,要迁移与 BREAKING 标注),再投影;② 与「结论限制/逐用例证据」同样处理,不做这一层,等真有生产者与形状再说。(原 #1060 实现任务 8)
- **比较条件只投了一半**:角色措辞已按 owner 决定收成 `对照组/实验组`(英文 `Control/Treatment`),与 CLI、CLI 参考文档和词汇表逐字一致,已进 view-model 并在报告页只读呈现,`test/studio/application/core-run-catalog.test.ts` 钉住它逐字等于 `plan.definition.comparisons` 且两方都是同一页已投影的被测版本。**可比性评估本身未接**——它不在运行产物集里,接它要先解决产物集包含什么,不属于视觉批次。(原 #1060 实现任务 9 的剩余部分)
- **键盘与读屏的边界要说清**:焦点顺序、焦点环颜色与三档表面状态都在真实页面量过,但**未做焦点陷阱**——弹层与窄屏抽屉打开后 Tab 能否走出容器没有被验证;**屏幕阅读器语义未实测**,本文件的可访问性结论只覆盖视觉判据。中文长句换行、系统字体差异与 Windows/Linux 字形覆盖同样未验证。(原 #1060「未覆盖边界」中仍未闭合的两条)
这些是 #1060 十批收口后仍然开着的部分;该 Issue 已关闭,未闭合项此后由本节跟踪。
### 状态与证据
现有 CSS 已集中定义 `--tone-success-*`、`--tone-warning-*`、`--tone-error-*`、`--tone-neutral-*`,受管生命周期分类使用 `--managed-tone-*`。语义 tone 与生命周期分类是不同维度,不因共享颜色而合并业务含义。
运行完成、证据完整、结论成立分别表达;候选的保留不等于内容已验证。来源缺失、不可读和不确定性必须明确呈现。状态的具体含义来自领域投影,展示层不重算或改写。
**待收敛:** 候选列表、侧栏工作区行与一级导航的选中色已在第四批统一到 `--studio-selection-fill`,小字号状态文字也已在真实表面(含悬停与按下档)量过对比度,这句原先的「待收敛」已不成立。仍然开着的是:状态浅底与色带在数据密集页上的组合没有逐例量过,以及「运行中」的蓝色指示条与浅紫选中底同时出现时是否需要更强的视觉差——这两项属配色评审范围,不由本文件替评审者定值。
## Typography
复用现有系统字体栈,保持中文优先。等宽字体用于代码、技术身份和原始记录,不把整段知识正文改为等宽排版。数字比较区使用等宽数字对齐,长标识仍需完整查看入口。
frontmatter 中的字号按**实际角色**命名。页级标题原本记作 `measure-page-title`(只有评测页有它),现在四个区共用同一档,故改名 `page-title`;`page-description` 是页级说明,`session-title` 是对话列表标题。它们不是统一全站的 display/headline 阶梯;缺乏明确来源的字重或字号不补默认值。
**已接入运行时(#1060 第四批)**:页级标题统一到 20px/28px。此前它散成 8 条规则、四种字号(22/20/18/17)加两处窄屏降档(18→16、20→17),Agent 页还是 18px/26px——同一个应用里「页标题」有四种视觉重量。同时对话阅读正文从 14px/1.8 升到 15px/27px,知识首页补出此前缺失的 h1(文案沿用分区导航已有的「知识载体/Knowledge artifacts」,不新造词)。这条尺度由 `test/architecture/studio-type-scale.test.ts` 锁住:任何一条命中 h1 的规则出现非 20px/28px 的字号或行高都会变红。
**仍然待收敛**:时间轴与部分计数存在 11px 这类更小字号(对比度已随配色批次达标,但字号本身没有角色);对话文本仍有直接显示 Markdown 标记的路径(正文是 `white-space: pre-wrap` 纯文本,无渲染器);`page-description` 与 `session-title` 尚未纳入统一尺度;字重仍随组件,未收敛成规范。断点与多栏结构已在第九批接入运行时(取值见「当前布局参数」)。
## Layout
### 已确认的空间边界
- 应用占满视口,页面根节点和外壳不承担横向、纵向滚动。导航、页面操作及关键摘要固定可达。
- 左侧栏是品牌、一级导航、工作区列表和设置入口的唯一载体;工作区内容通过外壳槽位加入,不另建一套全局导航。
- 先使用紧凑布局、分页、标签页与按需详情;确有长内容时才在表格、正文、时间轴、证据面板或抽屉内滚动,并约束高度、最小尺寸与滚动传播。
- 不能用 `overflow: hidden` 隐藏无法访问的内容。表格表头和单元格不自动换行;状态、数量和操作列保留空间,长文本用省略加完整提示/详情,或内部横向滚动。
- 普通双行列表优先采用约 56px 行高。独立挂载的报告不强制使用应用外壳;仅挂载 `/measure` 的预览宿主保留无导航的紧凑页头。
### 当前布局参数
这些是现有实现的上下文,不代表新的统一断点体系。
| 范围 | 当前实现 |
|---|---|
| 应用高度 | `100dvh`;弹性内容区域设置最小尺寸约束 |
| 侧栏 | 常规宽度 260px;窗口不超过 1024px 时为 220px |
| 窄窗口侧栏 | 窗口不超过 860px 时切为 280px 宽覆盖抽屉,由移动页头按钮控制;Esc 与遮罩点击都能收回,关闭后焦点回到触发它的按钮 |
| 内容内边距 | 常规为 12px 20px;窗口不超过 860px 时为 8px 12px |
| 无导航预览页头/移动页头 | 高度 52px |
| 对话阅读列 | 页头全宽,正文使用最大 960px 的居中阅读区;用户消息靠右、助手靠左,正文 16px/1.85 行高、段落最大 48em,表格与代码可使用阅读区全宽;连续助手消息保留轻分隔,时间与执行信息收在轮次尾部;消息开头的完整环境上下文默认折叠,原文可展开 |
| 候选核对三栏 | 不超过 1280px 收为两栏(第三栏整行放在下方);不超过 1024px 收为单栏 |
第八批起,`padding`/`margin`/`gap` 里不再允许出现字面 px:现网 80 条一次性值按「就近归档、同距向上」收进阶梯,由 `test/architecture/studio-type-scale.test.ts` 钉住。阶梯之外只有两个具名档位,都不算间距比例——`--studio-space-1`(2px 发丝档,图标与文字基线之间;抬到 4px 会把紧凑堆叠撑开)与 `--studio-collapsed-rail-offset`(折叠栏内容避让量,与 44px 轨道宽度绑定,是布局偏移不是间距)。`clamp()`/`max()` 里由视口派生的边界不受这条约束。
**第九批已收口(断点收敛)**:现存 10 个媒体条件(600/700×4/760×2/1000/1100+一个 `max-height:700`)收到 **1280/1024/860** 三个宽度档,与 #1060 原型评审定下的退化决定逐档对齐——1280 管候选三栏→两栏,1024 管侧栏收窄、阅读页头紧凑与候选两栏→单栏,860 管整个应用切抽屉导航(页头、工具条、时间轴同时退到窄屏形态)。`max-height:700` 保留:它管候选起始页在矮窗口里的纵向紧凑,不参与宽度阶梯。同一档保留多个块是刻意的,块与块之间有先后,合并成一个块会改变层叠顺序。
## Elevation & Depth
现有主界面主要通过背景、细边界与间距区分区域。桌面侧栏与普通表格容器自身没有专属阴影,不把所有内容都提升成悬浮卡片;Ant Design 控件和浮层仍遵循所用组件主题。
现有自定义阴影主要用于覆盖层或浮动入口:窄窗口侧栏使用 `0 0 24px rgba(25,34,54,.18)`,展开侧栏按钮使用 `0 1px 6px rgba(25,34,54,.12)`。它们是特定角色的当前值,不是任意卡片可复用的通用层级。
当前覆盖侧栏使用 `transform .2s ease` 过渡。本版不推定全局动效时长、缓动或减少动态效果支持已经统一;新增动效规则需另行验证。
## Shapes
控件基准圆角来自主题,导航项沿用 `rounded.control`;表格、证据等容器常见圆角为 `rounded.container`。结构边界通常为细线,而不是粗描边。
这两档自 #1060 第五批起接入运行时:样式里只有 `--studio-radius-control:6px` 与 `--studio-radius-container:8px` 两个来源,21 处硬编码像素已替换,圆形品牌标记保留 `50%`。这一条不新增形状,只是把已有的两档钉成变量——`test/architecture/studio-type-scale.test.ts` 会让随手写第三个圆角值的行为变红。边界(border)颜色与粗细仍未收敛,仍是有意的现状。原型评审时提过的第三档 `--studio-radius-overlay:10px`(覆盖层/抽屉)**没有产品来源**:现网抽屉圆角由 Ant Design 主题给出,因此这一档仍是提案,不接入。
品牌标记当前为 32px 圆形,属于品牌元素。时间轴圆点和紧凑节点表达各自的图形角色,不作为普通按钮或卡片的形状规范。
## Components
### 外壳、品牌与导航
- 复用 `StudioShell`。一级导航包含观测、评测、知识和 Agent;工作区列表与底部设置属于同一侧栏。用 `aria-current` 表达当前位置,并保留可见状态。导航项的默认、悬停与当前状态对应 frontmatter 中的三个 `navigation-item` 角色。
+ 复用 `StudioShell`。一级导航包含观测、评测和知识;观测下设“对话”与“数据来源”二级入口,数据来源承载本机 Agent 识别与日志采集报告。工作区列表与底部设置属于同一侧栏。用 `aria-current` 表达当前位置,并保留可见状态。导航项的默认、悬停与当前状态对应 frontmatter 中的三个 `navigation-item` 角色。
品牌文字在交互时保持稳定;其它可点表面应具有颜色或背景反馈。不能只增加不可见的语义属性,却让可点击项与静态文字完全一样。
### 按钮、输入框与弹层
现有基础控件来自 Ant Design,统一经过 `StudioTheme`。本版只记录实际主题覆盖的主色、文字色、背景、字体与圆角,不凭经验补写 Ant Design 的尺寸、派生悬停色、禁用态或阴影。
自定义链接与按钮的通用键盘焦点为品牌色轮廓(2px,外偏移 3px);侧栏部分自定义控件使用内偏移(-2px)。已有组件专属焦点样式按其作用范围保留,不能用一条全局覆盖规则替代所有控件状态。
### 列表与表格
表格容器复用 `table-container` 的表面与圆角,用 `border` 分隔。不要把空白表格、列宽或每页条数当作品牌视觉;它们取决于数据和任务。
普通双行列表区分标题与辅助信息。省略显示必须有完整内容提示或详情路径,操作列不得自动换行。横向滚动发生在表格内部,不传播为整个应用的横向溢出。
### 对话、候选与证据
知识正文、原始记录、派生解释与结果应保持可区分的身份。阅读排版可以改进,但不能覆盖原始证据,也不能因为视觉简化而删除来源、时间、修订或关联身份的访问路径。
候选审核要区分维护选择与验证效果;在确认向模型发送内容前保留来源范围预览。错误与证据不完整是可见状态,不包装成普通空白。
**待收敛:** 各页标题区、主要操作、空状态与阅读排版尚未成为统一组件规范。#1060 已把对话阅读、评测列表与候选核对这三类页面的配色、字号、间距和断点接入运行时并逐节点量过对比度,但组件层的统一(同一角色在各页是否同一结构)仍未收口;本版不宣称组件规范已落地。
## Do's and Don'ts
### 应当
- 复用已有外壳、主题和相应角色的基础值;修改规范时同时说明适用范围与源码依据。
- 保持用户可见文案中文优先,技术标识保留原语法;LLM judge 统一称为“评委”。
- 保留来源和不确定性,分别表达运行、证据、结论和维护状态。
- 改造页面时核对正常桌面与较矮窗口,以及 Observe、Measure、Knowledge、报告和异常页面的布局边界;四条泳道完整可见,表格操作可达。
- 将参考案例和待验证设计参数留在提案中,经真实页面量测验证后再提升为正式规范。
### 避免
- 把当前散落的所有硬编码色值、字号和页面特例都提升为全站规范。
- 用来源缺失替代“无问题”,用运行完成或候选保留替代效果已验证。
- 在外壳之外新增一级导航,靠整页滚动或裁切处理布局不足。
- 把官网大标题、装饰和宽留白直接套到密集的审核与证据界面。
- 将本版源码提取误报为像素级复刻、完整无障碍通过或所有页面已统一;把工具面板预览当成真实 Studio 验收。