[{"data":1,"prerenderedAt":930},["ShallowReactive",2],{"docs-nav-zh":3,"doc-\u002Fzh\u002Fdocs\u002Fdesign\u002Fdirection":80,"docs-search-sections-zh":507,"doc-surround-\u002Fzh\u002Fdocs\u002Fdesign\u002Fdirection":925},[4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76],{"path":5,"title":6,"icon":7},"\u002Fzh\u002Fdocs\u002Fquickstart","快速开始","ri-rocket-line",{"path":9,"title":10,"icon":11},"\u002Fzh\u002Fdocs\u002Fdevtool","本地调试","ri-terminal-box-line",{"path":13,"title":14,"icon":15},"\u002Fzh\u002Fdocs\u002Fatomm","atomm 对象","ri-plug-line",{"path":17,"title":18,"icon":19},"\u002Fzh\u002Fdocs\u002Fexport","导出能力 Export","ri-download-2-line",{"path":21,"title":22,"icon":23},"\u002Fzh\u002Fdocs\u002Fpublish","提交审核与上架","ri-send-plane-line",{"path":25,"title":26,"icon":27},"\u002Fzh\u002Fdocs\u002Ffaq","常见问题","ri-questionnaire-line",{"path":29,"title":30,"icon":31},"\u002Fzh\u002Fdocs\u002Fdesign\u002Foverview","总览","ri-book-open-line",{"path":33,"title":34,"icon":35},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor","色彩","ri-palette-line",{"path":37,"title":38,"icon":39},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ftypography","字体","ri-text",{"path":41,"title":42,"icon":43},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout","布局","ri-layout-line",{"path":45,"title":46,"icon":47},"\u002Fzh\u002Fdocs\u002Fdesign\u002Felevation","高度与深度","ri-stack-line",{"path":49,"title":50,"icon":51},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fshapes","形状","ri-shape-line",{"path":53,"title":54,"icon":55},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents","组件","ri-checkbox-multiple-line",{"path":57,"title":58,"icon":59},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fmotion","动效","ri-flashlight-line",{"path":61,"title":62,"icon":63},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ficon","图标","ri-apps-2-line",{"path":65,"title":66,"icon":67},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fdirection","方向（RTL）","ri-global-line",{"path":69,"title":70,"icon":71},"\u002Fzh\u002Fdocs\u002Fdesign\u002Faccessibility","无障碍","ri-eye-line",{"path":73,"title":74,"icon":75},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fplatform","平台约束","ri-shield-check-line",{"path":77,"title":78,"icon":79},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules","规则清单","ri-checkbox-circle-line",{"id":81,"title":66,"body":82,"description":501,"extension":502,"icon":67,"meta":503,"navigation":221,"path":65,"seo":504,"stem":505,"__hash__":506},"docs_zh\u002Fzh\u002Fdocs\u002Fdesign\u002F09.direction.md",{"type":83,"value":84,"toc":496},"minimark",[85,89,98,124,364,368],[86,87,66],"h1",{"id":88},"方向rtl",[90,91,92,93,97],"p",{},"平台会把你的生成器渲染在一个 ",[94,95,96],"code",{},"dir"," 跟随用户语言的文档里。镜像不是可选项，也没有第二份样式表——布局必须自己翻。",[90,99,100,101,105,106,109,110,109,113,109,116,119,120,123],{},"用",[102,103,104],"strong",{},"下面示例上方的 LTR \u002F RTL 开关","就地对照。按现代写法写，这几乎是免费的：每一个单侧取值都用逻辑属性——",[94,107,108],{},"margin-inline-start","、",[94,111,112],{},"padding-inline-end",[94,114,115],{},"inset-inline-start",[94,117,118],{},"text-align: start","。左右对称的简写完全不用管，flex 和 grid 会自己镜像；为 RTL 加 ",[94,121,122],{},"flex-row-reverse"," 是把一个已经翻好的布局再翻一次。",[125,126,128,316],"spec-demo",{":dir-toggle":127},"true",[129,130,132,133,132,233,315],"div",{"className":131},[96],"\n      ",[129,134,137,138,137,143,137,171,137,206,137,214,132],{"className":135},[136],"dir-rail","\n        ",[129,139,142],{"className":140},[141],"lay-sec","画板",[129,144,147,151,152],{"className":145},[146],"fieldrow",[148,149,150],"label",{},"عرض اللوح","\n          ",[153,154,158,166],"span",{"className":155},[156,157],"unitbox","unitbox--mm",[159,160],"input",{"className":161,"value":165},[162,163,164],"inp","inp-chip","w80","200",[153,167,170],{"className":168},[169],"unit","mm",[129,172,174,151,177],{"className":173},[146],[148,175,176],{},"画板高度",[153,178,181,185,151,188],{"className":179},[180,157],"nf",[159,182],{"className":183,"value":184},[162,163,164],"150",[153,186,170],{"className":187},[169],[153,189,192],{"className":190},[191],"nf-handle",[193,194,201,202],"svg",{"width":195,"height":195,"viewBox":196,"fill":197,"stroke":198,"strokeWidth":199,"strokeLineCap":200,"strokeLineJoin":200},"16","0 0 16 16","none","currentColor","1.5","round","\n            ",[203,204],"path",{"d":205},"M2 8h12M4.5 5.5 2 8l2.5 2.5M11.5 5.5 14 8l-2.5 2.5",[159,207],{"type":208,"min":209,"max":210,"value":211,"ariaLabel":212,"style":213},"range","0","100","35","密度","--f:35%",[148,215,218,222,230],{"className":216},[217],"sw",[159,219],{"type":220,"checked":221},"checkbox",true,[153,223,226],{"className":224},[225],"sw-track",[153,227],{"className":228},[229],"sw-knob",[153,231,232],{},"外框托盘",[129,234,137,237,137,243,132],{"className":235},[236],"dir-canvas",[129,238,242],{"className":239,"style":241},[240],"lay-float","inset-block-start:24px;inset-inline-end:8px","重新生成",[129,244,151,248,151,297,151,309,137],{"className":245,"dir":247},[246],"dir-fixed","ltr",[129,249,252,255,258,260,262,264,267,270,273,276,279,282,285,288,291,294],{"className":250},[251],"dir-ruler",[253,254,209],"i",{},[253,256,257],{},"50",[253,259,210],{},[253,261,184],{},[253,263,165],{},[253,265,266],{},"250",[253,268,269],{},"300",[253,271,272],{},"350",[253,274,275],{},"400",[253,277,278],{},"450",[253,280,281],{},"500",[253,283,284],{},"550",[253,286,287],{},"600",[253,289,290],{},"650",[253,292,293],{},"700",[253,295,296],{},"750",[129,298,301],{"className":299},[300],"dir-board",[193,302,201,306],{"viewBox":303,"width":304,"height":305},"0 0 132 96","132","96",[203,307],{"d":308},"M0 48h132M44 0v96M88 0v96",[153,310,314],{"className":311,"style":313},[312],"lay-dim","inset-block-start:158px;inset-inline-start:40px","200 mm","\n    ",[317,318,320],"template",{"v-slot:caption":319},"",[90,321,322,323,326,327,329,330,332,333,336,337,340,341,344,345,348,349,351,352,355,356,359,360,363],{},"点开关，注意",[102,324,325],{},"哪些翻了、哪些没翻","。翻的：轨换边、标签与数值互换、滑块从另一端填充、开关拇指移到另一侧——全部由逻辑属性和 flex 自己完成，没有一处 ",[94,328,122],{},"。没翻的：标尺零点、刻度方向、画板位置。第一行的阿拉伯语标签（",[94,331,150],{},"，画板宽度）是",[102,334,335],{},"文字自己","从右往左：LTR 下 ",[94,338,339],{},"عرض"," 在左、",[94,342,343],{},"اللوح"," 在右，RTL 下两个词调个头。下面那行中文只是整块靠右，",[102,346,347],{},"字仍然从左往右","——",[94,350,165],{}," 永远是 200 不会变成 002。方向属性改的是排列，不是文字内部的书写方向。",[102,353,354],{},"画板、标尺和产物永不镜像","——把画板那一层锁 ",[94,357,358],{},"direction: ltr","，它内部的逻辑属性就永远解析成左，产物朝向与围绕它的界面无关。但",[102,361,362],{},"画布上的浮层是界面、不是产物","，它们跟着翻：RTL 下「重新生成」落在镜像后的那一侧。",[365,366,367],"h3",{"id":367},"这套系统实测踩过的坑",[125,369,370],{},[371,372,315,373,315,387,495],"table",{},[374,375,376],"thead",{},[377,378,379,384],"tr",{},[380,381,383],"th",{"style":382},"width:36%","现象",[380,385,386],{},"原因与修法",[388,389,132,390,132,406,132,418,132,434,132,453,132,464,132,487,315],"tbody",{},[377,391,392,396],{},[393,394,395],"td",{},"滑块手柄往反方向走",[393,397,398,399,402,403],{},"webkit 填充用 ",[94,400,401],{},"linear-gradient(to right …)","，RTL 下要换成 ",[94,404,405],{},"to left",[377,407,408,411],{},[393,409,410],{},"拖拽改值方向相反",[393,412,413,414,417],{},"取 ",[94,415,416],{},"direction"," 后把 delta 符号取反",[377,419,420,423],{},[393,421,422],{},"下拉浮层错位",[393,424,425,426,430,431],{},"JS 定位时 RTL 下要和触发器",[427,428,429],"b",{},"右","边缘对齐，不能照搬 ",[94,432,433],{},"left",[377,435,436,439],{},[393,437,438],{},"居中的浮起提示偏一半",[393,440,441,442,445,446,449,450],{},"别用 ",[94,443,444],{},"inset-inline-start:50%"," + ",[94,447,448],{},"translateX(-50%)","，用 ",[94,451,452],{},"inset-inline:0; margin-inline:auto",[377,454,455,458],{},[393,456,457],{},"进度条从错误的一端长出",[393,459,460,463],{},[94,461,462],{},"transform-origin"," 要跟着换边",[377,465,466,469],{},[393,467,468],{},"开关拇指滑出轨道外",[393,470,471,472,474,475,478,479,482,483,486],{},"拇指起点用 ",[94,473,115],{}," 却用 ",[94,476,477],{},"translateX(16px)"," 走位移——",[94,480,481],{},"transform"," 是物理方向，RTL 下要 ",[94,484,485],{},"-16px","。任何用 transform 表达「往前走」的位移都要自己判一次方向",[377,488,489,492],{},[393,490,491],{},"标签与输入框相撞",[393,493,494],{},"单侧内边距没翻。全用逻辑属性","\n  ",{"title":319,"searchDepth":497,"depth":497,"links":498},2,[499],{"id":367,"depth":500,"text":367},3,"平台会把你的生成器渲染在一个 dir 跟随用户语言的文档里。镜像不是可选项，也没有第二份样式表——布局必须自己翻。","md",{},{"title":66,"description":501},"zh\u002Fdocs\u002Fdesign\u002F09.direction","GH5pLYOno1M_4t0CpW6YfgpD8HLsIWGruRopOkxn1Dc",[508,512,516,521,524,527,532,537,540,543,548,553,558,563,568,571,574,579,584,589,594,599,604,607,610,615,620,625,630,635,637,640,645,650,655,660,665,670,673,677,680,683,688,693,698,703,708,713,718,721,724,729,734,737,741,746,751,756,761,766,769,773,778,781,785,788,792,797,802,807,812,817,822,827,832,837,840,844,847,851,856,861,863,867,871,874,878,883,888,891,895,898,901,905,910,915,920],{"id":5,"title":6,"titles":509,"content":510,"level":511},[],"把任意技术栈写出的生成器接入 Atomm：创建生成器 → 引入一行 SDK 并接入能力 → 本地实时预览调试 → 提交审核上架。不需要安装任何命令行工具。",1,{"id":513,"title":6,"titles":514,"content":515,"level":511},"\u002Fzh\u002Fdocs\u002Fquickstart#快速开始",[],"把任意技术栈写出的生成器接入 Atomm：创建生成器 → 引入一行 SDK 并接入能力 → 本地实时预览调试 → 提交审核上架。不需要安装任何命令行工具。 纯 HTML、Vite、Vue、React…… 任意技术栈都行。Atomm 通过浏览器端 SDK 与你的应用通信，不限制你的构建方式。",{"id":517,"title":518,"titles":519,"content":520,"level":497},"\u002Fzh\u002Fdocs\u002Fquickstart#端到端流程","端到端流程",[6],"1. 在开发者后台创建生成器 先取一个名称作为公开标识（以小写字母开头，仅含小写字母、数字与连字符 -，创建后不可修改——它会成为运行子域名与访问路径的一部分），创建后进入应用详情页继续完善。这个名称在下一步本地预览与最终上架都会用到。 2. 在应用中引入 SDK 并接入能力 在你的页面里加入一行 script 获得全局 atomm 对象： \u003Cscript src=\"https:\u002F\u002Fstatic-res.atomm.com\u002Fscripts\u002Fjs\u002Fgenerator-sdk\u002Fplatform-sdk.js\">\u003C\u002Fscript> 再按需接入平台能力。以导出为例分两步——放一个导出按钮占位元素（SDK 会就地把它渲染成 Export 按钮），并注册 export 钩子提供结果文件： \u003C!-- 放在页面任意位置，SDK 就地把它渲染成 Export 下拉 -->\n\u003Cdiv data-atomm-export-button>\u003C\u002Fdiv> \u002F\u002F 平台在用户点导出时反拉你的结果文件\natomm.lifecycle.on('export', async () => ({ filename: 'design.glb', blob })) 详见 atomm 对象 与 导出能力。 3. 本地起服务，在浏览器里实时预览验证 本地启动你的服务（例如 http:\u002F\u002Flocalhost:5173），用第 1 步的生成器名称拼出预览地址，把本地地址填进 ?local=（仅支持 localhost \u002F 127.0.0.1 等回环地址）： https:\u002F\u002Fwww.atomm.com\u002Fcreativetools\u002Fcommunity\u002Fgenerator\u002F\u003C生成器名称>?local=http:\u002F\u002Flocalhost:5173\u002F DevTool 会把你的本地应用放进与线上一致的运行环境里实时预览，右侧接入助手面板提示 SDK 是否已引入、列出可接入的平台能力，你可在预览里验证导出等能力是否被正确调用。也可以直接在应用详情页的「本地调试」卡片里填入本地地址一键打开。详见 本地调试。 4. 上传产物、提交审核、上架 在应用详情页配置卡片展示资料、上传打包产物并提交审核。通过后自动上架到 ，用户在生成器聚合页即可直接打开使用，无需安装。详见 提交审核与上架。 html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"id":9,"title":10,"titles":522,"content":523,"level":511},[],"无需安装任何命令行工具。本地调试只有两步：引入 SDK，然后用浏览器打开在线 DevTool 加载你的本地服务。",{"id":525,"title":10,"titles":526,"content":523,"level":511},"\u002Fzh\u002Fdocs\u002Fdevtool#本地调试",[],{"id":528,"title":529,"titles":530,"content":531,"level":497},"\u002Fzh\u002Fdocs\u002Fdevtool#_1-引入平台-sdk","1. 引入平台 SDK",[10],"在你的应用页面引入： \u003Cscript src=\"https:\u002F\u002Fstatic-res.atomm.com\u002Fscripts\u002Fjs\u002Fgenerator-sdk\u002Fplatform-sdk.js\">\u003C\u002Fscript> SDK 加载完成后会向平台握手，并在全局注入 atomm 对象（见 atomm 对象）。",{"id":533,"title":534,"titles":535,"content":536,"level":497},"\u002Fzh\u002Fdocs\u002Fdevtool#_2-打开在线-devtool-预览","2. 打开在线 DevTool 预览",[10],"本地启动你的服务后（任意端口），在浏览器打开下面的地址，把本地地址填进 ?local=（仅支持 localhost \u002F 127.0.0.1 等回环地址）： https:\u002F\u002Fwww.atomm.com\u002Fcreativetools\u002Fcommunity\u002Fgenerator\u002F\u003C生成器名称>?local=http:\u002F\u002Flocalhost:5173\u002F 左侧：你的生成器实时预览（本地服务被放进与线上一致的运行环境，能力限制也一致）右侧：接入助手面板：\nSDK 整合提示：未引入 platform-sdk.js 时提示「整合未完成」，给出可复制的引入代码与文档链接；SDK 握手成功后自动消除。平台能力清单：列出平台提供的能力（导出 \u002F 下载、atomm 对象等），每项可「查看文档」或「复制接入 Prompt」交给 AI 接入。 dev 预览模式固定为 dev 环境、不扣费、平台能力默认全开，不依赖任何后台数据。 在开发者后台应用详情页的「本地调试」卡片里填入本地地址，即可直接打开上面的预览。 www.atomm.com 走 https。浏览器对 localhost 的 http 地址有混合内容豁免，所以本地 http 服务能正常加载；非 localhost 的 http 地址会被浏览器拦截，请使用 localhost 或为本地服务启用 https。 html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":13,"title":14,"titles":538,"content":539,"level":511},[],"atomm 是平台 SDK（platform-sdk.js）加载后注入到页面的全局对象，提供平台能力与 UI 工具。在生成器代码中可直接使用。",{"id":541,"title":14,"titles":542,"content":539,"level":511},"\u002Fzh\u002Fdocs\u002Fatomm#atomm-对象",[],{"id":544,"title":545,"titles":546,"content":547,"level":497},"\u002Fzh\u002Fdocs\u002Fatomm#生命周期-lifecycle","生命周期 lifecycle",[14],"通过 lifecycle.on 注册平台生命周期钩子： atomm.lifecycle.on('export', async () => { ... })",{"id":549,"title":550,"titles":551,"content":552,"level":497},"\u002Fzh\u002Fdocs\u002Fatomm#ui-工具-ui","UI 工具 ui",[14],"弹出平台全局提示（toast）。参数为对象： type：可选 success \u002F warning \u002F error \u002F info，默认 successmessage：提示文案duration：可选，展示时长，单位秒，0 表示不自动关闭；不传默认 3 秒 toast() 返回本条提示的 id；用 closeToast(id) 主动关闭。duration: 0 的常驻提示必须这样关，否则会一直挂着。 atomm.ui.toast({ type: 'success', message: '已完成' })\n\n\u002F\u002F 指定展示 5 秒\natomm.ui.toast({ type: 'info', message: '正在处理…', duration: 5 })\n\n\u002F\u002F duration: 0 常驻不自动关闭，任务完成后用 closeToast 关掉\nconst id = await atomm.ui.toast({ type: 'info', message: '导出中…', duration: 0 })\n\u002F\u002F …任务完成…\nawait atomm.ui.closeToast(id) 传字符串（如 toast('已完成')）不会生效——平台只读取对象上的 message 与 type，字符串会被当成空消息。ui 命名空间目前提供 toast（返回提示 id）与 closeToast。",{"id":554,"title":555,"titles":556,"content":557,"level":497},"\u002Fzh\u002Fdocs\u002Fatomm#应用信息-app","应用信息 app",[14],"\u002F\u002F 当前语言短码（zh \u002F en \u002F ja… 共 17 种）\nconst locale = await atomm.app.getLocale()\n\n\u002F\u002F 全部受支持语言（短码 + 展示名），用于做与平台一致的语言选择器\nconst locales = await atomm.app.getSupportedLocales()\n\u002F\u002F → [{ code: 'zh', name: '简体中文' }, { code: 'en', name: 'English' }, …]",{"id":559,"title":560,"titles":561,"content":562,"level":497},"\u002Fzh\u002Fdocs\u002Fatomm#用户-user","用户 user",[14],"\u002F\u002F 当前是否已登录（只回布尔，不含 token 与个人信息）\nconst loggedIn = await atomm.user.isLoggedIn()\n\n\u002F\u002F 未登录时主动拉起登录弹窗，等用户登录完成后继续；返回最终是否已登录\nif (!loggedIn) {\n  const ok = await atomm.user.login()\n  if (!ok) return \u002F\u002F 用户取消或登录失败\n}\n\u002F\u002F 到这里已登录，继续你的逻辑 login() 会弹出登录窗口，请在用户点击等手势的回调里调用，避免被浏览器弹窗拦截。登录是耗时交互，平台已为它放宽超时（约 5 分钟），无需你自己加超时。",{"id":564,"title":565,"titles":566,"content":567,"level":497},"\u002Fzh\u002Fdocs\u002Fatomm#安全调用","安全调用",[14],"不确定是否运行在平台内时，用可选链避免报错： window.atomm?.ui?.toast?.({ type: 'info', message: 'hi' }) html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}",{"id":17,"title":18,"titles":569,"content":570,"level":511},[],"注册 export 生命周期钩子，平台会在用户点击「导出」或「Open in Studio」时调用你的生成器并获取结果文件。返回值统一为 { filename, blob }，支持任意文件格式（图片、SVG、3D 模型、PDF 等）。",{"id":572,"title":18,"titles":573,"content":570,"level":511},"\u002Fzh\u002Fdocs\u002Fexport#导出能力-export",[],{"id":575,"title":576,"titles":577,"content":578,"level":497},"\u002Fzh\u002Fdocs\u002Fexport#放置导出按钮","放置导出按钮",[18],"导出按钮由你在应用内自己放置——在页面任意位置写一个带 data-atomm-export-button 的元素，SDK 会就地把它渲染成平台受控的 Export 下拉（下载 \u002F Open in Studio + 积分提示）。点击只经平台触发： \u003Cdiv data-atomm-export-button>\u003C\u002Fdiv> 位置与外层定位由你控制（如 position: fixed 固定在角落）；一页可放多个，各自独立水合。按钮渲染在 Shadow DOM 里做样式隔离；换肤只用文档化的 --atomm-export-* CSS 变量（在该元素或任意祖先上设置，自动继承进按钮）： [data-atomm-export-button] {\n  --atomm-export-bg: #d32f2f; \u002F* 按钮底色 *\u002F\n  --atomm-export-radius: 0; \u002F* 圆角 *\u002F\n  --atomm-export-width: 200px; \u002F* 宽度：px 或 100% 填满容器 *\u002F\n  --atomm-export-height: 40px; \u002F* 高度 *\u002F\n} 变量默认值控什么--atomm-export-bg \u002F -bg-hover \u002F -bg-active#070b10 \u002F #252c36 \u002F #1c2129按钮三态底色--atomm-export-color#fff按钮文字色--atomm-export-widthauto（贴内容）按钮宽度（px 或 100% 填满容器，下限 24px）--atomm-export-height32px按钮高度（px 或 100%，下限 24px）--atomm-export-radius8px圆角--atomm-export-font \u002F -font-sizeInter, system-ui, sans-serif \u002F 14px字体 \u002F 字号--atomm-export-menu-bg \u002F -menu-color \u002F -menu-hover-bg#fff \u002F #111 \u002F #f4f4f5下拉菜单配色--atomm-export-menu-radius \u002F -menu-shadow8px \u002F 0 4px 16px rgba(16,24,40,.12)菜单圆角 \u002F 阴影--atomm-export-z1000下拉浮层层级 仅上表这些 --atomm-export-* 变量是受支持的定制面；按钮内部 class 随时可能变化，请勿依赖。 导出按钮及其下载 \u002F Open in Studio \u002F 积分提示都由 atomm 平台驱动，只有当生成器运行在 atomm 环境里才生效——线上平台，或开发工具的本地预览（?local=）。若脱离 atomm 单独打开生成器（如直接开本地 HTML），按钮可能照常显示，但点击不会产出文件、也不显示计费状态——这是设计如此，并非 bug。请始终用本地预览或线上平台来验证导出。",{"id":580,"title":581,"titles":582,"content":583,"level":500},"\u002Fzh\u002Fdocs\u002Fexport#按钮上的免费次数-积分提示","按钮上的免费次数 \u002F 积分提示",[18,576],"按钮会自动显示当前计费状态（由平台下发，你无需干预）： 形态显示含义免费时段30s 倒计时一次导出成功后赠送的一小段时间，期内导出不计费免费次数免费 3\u002F3剩余 \u002F 总免费次数消耗积分积分币 + 数字免费用尽后每次导出消耗的积分数 本地调试（?local=），点击导出不会真实扣费，刷新页面即重置。",{"id":585,"title":586,"titles":587,"content":588,"level":497},"\u002Fzh\u002Fdocs\u002Fexport#注册-export-hook","注册 export hook",[18],"atomm.lifecycle.on('export', async () => {\n  \u002F\u002F 触发时不传入任何参数，handler 自行读取当前生成结果并产出一个 Blob\n  const blob = await exportCurrentResultAsBlob()\n  if (!blob) {\n    throw new Error('请先生成作品后再下载')\n  }\n\n  return {\n    filename: 'my-generator.glb', \u002F\u002F 含扩展名，决定下载文件名与 Open in Studio 的资产类型\n    blob, \u002F\u002F 任意格式的 Blob；MIME 取自 blob.type\n  }\n})",{"id":590,"title":591,"titles":592,"content":593,"level":497},"\u002Fzh\u002Fdocs\u002Fexport#返回值字段","返回值字段",[18],"字段类型说明filenamestring下载文件名，必须含扩展名（如 design.glb），且不含路径分隔符 \u002F \\blobBlob任意格式的文件内容，单文件 ≤ 100MB；MIME 取自 blob.type，为空时按文件名扩展名兜底",{"id":595,"title":596,"titles":597,"content":598,"level":497},"\u002Fzh\u002Fdocs\u002Fexport#多文件导出可选","多文件导出（可选）",[18],"handler 也可以返回一个文件数组，平台会把它们打成一个 zip 下载： atomm.lifecycle.on('export', async () => [\n  { filename: 'model.glb', blob: glbBlob },\n  { filename: 'preview.png', blob: pngBlob },\n]) 规则说明zip 文件名取数组中第一个文件的主名（model.glb → model.zip）同名文件自动去重为 name (1).ext大小上限所有文件字节总和 ≤ 100MB，超出整体失败数组长度 1直接下载该文件，不套 zipOpen in Studio支持多文件——返回的文件全部交给 Studio 打开，不限制格式；Studio 不支持的格式由 Studio 端提示。多文件导入需 xTool Studio 1.8+；单文件兼容旧版本 单文件仍用 { filename, blob }；多文件用数组。返回数组中任一项不合规（非 Blob \u002F 文件名无扩展名等）整体判为无效。",{"id":600,"title":601,"titles":602,"content":603,"level":497},"\u002Fzh\u002Fdocs\u002Fexport#怎么得到-blob","怎么得到 Blob",[18],"几乎任何导出源都能一行转成 Blob： 你手里的东西转 BlobCanvas（2D 图）canvas.toBlob(cb, 'image\u002Fpng')SVG 字符串 \u002F 文本 \u002F JSONnew Blob([str], { type: 'image\u002Fsvg+xml' })ArrayBuffer \u002F 3D 网格（glb\u002Fstl…）new Blob([buffer], { type: 'model\u002Fgltf-binary' })已有 data URL \u002F 远程 URLawait (await fetch(x)).blob()\u003Cinput type=file> 的 File直接用（File 本就是 Blob） 导出数据统一用 Blob 承载，支持任意格式——Blob 能原样保存任意文件类型的二进制内容。filename 必须带扩展名且不含路径分隔符；文件超过 100MB 或返回值不是合法 { filename, blob } 时，平台会判为无效、导出失败并提示。 下载支持任意格式落盘。「Open in Studio」会把文件交给 xTool Studio 打开——平台不预判格式，Studio 不支持的格式会由 Studio 端自行提示。 导出按钮对所有生成器开放（在应用里放 data-atomm-export-button 即出现）。用户点击导出时若你未注册 export hook，平台会得到「应用未提供下载方法」——提交审核会因此被驳回。凡是支持导出的生成器都必须注册该 hook，可在本地预览中点「导出」自测是否正常产出文件。 html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}",{"id":21,"title":22,"titles":605,"content":606,"level":511},[],"接入能力并在本地预览验证通过后，即可在开发者后台提交上架。不再需要本地打包工具——用你自己的构建方式产出静态文件即可。",{"id":608,"title":22,"titles":609,"content":606,"level":511},"\u002Fzh\u002Fdocs\u002Fpublish#提交审核与上架",[],{"id":611,"title":612,"titles":613,"content":614,"level":497},"\u002Fzh\u002Fdocs\u002Fpublish#_1-准备产物","1. 准备产物",[22],"用你熟悉的方式构建出可直接部署的静态 Web 文件（页面已引入平台 SDK），打包成一个 .zip（不超过 50 MB）。 线上应用同样靠页面里那行 platform-sdk.js 才能接上平台能力。某些构建配置可能让正式入口页漏掉这行 script，导致「本地预览正常、上架后导出失效」。上传前请确认正式产物的入口页就是你本地验证过、且仍引入了 SDK 的那个页面。",{"id":616,"title":617,"titles":618,"content":619,"level":497},"\u002Fzh\u002Fdocs\u002Fpublish#_2-创建应用","2. 创建应用",[22],"在开发者后台点击「创建应用」，先为你的生成器取一个名称作为运行标识（小写字母开头，仅含小写字母、数字与连字符）。该名称会关联线上运行子域名与访问路径，创建后不可修改，请谨慎选择；展示给用户的卡片标题在下一步单独设置。",{"id":621,"title":622,"titles":623,"content":624,"level":497},"\u002Fzh\u002Fdocs\u002Fpublish#_3-配置展示资料","3. 配置展示资料",[22],"进入应用详情页的「应用列表详情」，填写卡片标题、简要描述与封面图，右侧可实时预览应用卡片效果。这些信息决定用户在 Creative Tools 页面看到的样子，改动同样需要走审核。",{"id":626,"title":627,"titles":628,"content":629,"level":497},"\u002Fzh\u002Fdocs\u002Fpublish#_4-上传代码产物","4. 上传代码产物",[22],"切换到「代码产物」，上传打包好的 .zip（含 index.html 等静态文件）。本地实时调试请在开发阶段通过在线 DevTool 完成，详见 本地调试。",{"id":631,"title":632,"titles":633,"content":634,"level":497},"\u002Fzh\u002Fdocs\u002Fpublish#_5-提交审核","5. 提交审核",[22],"在「提交审核」中，平台会校验展示资料与代码产物是否填写完整；全部就绪后点击「提交审核」，展示资料改动与新产物会汇总为一次「待审核变更」一次性送审。审核结果（通过 \u002F 驳回 + 理由）会通过消息回流到你的后台。 提交后应用进入「审核中」，需等结果返回后才能再次提交新的改动。 通过后应用自动上架，运行地址为 ，用户在生成器聚合页即可直接打开。",{"id":25,"title":26,"titles":636,"content":319,"level":511},[],{"id":638,"title":26,"titles":639,"content":319,"level":511},"\u002Fzh\u002Fdocs\u002Ffaq#常见问题",[],{"id":641,"title":642,"titles":643,"content":644,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#需要安装命令行工具吗","需要安装命令行工具吗？",[26],"不需要。接入只靠在页面里引入一行 platform-sdk.js；调试用浏览器打开在线 DevTool 加载你的本地服务即可。",{"id":646,"title":647,"titles":648,"content":649,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#支持哪些技术栈","支持哪些技术栈？",[26],"任意。纯 HTML、Vite、Vue、React…… 只要最终能产出可部署的静态 Web 文件就行。",{"id":651,"title":652,"titles":653,"content":654,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#本地服务用什么地址为什么我的地址加载不了","本地服务用什么地址？为什么我的地址加载不了？",[26],"预览通过 ?local= 加载你的本地服务（仅支持 localhost \u002F 127.0.0.1 等回环地址）。www.atomm.com 走 https，浏览器只对 localhost 的 http 放行；非 localhost 的 http 地址会被混合内容策略拦截，请使用 localhost 或为本地服务启用 https。",{"id":656,"title":657,"titles":658,"content":659,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#平台能力不可用-面板提示整合未完成怎么办","平台能力不可用 \u002F 面板提示「整合未完成」怎么办？",[26],"说明页面没有成功加载 platform-sdk.js。检查 script 是否正确引入、本地服务是否可访问并重新加载页面。SDK 握手成功后提示会自动消除。",{"id":661,"title":662,"titles":663,"content":664,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#生成器名称运行标识能修改吗","生成器名称（运行标识）能修改吗？",[26],"不能。名称会作为运行子域名与访问路径的一部分，关联线上地址，创建后不可更改，请谨慎选择。",{"id":666,"title":667,"titles":668,"content":669,"level":497},"\u002Fzh\u002Fdocs\u002Ffaq#没接入导出能力会怎样","没接入导出能力会怎样？",[26],"导出按钮对所有生成器开放（在应用里放 data-atomm-export-button 即出现）。用户点击导出时若你未注册 export hook，会得到「应用未提供下载方法」，提交审核会因此被驳回。要支持导出就必须注册 export hook，可在本地预览中点「导出」自测是否正常产出文件。",{"id":29,"title":30,"titles":671,"content":672,"level":511},[],"这套规范有两种形态：下面这些页面给人读，design.md 给编码 agent 读——同一套令牌、组件规格和设计意图，写成标准 DESIGN.md 格式的单个文件，直接交给它就行。",{"id":674,"title":30,"titles":675,"content":676,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Foverview#总览",[],"这套规范有两种形态：下面这些页面给人读，design.md 给编码 agent 读——同一套令牌、组件规格和设计意图，写成标准 DESIGN.md 格式的单个文件，直接交给它就行。 下载 design.md 这些是建议，不是审核门槛。 照着做，你的生成器会像平台原生的一部分，而不是嵌在里面的另一个网站——用户不用重新学一遍控件长什么样、点了会怎样。不照着做也能上架，视觉风格不影响审核结论。 真正强制的只有平台约束那一章：导出必须走平台按钮、生成器只能用平台分配给它的那块区域、导出物用 1:1 实际尺寸。那些不是审美问题，是能不能跑起来、能不能过审的问题——比如没有注册 export 钩子的提交会被自动拒绝。下面其余各章都属于建议。 生成器是一张工作台，不是店面。参照物是专业创作工具的属性面板——外框是单色的、不起眼的，好让正在被制造的东西成为屏幕上唯一有颜色的物体。 使用者正处在工作中途。他会在一个下午里把同一个生成器跑二十遍，每次只调一个值。界面的价值体现在这种重复频率下的可预期：控件永远在同一个位置，数值永远清晰可读，第二十次的动效和第一次一模一样。 调性是安静而通透的。层级靠减重做出来：标签退到细体次要色，只有取值、主按钮和产物本身是深的。一抹红留作储备，标记屏幕上后果最重的那一个操作。 画板14 \u002F 500 · 主文本\n      宽度\n        mm\n      列数\n      随机度\n        %\n      共 30 块，单块 33.33 × 30.00 mm。\n    字段名 14 \u002F 400 \u002F 7.56:1 → 取值 14 \u002F 500 \u002F 17.74:1。两者差的是字重加颜色两档，不是字号。 标签退后一步，取值站出来；同一个 14px 里还能排下分区标题（500 \u002F 主文本）和说明（12px \u002F 三级色）。 层级不清时减轻标签，不是加重标签——面板整体反而更轻。 它不是什么：不是营销页、不是仪表盘、不是消费级应用。没有首屏高光时刻，没有渐变，没有玻璃，没有光晕，没有胶囊按钮，没有替自己道歉的插画空态，页面加载时也没有入场动画。那些属于必须先说服你留下的产品。这一个已经拥有你的注意力了。",{"id":33,"title":34,"titles":678,"content":679,"level":511},[],"两层书写：原色是原始取值，也是唯一出现 hex 的地方；语义令牌引用它们，说明这个颜色用在哪。组件引用语义层，绝不引用原色。",{"id":681,"title":34,"titles":682,"content":679,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#色彩",[],{"id":684,"title":685,"titles":686,"content":687,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#中性色阶","中性色阶",[34],"十三档。点击色卡复制 hex。 neutral-0\n       #ffffff\n     \n   \n     \n     \n       neutral-25\n       #fbfcfd\n     \n   \n     \n     \n       neutral-50\n       #f9fafb\n     \n   \n     \n     \n       neutral-100\n       #f3f4f6\n     \n   \n     \n     \n       neutral-200\n       #e5e7eb\n     \n   \n     \n     \n       neutral-300\n       #d1d5db\n     \n   \n     \n     \n       neutral-400\n       #9ca3af\n     \n   \n     \n     \n       neutral-500\n       #6b7280\n     \n   \n     \n     \n       neutral-600\n       #4b5563\n     \n   \n     \n     \n       neutral-700\n       #374151\n     \n   \n     \n     \n       neutral-800\n       #1f2937\n     \n   \n     \n     \n       neutral-850\n       #18202f\n     \n   \n     \n     \n       neutral-900\n       #111827\n     \n   语义层引用关系：900 → 品牌色 \u002F 取值 · 600 → 字段名 · 500 → 说明 · 400 → 禁用 \u002F 标尺数字 · 300 → 输入描边 \u002F 滑块轨道 · 200 → 浮层描边 · 100 → 分段轨道 · 25 → 画布",{"id":689,"title":690,"titles":691,"content":692,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#一致的冷味读作干净残留的色度读作脏","一致的冷味读作干净，残留的色度读作脏",[34],"这条阶梯每一档都偏冷，RGB 极差在中间调达到 19–26。这是刻意的，不是没调干净。 36101921242422冷味一致而果断：全阶梯色相同向，中间调 RGB 极差 19–26。这是刻意的，不是没调干净。 低色度的灰会落进模棱两可的区间——不够中性到读作灰，又不够冷到读作冷灰。 要么彻底中性，要么果断地冷。唯一采用纯中性灰的是标尺刻度：界面统一冷调、器械刻度中性，两者各自成立。 唯一的例外是标尺刻度，它用纯中性灰。界面统一冷调、器械刻度中性，两者各自成立，互不干扰。",{"id":694,"title":695,"titles":696,"content":697,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#文本四档每档约为上一档的一半","文本四档，每档约为上一档的一半",[34],"text-primary→ neutral-900\n     取值 200 mm · 分区标题 · 正文\n     17.74:1\n   \n     text-secondary→ neutral-600\n     字段名 · 次级按钮 · 图标按钮\n     7.56:1\n   \n     text-tertiary→ neutral-500\n     说明文字 · 单位后缀 · 时间戳\n     4.83:1\n   \n     text-disabled→ neutral-400\n     禁用态 · 标尺数字\n     2.54:1\n   四档的间距要均匀展开，每档约为上一档的一半。眼睛分辨的是比值而不是绝对值：17.7 和 12.4 会被读作同一档，而 4.8 到 2.5 的一跳就足够清晰。四档均匀铺开，\"让标签退后一步\"才有落点可选。",{"id":699,"title":700,"titles":701,"content":702,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#描边三档各有明确分工","描边三档，各有明确分工",[34],"stroke-divider\n        同一表面内部条目之间：分区之间、面板标题栏下方、统计块之间。最弱的一档。\n    \n    \n      \n      stroke-default\n        浮层与卡片的边界：下拉浮层、画布浮层、提示气泡、白纸轮廓。同时有阴影帮它成形。\n    \n    \n      \n      stroke-input\n        输入框、取值胶囊、下拉触发器、次级按钮。可交互控件的边界比装饰性边界重一档。\n    \n  hover 用描边加重，不用填充变浅。surface-subtle 和 background-input 在浅色模式里非常接近，改填充经常等于没变化；把描边从 stroke-input 提到 stroke-strong 则一定看得见。",{"id":704,"title":705,"titles":706,"content":707,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#画布与标尺","画布与标尺",[34],"画布台面 canvas-surface 只比面板的白低一档。画布不该比面板深——深画布会把注意力从产物上拉走。 020406080100120140160180200220020\n    mm\n    \n    \n      \n    \n    产物 19.2:1 · 标尺数字 2.47:1 · 主刻度 1.64:1 · 网格 1.22:1\n  \n  标尺是三层递减的器械 chrome：数字 2.47:1 · 主刻度 1.64:1 · 次刻度与网格 1.22:1。对照产物本身的 19.2:1——这条阶梯的意思是要看时看得见，不看时不碍事。",{"id":709,"title":710,"titles":711,"content":712,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#品牌与强调","品牌与强调",[34],"重新生成\n    对比上一版\n    保存参数\n    导出图纸\n  品牌色比正文文字更深一档——主按钮、滑块已填充段、开关开启态该压得住文字，层级才对。强调红每屏最多出现一次，落在要花钱、消耗积分、或无法撤销的操作上。它的力量完全来自稀缺：一屏里有两个红按钮，等于一个都没有。",{"id":714,"title":715,"titles":716,"content":717,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcolor#语义色成对使用","语义色成对使用",[34,710],"块数较多，预览分阶段计算。导出的图纸不受影响。参数已保存。单块最短边 9.52 mm，小于 12 mm 后不好拿也容易断。减少行列数，或把画板加大。宽度需在 40–900 mm 之间。浅底做填充，实色做图标，消息文字保持 text-primary。带色文字配浅色底是状态提示里最常见的无障碍错误——warning 配 warning-subtle 看着整洁，实际远低于 4.5:1。",{"id":37,"title":38,"titles":719,"content":720,"level":511},[],"全站 Inter，三档字重，行高用偶数像素而不是无单位倍数——垂直节奏必须能在密集的控件行里嵌套存活，而倍数会随字号漂移。",{"id":722,"title":38,"titles":723,"content":720,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ftypography#字体",[],{"id":725,"title":726,"titles":727,"content":728,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ftypography#三个语域不是一条字号阶梯","三个语域，不是一条字号阶梯",[38],"title · 16\u002F600\u002F22\n      Puzzle Cutline\n      仅应用栏\n    field-strong · 14\u002F500\u002F20\n      分区标题 · 取值 200 mm\n      结构与取值\n    field · 14\u002F400\u002F20\n      字段名：榫头大小\n      标签\n    label · 14\u002F600\u002F20\n      按钮文案\n      按钮专用\n    note · 12\u002F400\u002F18\n      \n        只影响图纸线宽，实际割缝由功率和焦距决定。行高 18 是为了让四行也不窒息。\n      成段说明\n    micro · 12\u002F400\u002F16\n      mm · 14:32 · 24px 密集控件\n      单位与时间\n    ruler · 9\u002F400\n      0 20 40 60 80 100\n      仅标尺\n  结构和说明是两个语域，不该一起抬。12px 不是\"小一号的 14\"，它是给成段说明的档位——行高 18 而不是 16，正因为四行 12px 配 16px 行高会窒息。整套字号回落只需改两组变量。",{"id":730,"title":731,"titles":732,"content":733,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ftypography#层级用字重加颜色不用字号","层级用字重加颜色，不用字号",[38],"同一个 14px 里排出三层。字段名和取值之间差的是字重加颜色两档，这比再加一个字号更清楚，也不会让面板变高。 分块14\u002F500 primary\n      列数\n      共 30 块，单块 33.33 × 30.00 mm。\n    分区标题 14\u002F500 主文本 → 字段名 14\u002F400 次要色 → 说明 12\u002F400 三级色。三层，一个字号。",{"id":41,"title":42,"titles":735,"content":736,"level":511},[],"画布优先。画布不是一张卡片，是撑满的底层；两侧栏贴在它旁边，各管一件事。",{"id":738,"title":42,"titles":739,"content":740,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#布局",[],"画布优先。画布不是一张卡片，是撑满的底层；两侧栏贴在它旁边，各管一件事。 前导侧栏管「加入什么」——模板、预设、素材、图层。它回答\"这张画布上要放什么\"， 内容是可选可换的条目，所以用缩略图或列表，选中态明确。 尾侧栏管「调什么参数」——当前对象的属性栈。它回答\"放上去的这个东西长什么样\"， 内容是分区加字段行，导出钉在它的底部，不用滚到底才找得到。 这条分工决定了两栏不可互换：加入是离散选择，调参是连续调节。 把它们混在一栏里，用户每改一个数值都要重新在缩略图和滑块之间找位置。 派生结果（用量、时长、块数）不单独占一栏——它跟着导出放在尾侧栏底部， 或者作为尺寸标注直接画在画布上。 模板 \n        \n          经典拼图\n          六边形\n          波浪切割\n        \n      \n      \n        重新生成\n        预览 \u002F 线稿\n        100%\n        \n          \n            \n          \n        \n        200 mm\n        画布 · 吃掉剩下全部\n      \n      \n        参数 \n        \n          画板 \n          宽度200\n          高度150\n          分块 \n          列数6\n          行数5\n        \n        \n          切割线总长3.75 m\n          导出免费\n        \n      \n    三栏零间隙、零圆角。侧栏宽度固定（前导 320 · 尾侧 272），画布随窗口伸缩—— 参数栏不该因为窗口变宽而变宽。两栏都可折叠成 40px 细导轨；折叠尾侧栏时画布长出来， 折叠前导侧栏适合已经选定模板、进入纯调参阶段的时候。 没有内容库的生成器（只有参数、没有模板可选）直接去掉前导侧栏，两栏就够—— 多一栏空面板比少一栏更糟。",{"id":742,"title":743,"titles":744,"content":745,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#主流程必须一目了然","主流程必须一目了然",[42],"输入 → 配置 → 生成 → 查看 → 调整 → 导出。不是每个生成器都有每一步：实时预览类根本没有\"生成\"这一步，给它加一个生成按钮是缺陷，不是体贴。",{"id":747,"title":748,"titles":749,"content":750,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#垂直节奏只有一条阶梯","垂直节奏只有一条阶梯",[42],"分隔线\n    分块↑ 24\n    ↑ 12\n    列数\n      \n    \n    \n    ↑ 16\n    行数\n      \n    ↑ 4\n    \n    \n    \n  4 和 16 的对比让说明明确归属上面那个控件；12 \u003C 16 让标题明确归属下面那一组。面板横向水槽统一 16px。如果某个布局只有在 14px 时才顺眼，问题出在对齐，不在量表。",{"id":752,"title":753,"titles":754,"content":755,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#分组用线不用框","分组用线，不用框",[42],"画板\n        \n      \n        分块\n        \n      \n        榫卯\n        \n    \n  面板内部用分隔线分组。面板本身已经是一块封闭区域，划界一次就够； 而卡片的圆角会跟输入框的圆角互相抢注意力。卡片留给真正离开平面的东西——浮层、下拉浮层、弹窗， 它们需要一道 stroke-default 加接触阴影来交代自己浮在哪。",{"id":757,"title":758,"titles":759,"content":760,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#预览三个状态三个都要设计","预览三个状态，三个都要设计",[42],"状态必须有什么理由\n    \n      初始示例结果或最近记录一个空白矩形会被读成\"坏了\"\n      计算中阶段名 + 数字 + 取消入口绝不是无限转圈。有个性的转圈是你不知道进度时才做的东西，而这里你知道\n      完成放大、平移、对比、重新生成调参是循环，不是单程 错误属于出错的那个控件旁边，说清原因并给出下一步。屏幕顶部的 toast 是错误信息被忽略的地方。",{"id":762,"title":763,"titles":764,"content":765,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Flayout#尺寸与滚动","尺寸与滚动",[42],"决定你尺寸的是平台分配给你的区域，不是视口。面板自适应用容器查询，不用媒体查询。窄于 960px 改为分步流程（底部切换），并把生成操作固定在底部；此时竖向分割线要清掉。 工程细节三条：① 面板必须 flex:1，只写 min-height:0 的容器只有内容高，会让预览栏撑不满、配置栏溢出而不内部滚动。② 用细滚动条（8px 自绘），经典滚动条会从内边距吃走 15px，让面板右侧看起来比左侧宽一倍。③ 绝不横向滚动，绝不在滚动容器里再套滚动容器。",{"id":45,"title":46,"titles":767,"content":768,"level":511},[],"深度先靠表面色阶与描边，再靠阴影。三枚阴影，加第四枚就是设计系统开始漏水的时刻。",{"id":770,"title":46,"titles":771,"content":772,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Felevation#高度与深度",[],"深度先靠表面色阶与描边，再靠阴影。三枚阴影，加第四枚就是设计系统开始漏水的时刻。 subtle\n      0 8px 28px \u002F 10%弹窗、下拉浮层\n    micro\n      0 1px 3px \u002F 8%画布浮层、白纸、分段活动段\n    \n        \n      \n      0 1px 2px \u002F 20%滑块手柄、开关滑块\n  knob 存在的理由很具体：白色圆形落在浅色轨道上，光靠 micro 会化开。手柄是靠形状承载数值位置的东西，它化开等于读不出值。别拿 micro 顶替，也别为了救手柄而把 micro 整体调重——那会让所有浮层变脏。阴影都绝不在 hover 时做动画。",{"id":774,"title":775,"titles":776,"content":777,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Felevation#焦点自成一层不参与高度体系","焦点自成一层，不参与高度体系",[46],"主按钮\n    次级\n    \n  焦点环 2px 宽 + 2px offset。offset 是承重的，不是装饰：它把环与控件自身的填充分开。 算给你看——环带 offset 时相邻色是面板白底，6.08:1；直接贴在近黑填充上只有 2.92:1，达不到 3:1。 输入框族是焦点环的唯一例外：输入框、取值胶囊、下拉触发器用描边从 stroke-input 切到 brand-default 表示聚焦。它们本来就有描边，加环等于两层边界。 输入框族是焦点环的例外——输入框、取值胶囊、下拉触发器用描边从 stroke-input 切到 brand-default 表示聚焦。因为它们本来就有描边，加环等于两层边界。",{"id":49,"title":50,"titles":779,"content":780,"level":511},[],"四档圆角矩形，且圆角随高度。这个对应关系比单个数值更重要。",{"id":782,"title":50,"titles":783,"content":784,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fshapes#形状",[],"四档圆角矩形，且圆角随高度。这个对应关系比单个数值更重要。 6\n      24px 控件\n    8\n      28 \u002F 32px\n    10\n      40px\n    12\n      卡片 \u002F 弹窗 \u002F 浮层\n    \n      \n      唯一胶囊例外\n  40px 的控件配 6px 圆角显得没做完，同一个控件配 20px 圆角则像是另一个产品。主控件绝不做胶囊形，即使最大的按钮也封顶在 10px。full 只留给真正的圆和圆盘：状态点、滑块手柄、开关滑块。开关轨道是唯一的胶囊例外——它配得上这个例外，因为圆角矩形的开关会被读成复选框。 圆角是唯一的形状手段。没有斜切，没有缺口，没有装饰性边框，没有渐变描边。",{"id":53,"title":54,"titles":786,"content":787,"level":511},[],"控件建立在四档高度上——24、28、32、40。32 是按钮的默认档，40 是输入框族的默认档。",{"id":789,"title":54,"titles":790,"content":791,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#组件",[],"控件建立在四档高度上——24、28、32、40。32 是按钮的默认档，40 是输入框族的默认档。 每个可交互元素支持同一套状态，且这套是封闭的：default、hover、active、focus-visible、disabled、loading、selected、error。没有别的状态。一个需要新状态的控件，是一个需要重新想清楚的控件。",{"id":793,"title":794,"titles":795,"content":796,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#按钮","按钮",[54],"主按钮\n    次级\n    幽灵\n    禁用\n    清空记录\n    导出图纸\n  破坏性操作用次级外壳配 error 文字，并加二次确认——绝不用红色实底。一个大红「删除」恰恰招来它本要防止的误点。按钮文案是动词：生成、导出、重新生成，不是「确定」不是「提交」。loading 保留宽度和文案，只把前置图标换成 spinner 并设 aria-busy。",{"id":798,"title":799,"titles":800,"content":801,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#输入框族白底-描边","输入框族：白底 + 描边",[54],"宽度需在 40–900 mm 之间。\n    \n  输入框族一律白底 + 1px stroke-input 描边。白底加描边把\"可以往里写字\"说得最清楚；灰底 background-input 因此空出来，专门留给取值胶囊和分段轨道。状态全靠描边表达：hover 提到 stroke-strong，focus 提到 brand-default，error 取 error。错误信息放在字段旁边。",{"id":803,"title":804,"titles":805,"content":806,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#取值胶囊一种外形四种宽度","取值胶囊：一种外形，四种宽度",[54],"列数\n      随机度\n        %\n      外框圆角\n        mm\n      种子\n    统一落在外形上，宽度随内容走。四个胶囊的填充、描边、圆角、高度、对齐、字重完全一致； 宽度按内容分档。视觉锚点是右边缘，而它由布局对齐着——所以左边缘参差不齐不影响读取， 而一位数躺在三位数的框里会很显眼。每档余量控制在 13px 以内。 档值构成用于\n    \n      chip-w-sm48px10 + 两位数 17 + 10纯整数，无单位\n      chip-w64px10 + 17 + 单位 26–34两位数 + % 或 mm\n      chip-w-lg80px10 + 三位数 25 + 共用格 32带拖拽手柄\n      自定88px+按位数算六位以上（如种子）\n    \n  统一的是外形，不是宽度。外形——白底、stroke-input 描边、8px 圆角、32 高、右对齐、500 字重、tabular-nums——必须完全一致；宽度按内容分档，每档余量控制在 13px 以内。",{"id":808,"title":809,"titles":810,"content":811,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#数值字段的横向拖拽","数值字段的横向拖拽",[54],"原生上下箭头一律不用：命中区小，和工具面板的语域不符。改成右端一个 24×24 的横向拖拽手柄。把光标移到下面的胶囊上试试——单位淡出、手柄淡入。 宽度\n      mm\n      \n        \n    种子\n      \n      \n        \n  单位后缀和拖拽手柄占同一格。各留一格会在每个胶囊右侧多出 24px 常年空白（手柄不 hover 时看不见）。你正要拖的时候不需要看单位。 其余规则：位移 \u003C 3px 判定为点击 → 聚焦并全选 · Shift 十倍步进 · setPointerCapture 拖出面板不丢 · RTL 下向左拖是增大 · 拿掉原生 spinner 就丢了键盘粗调，必须补 Shift + ↑\u002F↓ = 十步 · 手柄 aria-hidden 且不进 Tab 序列 · 触摸设备手柄常驻 · 同一行已有滑块时不加手柄。",{"id":813,"title":814,"titles":815,"content":816,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#下拉自造-listbox","下拉：自造 listbox",[54],"经典榫卯\n        \n      \n      \n        经典榫卯\n          \n        宽榫头\n          \n        波浪\n          \n      \n    \n  原生 \u003Cselect> 的弹出层无法换肤，在工具面板里会突然掉出一块系统 UI。所以自造，代价是把整份键盘与屏幕阅读器契约还回来，这不是可选项。选中态是 background-active 加一个对勾——光靠底色区分选中，在只有四项的列表里太弱，而且颜色不能单独承载含义。 契约项要求\n    \n      角色role=\"combobox\" \u002F listbox \u002F option，配 aria-expanded、aria-selected、aria-activedescendant\n      焦点模型ARIA 1.2 select-only combobox：焦点始终留在触发器上，不做焦点搬运（搬焦点更容易在关闭时把焦点丢在 body 上）\n      关闭态键位↑↓ \u002F Enter \u002F Space \u002F Home \u002F End \u002F 任意字符 → 展开\n      展开态键位↑↓ 移动 · Home\u002FEnd 到头尾 · Enter\u002FSpace 选中并关闭 · Escape 关闭且不改值 · Tab 关闭 · 点击外部关闭 · 首字母跳转\n      焦点归还关闭后把焦点还给触发器\n      浮层挂载挂到 body 用 position:fixed——留在原地会被滚动容器和 overflow:hidden 裁掉。空间不够向上翻，夹在视口内。RTL 下与触发器右边缘对齐\n      无脚本回退HTML 里保留原生 \u003Cselect>，样式与触发器一致\n      移动端代价丢掉系统选择器，32px 选项在触屏偏小。手机场景多的话，窄断点下退回原生",{"id":818,"title":819,"titles":820,"content":821,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#滑块三个数字是承重的","滑块：三个数字是承重的",[54],"三个数字是承重的：轨道 6px、未填充段用 track-off（neutral-300）、 手柄 18px 配 1px stroke-strong 描边和 knob 阴影。 未填充段的 1.47:1 靠面积成立——同样的比值画成发丝线就看不见了，画成 6px 带子就看得见； 已填充与未填充之间是 12:1，位置一眼读出。手柄的描边同理：白圆落在浅轨道上，光靠阴影会化开， 而手柄是靠形状承载数值位置的东西。 滑块是参数驱动型生成器的主力，而且从不单独使用。当前值永远以数字形式显示在行尾——手柄位置不是一个数值。当精度要紧时（步数、种子、尺寸）给它配数字输入框，因为滑块没法打字。步长和范围来自模型的真实约束，而不是来自\"手感顺滑\"；被静默截断的值是用户看不见的 bug。禁用态要看得出\"在这儿但不能动\"，而不是整条消失。",{"id":823,"title":824,"titles":825,"content":826,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#开关","开关",[54],"外框托盘\n    已开启\n  结构是一个真实的 \u003Cinput type=\"checkbox\">，轨道和滑块只是画在它之上的装饰。 每一层装饰都必须 pointer-events: none，点击要落到底下那个真实 input 上； 并把整个东西包进它的 \u003Clabel>，让命中区覆盖文字。轨道高 24px 刚好等于最小命中区。",{"id":828,"title":829,"titles":830,"content":831,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#分段控件-与-分区标题","分段控件 与 分区标题",[54],"预览\n      线稿\n    \n    \n      \n        榫卯\n        \n          \n      \n      \n    \n  分段控件：灰轨道 + 3px 内边距 + 10px 圆角，活动段白色 + micro。它不是 Tab，不承载页面切换。 分区标题：整行是一个 \u003Cbutton aria-expanded>，标题文字在左、箭头在行尾——这样标题文字和字段名对齐成一条线，箭头和取值胶囊对齐成另一条线。箭头用上\u002F下而不是左\u002F右，因为上下不参与 RTL 镜像，省掉一条特例规则。只动 hidden 和一个 transform，没有高度动画。",{"id":833,"title":834,"titles":835,"content":836,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fcomponents#说明文字要吝啬","说明文字要吝啬",[54],"榫头大小\n        %\n      随机度\n        %\n      线宽\n      实际割缝由功率和焦距决定。\n    说明文字要吝啬。能写进单位后缀的就不要写成一句话——20 % 好过\"占单块边长的百分比\"； 能从结果栏读到的就不要在配置栏重复。三级文本色适合一行提示，不适合成段。 理想状态是整个配置面板只剩两三条真正带约束的说明，比如上面这条——它给的是生产事实，不是把标签再说一遍。",{"id":57,"title":58,"titles":838,"content":839,"level":511},[],"动效确认「变化发生了」。它从不单独承载含义，也从不让用户等待。",{"id":841,"title":58,"titles":842,"content":843,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fmotion#动效",[],"动效确认「变化发生了」。它从不单独承载含义，也从不让用户等待。 fast · 150ms\n        hover、按下、切换、聚焦、描边变色\n      base · 200ms\n        面板展开、弹窗进出、抽屉\n      cubic-bezier(.2,0,.38,1)\n        全站唯一一条曲线\n    只动 opacity 和 transform——在 GPU 本就繁忙的预览密集界面里，动 height 或 width 必然掉帧。不超过 200ms，不弹跳，不过冲，不逗留。生成进度不是动画，它是一个数字和一个阶段名。加载时不做入场动画：你的应用是在一个已经可见的容器里打开的，淡入只会被读成慢。prefers-reduced-motion 把所有时长压到零，不会损失任何东西，因为从来没有任何状态是单靠动效表达的。",{"id":61,"title":62,"titles":845,"content":846,"level":511},[],"图标内联成描边 SVG，不用图标字体。",{"id":848,"title":62,"titles":849,"content":850,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ficon#图标",[],"图标内联成描边 SVG，不用图标字体。 图标内联成描边 SVG。规格：fill:none · stroke:currentColor · stroke-width:1.5 · linecap\u002Flinejoin:round，颜色永远从父级的语义文本令牌继承——自带硬编码颜色的图标， 是一个在下一个状态里就会出错的图标。 不用图标字体：它是外部依赖，取不到时纯图标按钮会变成空白方框。图标出现的频率决定了不该赌一个外部依赖。",{"id":852,"title":853,"titles":854,"content":855,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ficon#命中区四档字形跟着走","命中区四档，字形跟着走",[62],"20 \u002F 16\n    \n      24 \u002F 18\n    \n      32 \u002F 20 · 默认\n    \n      40 \u002F 24\n  20px 那一档低于无障碍最小尺寸，只有当同一操作还能通过一个达到 24px 的目标触达时才允许使用。注意档位名与控件高度重名但数值不同：mini 控件是 24px 高，mini 图标按钮是 20px 见方。",{"id":857,"title":858,"titles":859,"content":860,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Ficon#三类图标三种义务","三类图标，三种义务",[62],"类型义务为什么\n    \n      装饰性aria-hidden=\"true\"它与自己的文字标签并列，否则被播报两次\n      可交互aria-label描述动作而不是描述图案：「换一个种子」不是「骰子」\n      指示性屏幕阅读器文本状态点这类图标，颜色和形状本身不传达含义 方向性图标——箭头、chevron、返回与前进、缩进、撤销——需要一个能让 RTL 翻转的 class。时钟、对勾、播放按钮、Logo、带时间轴的图表，永远不要翻转。上\u002F下箭头不需要翻转，所以在能选的时候优先用上下。",{"id":65,"title":66,"titles":862,"content":501,"level":511},[],{"id":864,"title":66,"titles":865,"content":866,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fdirection#方向rtl",[],"平台会把你的生成器渲染在一个 dir 跟随用户语言的文档里。镜像不是可选项，也没有第二份样式表——布局必须自己翻。 用下面示例上方的 LTR \u002F RTL 开关就地对照。按现代写法写，这几乎是免费的：每一个单侧取值都用逻辑属性——margin-inline-start、padding-inline-end、inset-inline-start、text-align: start。左右对称的简写完全不用管，flex 和 grid 会自己镜像；为 RTL 加 flex-row-reverse 是把一个已经翻好的布局再翻一次。 画板\n        عرض اللوح\n          mm\n        画板高度\n          mm\n          \n            \n        \n        外框托盘\n      \n      \n        重新生成\n        \n          050100150200250300350400450500550600650700750\n          \n            \n          200 mm\n        \n      \n    点开关，注意哪些翻了、哪些没翻。翻的：轨换边、标签与数值互换、滑块从另一端填充、开关拇指移到另一侧——全部由逻辑属性和 flex 自己完成，没有一处 flex-row-reverse。没翻的：标尺零点、刻度方向、画板位置。第一行的阿拉伯语标签（عرض اللوح，画板宽度）是文字自己从右往左：LTR 下 عرض 在左、اللوح 在右，RTL 下两个词调个头。下面那行中文只是整块靠右，字仍然从左往右——200 永远是 200 不会变成 002。方向属性改的是排列，不是文字内部的书写方向。画板、标尺和产物永不镜像——把画板那一层锁 direction: ltr，它内部的逻辑属性就永远解析成左，产物朝向与围绕它的界面无关。但画布上的浮层是界面、不是产物，它们跟着翻：RTL 下「重新生成」落在镜像后的那一侧。",{"id":868,"title":367,"titles":869,"content":870,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fdirection#这套系统实测踩过的坑",[66],"现象原因与修法\n    \n      滑块手柄往反方向走webkit 填充用 linear-gradient(to right …)，RTL 下要换成 to left\n      拖拽改值方向相反取 direction 后把 delta 符号取反\n      下拉浮层错位JS 定位时 RTL 下要和触发器右边缘对齐，不能照搬 left\n      居中的浮起提示偏一半别用 inset-inline-start:50% + translateX(-50%)，用 inset-inline:0; margin-inline:auto\n      进度条从错误的一端长出transform-origin 要跟着换边\n      开关拇指滑出轨道外拇指起点用 inset-inline-start 却用 translateX(16px) 走位移——transform 是物理方向，RTL 下要 -16px。任何用 transform 表达「往前走」的位移都要自己判一次方向\n      标签与输入框相撞单侧内边距没翻。全用逻辑属性",{"id":69,"title":70,"titles":872,"content":873,"level":511},[],"这是地板，不是天花板。",{"id":875,"title":70,"titles":876,"content":877,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Faccessibility#无障碍",[],"这是地板，不是天花板。 要求细节\n    \n      目标 ≥ 24×24pxWCAG 2.2 SC 2.5.8。宽度也要查，因为纯图标按钮是正方形。视觉上刻意更矮时（滑块导轨、复选框字形）撑开命中区，而不是缩小目标\n      对比度逐对验证不靠假设。每次改色阶都把关键配对重算一遍，包括小字号落在浅底上的最差组合\n      键盘全覆盖能到达鼠标能到达的一切，顺序可见。弹窗打开期间收束焦点，关闭时把焦点还给触发器\n      [hidden] 需要恢复任何设了 display:flex 或 grid 的组件都会盖掉浏览器默认的 [hidden]{display:none}。在基础样式表里落地 [hidden]{display:none !important}——离屏面板泄漏到视野里就是这么发生的\n      含义不单独依赖颜色红色描边需要配一条消息；转圈需要配文字；选中态需要配对勾",{"id":879,"title":880,"titles":881,"content":882,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Faccessibility#关键配对实测","关键配对实测",[70],"配对实测门槛结果\n    取值 \u002F 正文 900 在白底\n          17.74:14.5\n          通过字段名 600 在白底\n          7.56:14.5\n          通过字段名 600 在胶囊底\n          6.87:14.5\n          通过说明 500 在白底\n          4.83:14.5\n          通过说明 500 在画布\n          4.71:14.5\n          通过白字在主按钮\n          17.74:14.5\n          通过白字在强调红\n          5.27:14.5\n          通过已填充 vs 未填充轨道\n          12.04:13\n          通过焦点环在白底（2px offset 后的相邻色）这就是 offset 承重的地方：有偏移时环的相邻色是面板白底；没有偏移时它贴着近黑填充，只剩 2.92:1。\n          6.08:13\n          通过",{"id":884,"title":885,"titles":886,"content":887,"level":497},"\u002Fzh\u002Fdocs\u002Fdesign\u002Faccessibility#已知的刻意接受的偏离","已知的、刻意接受的偏离",[70],"规范应该记录自己的债务，而不是假装没有。 项实测门槛理由\n    \n      stroke-default 作浮层唯一边界1.24:13:1浮层同时有阴影，边界不只靠描边\n      stroke-input 作输入框唯一边界1.47:13:1整体观感的主要来源。要合规需压到 #949ba5 左右，边会明显变重——提供一个覆盖档即可，改一个令牌\n      标尺数字2.47:14.5:1器械刻度不是内容；画板尺寸在结果栏有明确数值",{"id":73,"title":74,"titles":889,"content":890,"level":511},[],"这些不是风格选择——是在 atomm 里运行的前提条件。",{"id":892,"title":74,"titles":893,"content":894,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Fplatform#平台约束",[],"这些不是风格选择——是在 atomm 里运行的前提条件。 约束要求\n    \n      导出走平台按钮在你想要的位置放 \u003Cdiv data-atomm-export-button>\u003C\u002Fdiv>，并注册 atomm.lifecycle.on('export', …)。按钮由 SDK 渲染，只有它的 --atomm-export-* 变量可换肤。没有注册 export 钩子的提交会在审核时被自动拒绝。开发期可以在同一插槽里渲染回退按钮，但必须以 SDK 存在为优先\n      导出物按机器面对待1:1 实际尺寸、mm 单位、width=\"200mm\" 加 mm 坐标系的 viewBox。切割线颜色可能被设备映射到工序，改它需要单独确认，不跟界面色阶一起走。预览用的参考图不进图纸\n      顶栏属于平台品牌、账号、积分。不要重建，也不要模仿。生成器自己的控件（项目、保存、历史）放在你自己内容区上方的轻量栏里\n      你在别人的容器里你盖不住平台外框，你不知道视口尺寸，你的层叠上下文完全是你自己的——一层浮层加一层 toast 就够了，z-index 封顶在 3",{"id":77,"title":78,"titles":896,"content":897,"level":511},[],"渐变、玻璃、胶囊、首屏高光，总览里的参照物已经把它们排除掉了。下面这 26 条是参照物承担不了的部分——每一条都来自这套系统的实测。",{"id":899,"title":78,"titles":900,"content":897,"level":511},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#规则清单",[],{"id":902,"title":34,"titles":903,"content":904,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#色彩",[78],"01让中性色阶的冷味一致而果断。低色度的灰会落进模棱两可的区间，读作脏。02让文本四档每档约为上一档的一半。四档挤在同一端等于只有两档。03每次改色阶就把关键配对重算一遍，包括小字号落在浅底上的最差组合。04画布保持比面板浅。产物是屏幕上唯一该响的东西。05用实测对比度做判断。靠面积成立的元素（轨道、色带）和靠线条成立的元素（描边、刻度），同一个比值的可见性完全不同。",{"id":906,"title":907,"titles":908,"content":909,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#层级","层级",[78],"06靠减重建立层级：标签退到细体次要色，取值站出来。07用字重加颜色区分同一字号里的三层，而不是再加一个字号。08结构标签和说明文字各用自己的语域：一个是骨架，一个是脚注。09层级不清时先减轻标签，面板整体会更轻而层级更清。",{"id":911,"title":912,"titles":913,"content":914,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#形状与空间","形状与空间",[78],"10让统一落在外形上——填充、描边、圆角、高度完全一致。11让宽度随内容走，右边缘交给布局对齐。12在已封闭的面板里用分隔线分组；卡片留给真正离开平面的东西。13让从不同时出现的元素共用同一格（单位后缀与拖拽手柄）。14所有取值都从 8px 量表里取。只在 14px 时才顺眼的布局，问题出在对齐。",{"id":916,"title":917,"titles":918,"content":919,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#控件","控件",[78],"15把红色强调档花在每屏恰好一个操作上，或者一个都不花。16把状态集当作封闭的。一个看起来需要第九种状态的控件，需要的其实是重新想清楚。17自造原生控件的替代品之前，先把它欠的键盘与屏幕阅读器契约写成清单，然后逐条还。18给装饰层加 pointer-events: none，把点击留给它下面的真实控件。19破坏性操作用次级外壳配 error 文字加二次确认。20同一行只放一个拖拽入口。21按钮文案用动词：生成、导出、重新生成。",{"id":921,"title":922,"titles":923,"content":924,"level":500},"\u002Fzh\u002Fdocs\u002Fdesign\u002Frules#工程","工程",[78],"22给需要撑满的面板写 flex: 1，不是只写 min-height: 0。23把图标内联成描边 SVG，不依赖图标字体。24每次改完令牌跑一遍悬空变量检查：删掉一档中性色而忘了改引用它的语义令牌，会让某个状态静默失效。25用细滚动条，让面板左右内边距保持对称。26把浮层挂到 body 并用 position: fixed，避免被滚动容器裁掉。",[926,928],{"title":62,"path":61,"stem":927,"children":-1},"zh\u002Fdocs\u002Fdesign\u002F08.icon",{"title":70,"path":69,"stem":929,"children":-1},"zh\u002Fdocs\u002Fdesign\u002F10.accessibility",1785489601650]