printbench 0.3.5 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -84,6 +84,7 @@ function onExported(payload: PrintBenchExportedPayload) {
84
84
  | `mode` | `'edit' | 'preview'` | `'edit'` | `preview` 为嵌入几何只读:隐藏工作台壳,画布可旋转与点选零件,不能改网格 |
85
85
  | `selectedPartIds` | `string[]` | — | 受控选中。传入后画布点击只触发 `select-part`,由宿主回写 |
86
86
  | `partColors` | `Record<string, string>` | — | 受控零件色,`#RRGGBB`,key 为零件 `id` |
87
+ | `diagnosisZIndex` | `number` | `100` | 诊断浮层 `z-index`。也可在外层设 CSS 变量 `--printbench-diagnosis-z` |
87
88
  | `features` | `{ numeric?, primitives?, split?, drafts?, extras?, importUnit? }` | 全 `false` | 进阶能力。缺省精简:左栏仅导入 / 零件 / 导出 / 快照。未开 `drafts` 时不读不写自动草稿。未开 `importUnit` 时导入不弹单位确认,直接用文件声明单位或设置里的默认单位。 |
88
89
 
89
90
 
@@ -133,7 +134,7 @@ async function upload() {
133
134
 
134
135
  `mode="preview"` 时插件不显示导出 / 快照按钮。宿主用 `ref.exportFile()` / `ref.exportSnapshot()` 只要文件:`customExport` 为 true 时不本地下载、不 POST,返回 `blob` 后由宿主保存或上传。工作台左栏导出与快照仍可用 `uploadUrl` 走插件上传。
135
136
 
136
- `@parts` 在导入/求值后给出 `{ id, index, name }[]`。`id` 为 meshId 或基本体/布尔节点 id,不要用下标当主键。
137
+ `@parts` 在导入/求值/变换后给出零件列表。`id` 为 meshId 或基本体/布尔节点 id,不要用下标当主键。每项含 `size`(当前 AABB 边长 mm)与 `initialSize`(导入时该 id 的边长;导入后新建的零件为 `null`)。
137
138
 
138
139
  **填色优先级**:有 `partColors` / 打印色时用纯色(盖过导入贴图);否则用导入外观;再否则默认蓝。
139
140
 
@@ -144,10 +145,11 @@ async function upload() {
144
145
  | -------------------- | ------------------------------------------------- | -------------------------------------------------- |
145
146
  | `ready` | — | 几何内核就绪 |
146
147
  | `error` | `string` | 可展示错误 |
147
- | `exported` | `{ action, format, fileName, blob, unit, axis? }` | 网格导出完成。`action` 为 `'download'`(下载)或 `'upload'`(一键上传) |
148
+ | `exported` | `{ action, format, fileName, blob, unit, size, axis? }` | 网格导出完成。`action` 为 `'download'`(下载)或 `'upload'`(一键上传);`size` 为导出单位下的包围盒 `[x,y,z]` |
148
149
  | `snapshot` | `{ action, format, fileName, blob, mime, width, height }` | 模型快照完成。`format` 为 `'png'` \| `'jpeg'` |
149
150
  | `report` | 审核报告对象 | 下载 JSON / HTML 审核报告时触发 |
150
- | `parts` | `{ id, index, name }[]` | 当前零件列表 |
151
+ | `parts` | `{ id, index, name, initialSize, size, unit }[]` | 零件列表;`size` 为当前尺寸,`initialSize` 为导入时尺寸(无则为 `null`) |
152
+ | `bbox` | `{ min, max, size, initialSize, unit, parts }` | 整模包围盒(含 `initialSize`)并附带同上的 `parts` |
151
153
  | `select-part` | `{ id, index, additive }` | 画布或零件树点选 |
152
154
  | `part-colors-change` | `Record<string, string>` | 工作台内改色时抛出(嵌入预览以 `partColors` 为准) |
153
155
 
@@ -163,13 +165,15 @@ async function upload() {
163
165
  | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
166
  | `exportFile(options?)` | 不打开插件对话框。`action`: `'download'` \| `'upload'`;`format`: `'stl'` \| `'3mf'` \| `'glb'`;`unit` 默认 mm;`silent: true` 跳过黄级确认。红级阻断返回 `null`。成功返回与 `exported` 相同的 payload。 |
165
167
  | `exportSnapshot(options?)` | 按当前视角截取模型图(不含网格、手柄、切面)。`action`: `'download'` \| `'upload'`;`format`: `'png'`(默认)\| `'jpeg'`;`quality` 仅 JPEG。成功返回与 `snapshot` 相同的 payload。`customExport` 时不本地下载、不 POST。 |
168
+ | `getPartBounds()` | 同步返回与 `@parts` 相同结构的零件列表(含 `initialSize` / `size`)。无模型时为 `[]`。 |
169
+ | `getBBox()` | 同步返回与 `@bbox` 相同结构的整模载荷(含 `parts`)。尚无诊断包围盒时为 `null`。 |
166
170
 
167
171
 
168
172
 
169
173
 
170
174
  ## 工作台能力
171
175
 
172
- 推荐流程:导入模型并确认单位 → 需要时展开右侧诊断并一键修复 → 导出 STL / 3MF 给切片软件(坐标按毫米或导出时所选单位解释)。
176
+ 推荐流程:导入模型并确认单位 → 需要时展开右侧诊断并修复 → 导出 STL / 3MF 给切片软件(坐标按毫米或导出时所选单位解释)。
173
177
 
174
178
  有红色阻断项时无法导出。黄色警告可继续,但可能影响打印质量。
175
179
 
@@ -186,7 +190,7 @@ async function upload() {
186
190
  | --- | ------------------------------------------------------ |
187
191
  | 左栏 | 导入、导出、快照、零件树、上色、移动/旋转/缩放;`features` 打开后才有数值变换、基本体、拆件、草稿与观察工具 |
188
192
  | 画布 | 轨道旋转缩放;双击或 **F** 自适应;**复位视角** 回默认相机 |
189
- | 右栏 | 诊断与测量,默认收起 |
193
+ | 右栏 | 诊断与测量浮层(右上,默认 `z-index: 100`),默认收起 |
190
194
  | 底栏 | 包围盒、内部单位 mm、体积、文件名 |
191
195
 
192
196
 
@@ -1 +1 @@
1
- :root{--bg: #0e1116;--panel: #171b22;--panel-2: #1e242e;--border: #2c3440;--text: #e8edf4;--muted: #8b95a5;--accent: #5b8def;--danger: #ff5c5c;--warn: #f0b429;--ok: #3dcc7a;--shadow: 0 8px 32px rgba(0, 0, 0, .35);font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root,.printbench-root *{box-sizing:border-box}.printbench-root{height:100%;min-height:0;background:var(--bg);color:var(--text);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root button,.printbench-root input,.printbench-root select,.printbench-root textarea{font:inherit;color:inherit;color-scheme:dark}.printbench-root select option{background:var(--panel-2);color:var(--text)}.workbench{position:relative;display:grid;grid-template-rows:1fr 28px;grid-template-columns:292px 1fr 300px;height:100%}.workbench.no-left{grid-template-columns:36px 1fr 300px}.workbench.no-right{grid-template-columns:292px 1fr 36px}.workbench.no-left.no-right{grid-template-columns:36px 1fr 36px}.workbench.left-float{grid-template-columns:1fr 300px}.workbench.left-float.no-right{grid-template-columns:1fr 36px}.workbench.left-float>.panel.parts{position:absolute;left:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:12;grid-column:1;grid-row:1;border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.workbench.left-float>.panel.parts.collapsed{width:36px;max-height:none;bottom:40px}.workbench.left-float>.canvas-wrap{grid-column:1;grid-row:1;min-width:0}.workbench.left-float>.panel.right{grid-column:2;grid-row:1}.workbench.preview-shell{grid-template-rows:1fr;grid-template-columns:1fr}.item input.swatch{flex:none;width:22px;height:18px;padding:0;border:1px solid var(--border);border-radius:4px;background:transparent;cursor:pointer}.statusbar{grid-column:1 / -1}.panel{background:var(--panel);border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0}.panel.right{border-right:none;border-left:1px solid var(--border)}.panel-hd{display:flex;align-items:center;gap:6px;padding:10px 12px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--border)}.panel-hd .ttl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel-toggle{flex:none;width:24px;height:24px;padding:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;color:var(--text);cursor:pointer;line-height:1;font-size:16px;display:inline-flex;align-items:center;justify-content:center}.panel-toggle:hover{border-color:var(--accent);color:var(--accent)}.panel-toggle .ico{width:14px;height:14px;display:block}.panel.collapsed .panel-hd{flex-direction:column;height:100%;padding:8px 4px;border-bottom:none;justify-content:flex-start}.panel.collapsed .panel-toggle{order:-1}.panel.collapsed .ttl{writing-mode:vertical-rl;flex:none;letter-spacing:.2em}.panel-bd{padding:10px;overflow:auto;flex:1;display:flex;flex-direction:column;gap:8px}.btn{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 10px;cursor:pointer}.btn:hover{border-color:var(--accent)}.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn.danger{border-color:var(--danger);color:var(--danger)}.btn:disabled{opacity:.45;cursor:not-allowed}.canvas-wrap{position:relative;min-width:0;min-height:0;background:#12151c}.canvas-wrap canvas{width:100%;height:100%;display:block}.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;color:var(--muted);text-align:center}.empty h2{color:var(--text);margin:0 0 8px;font-weight:600}.steps{display:flex;gap:18px;margin-top:16px;font-size:13px}.steps b{color:var(--accent)}.tree{display:flex;flex-direction:column;gap:2px;background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:4px;min-height:120px;overflow-y:auto}.tree-empty{margin:0;padding:14px 8px;text-align:center;font-size:12px;color:var(--muted)}.item{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;cursor:pointer}.item:hover{background:#5b8def14}.item.active{background:#263044}.item .idx{flex:none;width:18px;font-size:11px;color:var(--muted);text-align:right}.item .grow{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.item .rename-btn{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:auto;padding:2px 6px;font-size:11px;line-height:1.3;color:var(--text);opacity:0;pointer-events:none}.item:hover .rename-btn,.item:focus-within .rename-btn{opacity:1;pointer-events:auto}.item:hover .grow,.item:focus-within .grow{padding-right:40px}.item input[type=checkbox]{accent-color:var(--accent);margin:0}.hint{margin:0;font-size:11px;line-height:1.45;color:var(--muted)}.sec{margin:4px 0 0;padding:10px 0 2px;border-top:1px solid var(--border);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.btn-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.btn-grid .btn,.btn-row .btn{width:100%;font-size:12px;padding:6px 8px}.btn-grid.core-actions.compact,.btn-grid.tool-mode.compact{gap:4px}.btn-grid.core-actions.icon-text{grid-template-columns:1fr 1fr}.btn-grid.core-actions.icons-only{grid-template-columns:repeat(5,1fr)}.btn-grid.tool-mode{grid-template-columns:repeat(3,1fr)}.btn-grid.core-actions .btn.icon-btn,.btn-grid.tool-mode .btn.icon-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 6px;font-size:11px;min-height:28px}.btn-grid.core-actions.icons-only .btn.icon-btn,.btn-grid.tool-mode.icons-only .btn.icon-btn{padding:4px}.btn-grid.core-actions .btn.icon-btn .ico,.btn-grid.tool-mode .btn.icon-btn .ico{width:14px;height:14px;flex:none;display:block}.btn-grid.core-actions .btn.icon-btn span,.btn-grid.tool-mode .btn.icon-btn span{line-height:1.2;white-space:nowrap}.btn-grid select{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:6px 8px;font-size:12px}.btn-row{display:flex;gap:6px}.split-list{display:flex;flex-direction:column;gap:6px}.split-list .btn-row .btn:first-child{flex:1;width:auto}.split-list .btn-row .btn.danger{flex:none;width:auto}.xyz{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;align-items:center;font-size:12px}.xyz>span{color:var(--muted)}.xyz input,.xyz select{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.xyz input{text-align:center}.xyz select{grid-column:2 / -1}.xyz-hd{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;font-size:10px;color:var(--muted);text-align:center;margin-bottom:-2px}.stack{display:flex;flex-direction:column;gap:6px}.stack select,.stack input[type=number]{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px}.check{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.diag{border-left:3px solid var(--border);padding:8px 10px;margin-bottom:8px;background:var(--panel-2);border-radius:0 6px 6px 0;cursor:pointer}.diag.red{border-color:var(--danger)}.diag.yellow{border-color:var(--warn)}.diag.green{border-color:var(--ok)}.diag h4{margin:0 0 4px;font-size:13px}.diag p{margin:0;font-size:12px;color:var(--muted)}.statusbar{display:flex;align-items:center;gap:16px;padding:0 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.overlay{position:absolute;inset:0;background:#0000008c;display:flex;align-items:center;justify-content:center;z-index:40}.workbench>.overlay{grid-column:1 / -1;grid-row:1 / -1}.dialog{width:min(480px,calc(100% - 24px),92vw);max-width:100%;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);padding:18px}.dialog h3{margin:0 0 10px}.dialog .row{margin:10px 0;display:flex;gap:8px;align-items:center}.dialog select{background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:5px 8px;color-scheme:dark}.dialog select option{background:var(--panel-2);color:var(--text)}.dialog .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px}.dialog .actions>.btn{flex:0 0 auto;white-space:nowrap}.dialog.help{width:min(640px,94vw);max-height:min(82vh,720px);overflow:auto}.dialog.help p{font-size:13px;line-height:1.55}.dialog .url-input{width:100%;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}.dialog .snapshot-preview{display:block;width:100%;max-height:min(52vh,420px);object-fit:contain;background:#12151c;border:1px solid var(--border);border-radius:8px}.toasts{position:fixed;right:16px;bottom:40px;display:flex;flex-direction:column;gap:8px;z-index:50}.toast{padding:10px 14px;border-radius:8px;background:var(--panel-2);border:1px solid var(--border)}.toast.ok{border-color:var(--ok)}.toast.fail{border-color:var(--danger)}.busy{position:absolute;inset:0;background:#0e11168c;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;cursor:wait;-webkit-user-select:none;user-select:none}.bar{width:180px;height:4px;background:#2a303c;border-radius:4px;overflow:hidden}.bar i{display:block;height:100%;width:40%;background:var(--accent);animation:slide 1s infinite}@keyframes slide{0%{transform:translate(-100%)}to{transform:translate(280%)}}.field{display:flex;align-items:center;gap:8px;margin:6px 0;font-size:13px}.field input,.field select{background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 6px;width:90px}.tour{position:absolute;left:50%;top:72px;transform:translate(-50%);background:var(--panel);border:1px solid var(--accent);border-radius:10px;padding:14px 16px;z-index:8;width:360px}.preview-tag{position:absolute;top:10px;left:10px;background:#1d3a24;color:#9dffb0;padding:4px 8px;border-radius:4px;font-size:12px}.marquee{position:absolute;border:1px dashed var(--accent);background:#5b8def1f;pointer-events:none}.ctx{position:fixed;z-index:60;background:var(--panel);border:1px solid var(--border);border-radius:6px;min-width:140px;padding:4px}.ctx button{display:block;width:100%;text-align:left;background:none;border:none;padding:6px 8px;cursor:pointer}.ctx button:hover{background:var(--panel-2)}.clip-slider{position:absolute;top:12px;left:50%;transform:translate(-50%);background:#141820e0;padding:8px 12px;border-radius:8px;font-size:12px;display:flex;align-items:center;gap:8px;z-index:4}.clip-slider input{width:180px}.diag.active{outline:1px solid var(--accent)}.live-read{position:absolute;left:12px;bottom:12px;background:#141820d9;padding:6px 10px;border-radius:6px;font-size:13px;color:#ffe08a}
1
+ :root{--bg: #0e1116;--panel: #171b22;--panel-2: #1e242e;--border: #2c3440;--text: #e8edf4;--muted: #8b95a5;--accent: #5b8def;--danger: #ff5c5c;--warn: #f0b429;--ok: #3dcc7a;--shadow: 0 8px 32px rgba(0, 0, 0, .35);font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root,.printbench-root *{box-sizing:border-box}.printbench-root{height:100%;min-height:0;background:var(--bg);color:var(--text);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root button,.printbench-root input,.printbench-root select,.printbench-root textarea{font:inherit;color:inherit;color-scheme:dark}.printbench-root select option{background:var(--panel-2);color:var(--text)}.workbench{position:relative;display:grid;grid-template-rows:1fr 28px;grid-template-columns:292px 1fr;height:100%}.workbench.no-left{grid-template-columns:36px 1fr}.workbench.left-float{grid-template-columns:1fr}.workbench.left-float>.panel.parts{position:absolute;left:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:12;grid-column:1;grid-row:1;border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.workbench.left-float>.panel.parts.collapsed{width:36px;max-height:none;bottom:40px}.workbench.left-float>.canvas-wrap{grid-column:1;grid-row:1;min-width:0}.workbench.preview-shell{grid-template-rows:1fr;grid-template-columns:1fr}.item input.swatch{flex:none;width:22px;height:18px;padding:0;border:1px solid var(--border);border-radius:4px;background:transparent;cursor:pointer}.statusbar{grid-column:1 / -1}.panel{background:var(--panel);border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0}.workbench>.panel.right{position:absolute;right:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:var(--printbench-diagnosis-z, 100);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-right:1px solid var(--border);border-left:1px solid var(--border)}.workbench>.panel.right.collapsed{width:36px;max-height:none}.panel-hd{display:flex;align-items:center;gap:6px;padding:10px 12px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--border)}.panel-hd .ttl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel-toggle{flex:none;width:24px;height:24px;padding:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;color:var(--text);cursor:pointer;line-height:1;font-size:16px;display:inline-flex;align-items:center;justify-content:center}.panel-toggle:hover{border-color:var(--accent);color:var(--accent)}.panel-toggle .ico{width:14px;height:14px;display:block}.panel.collapsed .panel-hd{flex-direction:column;height:100%;padding:8px 4px;border-bottom:none;justify-content:flex-start}.panel.collapsed .panel-toggle{order:-1}.panel.collapsed .ttl{writing-mode:vertical-rl;flex:none;letter-spacing:.2em}.panel-bd{padding:10px;overflow:auto;flex:1;display:flex;flex-direction:column;gap:8px}.btn{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 10px;cursor:pointer}.btn:hover{border-color:var(--accent)}.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn.danger{border-color:var(--danger);color:var(--danger)}.btn:disabled{opacity:.45;cursor:not-allowed}.canvas-wrap{position:relative;min-width:0;min-height:0;background:#12151c}.canvas-wrap canvas{width:100%;height:100%;display:block}.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;color:var(--muted);text-align:center}.empty h2{color:var(--text);margin:0 0 8px;font-weight:600}.steps{display:flex;gap:18px;margin-top:16px;font-size:13px}.steps b{color:var(--accent)}.tree{display:flex;flex-direction:column;gap:2px;background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:4px;min-height:120px;overflow-y:auto}.tree-empty{margin:0;padding:14px 8px;text-align:center;font-size:12px;color:var(--muted)}.item{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;cursor:pointer}.item:hover{background:#5b8def14}.item.active{background:#263044}.item .idx{flex:none;width:18px;font-size:11px;color:var(--muted);text-align:right}.item .grow{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.item .rename-btn{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:auto;padding:2px 6px;font-size:11px;line-height:1.3;color:var(--text);opacity:0;pointer-events:none}.item:hover .rename-btn,.item:focus-within .rename-btn{opacity:1;pointer-events:auto}.item:hover .grow,.item:focus-within .grow{padding-right:40px}.item input[type=checkbox]{accent-color:var(--accent);margin:0}.hint{margin:0;font-size:11px;line-height:1.45;color:var(--muted)}.sec{margin:4px 0 0;padding:10px 0 2px;border-top:1px solid var(--border);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.btn-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.btn-grid .btn,.btn-row .btn{width:100%;font-size:12px;padding:6px 8px}.btn-grid.core-actions.compact,.btn-grid.tool-mode.compact{gap:4px}.btn-grid.core-actions.icon-text{grid-template-columns:1fr 1fr}.btn-grid.core-actions.icons-only{grid-template-columns:repeat(5,1fr)}.btn-grid.tool-mode{grid-template-columns:repeat(3,1fr)}.btn-grid.core-actions .btn.icon-btn,.btn-grid.tool-mode .btn.icon-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 6px;font-size:11px;min-height:28px}.btn-grid.core-actions.icons-only .btn.icon-btn,.btn-grid.tool-mode.icons-only .btn.icon-btn{padding:4px}.btn-grid.core-actions .btn.icon-btn .ico,.btn-grid.tool-mode .btn.icon-btn .ico{width:14px;height:14px;flex:none;display:block}.btn-grid.core-actions .btn.icon-btn span,.btn-grid.tool-mode .btn.icon-btn span{line-height:1.2;white-space:nowrap}.btn-grid select{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:6px 8px;font-size:12px}.btn-row{display:flex;gap:6px}.split-list{display:flex;flex-direction:column;gap:6px}.split-list .btn-row .btn:first-child{flex:1;width:auto}.split-list .btn-row .btn.danger{flex:none;width:auto}.xyz{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;align-items:center;font-size:12px}.xyz>span{color:var(--muted)}.xyz input,.xyz select{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.xyz input{text-align:center}.xyz select{grid-column:2 / -1}.xyz-hd{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;font-size:10px;color:var(--muted);text-align:center;margin-bottom:-2px}.stack{display:flex;flex-direction:column;gap:6px}.stack select,.stack input[type=number]{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px}.check{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.diag{border-left:3px solid var(--border);padding:8px 10px;margin-bottom:8px;background:var(--panel-2);border-radius:0 6px 6px 0;cursor:pointer}.diag.red{border-color:var(--danger)}.diag.yellow{border-color:var(--warn)}.diag.green{border-color:var(--ok)}.diag h4{margin:0 0 4px;font-size:13px}.diag p{margin:0;font-size:12px;color:var(--muted)}.statusbar{display:flex;align-items:center;gap:16px;padding:0 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.overlay{position:absolute;inset:0;background:#0000008c;display:flex;align-items:center;justify-content:center;z-index:40}.workbench>.overlay{grid-column:1 / -1;grid-row:1 / -1}.dialog{width:min(480px,calc(100% - 24px),92vw);max-width:100%;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);padding:18px}.dialog h3{margin:0 0 10px}.dialog .row{margin:10px 0;display:flex;gap:8px;align-items:center}.dialog select{background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:5px 8px;color-scheme:dark}.dialog select option{background:var(--panel-2);color:var(--text)}.dialog .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px}.dialog .actions>.btn{flex:0 0 auto;white-space:nowrap}.dialog.help{width:min(640px,94vw);max-height:min(82vh,720px);overflow:auto}.dialog.help p{font-size:13px;line-height:1.55}.dialog .url-input{width:100%;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}.dialog .snapshot-preview{display:block;width:100%;max-height:min(52vh,420px);object-fit:contain;background:#12151c;border:1px solid var(--border);border-radius:8px}.toasts{position:fixed;top:16px;left:50%;transform:translate(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;z-index:50;pointer-events:none}.toast{pointer-events:auto;padding:10px 14px;border-radius:8px;background:#1e242e;border:1px solid var(--border);color:var(--text);box-shadow:var(--shadow)}.toast.ok{background:#15261c;border-color:var(--ok)}.toast.fail{background:#2a1518;border-color:var(--danger)}.toast.info{background:#1e242e}.busy{position:absolute;inset:0;background:#0e11168c;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;cursor:wait;-webkit-user-select:none;user-select:none}.bar{width:180px;height:4px;background:#2a303c;border-radius:4px;overflow:hidden}.bar i{display:block;height:100%;width:40%;background:var(--accent);animation:slide 1s infinite}@keyframes slide{0%{transform:translate(-100%)}to{transform:translate(280%)}}.field{display:flex;align-items:center;gap:8px;margin:6px 0;font-size:13px}.field input,.field select{background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 6px;width:90px}.tour{position:absolute;left:50%;top:72px;transform:translate(-50%);background:var(--panel);border:1px solid var(--accent);border-radius:10px;padding:14px 16px;z-index:8;width:360px}.preview-tag{position:absolute;top:10px;left:10px;background:#1d3a24;color:#9dffb0;padding:4px 8px;border-radius:4px;font-size:12px}.marquee{position:absolute;border:1px dashed var(--accent);background:#5b8def1f;pointer-events:none}.ctx{position:fixed;z-index:60;background:var(--panel);border:1px solid var(--border);border-radius:6px;min-width:140px;padding:4px}.ctx button{display:block;width:100%;text-align:left;background:none;border:none;padding:6px 8px;cursor:pointer}.ctx button:hover{background:var(--panel-2)}.clip-slider{position:absolute;top:12px;left:50%;transform:translate(-50%);background:#141820e0;padding:8px 12px;border-radius:8px;font-size:12px;display:flex;align-items:center;gap:8px;z-index:4}.clip-slider input{width:180px}.diag.active{outline:1px solid var(--accent)}.live-read{position:absolute;left:12px;bottom:12px;background:#141820d9;padding:6px 10px;border-radius:6px;font-size:13px;color:#ffe08a}