diff --git a/CHANGELOG.md b/CHANGELOG.md index 5795bc2..2dd416a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [0.9.1] - 2026-08-22 +### 新增 +- **编辑级 `diagram` 组件(diagram-design 移植,PR #9)**:白名单新增 `diagram` 节点——27 种 kind(architecture/flowchart/sequence/state/er/timeline/swimlane/quadrant/radar/loop 等)、正交连接器、语义 token 主题(light/dark/editorial 变体)、dotted-paper 底纹、Zone 分组(≤3 个虚线容器 + mono eyebrow 标签)、64px 节点排版与底部 Legend 色板条。复杂度预算由 guard 强制(节点/边/焦点上限),坐标取整 4px 网格、重复 id 自愈、主题色安全校验;`figcaption` 与 SVG `` 分离 id,`aria-labelledby` 稳定指向 `<title>`。 + ## [0.9.0] - 2026-08-17 ### 新增 - **ECharts 集成组件**:新增 `echart` 节点类型,支持模型输出完整 ECharts 图表。两种模式: diff --git a/SKILL.md b/SKILL.md index 3550dd4..b7dcfbe 100644 --- a/SKILL.md +++ b/SKILL.md @@ -16,7 +16,7 @@ description: "Render structured interactive UI inline in your reply via the dsh- 布局:`text` `row` `col` `grid` `card` `divider` `spacer` 展示:`stat` `badge` `progress` `list` `table` `keyvalue` `avatar` `audio` `video` `timeline` `file-tree` `breadcrumb` `diff` `json` `code` `callout` `steps` 图表:`chart`(bars/line/donut,可多序列)`plot`(数学函数图)`echart`(ECharts 全功能图表)交互:`button` `input` `select` `checkbox` `radio` `switch` `textarea` `tabs` `accordion` `copy` -高级:`mermaid`(流程图/时序/甘特等)`scene3d`(3D WebGL)`quiz`(点选判题 + 解析 + 重试) +交互:`button` `input` `select` `checkbox` `radio` `switch` `textarea` `tabs` `accordion` `copy` ### 布局 - text: `{"type":"text","size":"h1|h2|h3|body|muted|caption","content":"...","center":true?}` @@ -72,6 +72,7 @@ description: "Render structured interactive UI inline in your reply via the dsh- ### 高级 - mermaid: `{"type":"mermaid","code":"graph TD\\nA-->B"}` — flowchart/sequence/class/gantt/pie/er/state/journey;主题自动跟随宿主(暗/浅) +- diagram: `{"type":"diagram","kind":"architecture","title":"可选标题","variant":"light|dark|editorial","nodes":[...],"edges":[...],"theme":{...}}` — **编辑级品牌图**(移植自 diagram-design 的 27 种视觉类型)。节点: `{"id":"a","label":"Web","type":"focal|backend|store|external|input|optional|security","x":40,"y":40,"w":128,"h":48,"sub":"可选技术子标签","tag":"可选角标如 API"}`;边: `{"from":"a","to":"b","label":"WRITE","kind":"solid|dashed|accent|link"}`。**规则由渲染器强制**: 正交连接器(r=8 弯折、禁止斜线)、4px 网格、语义 token(paper/ink/muted/accent)、焦点色 ≤2 个、复杂度预算(≤9 节点/≤12 边)、z-order(箭头在节点后)、边标签 6-10px 间隙。27 种 kind:architecture / it-state / flowchart / sequence / state / er / timeline / swimlane / quadrant / radar / loop / nested / tree / org-chart / layers / venn / pyramid / bar / line / gantt / scatter / high-level / process / medallion / data-flow / dp-integration / dp-security-matrix。**坐标类 kind**(architecture/it-state/high-level/process/medallion/data-flow/dp-integration)用 x/y/w/h 精确定位;**规则类 kind** 只给数据自动排版。架构/流程/层次结构优先用 diagram 而非 mermaid(自动布局用 mermaid,编辑级排版用 diagram)。 - scene3d: `{"type":"scene3d","title":"...","meshes":[{"shape":"box|sphere|cone|cylinder|torus","color":"#hex?","size":n|[w,h,d]?,"position":[x,y,z]?,"rotation":[rx,ry,rz]?,"scale":n?|[...]?}],"ambient":0-2?,"background":"#hex?"}` — 3D WebGL,可拖拽旋转、滚轮缩放;mesh 数量 1–5 个 - quiz: `{"type":"quiz","question":"...","options":[{"label":"...","correct":true?,"feedback":"..."?}],"explanation":"...","id":"..."?,"action":"answer"?}` — 教学问答:点选即判题、可重试;`id` 变化时重置;带 action 时另回传 `{type:'quiz',question,answer,correct}` @@ -86,6 +87,7 @@ description: "Render structured interactive UI inline in your reply via the dsh- | 数据对比 / 趋势 / 占比 | `chart`(bars/line/donut)、`echart`(ECharts 全功能)、`table` | | 关键指标数字 / 进度状态 | `stat`、`progress`、`badge` | | 流程 / 步骤 / 阶段 / 时间线 | `steps`、`timeline`、`mermaid`(flowchart/sequence/gantt) | +| 架构 / 系统拓扑 / 数据流 / 品牌图 | `diagram`(编辑级,27 种类型;自动布局需求才用 `mermaid`) | | 目录 / 文件结构 / 层级关系 | `file-tree`、`mermaid`、`accordion` | | 状态一览 / 检查结果 | `badge` + `table` + `progress` 组合 | | 代码 / 配置 / 改动对比 | `code`、`diff`、`json` | diff --git a/docs/diagram-component-design.md b/docs/diagram-component-design.md new file mode 100644 index 0000000..b22374d --- /dev/null +++ b/docs/diagram-component-design.md @@ -0,0 +1,246 @@ +# dsh-genui `diagram` 组件设计文档(移植 diagram-design) + +> 目标:把 [cathrynlavery/diagram-design](https://github.com/cathrynlavery/diagram-design) +> 的 27 种编辑级视觉类型 + 设计系统(语义 token、正交连接器、反模式清单) +> 移植为 dsh-genui 的一等公民组件 `diagram`,让模型能在 ```dsh-ui 围栏里 +> 直接输出品牌化、可访问、编辑级的 SVG 图。 +> +> 状态:设计定稿(实现前基线)。上游版本:diagram-design v2.4 / dsh-genui 0.8.3。 + +--- + +## 1. 设计目标与原则 + +| 原则 | 含义 | +|---|---| +| **一等公民** | `diagram` 进 spec.ts 白名单 + render-node switch,与 `mermaid`/`plot` 同级,自动获得 guard、流式、持久化、自愈 | +| **声明式 spec** | 模型输出**数据**(节点/边/布局意图),渲染器负责布局与样式——模型不需要手写 SVG path | +| **编辑级默认** | 正交连接器、4px 网格、语义 token、反模式清单全部编码进渲染器,模型无法产出"AI slop" | +| **可访问** | 每个图 `role="img"` + `aria-label`/`aria-describedby`;交互不引入 | +| **上限硬编码** | 节点数、边数、accent 数等沿用 diagram-design 的复杂度预算,守卫层钳制 | +| **轻依赖** | 纯 React + SVG,无 mermaid/three 运行时依赖;不新增资产路由 | + +### 与 mermaid 的关系(不重复) + +`mermaid` 已覆盖 flowchart/sequence/class/gantt/pie/er/state/journey 的**自动布局**通用图。 +`diagram` 定位不同:**编辑级布局**——模型提供坐标意图(或按类型规则自动布局), +渲染器按 diagram-design 规范精确排版。两者并存:用户要"快速自动布局"用 mermaid, +要"编辑级品牌图"用 diagram。 + +--- + +## 2. Spec 形状 + +### 顶层 + +```json +{ + "type": "diagram", + "kind": "architecture | flowchart | sequence | state | er | timeline | swimlane | quadrant | radar | loop | nested | tree | org-chart | layers | venn | pyramid | bar | line | gantt | scatter | high-level | process | medallion | data-flow | dp-integration | dp-security-matrix | it-state", + "title": "可选标题(Instrument Serif)", + "variant": "light | dark | editorial", + "nodes": [ ... ], + "edges": [ ... ], + "meta": { "focal": 2, "density": 4 } +} +``` + +- `kind` 决定布局语法与复杂度预算(见 §4)。 +- `variant` 缺省跟随宿主主题(`light` 或 `dark`);`editorial` 强制编辑级皮肤。 +- 品牌 token 缺省用内置 style-guide 默认;可选 `theme` 字段覆盖(见 §5)。 + +### 节点 Node + +```json +{ + "id": "n1", + "label": "用户可见名称(Geist sans)", + "sub": "可选技术子标签(Geist mono)", + "type": "focal | backend | store | external | input | optional | security", + "x": 40, "y": 40, "w": 120, "h": 48, + "tag": "可选类型角标,如 API" +} +``` + +### 边 Edge + +```json +{ + "from": "n1", "to": "n2", + "label": "可选边标签(≤14 字符,全大写)", + "kind": "solid | dashed | accent | link", + "route": "auto | orthogonal | straight" +} +``` + +### 布局模型 + +**两种模式,由 `kind` 决定:** + +1. **坐标模式**(architecture / it-state / high-level / process / data-flow / dp-* 等自由布局类): + 模型给 `x/y/w/h`,渲染器负责正交连线、端口选择、桥接、边标签遮罩。 +2. **规则布局模式**(flowchart / sequence / state / er / timeline / swimlane / quadrant / + radar / loop / nested / tree / org-chart / layers / venn / pyramid / bar / line / + gantt / scatter):模型只给数据,渲染器按类型规则自动排版(与 diagram-design + 各 type-*.md 的布局约定一致)。 + +两种模式都执行**规范强制层**(§6):4px 网格、复杂度预算、反模式检查。 + +--- + +## 3. 组件清单(27 种 kind → 渲染策略) + +| kind | 布局模式 | 数据形状 | 复杂度预算 | +|---|---|---|---| +| `architecture` | 坐标 | nodes+edges+可zone | ≤9 节点,≤12 边,≤3 zones | +| `it-state` | 坐标 | phase 分组 nodes | ≤9 节点,≤3 阶段 | +| `flowchart` | 规则 | 节点+分支边 | ≤9 节点 | +| `sequence` | 规则 | lifelines+messages | ≤5 lifelines,≤1 fragment | +| `state` | 规则 | states+transitions+guards | ≤9 states | +| `er` | 规则 | entities+fields+relations | ≤8 entities | +| `timeline` | 规则 | events on axis | ≤12 events | +| `swimlane` | 规则 | lanes+steps+handoffs | ≤5 lanes | +| `quadrant` | 规则 | 2 轴 + items | ≤12 items | +| `radar` | 规则 | axes+series | ≤5 axes,≤5 series | +| `loop` | 规则 | hub+stations | ≤8 stations | +| `nested` | 规则 | containment 树 | ≤6 层 | +| `tree` | 规则 | 父子树 | ≤4 深 | +| `org-chart` | 规则 | 归属/汇报树 | ≤12 节点,≤4 深 | +| `layers` | 规则 | 层列表 | ≤6 层 | +| `venn` | 规则 | 集合 | ≤3 圆 | +| `pyramid` | 规则 | 层级值 | ≤6 层 | +| `bar` | 规则 | 类目值 | ≤8 bars | +| `line` | 规则 | 序列点 | ≤5 series | +| `gantt` | 规则 | tasks+phases | ≤12 tasks | +| `scatter` | 规则 | 点 | ≤30 点 | +| `high-level` | 坐标 | 栈+集群 | ≤9 节点 | +| `process` | 坐标 | 多角色步骤+数据交接 | ≤9 节点 | +| `medallion` | 坐标 | 分层数据存储 | ≤9 节点 | +| `data-flow` | 坐标 | 角色+步骤 | ≤9 节点 | +| `dp-integration` | 坐标 | 源→核心→消费者 | ≤9 节点 | +| `dp-security-matrix` | 规则 | 角色×权限矩阵 | ≤9×9 | +| `it-state` | 坐标 | 阶段分组 | ≤9 节点 | + +> 具体每个 kind 的 spec 字段与布局规则见 `docs/diagram-kinds.md`(随实现同步生成)。 + +--- + +## 4. 设计系统(内置 style-guide,语义 token) + +渲染器内置 diagram-design 的默认皮肤,以 CSS 变量或 SVG 常量形式存在: + +| 角色 | Light | Dark | +|---|---|---| +| `paper` | `#f5f5f5` | `#2d3142` | +| `paper-2` | `#ececec` | `#393e53` | +| `ink` | `#2d3142` | `#f5f5f5` | +| `muted` | `#4f5d75` | `#bfc0c0` | +| `soft` | `#7a8399` | `#8e98ac` | +| `rule` | `rgba(45,49,66,0.12)` | `rgba(245,245,245,0.12)` | +| `accent` | `#eb6c36` | `#f08a59` | +| `accent-tint` | `rgba(235,108,54,0.08)` | `rgba(240,138,89,0.10)` | +| `link` | `#2e5aa8` | `#6a95d8` | + +- **焦点规则**:`accent` 只上 1–2 个元素;spec 的 `meta.focal` 计数,超出降级为 `ink`。 +- **节点类型 → 填充/描边**:focal→accent-tint/accent;backend→white/ink; + store→ink@5%/muted;external→ink@3%/ink@30%;input→muted@10%/soft; + optional→ink@2%/ink@20% dashed;security→accent@5%/accent@50% dashed。 +- **字体栈**:标题 Instrument Serif;节点名 Geist sans 600;子标签/边标签 Geist Mono。 + (渲染器内用 CSS 栈,不强制外链 Google Fonts——宿主已提供字体环境时直接继承。) + +### 主题覆盖(可选) + +```json +"theme": { "paper": "#fffdf7", "ink": "#2a2416", "accent": "#c94f1e" } +``` + +渲染器合并进语义 token;未提供字段回退内置默认。PR 阶段先支持整组 token 覆盖, +品牌抓取(onboarding)属于后续迭代(见 §9)。 + +--- + +## 5. 渲染器结构 + +新增 `src/client/blocks/diagram.tsx`(+ 必要时 `diagram/` 子模块): + +``` +src/client/blocks/diagram/ + index.tsx # DiagramNode 入口:variant/主题解析、复杂度守卫、a11y 外壳 + layout.ts # kind → 布局器(坐标透传或规则布局) + geometry.ts # 正交连接器(elbow path r=8)、端口选择、桥接、边标签遮罩 + theme.ts # 语义 token 表 + 主题合并 + kinds/ # 每个规则布局 kind 一个布局器(共 ~27,可分组) +``` + +**接入点:** +- `src/client/spec.ts` — 新增 `GenuiDiagram` / `GenuiDiagramNode` / `GenuiDiagramEdge` 接口,并入 `GenuiNode` 联合。 +- `src/client/blocks/render-node.tsx` — `case 'diagram': return <DiagramNode .../>`。 +- `src/client/guard.ts` — 新增 `maxDiagramNodes`(9)/`maxDiagramEdges`(12)/`maxDiagramZones`(3)等上限, + 并在 `repairGenuiSpec` 里按 kind 钳制(未知 kind 降级为 `architecture` 或丢弃)。 +- `src/client/GenuiBlock.module.css` — diagram 容器样式(尺寸、边框、可访问焦点)。 +- `src/plugin/index.ts` 的 `GENUI_SECTION_TEXT` + `SKILL.md` — 教模型 `diagram` 语法。 + +**可访问性:** 根 `<svg role="img" aria-label={title ?? kind} aria-describedby=...>`;title/desc 首子元素。 + +--- + +## 6. 规范强制层(渲染时硬编码) + +与 diagram-design SKILL.md §5–7 对齐,全部在渲染器实现,模型无法绕过: + +1. **4px 网格**:所有坐标/尺寸/字号对齐到 4(布局器输出时取整;坐标模式把模型输入 round 到 4)。 +2. **正交连接器强制**:非共享轴连线一律 elbow path(`r=8`);斜线连接自动重路由。 +3. **端口选择**:垂直为主用顶/底端口,水平为主用左/右端口;同边多端口 fan(≥12px)。 +4. **边标签遮罩 + 6–10px 间隙**:标签永远不压线;遮罩不压节点(节点后画)。 +5. **桥接/跳线**:交叉时次要边加 hop arc;两条边永不同路径。 +6. **z-order**:bg → zones → arrows → labels → nodes。 +7. **焦点预算**:accent > `meta.focal` 时降级。 +8. **复杂度预算**:按 kind 钳制节点/边/深度,超出截断(守卫层)。 +9. **反模式内置**:无阴影、无发光、无 `rounded-2xl`(rx ≤ 8)、无 3 等宽卡、图例在底部条。 + +--- + +## 7. 教学(SKILL.md + GENUI_SECTION_TEXT) + +- `GENUI_SECTION_TEXT` 增加一行: + `- diagram: {"type":"diagram","kind":"architecture","nodes":[...],"edges":[...]} — 编辑级品牌图(27 种类型,正交连接器,语义 token;替代 mermaid 的自动布局)`。 +- `SKILL.md` 增加 `diagram` 一节:kind 选择表、节点/边字段、布局模式、焦点规则、 + 复杂度预算、"何时用 diagram 而非 mermaid"、示例 spec。 +- 新增 skill 教学文件 `SKILL.diagram.md`(可选,作为 genui skill 的附属参考)。 + +--- + +## 8. 测试 + +- `tests/genui-diagram.spec.tsx` — 渲染冒烟:每个 kind 至少一个最小 spec 渲染出 `<svg role="img">`。 +- `tests/genui-diagram-guard.spec.ts` — 未知 kind 降级;超预算截断;4px 取整;accent 降级。 +- `tests/genui-diagram-connector.spec.ts` — 正交路径、端口选择、边标签遮罩、桥接。 +- `tests/genui-diagram-a11y.spec.tsx` — aria-label/describedby、无重复 id。 +- 回归:现有 `genui.spec.tsx` 全绿(白名单扩展不破坏旧组件)。 + +--- + +## 9. 范围与迭代顺序 + +**v1(本次 PR):** +- 核心渲染器 + 全部 27 kind 的**最小可用布局器**(坐标类完整;规则类用统一 + 自动布局器按 kind 参数化,保证每个 kind 能渲染)。 +- 内置默认皮肤(light/dark 跟随宿主)、语义 token、焦点规则、复杂度预算、正交连接器。 +- spec.ts / guard / render-node / SKILL.md / GENUI_SECTION_TEXT / 测试。 + +**v2(后续):** +- 每种 kind 的精细布局(swimlane 分栏、sequence lifeline 激活条、radar 网格等)。 +- 品牌抓取(onboarding)、编辑级 `editorial` 变体精修、`sketchy`/`terminal` 皮肤。 +- drawio/mermaid 导入重绘(对应 diagram-design 的 scripts/*.py)。 + +**PR 可合入标准:** v1 全部完成;每个 kind 有最小 spec 渲染 + 测试;文档齐全; +现有 0.8.3 功能零回归。 + +--- + +## 10. 参考 + +- diagram-design:[README](https://github.com/cathrynlavery/diagram-design)、 + `skills/diagram-design/SKILL.md`(v2.4)、`references/style-guide.md`、各 `type-*.md`。 +- dsh-genui:当前 0.8.3,`src/client/spec.ts`、`blocks/render-node.tsx`、`guard.ts`。 +- 移植基线:本仓库 fork,分支 `feat/diagram-component`。 diff --git a/lib/client.js b/lib/client.js index 5cbc549..a5fde2d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,5 +1,5 @@ -window.__ModuleLoader__.load({id:`@omdsh-dev/dsh-genui`,factory:e=>{var t={exports:{}},n=t.exports;Object.defineProperty(n,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},u=(e,t)=>{let n={};for(var r in e)i(n,r,{get:e[r],enumerable:!0});return t||i(n,Symbol.toStringTag,{value:`Module`}),n},d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e},f=(e,t,n)=>(n=e==null?{}:r(s(e)),d(t||!e||!e.__esModule||!c.call(e,`default`)?i(n,`default`,{value:e,enumerable:!0}):n,e));let p=e("@deepseek-ai/dsh-client-ui-primitives");p=f(p,1);let m=e("react"),ee=e("react-dom/client"),h=e("react/jsx-runtime"),g=(0,m.createContext)(void 0),_=p.GenuiActionContext??g;function v(){return(0,m.useContext)(_)}let y={display:`flex`,flexDirection:`column`,gap:`4px`,padding:`8px 12px`,margin:`4px 0`,borderRadius:`8px`,border:`1px solid rgba(127,127,127,0.35)`,background:`rgba(127,127,127,0.08)`,color:`inherit`,fontSize:`12px`,lineHeight:1.5,fontFamily:`inherit`};var b=class extends m.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){console.error(`[dsh-genui] render failed:`,e,t.componentStack??``)}render(){let{error:e}=this.state;return e===null?this.props.children:(0,h.jsxs)(`div`,{style:y,role:`alert`,"data-genui-error":!0,children:[(0,h.jsxs)(`span`,{style:{fontWeight:600},children:[`⚠️ `,this.props.label??`此界面`,`渲染失败(已隔离,不影响其他内容)`]}),(0,h.jsx)(`span`,{style:{opacity:.75,overflowWrap:`anywhere`},children:e.message})]})}};let x=`@omdsh-dev/dsh-genui/GenuiBlock.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(x)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@omdsh-dev/dsh-genui`,e.dataset.pluginCss=x,e.textContent=`.V1MMBW_block{--dsl-g-radius-surface:12px;--dsl-g-radius-control:8px;--dsl-g-radius-pill:999px;--dsl-g-font-display:24px;--dsl-g-font-h1:20px;--dsl-g-font-h2:16px;--dsl-g-font-h3:14px;--dsl-g-font-body:14px;--dsl-g-font-title:13px;--dsl-g-font-meta:12px;--dsl-g-font-data:11px;--dsl-g-gap-lg:16px;--dsl-g-gap-md:12px;--dsl-g-gap-sm:8px;--dsl-g-gap-xs:4px;--dsl-g-border:var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,#ffffff1f));--dsl-g-border-strong:var(--dsw-alias-border-l2,#ffffff1f);--dsl-g-accent:var(--dsw-alias-state-business-primary,#4f8ef7);--dsl-g-accent-soft:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);--dsl-g-hover:color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);--dsl-g-tint:8%;--dsl-g-tint-strong:14%;--dsl-g-font-mono:var(--ds-font-family-code,ui-monospace, "SF Mono", monospace);color:var(--dsw-alias-label-primary);margin:8px 0}.V1MMBW_banner{font-size:var(--dsl-g-font-title);letter-spacing:.01em;color:var(--dsw-alias-label-primary);margin-bottom:var(--dsl-g-gap-lg);border-bottom:1px solid var(--dsl-g-border);padding-bottom:10px;font-weight:600}.V1MMBW_col{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_row{align-items:center;gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_row.V1MMBW_wrap{flex-wrap:wrap}.V1MMBW_grid{gap:var(--dsl-g-gap-md);display:grid}.V1MMBW_spacer{flex:1}.V1MMBW_divider{background:var(--dsw-alias-markdown-hr,var(--dsl-g-border));height:1px;margin:var(--dsl-g-gap-xs) 0;border:none}.V1MMBW_card{background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);padding:var(--dsl-g-gap-lg);gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_cardTitle{font-size:var(--dsl-g-font-meta);letter-spacing:.02em;color:var(--dsw-alias-label-secondary);font-weight:600}.V1MMBW_text{color:var(--dsw-alias-label-primary)}.V1MMBW_text.V1MMBW_h1{font-size:var(--dsl-g-font-h1);letter-spacing:-.02em;font-weight:700;line-height:1.3}.V1MMBW_text.V1MMBW_h2{font-size:var(--dsl-g-font-h2);letter-spacing:-.01em;font-weight:600;line-height:1.35}.V1MMBW_text.V1MMBW_h3{font-size:var(--dsl-g-font-h3);font-weight:600;line-height:1.5}.V1MMBW_text.V1MMBW_body{font-size:var(--dsl-g-font-body);color:var(--dsw-alias-label-primary);line-height:1.6}.V1MMBW_text.V1MMBW_muted{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);line-height:1.5}.V1MMBW_text.V1MMBW_caption{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;line-height:1.5}.V1MMBW_text.V1MMBW_center{text-align:center}.V1MMBW_button{border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:var(--dsl-g-radius-control);padding:8px var(--dsl-g-gap-lg);font-size:var(--dsl-g-font-title);cursor:pointer;text-align:center;font-family:inherit;font-weight:600;line-height:1.4;transition:border-color .15s,filter .15s,background .15s,transform .1s}.V1MMBW_button:hover:not(:disabled){border-color:var(--dsl-g-accent);filter:brightness(1.06)}.V1MMBW_button.V1MMBW_primary:hover:not(:disabled){filter:brightness(1.08)}.V1MMBW_button:active:not(:disabled){filter:brightness(.97);transform:translateY(1px)}.V1MMBW_button:disabled{cursor:not-allowed;opacity:.45;filter:none;box-shadow:none;pointer-events:none}.V1MMBW_button.V1MMBW_primary{background:var(--dsl-g-accent);color:#fff;border:none;box-shadow:inset 0 1px #ffffff24}.V1MMBW_button.V1MMBW_danger{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent);color:var(--dsw-alias-state-error-primary,#ffb3b3)}.V1MMBW_button.V1MMBW_success{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent);color:var(--dsw-alias-state-success-secondary,#9fe8c5)}.V1MMBW_button.V1MMBW_ghost{background:0 0}.V1MMBW_button.V1MMBW_full{width:100%}.V1MMBW_button.V1MMBW_small{font-size:var(--dsl-g-font-meta);border-radius:var(--dsl-g-radius-control);padding:4px 12px}.V1MMBW_field{gap:var(--dsl-g-gap-xs);flex-direction:column;display:flex}.V1MMBW_field>span{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_input,.V1MMBW_select{background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);color:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-title);outline:none;width:100%;padding:8px 12px;font-family:inherit}.V1MMBW_input:focus,.V1MMBW_select:focus{border-color:var(--dsl-g-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_input::placeholder{color:var(--dsw-alias-label-caption,#5b6378)}.V1MMBW_checkbox{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;display:flex}.V1MMBW_checkbox input{accent-color:var(--dsl-g-accent);width:15px;height:15px}.V1MMBW_checkbox input:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:4px}.V1MMBW_link{color:var(--dsl-g-accent);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:none;padding:0;font-family:inherit;text-decoration:none}.V1MMBW_link:hover{text-decoration:underline}.V1MMBW_linkText{color:var(--dsl-g-accent);font-size:var(--dsl-g-font-title);font-family:inherit;text-decoration:none}.V1MMBW_media{padding:var(--dsl-g-gap-md);gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;margin:0;display:flex}.V1MMBW_mediaLabel{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_mediaPlayer{width:100%;min-width:0;display:block}.V1MMBW_videoPlayer{object-fit:contain;background:#000;max-height:min(70vh,720px)}.V1MMBW_mediaError{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#f25a5a)}.V1MMBW_badge{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);letter-spacing:.01em;border-radius:var(--dsl-g-radius-pill);background:color-mix(in srgb, var(--dsw-alias-label-tertiary) var(--dsl-g-tint), transparent);width:fit-content;color:var(--dsw-alias-label-secondary);border:1px solid var(--dsl-g-border);padding:1px 10px;font-weight:500;line-height:1.5;display:inline-flex}.V1MMBW_badge.V1MMBW_success{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-success-secondary,#7fe3b4);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent)}.V1MMBW_badge.V1MMBW_warn{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-warn-secondary,#f7cf7d);border-color:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) 30%, transparent)}.V1MMBW_badge.V1MMBW_danger{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-error-primary,#ff9d9d);border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent)}.V1MMBW_badge.V1MMBW_accent{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-business-primary,#9cc3ff);border-color:color-mix(in srgb, var(--dsl-g-accent) 30%, transparent)}.V1MMBW_stat{padding:6px var(--dsl-g-gap-lg);flex-direction:column;gap:2px;display:flex}.V1MMBW_grid>.V1MMBW_stat,.V1MMBW_row>.V1MMBW_stat{border-left:1px solid var(--dsl-g-border)}.V1MMBW_grid>.V1MMBW_stat:first-child,.V1MMBW_row>.V1MMBW_stat:first-child{padding-left:var(--dsl-g-gap-xs);border-left:none}.V1MMBW_statLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);letter-spacing:.02em}.V1MMBW_statValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-display);letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.2}.V1MMBW_statDelta{font-size:var(--dsl-g-font-meta);font-weight:500}.V1MMBW_statDelta.V1MMBW_up{color:var(--dsw-alias-state-success-primary,#22c55e)}.V1MMBW_statDelta.V1MMBW_down{color:var(--dsw-alias-state-error-primary,#f25a5a)}.V1MMBW_progress{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_progressRow{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);justify-content:space-between;display:flex}.V1MMBW_progressRow span:last-child{font-family:var(--dsl-g-font-mono)}.V1MMBW_track{border-radius:var(--dsl-g-radius-pill);background:var(--dsw-alias-bg-layer-1);height:6px;box-shadow:inset 0 0 0 1px var(--dsl-g-border);overflow:hidden}.V1MMBW_fill{border-radius:var(--dsl-g-radius-pill);background:linear-gradient(180deg, color-mix(in srgb, var(--dsl-g-accent) 85%, white), var(--dsl-g-accent));height:100%;transition:width .5s}.V1MMBW_list{flex-direction:column;display:flex}.V1MMBW_li{padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-xs);flex-direction:column;gap:2px;display:flex}.V1MMBW_li+.V1MMBW_li{border-top:1px solid var(--dsl-g-border)}.V1MMBW_li:last-child{border-bottom:none}.V1MMBW_liTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_liDesc{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);line-height:1.5}.V1MMBW_tableWrap{border-radius:var(--dsl-g-radius-control);overscroll-behavior-x:contain;min-width:0;max-width:100%;overflow-x:auto}.V1MMBW_table{border-collapse:collapse;width:100%;font-size:var(--dsl-g-font-title)}.V1MMBW_table th{text-align:left;padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-md);color:var(--dsw-alias-label-tertiary);font-weight:600;font-size:var(--dsl-g-font-meta);border-bottom:1px solid var(--dsl-g-border);white-space:nowrap}.V1MMBW_table td{padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-md);border-bottom:1px solid var(--dsl-g-border);color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;line-height:1.5}.V1MMBW_table tr:last-child td{border-bottom:none}.V1MMBW_table tbody tr{transition:background .12s}.V1MMBW_table tbody tr:hover{background:var(--dsl-g-hover)}.V1MMBW_table th.V1MMBW_thNum,.V1MMBW_table td.V1MMBW_tdNum{text-align:right}.V1MMBW_thSort{color:inherit;font:inherit;font-weight:inherit;cursor:pointer;text-align:left;background:0 0;border:none;margin:0;padding:0;transition:color .12s}.V1MMBW_table th.V1MMBW_thNum .V1MMBW_thSort{text-align:right;width:100%}.V1MMBW_thSort:hover,.V1MMBW_table th[aria-sort]:not([aria-sort=none]) .V1MMBW_thSort{color:var(--dsw-alias-label-primary)}.V1MMBW_thSortMark{color:var(--dsl-g-accent)}.V1MMBW_thSort:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px;border-radius:var(--dsl-g-radius-control)}.V1MMBW_chart{gap:var(--dsl-g-gap-xs);flex-direction:column;display:flex}.V1MMBW_chartPlot{align-items:flex-end;gap:var(--dsl-g-gap-sm);height:132px;display:flex;position:relative}.V1MMBW_baseline{background:var(--dsl-g-border-strong);pointer-events:none;height:1px;position:absolute;bottom:0;left:0;right:0}.V1MMBW_gridline{background:var(--dsw-alias-border-l1,#ffffff0f);pointer-events:none;height:1px;position:absolute;left:0;right:0}.V1MMBW_chartLabels{gap:var(--dsl-g-gap-sm);display:flex}.V1MMBW_chartLabels>span{flex:1;min-width:0}.V1MMBW_barCol{justify-content:flex-end;gap:var(--dsl-g-gap-xs);flex-direction:column;flex:1;min-width:0;height:100%;display:flex}.V1MMBW_barValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);text-align:center;line-height:1.2}.V1MMBW_barFill{background:var(--dsl-g-accent);border-radius:4px 4px 2px 2px;min-height:4px;transition:height .6s,filter .15s}.V1MMBW_barFill:hover{filter:brightness(1.18)}.V1MMBW_barLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);text-align:center;white-space:nowrap;text-overflow:ellipsis;line-height:1.5;overflow:hidden}.V1MMBW_tabs{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_tabBar{gap:var(--dsl-g-gap-xs);border-bottom:1px solid var(--dsl-g-border);display:flex}.V1MMBW_tab{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-1px;padding:6px 12px;font-family:inherit;font-weight:600;line-height:1.5;transition:color .15s,border-bottom-color .15s}.V1MMBW_tab:hover{color:var(--dsw-alias-label-secondary)}.V1MMBW_tabActive{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsl-g-accent)}.V1MMBW_avatar{width:32px;height:32px;font-size:var(--dsl-g-font-title);color:#fff;border:1px solid #ffffff24;border-radius:50%;flex-shrink:0;place-items:center;font-weight:700;display:grid;box-shadow:inset 0 1px #ffffff29}.V1MMBW_callout{border-radius:var(--dsl-g-radius-control);border:1px solid var(--dsl-g-border);font-size:var(--dsl-g-font-title);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));flex-direction:column;gap:2px;padding:10px 14px;line-height:1.6;display:flex}.V1MMBW_calloutInfo{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent)}.V1MMBW_calloutSuccess{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent)}.V1MMBW_calloutWarning{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) var(--dsl-g-tint), transparent)}.V1MMBW_calloutError{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent)}.V1MMBW_calloutTitle{font-weight:600;font-size:var(--dsl-g-font-meta);letter-spacing:.02em;color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;display:flex}.V1MMBW_calloutTitle:before{content:"";background:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));border-radius:50%;width:6px;height:6px}.V1MMBW_calloutInfo .V1MMBW_calloutTitle:before{background:var(--dsl-g-accent)}.V1MMBW_calloutSuccess .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_calloutWarning .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-warn-primary,#f5b83d)}.V1MMBW_calloutError .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-error-primary,#ff6b6b)}.V1MMBW_calloutBody{color:var(--dsw-alias-label-secondary)}.V1MMBW_steps{gap:var(--dsl-g-gap-sm);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.V1MMBW_step{gap:var(--dsl-g-gap-md);align-items:flex-start;display:flex}.V1MMBW_stepMarker{width:24px;height:24px;font-size:var(--dsl-g-font-meta);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsl-g-border);color:var(--dsw-alias-label-tertiary);border-radius:50%;flex-shrink:0;place-items:center;font-weight:700;display:grid}.V1MMBW_stepDone .V1MMBW_stepMarker{background:var(--dsw-alias-state-success-primary,#3ecf8e);color:#fff;border-color:#0000;font-size:13px}.V1MMBW_stepActive .V1MMBW_stepMarker{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent);border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}.V1MMBW_stepContent{flex-direction:column;gap:2px;padding-top:3px;display:flex}.V1MMBW_stepTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_stepDesc{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);line-height:1.5}.V1MMBW_keyvalue{flex-direction:column;margin:0;display:flex}.V1MMBW_kvRow{gap:var(--dsl-g-gap-md);font-size:var(--dsl-g-font-title);padding:6px 0;display:flex}.V1MMBW_kvRow+.V1MMBW_kvRow{border-top:1px solid var(--dsl-g-border)}.V1MMBW_kvRow:last-child{border-bottom:none}.V1MMBW_kvKey{width:96px;color:var(--dsw-alias-label-tertiary);flex-shrink:0;font-weight:600}.V1MMBW_kvValue{color:var(--dsw-alias-label-primary);word-break:break-word;margin:0;line-height:1.5}.V1MMBW_jsonScalar{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary)}.V1MMBW_lineChart{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_linePath{fill:none;stroke:var(--dsl-g-accent);stroke-width:2px;stroke-linejoin:round;stroke-linecap:round}.V1MMBW_lineDot{fill:var(--dsl-g-accent);transition:filter .15s}.V1MMBW_lineDot:hover{filter:brightness(1.3)}.V1MMBW_lineGrid{stroke:var(--dsw-alias-border-l1,#ffffff12);stroke-width:1px}.V1MMBW_lineGridAxis{stroke:var(--dsl-g-border-strong);stroke-width:1px}.V1MMBW_lineTick{fill:var(--dsw-alias-label-tertiary);font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data)}.V1MMBW_lineLabels{justify-content:space-between;display:flex}.V1MMBW_groupedBars{gap:var(--dsl-g-gap-xs);align-items:flex-end;width:100%;height:100%;display:flex}.V1MMBW_groupedBar{flex-direction:column;flex:1;justify-content:flex-end;align-items:center;gap:2px;min-width:0;height:100%;display:flex}.V1MMBW_groupValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;max-width:100%;line-height:1.2;overflow:hidden}.V1MMBW_groupedFill{background:var(--dsl-g-accent);border-radius:4px 4px 2px 2px;flex:none;width:100%;min-height:3px;transition:filter .15s}.V1MMBW_groupedFill:hover{filter:brightness(1.18)}.V1MMBW_donut{align-items:center;gap:var(--dsl-g-gap-lg);display:flex}.V1MMBW_donutTrack{stroke:var(--dsw-alias-border-l1,#ffffff14)}.V1MMBW_donutSeg{transition:filter .15s}.V1MMBW_donutSeg:hover{filter:brightness(1.18)}.V1MMBW_donutTotal{fill:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-h2);font-weight:700}.V1MMBW_donutTotalLabel{fill:var(--dsw-alias-label-tertiary);font-size:10px}.V1MMBW_donutLegend{gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);flex-direction:column;line-height:1.5;display:flex}.V1MMBW_fieldGroup{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_fieldLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_radio{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;line-height:1.5;display:flex}.V1MMBW_radio input{accent-color:var(--dsl-g-accent)}.V1MMBW_radio input:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:50%}.V1MMBW_submitRow{align-items:center;gap:var(--dsl-g-gap-md);margin-top:2px;display:flex}.V1MMBW_submit{align-self:flex-start}.V1MMBW_submitHint{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_btnSent{margin-left:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-state-success-primary,#3ecf8e);font-weight:600}.V1MMBW_gradeWrap{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_gradeScore{align-items:baseline;gap:var(--dsl-g-gap-sm);display:flex}.V1MMBW_gradeScoreValue{font-size:var(--dsl-g-font-display);color:var(--dsw-alias-label-primary);font-weight:700;line-height:1.2}.V1MMBW_gradeScoreLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_gradeList{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_gradeItem{font-size:var(--dsl-g-font-title);padding:var(--dsl-g-gap-sm) 12px;border-radius:var(--dsl-g-radius-control);border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);grid-template-columns:auto auto 1fr;align-items:baseline;gap:6px 10px;line-height:1.5;display:grid}.V1MMBW_gradeItemOk{border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent)}.V1MMBW_gradeItemNo{border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent)}.V1MMBW_gradeQ{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_gradeTag{font-weight:700}.V1MMBW_gradeItemOk .V1MMBW_gradeTag{color:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_gradeItemNo .V1MMBW_gradeTag{color:var(--dsw-alias-state-error-primary,#ff6b6b)}.V1MMBW_gradeAns{color:var(--dsw-alias-label-secondary)}.V1MMBW_gradeRight{color:var(--dsw-alias-state-error-primary,#ffb3b3)}.V1MMBW_gradeExp{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);grid-column:1/-1;line-height:1.5}.V1MMBW_switchRow{justify-content:space-between;align-items:center;gap:var(--dsl-g-gap-md);cursor:pointer;display:flex}.V1MMBW_switchRow:focus-within .V1MMBW_switch{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_switchLabel{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);line-height:1.5}.V1MMBW_switch{border-radius:var(--dsl-g-radius-pill);border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-base,#17171a);width:38px;height:22px;transition:background .2s;position:relative}.V1MMBW_switchOn{background:var(--dsl-g-accent);border-color:#0000}.V1MMBW_switchKnob{background:#fff;border-radius:50%;width:14px;height:14px;transition:left .2s;position:absolute;top:3px;left:3px;box-shadow:0 1px 2px #0000004d}.V1MMBW_switchOn .V1MMBW_switchKnob{left:19px}.V1MMBW_sliderRow{align-items:center;gap:var(--dsl-g-gap-md);width:100%;display:flex}.V1MMBW_sliderInput{min-width:0;accent-color:var(--dsl-g-accent);flex:1}.V1MMBW_sliderInput:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:4px}.V1MMBW_sliderValue{text-align:right;min-width:44px;font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);color:var(--dsw-alias-label-primary)}.V1MMBW_textarea{background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);width:100%;color:var(--dsw-alias-label-primary);padding:var(--dsl-g-gap-sm) 12px;font-size:var(--dsl-g-font-title);resize:vertical;outline:none;font-family:inherit;line-height:1.5}.V1MMBW_textarea:focus{border-color:var(--dsl-g-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_accordion{border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex;overflow:hidden}.V1MMBW_accItem{border-bottom:1px solid var(--dsl-g-border)}.V1MMBW_accItem:last-child{border-bottom:none}.V1MMBW_accHead{justify-content:space-between;align-items:center;gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-title);cursor:pointer;border:none;padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;transition:background .15s,color .15s;display:flex}.V1MMBW_accHead:hover{background:color-mix(in srgb, var(--dsw-alias-label-primary) 5%, var(--dsw-alias-bg-layer-1))}.V1MMBW_accHead:active{color:var(--dsl-g-accent)}.V1MMBW_accChevron{color:var(--dsw-alias-label-tertiary);transition:transform .2s}.V1MMBW_accBody{padding:var(--dsl-g-gap-md) 14px;gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-base,#17171a);flex-direction:column;display:flex}.V1MMBW_copyChip{border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;width:fit-content;padding:6px 14px;font-family:inherit;font-weight:600;transition:all .15s}.V1MMBW_copyChip:hover{border-color:var(--dsl-g-accent)}.V1MMBW_copyChip:active{transform:translateY(1px)}.V1MMBW_copyChipDone{border-color:var(--dsw-alias-state-success-primary,#3ecf8e);color:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_mermaid{padding:var(--dsl-g-gap-xs) 0;overflow-x:auto}.V1MMBW_mermaid svg{max-width:100%;height:auto}.V1MMBW_mermaidFallback{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_mermaidFallback pre{padding:var(--dsl-g-gap-sm) 10px;background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-meta);margin:0;overflow-x:auto}.V1MMBW_mermaidErr{color:var(--dsw-alias-state-error-primary,#ff6b6b);font-size:var(--dsl-g-font-meta)}.V1MMBW_mermaidHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_scene3dWrap{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_echartWrap{gap:var(--dsl-g-gap-sm);padding:var(--dsl-g-gap-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_echartTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_echartCanvas{width:100%;min-height:0}.V1MMBW_echartHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_echartFallback{gap:var(--dsl-g-gap-sm);padding:var(--dsl-g-gap-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_echartErr{color:var(--dsw-alias-state-error-primary,#ff6b6b);font-size:var(--dsl-g-font-meta)}.V1MMBW_scene3dTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:700}.V1MMBW_scene3dCanvas{border-radius:var(--dsl-g-radius-surface);background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);height:240px;overflow:hidden}.V1MMBW_scene3dCanvas canvas{display:block}.V1MMBW_scene3dHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_timeline{flex-direction:column;display:flex}.V1MMBW_tlItem{gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_tlRail{flex-direction:column;flex-shrink:0;align-items:center;width:12px;display:flex}.V1MMBW_tlDot{background:var(--dsl-g-accent);width:10px;height:10px;box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent);border-radius:50%;flex-shrink:0;margin-top:4px}.V1MMBW_tlLine{background:var(--dsl-g-border);flex:1;width:2px;margin:2px 0}.V1MMBW_tlBody{padding-bottom:var(--dsl-g-gap-lg);flex:1;min-width:0}.V1MMBW_tlHead{align-items:baseline;gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_tlTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_tlTime{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);white-space:nowrap;margin-left:auto}.V1MMBW_tlDesc{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);margin-top:2px;line-height:1.5}.V1MMBW_fileTree{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-meta);overscroll-behavior-x:contain;flex-direction:column;min-width:0;max-width:100%;display:flex;overflow-x:auto}.V1MMBW_ftRow{align-items:center;gap:var(--dsl-g-gap-sm);padding:3px var(--dsl-g-gap-xs);border-radius:var(--dsl-g-radius-control);display:flex}.V1MMBW_ftRow:hover{background:var(--dsw-alias-bg-layer-1)}.V1MMBW_ftIcon{text-align:center;width:13px;font-size:10px;font-family:var(--dsl-g-font-mono);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));flex-shrink:0;line-height:1}.V1MMBW_ftIconDir{color:var(--dsl-g-accent);font-size:11px}.V1MMBW_ftName{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.V1MMBW_ftDir{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_ftNameBtn{align-items:center;gap:var(--dsl-g-gap-sm);min-width:0;max-width:100%;font-family:inherit;font-size:var(--dsl-g-font-body);cursor:default;text-align:left;background:0 0;border:none;padding:0;display:inline-flex}button.V1MMBW_ftNameBtn[aria-expanded]{cursor:pointer}.V1MMBW_ftNameBtn:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px;border-radius:var(--dsl-g-radius-control)}.V1MMBW_breadcrumb{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-title);flex-wrap:wrap;display:flex}.V1MMBW_bcItem{align-items:center;gap:var(--dsl-g-gap-xs);display:inline-flex}.V1MMBW_bcText{color:var(--dsw-alias-label-secondary);cursor:pointer}.V1MMBW_bcText:hover{color:var(--dsl-g-accent)}.V1MMBW_bcCurrent{color:var(--dsw-alias-label-primary);cursor:default;font-weight:600}.V1MMBW_bcSep{color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary))}@keyframes V1MMBW_genuiReveal{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes V1MMBW_genuiPopIn{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.V1MMBW_reveal{animation:.45s cubic-bezier(.22,1,.36,1) both V1MMBW_genuiReveal}.V1MMBW_btnSent{animation:.2s both V1MMBW_genuiPopIn}@media (prefers-reduced-motion:reduce){.V1MMBW_reveal,.V1MMBW_btnSent{animation:none}.V1MMBW_fill,.V1MMBW_barFill,.V1MMBW_switch,.V1MMBW_switchKnob{transition:none}}.V1MMBW_tableWrap,.V1MMBW_fileTree,.V1MMBW_mermaid,.V1MMBW_panelBody{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l2,#ffffff38) transparent}.V1MMBW_tableWrap::-webkit-scrollbar,.V1MMBW_fileTree::-webkit-scrollbar,.V1MMBW_mermaid::-webkit-scrollbar,.V1MMBW_panelBody::-webkit-scrollbar{width:8px;height:8px}.V1MMBW_tableWrap::-webkit-scrollbar-thumb,.V1MMBW_fileTree::-webkit-scrollbar-thumb,.V1MMBW_mermaid::-webkit-scrollbar-thumb,.V1MMBW_panelBody::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l2,#ffffff38);border-radius:4px}.V1MMBW_tableWrap::-webkit-scrollbar-track,.V1MMBW_fileTree::-webkit-scrollbar-track,.V1MMBW_mermaid::-webkit-scrollbar-track,.V1MMBW_panelBody::-webkit-scrollbar-track{background:0 0}.V1MMBW_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.V1MMBW_quiz{gap:var(--dsl-g-gap-md);padding:var(--dsl-g-gap-lg);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_quizQuestion{font-size:var(--dsl-g-font-body);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.6}.V1MMBW_quizOptions{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_quizOpt{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;padding:10px 14px;font-family:inherit;line-height:1.5;transition:border-color .15s,background .15s;display:flex}.V1MMBW_quizOpt:hover:not(:disabled){border-color:var(--dsl-g-accent);background:var(--dsl-g-accent-soft)}.V1MMBW_quizOpt:focus-visible,.V1MMBW_button:focus-visible,.V1MMBW_tab:focus-visible,.V1MMBW_accHead:focus-visible,.V1MMBW_copyChip:focus-visible,.V1MMBW_link:focus-visible,.V1MMBW_quizRetry:focus-visible,.V1MMBW_resetBtn:focus-visible,.V1MMBW_playBtn:focus-visible,.V1MMBW_bcText:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px}.V1MMBW_quizOpt:disabled{cursor:default;opacity:.85}.V1MMBW_quizOptCorrect{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 40%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;display:flex}.V1MMBW_quizOptWrong{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#ff6b6b);padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;display:flex}.V1MMBW_quizOptReveal{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border:1px dashed color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 40%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);padding:10px 14px;font-family:inherit;line-height:1.5;display:flex}.V1MMBW_quizMarker{text-align:center;width:16px;font-weight:700}.V1MMBW_quizResult{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_quizCorrectMsg{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);font-weight:600}.V1MMBW_quizWrongMsg{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#ff6b6b);font-weight:600}.V1MMBW_quizFeedback{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);margin-top:3px;font-weight:400;line-height:1.5}.V1MMBW_quizExplanation{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);padding:var(--dsl-g-gap-sm) 10px;border-top:1px solid var(--dsl-g-border);line-height:1.6}.V1MMBW_quizRetry{border:1px solid var(--dsl-g-border);width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;padding:6px 14px;font-family:inherit}.V1MMBW_quizRetry:hover{border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}.V1MMBW_tool{margin:4px 0}.V1MMBW_toolFallback{align-items:center;gap:var(--dsl-g-gap-md);padding:var(--dsl-g-gap-sm) 12px;border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));font-size:var(--dsl-g-font-title);display:flex}.V1MMBW_toolFallbackTitle{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_toolFallbackMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.V1MMBW_panel{border:1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) 35%, transparent);background:var(--dsw-alias-bg-layer-1,#ffffff0a);border-radius:14px;margin:10px 14px 2px;overflow:hidden}.V1MMBW_panelHeader{align-items:center;display:flex}.V1MMBW_panelToggle{align-items:center;gap:var(--dsl-g-gap-sm);min-width:0;color:inherit;font:inherit;font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:0;flex:auto;padding:9px 14px;display:flex}.V1MMBW_panelToggle:hover{background:#ffffff0a}.V1MMBW_panelClose{width:26px;height:26px;color:inherit;cursor:pointer;opacity:.65;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;margin-right:8px;padding:0;font-size:13px;line-height:1;display:flex}.V1MMBW_panelClose:hover{opacity:1;background:#ffffff14}.V1MMBW_panelClose:focus-visible{outline:1px solid var(--dsw-alias-state-business-primary,#4f8ef7);outline-offset:1px;opacity:1}.V1MMBW_panelBadge{padding:0 var(--dsl-g-gap-sm);background:color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) var(--dsl-g-tint-strong), transparent);color:var(--dsw-alias-state-business-primary,#7ba8ff);letter-spacing:.04em;border-radius:6px;flex:none;font-size:11px;font-weight:600;line-height:1.6}.V1MMBW_panelTitle{color:var(--dsw-alias-label-primary,#e6e6e6);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.V1MMBW_panelChevron{color:var(--dsw-alias-label-secondary,#ffffff8c);font-size:var(--dsl-g-font-meta);margin-left:auto}.V1MMBW_panelBody{height:360px;padding:0 16px var(--dsl-g-gap-lg);overflow-y:auto}.V1MMBW_panelResizeHandle{cursor:ns-resize;touch-action:none;background:0 0;border-radius:3px;height:6px;transition:background .15s}.V1MMBW_panelResizeHandle:hover,.V1MMBW_panelResizeHandleActive{background:color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) 35%, transparent)}`,document.head.appendChild(e)}var S={accBody:`V1MMBW_accBody`,accChevron:`V1MMBW_accChevron`,accHead:`V1MMBW_accHead`,accItem:`V1MMBW_accItem`,accent:`V1MMBW_accent`,accordion:`V1MMBW_accordion`,avatar:`V1MMBW_avatar`,badge:`V1MMBW_badge`,banner:`V1MMBW_banner`,barCol:`V1MMBW_barCol`,barFill:`V1MMBW_barFill`,barLabel:`V1MMBW_barLabel`,barValue:`V1MMBW_barValue`,baseline:`V1MMBW_baseline`,bcCurrent:`V1MMBW_bcCurrent`,bcItem:`V1MMBW_bcItem`,bcSep:`V1MMBW_bcSep`,bcText:`V1MMBW_bcText`,block:`V1MMBW_block`,body:`V1MMBW_body`,breadcrumb:`V1MMBW_breadcrumb`,btnSent:`V1MMBW_btnSent`,button:`V1MMBW_button`,callout:`V1MMBW_callout`,calloutBody:`V1MMBW_calloutBody`,calloutError:`V1MMBW_calloutError`,calloutInfo:`V1MMBW_calloutInfo`,calloutSuccess:`V1MMBW_calloutSuccess`,calloutTitle:`V1MMBW_calloutTitle`,calloutWarning:`V1MMBW_calloutWarning`,caption:`V1MMBW_caption`,card:`V1MMBW_card`,cardTitle:`V1MMBW_cardTitle`,center:`V1MMBW_center`,chart:`V1MMBW_chart`,chartLabels:`V1MMBW_chartLabels`,chartPlot:`V1MMBW_chartPlot`,checkbox:`V1MMBW_checkbox`,col:`V1MMBW_col`,copyChip:`V1MMBW_copyChip`,copyChipDone:`V1MMBW_copyChipDone`,danger:`V1MMBW_danger`,divider:`V1MMBW_divider`,donut:`V1MMBW_donut`,donutLegend:`V1MMBW_donutLegend`,donutSeg:`V1MMBW_donutSeg`,donutTotal:`V1MMBW_donutTotal`,donutTotalLabel:`V1MMBW_donutTotalLabel`,donutTrack:`V1MMBW_donutTrack`,down:`V1MMBW_down`,echartCanvas:`V1MMBW_echartCanvas`,echartErr:`V1MMBW_echartErr`,echartFallback:`V1MMBW_echartFallback`,echartHint:`V1MMBW_echartHint`,echartTitle:`V1MMBW_echartTitle`,echartWrap:`V1MMBW_echartWrap`,field:`V1MMBW_field`,fieldGroup:`V1MMBW_fieldGroup`,fieldLabel:`V1MMBW_fieldLabel`,fileTree:`V1MMBW_fileTree`,fill:`V1MMBW_fill`,ftDir:`V1MMBW_ftDir`,ftIcon:`V1MMBW_ftIcon`,ftIconDir:`V1MMBW_ftIconDir`,ftName:`V1MMBW_ftName`,ftNameBtn:`V1MMBW_ftNameBtn`,ftRow:`V1MMBW_ftRow`,full:`V1MMBW_full`,genuiPopIn:`V1MMBW_genuiPopIn`,genuiReveal:`V1MMBW_genuiReveal`,ghost:`V1MMBW_ghost`,gradeAns:`V1MMBW_gradeAns`,gradeExp:`V1MMBW_gradeExp`,gradeItem:`V1MMBW_gradeItem`,gradeItemNo:`V1MMBW_gradeItemNo`,gradeItemOk:`V1MMBW_gradeItemOk`,gradeList:`V1MMBW_gradeList`,gradeQ:`V1MMBW_gradeQ`,gradeRight:`V1MMBW_gradeRight`,gradeScore:`V1MMBW_gradeScore`,gradeScoreLabel:`V1MMBW_gradeScoreLabel`,gradeScoreValue:`V1MMBW_gradeScoreValue`,gradeTag:`V1MMBW_gradeTag`,gradeWrap:`V1MMBW_gradeWrap`,grid:`V1MMBW_grid`,gridline:`V1MMBW_gridline`,groupValue:`V1MMBW_groupValue`,groupedBar:`V1MMBW_groupedBar`,groupedBars:`V1MMBW_groupedBars`,groupedFill:`V1MMBW_groupedFill`,h1:`V1MMBW_h1`,h2:`V1MMBW_h2`,h3:`V1MMBW_h3`,input:`V1MMBW_input`,jsonScalar:`V1MMBW_jsonScalar`,keyvalue:`V1MMBW_keyvalue`,kvKey:`V1MMBW_kvKey`,kvRow:`V1MMBW_kvRow`,kvValue:`V1MMBW_kvValue`,li:`V1MMBW_li`,liDesc:`V1MMBW_liDesc`,liTitle:`V1MMBW_liTitle`,lineChart:`V1MMBW_lineChart`,lineDot:`V1MMBW_lineDot`,lineGrid:`V1MMBW_lineGrid`,lineGridAxis:`V1MMBW_lineGridAxis`,lineLabels:`V1MMBW_lineLabels`,linePath:`V1MMBW_linePath`,lineTick:`V1MMBW_lineTick`,link:`V1MMBW_link`,linkText:`V1MMBW_linkText`,list:`V1MMBW_list`,media:`V1MMBW_media`,mediaError:`V1MMBW_mediaError`,mediaLabel:`V1MMBW_mediaLabel`,mediaPlayer:`V1MMBW_mediaPlayer`,mermaid:`V1MMBW_mermaid`,mermaidErr:`V1MMBW_mermaidErr`,mermaidFallback:`V1MMBW_mermaidFallback`,mermaidHint:`V1MMBW_mermaidHint`,muted:`V1MMBW_muted`,panel:`V1MMBW_panel`,panelBadge:`V1MMBW_panelBadge`,panelBody:`V1MMBW_panelBody`,panelChevron:`V1MMBW_panelChevron`,panelClose:`V1MMBW_panelClose`,panelHeader:`V1MMBW_panelHeader`,panelResizeHandle:`V1MMBW_panelResizeHandle`,panelResizeHandleActive:`V1MMBW_panelResizeHandleActive`,panelTitle:`V1MMBW_panelTitle`,panelToggle:`V1MMBW_panelToggle`,playBtn:`V1MMBW_playBtn`,primary:`V1MMBW_primary`,progress:`V1MMBW_progress`,progressRow:`V1MMBW_progressRow`,quiz:`V1MMBW_quiz`,quizCorrectMsg:`V1MMBW_quizCorrectMsg`,quizExplanation:`V1MMBW_quizExplanation`,quizFeedback:`V1MMBW_quizFeedback`,quizMarker:`V1MMBW_quizMarker`,quizOpt:`V1MMBW_quizOpt`,quizOptCorrect:`V1MMBW_quizOptCorrect`,quizOptReveal:`V1MMBW_quizOptReveal`,quizOptWrong:`V1MMBW_quizOptWrong`,quizOptions:`V1MMBW_quizOptions`,quizQuestion:`V1MMBW_quizQuestion`,quizResult:`V1MMBW_quizResult`,quizRetry:`V1MMBW_quizRetry`,quizWrongMsg:`V1MMBW_quizWrongMsg`,radio:`V1MMBW_radio`,resetBtn:`V1MMBW_resetBtn`,reveal:`V1MMBW_reveal`,row:`V1MMBW_row`,scene3dCanvas:`V1MMBW_scene3dCanvas`,scene3dHint:`V1MMBW_scene3dHint`,scene3dTitle:`V1MMBW_scene3dTitle`,scene3dWrap:`V1MMBW_scene3dWrap`,select:`V1MMBW_select`,sliderInput:`V1MMBW_sliderInput`,sliderRow:`V1MMBW_sliderRow`,sliderValue:`V1MMBW_sliderValue`,small:`V1MMBW_small`,spacer:`V1MMBW_spacer`,stat:`V1MMBW_stat`,statDelta:`V1MMBW_statDelta`,statLabel:`V1MMBW_statLabel`,statValue:`V1MMBW_statValue`,step:`V1MMBW_step`,stepActive:`V1MMBW_stepActive`,stepContent:`V1MMBW_stepContent`,stepDesc:`V1MMBW_stepDesc`,stepDone:`V1MMBW_stepDone`,stepMarker:`V1MMBW_stepMarker`,stepTitle:`V1MMBW_stepTitle`,steps:`V1MMBW_steps`,submit:`V1MMBW_submit`,submitHint:`V1MMBW_submitHint`,submitRow:`V1MMBW_submitRow`,success:`V1MMBW_success`,switch:`V1MMBW_switch`,switchKnob:`V1MMBW_switchKnob`,switchLabel:`V1MMBW_switchLabel`,switchOn:`V1MMBW_switchOn`,switchRow:`V1MMBW_switchRow`,tab:`V1MMBW_tab`,tabActive:`V1MMBW_tabActive`,tabBar:`V1MMBW_tabBar`,table:`V1MMBW_table`,tableWrap:`V1MMBW_tableWrap`,tabs:`V1MMBW_tabs`,tdNum:`V1MMBW_tdNum`,text:`V1MMBW_text`,textarea:`V1MMBW_textarea`,thNum:`V1MMBW_thNum`,thSort:`V1MMBW_thSort`,thSortMark:`V1MMBW_thSortMark`,timeline:`V1MMBW_timeline`,tlBody:`V1MMBW_tlBody`,tlDesc:`V1MMBW_tlDesc`,tlDot:`V1MMBW_tlDot`,tlHead:`V1MMBW_tlHead`,tlItem:`V1MMBW_tlItem`,tlLine:`V1MMBW_tlLine`,tlRail:`V1MMBW_tlRail`,tlTime:`V1MMBW_tlTime`,tlTitle:`V1MMBW_tlTitle`,tool:`V1MMBW_tool`,toolFallback:`V1MMBW_toolFallback`,toolFallbackMeta:`V1MMBW_toolFallbackMeta`,toolFallbackTitle:`V1MMBW_toolFallbackTitle`,track:`V1MMBW_track`,up:`V1MMBW_up`,videoPlayer:`V1MMBW_videoPlayer`,visuallyHidden:`V1MMBW_visuallyHidden`,warn:`V1MMBW_warn`,wrap:`V1MMBW_wrap`};let C=`dsh.genui.interaction`;function w(){return{order:[],blocks:{}}}function T(){try{let e=localStorage.getItem(C);if(e===null)return w();let t=JSON.parse(e);return!Array.isArray(t.order)||typeof t.blocks!=`object`||t.blocks===null?w():{order:t.order.filter(e=>typeof e==`string`),blocks:t.blocks}}catch{return w()}}function te(e){try{localStorage.setItem(C,JSON.stringify(e))}catch{}}function ne(e){return e===``?null:T().blocks[e]??null}function re(e,t){if(e===``)return;let n=T(),r=n.order.filter(t=>t!==e);r.unshift(e);let i={...n.blocks,[e]:t};for(;r.length>200;){let e=r.pop();e!==void 0&&delete i[e]}te({order:r,blocks:i})}function ie(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)>>>0;return t.toString(36)}function ae(e,t,n){return`f:${e}:${String(t)}:${ie(n)}`}function oe(e,t){return`p:${e}:${ie(t)}`}function se(e,t){return`t:${e}:${t}`}function E(e){if(typeof e!=`object`||!e)return null;let t=e;if(typeof t.type!=`string`||t.type===``)return null;let n={type:`col`,items:[e]};return t.panel===!0&&(n.panel=!0),t.append===!0&&(n.append=!0),n}function ce(e){if(typeof e!=`object`||!e)return!1;let t=e;return!(!Array.isArray(t.items)||t.title!==void 0&&typeof t.title!=`string`||t.gap!==void 0&&typeof t.gap!=`number`)}let D={maxDepth:8,maxNodes:200,maxString:2e3,maxCode:12e3,maxMermaid:8e3,maxGridCols:12,maxTabs:12,maxAccordionItems:24,maxListItems:50,maxOptions:50,maxTableRows:50,maxTableCols:12,maxChartPoints:60,maxPlotSeries:8,maxPlotParams:6,maxMeshes:5,maxQuizOptions:8,maxSteps:24,maxTimelineItems:24,maxBreadcrumbItems:12,maxKeyValuePairs:24,maxTreeDepth:6,maxEChartOptionDepth:10,maxEChartArrayLen:500,maxEChartOptionNodes:2e3};function le(e,t){return typeof e==`string`&&t.includes(e)}function O(e,t){return typeof e==`string`?e.slice(0,t):void 0}let ue=/^(?:#[\da-fA-F]{3,8}|rgba?\([^)]{0,64}\)|hsla?\([^)]{0,64}\)|var\(--dsw-[\w-]+(?:,\s*#[0-9a-fA-F]{3,8})?\))$/;function k(e){if(typeof e!=`string`)return;let t=e.trim();return t.length<=64&&ue.test(t)?t:void 0}function de(e){if(typeof e!=`string`)return;let t=e.trim();if(!(t.length>2048))return/^https?:\/\//i.test(t)||/^mailto:[^@\s]+@[^@\s]+$/i.test(t)?t:void 0}function fe(e){if(typeof e!=`string`)return;let t=e.trim();if(!(t===``||t.length>2048)&&(/^https?:\/\//i.test(t)||!(/^[a-z][a-z0-9+.-]*:/i.test(t)||/^[/\\]{2}/.test(t))))return t}function A(e,t,n){return typeof e==`number`&&Number.isFinite(e)?Math.min(n,Math.max(t,e)):void 0}function j(e,t,n){return typeof e==`number`&&Number.isFinite(e)?Math.min(n,Math.max(t,Math.trunc(e))):void 0}function M(e,t){return le(e,t)?e:void 0}function N(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function P(e,t){return t===void 0?{}:{[e]:t}}let pe=[`h1`,`h2`,`h3`,`body`,`muted`,`caption`],me=[`primary`,`danger`,`success`,`ghost`],he=[`success`,`warn`,`danger`,`accent`],ge=[`text`,`email`,`password`],_e=[`info`,`success`,`warning`,`error`],ve=[`bars`,`line`,`donut`],ye=[`line`,`area`,`scatter`],be=[`16:9`,`4:3`,`1:1`,`9:16`],xe=[`box`,`sphere`,`cone`,`cylinder`,`torus`],Se=[`file`,`dir`],Ce=[`bar`,`line`,`area`,`pie`,`scatter`];function F(e,t,n){if(!Array.isArray(e))return[];let r=[];for(let i of e){if(t.remaining<=0)break;--t.remaining;let e=we(i,t,n);e!==null&&r.push(e)}return r}function we(e,t,n){if(n>D.maxDepth)return null;let r=N(e);if(r===void 0)return null;let i=r.type;if(typeof i!=`string`)return null;switch(i){case`text`:{let e=O(r.content,D.maxString)??O(r.text,D.maxString);return e===void 0?null:{type:`text`,content:e,...P(`size`,M(r.size,pe)),...P(`center`,r.center===!0||void 0)}}case`row`:return{type:`row`,items:F(r.items,t,n+1),...P(`wrap`,r.wrap===!0||void 0),...P(`spacer`,r.spacer===!0||void 0)};case`col`:return{type:`col`,items:F(r.items,t,n+1),...P(`gap`,A(r.gap,0,96))};case`grid`:return{type:`grid`,cols:j(r.cols,1,D.maxGridCols)??1,items:F(r.items,t,n+1)};case`card`:return{type:`card`,items:F(r.items,t,n+1),...P(`title`,O(r.title,D.maxString))};case`button`:{let e=O(r.label,D.maxString);return e===void 0?null:{type:`button`,label:e,...P(`tone`,M(r.tone,me)),...P(`full`,r.full===!0||void 0),...P(`small`,r.small===!0||void 0),...P(`icon`,O(r.icon,64)),...P(`action`,O(r.action,200))}}case`input`:return{type:`input`,...P(`label`,O(r.label,D.maxString)),...P(`placeholder`,O(r.placeholder,D.maxString)),...P(`value`,O(r.value,D.maxString)),...P(`inputType`,M(r.inputType,ge)),...P(`action`,O(r.action,200)),...P(`id`,O(r.id,200))};case`select`:{let e=I(r.options,D.maxOptions,D.maxString);return e===void 0?null:{type:`select`,options:e,...P(`label`,O(r.label,D.maxString)),...P(`action`,O(r.action,200)),...P(`selected`,j(r.selected,0,e.length-1)),...P(`id`,O(r.id,200))}}case`checkbox`:{let e=O(r.label,D.maxString);return e===void 0?null:{type:`checkbox`,label:e,...P(`checked`,r.checked===!0||void 0),...P(`action`,O(r.action,200))}}case`link`:{let e=O(r.label,D.maxString);return e===void 0?null:{type:`link`,label:e,...P(`href`,de(r.href))}}case`audio`:{let e=fe(r.src);return e===void 0?null:{type:`audio`,src:e,...P(`alt`,O(r.alt,D.maxString)),...P(`loop`,r.loop===!0||void 0)}}case`video`:{let e=fe(r.src);return e===void 0?null:{type:`video`,src:e,...P(`alt`,O(r.alt,D.maxString)),...P(`poster`,fe(r.poster)),...P(`loop`,r.loop===!0||void 0),...P(`muted`,r.muted===!0||void 0),...P(`aspectRatio`,M(r.aspectRatio,be))}}case`badge`:{let e=O(r.label,D.maxString)??O(r.text,D.maxString)??O(r.value,D.maxString);return e===void 0?null:{type:`badge`,label:e,...P(`tone`,M(r.tone,he)),...P(`icon`,O(r.icon,64))}}case`stat`:{let e=O(r.label,D.maxString),t=O(r.value,128);return e===void 0||t===void 0?null:{type:`stat`,label:e,value:t,...P(`delta`,O(r.delta,64))}}case`progress`:{let e=A(r.value,0,100);return e===void 0?null:{type:`progress`,value:e,...P(`label`,O(r.label,D.maxString)),...P(`valueLabel`,O(r.valueLabel,64))}}case`divider`:return{type:`divider`};case`spacer`:return{type:`spacer`};case`avatar`:{let e=O(r.name,64);return e===void 0?null:{type:`avatar`,name:e,...P(`color`,k(r.color))}}case`list`:{let e=Te(r.items,D.maxListItems,t,n+1);return e===void 0?null:{type:`list`,items:e}}case`table`:{let e=I(r.columns,D.maxTableCols,128),t=Ee(r.rows,D.maxTableRows,D.maxTableCols);return e===void 0||t===void 0?null:{type:`table`,columns:e,rows:t}}case`chart`:{let e=De(r.data,D.maxChartPoints),t=Array.isArray(r.series)?Oe(r.series,D.maxPlotSeries,D.maxChartPoints):void 0;return e===void 0&&t===void 0?null:{type:`chart`,data:e??[],...P(`kind`,M(r.kind,ve)),...P(`series`,t)}}case`tabs`:{let e=ke(r.tabs,t,n);return e===void 0?null:{type:`tabs`,tabs:e}}case`plot`:{let e=Ae(r.series,D.maxPlotSeries);return e===void 0?null:{type:`plot`,series:e,...P(`xMin`,A(r.xMin,-1e6,1e6)),...P(`xMax`,A(r.xMax,-1e6,1e6)),...P(`yMin`,A(r.yMin,-1e9,1e9)),...P(`yMax`,A(r.yMax,-1e9,1e9)),...P(`title`,O(r.title,D.maxString))}}case`callout`:{let e=O(r.content,D.maxString);return e===void 0?null:{type:`callout`,content:e,...P(`tone`,M(r.tone,_e)),...P(`title`,O(r.title,D.maxString))}}case`steps`:{let e=je(r.steps);return e===void 0?null:{type:`steps`,steps:e,...P(`current`,j(r.current,0,e.length))}}case`keyvalue`:{let e=Me(r.pairs,D.maxKeyValuePairs);return e===void 0?null:{type:`keyvalue`,pairs:e}}case`diff`:{let e=Ne(r.diffs);return e===void 0?null:{type:`diff`,diffs:e}}case`json`:return`value`in r?{type:`json`,value:r.value}:null;case`code`:{let e=O(r.code,D.maxCode);return e===void 0?null:{type:`code`,code:e,...P(`lang`,O(r.lang,64))}}case`radio`:{let e=I(r.options,D.maxOptions,D.maxString);return e===void 0?null:{type:`radio`,options:e,...P(`label`,O(r.label,D.maxString)),...P(`selected`,j(r.selected,0,e.length-1)),...P(`action`,O(r.action,200)),...P(`group`,O(r.group,200)),...P(`answer`,typeof r.answer==`number`&&Number.isFinite(r.answer)&&r.answer>=0&&r.answer<e.length?Math.trunc(r.answer):typeof r.answer==`string`?r.answer.slice(0,512):void 0),...P(`explanation`,O(r.explanation,D.maxString))}}case`submit`:{let e=O(r.label,D.maxString),t=O(r.action,200);return e===void 0?null:{type:`submit`,label:e,...P(`action`,t),...P(`resetAction`,O(r.resetAction,200)),...P(`groups`,I(r.groups,D.maxOptions,200))}}case`switch`:{let e=O(r.label,D.maxString);return e===void 0?null:{type:`switch`,label:e,...P(`checked`,r.checked===!0||void 0),...P(`action`,O(r.action,200))}}case`slider`:{let e=A(r.min,-1e9,1e9)??0,t=A(r.max,-1e9,1e9)??100,n=Math.min(e,t),i=Math.max(e,t),a=A(r.step,1e-9,Math.max(i-n,1e-9)),o=A(r.value,n,i)??n;return{type:`slider`,min:n,max:i,...P(`step`,a),value:o,...P(`label`,O(r.label,D.maxString)),...P(`action`,O(r.action,200)),...P(`id`,O(r.id,200))}}case`textarea`:return{type:`textarea`,...P(`label`,O(r.label,D.maxString)),...P(`placeholder`,O(r.placeholder,D.maxString)),...P(`rows`,j(r.rows,1,30)),...P(`value`,O(r.value,D.maxString)),...P(`action`,O(r.action,200)),...P(`id`,O(r.id,200))};case`accordion`:{let e=Pe(r.items,t,n);return e===void 0?null:{type:`accordion`,items:e}}case`copy`:{let e=O(r.text,D.maxCode);return e===void 0?null:{type:`copy`,text:e,...P(`label`,O(r.label,128))}}case`mermaid`:{let e=O(r.code,D.maxMermaid);return e===void 0?null:{type:`mermaid`,code:e}}case`scene3d`:{let e=Fe(r.meshes);return e===void 0?null:{type:`scene3d`,meshes:e,...P(`title`,O(r.title,D.maxString)),...P(`ambient`,A(r.ambient,0,2)),...P(`background`,k(r.background))}}case`timeline`:{let e=Ie(r.items,D.maxTimelineItems);return e===void 0?null:{type:`timeline`,items:e}}case`file-tree`:{let e=Le(r.items,D.maxListItems);return e===void 0?null:{type:`file-tree`,items:e}}case`breadcrumb`:{let e=I(r.items,D.maxBreadcrumbItems,D.maxString);return e===void 0?null:{type:`breadcrumb`,items:e}}case`quiz`:{let e=O(r.question,D.maxString),t=ze(r.options);return e===void 0||t===void 0?null:{type:`quiz`,question:e,options:t,...P(`explanation`,O(r.explanation,D.maxString)),...P(`id`,O(r.id,200)),...P(`action`,O(r.action,200))}}case`echart`:{let e=r.data===void 0?void 0:De(r.data,D.maxChartPoints),t=r.series!==void 0&&Array.isArray(r.series)?Oe(r.series,D.maxPlotSeries,D.maxChartPoints):void 0,n=r.option===void 0?void 0:Ve(r.option,0,{count:D.maxEChartOptionNodes}),i=n===void 0||typeof n!=`object`||!n||Array.isArray(n)?void 0:n;return i===void 0&&e===void 0&&t===void 0?null:{type:`echart`,...P(`title`,O(r.title,D.maxString)),...P(`height`,j(r.height,100,800)),...P(`preset`,M(r.preset,Ce)),...P(`data`,e),...P(`series`,t),...P(`option`,i)}}default:return e}}function I(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;if(typeof i==`string`)r.push(i.slice(0,n));else if(typeof i==`object`&&i){let e=i,t=typeof e.label==`string`?e.label:typeof e.value==`string`?e.value:typeof e.title==`string`?e.title:JSON.stringify(i);r.push(t.slice(0,n))}}return r}function Te(e,t,n,r){if(!Array.isArray(e))return;let i=[];for(let a of e){if(i.length>=t)break;if(typeof a==`string`){i.push(a.slice(0,D.maxString));continue}let e=N(a),o=e===void 0?void 0:O(e.title,D.maxString);if(o!==void 0){i.push({title:o,...P(`desc`,e===void 0?void 0:O(e.desc,D.maxString))});continue}if(e!==void 0&&typeof e.type==`string`){if(n.remaining<=0)break;--n.remaining;let t=we(e,n,r);t!==null&&i.push(t)}}return i}function Ee(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;if(!Array.isArray(i))continue;let e=[];for(let t of i){if(e.length>=n)break;typeof t==`string`?e.push(t.slice(0,256)):typeof t==`number`&&Number.isFinite(t)&&e.push(t)}e.length>0&&r.push(e)}return r}function De(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=N(r),i=e===void 0?void 0:O(e.label,128),a=e===void 0?void 0:A(e.value,-0xe8d4a51000,0xe8d4a51000);i!==void 0&&a!==void 0&&n.push({label:i,value:a,...P(`color`,e===void 0?void 0:k(e.color))})}return n}function Oe(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;let e=N(i),a=e===void 0?void 0:O(e.label,128),o=e===void 0?void 0:De(e.data,n);a!==void 0&&o!==void 0&&r.push({label:a,data:o,...P(`color`,e===void 0?void 0:k(e.color))})}return r}function ke(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=D.maxTabs)break;let e=N(i),a=e===void 0?void 0:O(e.label,128);a!==void 0&&e!==void 0&&r.push({label:a,items:F(e.items,t,n+1)})}return r}function Ae(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=N(r),i=e===void 0?void 0:O(e.expr,512);if(i===void 0||e===void 0)continue;let a=[];if(Array.isArray(e.params))for(let t of e.params){if(a.length>=D.maxPlotParams)break;let e=N(t),n=e===void 0?void 0:O(e.name,64),r=e===void 0?void 0:A(e.value,-1e9,1e9);n!==void 0&&r!==void 0&&a.push({name:n,value:r,...P(`min`,e===void 0?void 0:A(e.min,-1e9,1e9)),...P(`max`,e===void 0?void 0:A(e.max,-1e9,1e9)),...P(`step`,e===void 0?void 0:A(e.step,1e-9,1e9)),...P(`animateTo`,e===void 0?void 0:A(e.animateTo,-1e9,1e9)),...P(`durationMs`,e===void 0?void 0:A(e.durationMs,1,12e4)),...P(`loop`,e===void 0?void 0:e.loop===!0||void 0)})}n.push({expr:i,...P(`label`,O(e.label,128)),...P(`color`,k(e.color)),...P(`kind`,M(e.kind,ye)),...P(`params`,a.length>0?a:void 0)})}return n}function je(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=D.maxSteps)break;let e=N(n),r=e===void 0?void 0:O(e.title,256);r!==void 0&&t.push({title:r,...P(`desc`,e===void 0?void 0:O(e.desc,D.maxString))})}return t}function Me(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=N(r),i=e===void 0?void 0:O(e.key,256),a=e===void 0?void 0:O(e.value,D.maxString);i!==void 0&&a!==void 0&&n.push({key:i,value:a})}return n}function Ne(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=24)break;let e=N(n),r=e===void 0?void 0:O(e.path,1024),i=e===void 0?void 0:O(e.newText,2e4);if(r===void 0||i===void 0)continue;let a=e===void 0?void 0:e.oldText;t.push({path:r,newText:i,oldText:a===null||typeof a!=`string`?null:a.slice(0,2e4)})}return t}function Pe(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=D.maxAccordionItems)break;let e=N(i),a=e===void 0?void 0:O(e.title,256);a!==void 0&&e!==void 0&&r.push({title:a,items:F(e.items,t,n+1)})}return r}function Fe(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=D.maxMeshes)break;let e=N(n),r=e===void 0?void 0:M(e.shape,xe);if(r===void 0)continue;let i=e===void 0?void 0:A(e.scale,-1e6,1e6)??L(e.scale),a=e===void 0?void 0:A(e.size,-1e6,1e6)??L(e.size);t.push({shape:r,...P(`color`,e===void 0?void 0:k(e.color)),...P(`position`,e===void 0?void 0:L(e.position)),...P(`rotation`,e===void 0?void 0:L(e.rotation)),...P(`scale`,i),...P(`size`,a)})}return t}function L(e){if(!Array.isArray(e)||e.length!==3)return;let[t,n,r]=e;if(!(typeof t!=`number`||!Number.isFinite(t)||typeof n!=`number`||!Number.isFinite(n)||typeof r!=`number`||!Number.isFinite(r)))return[Math.min(1e6,Math.max(-1e6,t)),Math.min(1e6,Math.max(-1e6,n)),Math.min(1e6,Math.max(-1e6,r))]}function Ie(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=N(r),i=e===void 0?void 0:O(e.title,256);i!==void 0&&n.push({title:i,...P(`desc`,e===void 0?void 0:O(e.desc,D.maxString)),...P(`time`,e===void 0?void 0:O(e.time,128))})}return n}function Le(e,t){return Re(e,t,D.maxTreeDepth)}function Re(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;let e=N(i),a=e===void 0?void 0:O(e.name,256);if(a===void 0)continue;let o=e!==void 0&&n>0&&Array.isArray(e.children)?Re(e.children,t,n-1):void 0;r.push({name:a,...P(`type`,e===void 0?void 0:M(e.type,Se)),...P(`children`,o)})}return r}function ze(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=D.maxQuizOptions)break;let e=N(n),r=e===void 0?void 0:O(e.label,512);r!==void 0&&t.push({label:r,...P(`correct`,e===void 0?void 0:e.correct===!0||void 0),...P(`feedback`,e===void 0?void 0:O(e.feedback,D.maxString))})}return t}let Be=/<(?:script|img|svg|iframe|video|audio|object|embed|source)\b|on[a-z]+\s*=|javascript:/i;function Ve(e,t,n){if(n.count<=0||(--n.count,t>D.maxEChartOptionDepth))return;if(typeof e==`string`){let t=e.slice(0,D.maxString);return t.toLowerCase().includes(`url(`)||Be.test(t)?void 0:t}if(typeof e==`number`&&Number.isFinite(e)||typeof e==`boolean`)return e;if(e===null)return null;if(Array.isArray(e)){let r=Math.min(e.length,D.maxEChartArrayLen),i=[];for(let a=0;a<r;a++){let r=Ve(e[a],t+1,n);r!==void 0&&i.push(r)}return i.length>0?i:void 0}let r=N(e);if(r===void 0)return;let i={};for(let[e,a]of Object.entries(r)){let r=Ve(a,t+1,n);r!==void 0&&(e===`tooltip`&&typeof r==`object`&&r&&!Array.isArray(r)&&(r.renderMode=`richText`),i[e]=r)}return Object.keys(i).length>0?i:void 0}function R(e){let t=N(e);if(t===void 0)return null;if(!Array.isArray(t.items)){let t=E(e);return t===null?null:R(t)}let n={remaining:D.maxNodes};return{...P(`title`,O(t.title,D.maxString)),...P(`gap`,A(t.gap,0,96)),...P(`panel`,t.panel===!0||void 0),...P(`append`,t.append===!0||void 0),items:F(t.items,n,0)}}function He(e,t=1/0){let n=0,r=e=>{if(Array.isArray(e))for(let i of e){if(n>=t)return;n+=1;let e=N(i);if(e!==void 0){if(e.type===`tabs`&&Array.isArray(e.tabs))for(let i of e.tabs){if(n>=t)return;let e=N(i);e!==void 0&&r(e.items)}else if(e.type===`accordion`&&Array.isArray(e.items))for(let i of e.items){if(n>=t)return;let e=N(i);e!==void 0&&r(e.items)}else if(e.type===`file-tree`&&Array.isArray(e.items))r(e.items);else if(e.type===`list`&&Array.isArray(e.items))for(let i of e.items){if(n>=t)return;let e=N(i);e!==void 0&&typeof e.type==`string`&&r([e])}}}},i=N(e);return r(i===void 0?[]:i.items),n}let Ue=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-deepseek-300)`,`var(--dsw-static-neutral-bluish-400)`];function We(e){let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)>>>0;return Ue[t%Ue.length]}function Ge({className:e,disabled:t,onClick:n,children:r}){let[i,a]=(0,m.useState)(!1),o=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{o.current!==null&&clearTimeout(o.current)},[]),(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)(`button`,{type:`button`,className:e,disabled:t,onClick:n===void 0?void 0:()=>{n(),o.current!==null&&clearTimeout(o.current),a(!0),o.current=setTimeout(()=>a(!1),1400)},children:[r,i&&(0,h.jsx)(`span`,{className:S.btnSent,"aria-hidden":!0,children:`✓ 已触发`})]}),(0,h.jsx)(`span`,{className:S.visuallyHidden,role:`status`,children:i?`已触发`:``})]})}let Ke=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,h.jsxs)(`figure`,{className:S.media,children:[e.alt!==void 0&&(0,h.jsx)(`figcaption`,{className:S.mediaLabel,children:e.alt}),t?(0,h.jsx)(`div`,{className:S.mediaError,role:`alert`,children:`音频无法播放`}):(0,h.jsx)(`audio`,{className:S.mediaPlayer,src:e.src,"aria-label":e.alt??`音频`,controls:!0,preload:`metadata`,loop:e.loop===!0,onError:()=>n(!0)})]})}),qe=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,h.jsxs)(`figure`,{className:S.media,children:[e.alt!==void 0&&(0,h.jsx)(`figcaption`,{className:S.mediaLabel,children:e.alt}),t?(0,h.jsx)(`div`,{className:S.mediaError,role:`alert`,children:`视频无法播放`}):(0,h.jsx)(`video`,{className:`${S.mediaPlayer} ${S.videoPlayer}`,src:e.src,poster:e.poster,"aria-label":e.alt??`视频`,controls:!0,preload:`metadata`,playsInline:!0,loop:e.loop===!0,muted:e.muted===!0,style:e.aspectRatio===void 0?void 0:{aspectRatio:e.aspectRatio.replace(`:`,` / `)},onError:()=>n(!0)})]})}),Je=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-neutral-bluish-400)`,`var(--dsw-static-deepseek-300)`],Ye=(e,t,n)=>n??(t>1?Je[e%Je.length]:void 0);function Xe(e){if(typeof e==`number`)return Number.isFinite(e)?e:NaN;if(typeof e!=`string`)return NaN;let t=e.trim();if(t===``)return NaN;t=t.replace(/^[¥$€£]/,``),t.endsWith(`%`)&&(t=t.slice(0,-1));let n=1;if(t.endsWith(`万`))n=1e4,t=t.slice(0,-1);else if(t.endsWith(`亿`))n=1e8,t=t.slice(0,-1);else if(/[kmb]$/i.test(t)){let e=t.slice(-1).toLowerCase();n=e===`k`?1e3:e===`m`?1e6:1e9,t=t.slice(0,-1)}t=t.replace(/[,,\s]/g,``);let r=Number(t);return Number.isFinite(r)?r*n:NaN}function Ze(e,t){return Array.from({length:t},(t,n)=>{let r=!1;for(let t of e){let e=t[n];if(e!=null&&e!==``){if(!Number.isFinite(Xe(e)))return!1;r=!0}}return r})}let Qe=(0,m.memo)(function({node:e}){let t=e.columns.slice(0,D.maxTableCols),n=e.rows.slice(0,D.maxTableRows),[r,i]=(0,m.useState)(null),a=r===null?n:[...n].sort((e,t)=>{let n=Xe(e[r.col]),i=Xe(t[r.col]);if(Number.isFinite(n)&&Number.isFinite(i)&&n!==i)return(n-i)*r.dir;if(Number.isFinite(n)!==Number.isFinite(i))return Number.isFinite(n)?-r.dir:r.dir;let a=String(e[r.col]??``),o=String(t[r.col]??``);return(a<o?-1:+(a>o))*r.dir}),o=e=>{i(t=>t!==null&&t.col===e?t.dir===1?{col:e,dir:-1}:null:{col:e,dir:1})},s=Ze(n,t.length);return(0,h.jsx)(`div`,{className:S.tableWrap,children:(0,h.jsxs)(`table`,{className:S.table,children:[(0,h.jsx)(`thead`,{children:(0,h.jsx)(`tr`,{children:t.map((e,t)=>(0,h.jsx)(`th`,{className:s[t]?S.thNum:void 0,"aria-sort":r!==null&&r.col===t?r.dir===1?`ascending`:`descending`:`none`,children:(0,h.jsxs)(`button`,{type:`button`,className:S.thSort,onClick:()=>o(t),children:[e,r!==null&&r.col===t&&(0,h.jsx)(`span`,{className:S.thSortMark,"aria-hidden":!0,children:r.dir===1?` ▲`:` ▼`})]})},t))})}),(0,h.jsx)(`tbody`,{children:a.map((e,n)=>(0,h.jsx)(`tr`,{children:e.slice(0,t.length).map((e,t)=>(0,h.jsx)(`td`,{className:s[t]?S.tdNum:void 0,children:String(e)},t))},n))})]})})}),$e=(0,m.memo)(function({chart:e}){let t=e.kind??`bars`;return t===`donut`?(0,h.jsx)(nt,{chart:e}):t===`line`?(0,h.jsx)(tt,{chart:e}):(0,h.jsx)(et,{chart:e})}),et=(0,m.memo)(function({chart:e}){let t=e.series===void 0?void 0:e.series.slice(0,D.maxPlotSeries);if(t!==void 0&&t.length>0){let e=t[0].data.map(e=>e.label),n=Math.max(...t.flatMap(e=>e.data.map(e=>Number(e.value)||0)),1);return(0,h.jsxs)(`div`,{className:S.chart,children:[(0,h.jsxs)(`div`,{className:S.chartPlot,children:[[0,25,50,75].map(e=>(0,h.jsx)(`span`,{className:e===0?S.baseline:S.gridline,style:{bottom:`${e}%`}},e)),e.map((e,r)=>(0,h.jsx)(`div`,{className:S.barCol,children:(0,h.jsx)(`div`,{className:S.groupedBars,children:t.map((e,i)=>{let a=e.data[r],o=a===void 0?0:Number(a.value)||0,s=a===void 0?0:Math.min(Math.round(Math.max(0,o)/n*100),82);return(0,h.jsxs)(`div`,{className:S.groupedBar,title:a===void 0?e.label:`${e.label}: ${String(a.value)}`,children:[(0,h.jsx)(`span`,{className:S.groupValue,children:a===void 0?``:String(a.value)}),(0,h.jsx)(`div`,{className:S.groupedFill,style:{height:`${s}%`,background:Ye(i,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}})]},i)})})},r))]}),(0,h.jsx)(`div`,{className:S.chartLabels,children:e.map(e=>(0,h.jsx)(`span`,{className:S.barLabel,children:e},e))})]})}let n=e.data.slice(0,D.maxChartPoints),r=Math.max(...n.map(e=>Number(e.value)||0),1);return(0,h.jsxs)(`div`,{className:S.chart,children:[(0,h.jsxs)(`div`,{className:S.chartPlot,children:[[0,25,50,75].map(e=>(0,h.jsx)(`span`,{className:e===0?S.baseline:S.gridline,style:{bottom:`${e}%`}},e)),n.map((e,t)=>{let n=Number(e.value)||0,i=Math.min(Math.round(Math.max(0,n)/r*100),85);return(0,h.jsxs)(`div`,{className:S.barCol,title:`${e.label}: ${String(e.value)}`,children:[(0,h.jsx)(`span`,{className:S.barValue,children:String(e.value)}),(0,h.jsx)(`div`,{className:S.barFill,style:{height:`${i}%`,...e.color===void 0?{}:{background:e.color}}})]},t)})]}),(0,h.jsx)(`div`,{className:S.chartLabels,children:n.map(e=>(0,h.jsx)(`span`,{className:S.barLabel,children:e.label},e.label))})]})}),tt=(0,m.memo)(function({chart:e}){let t=e.data.slice(0,D.maxChartPoints),n=Math.max(...t.map(e=>Number(e.value)||0),1),r=Math.min(...t.map(e=>Number(e.value)||0),0),i=n-r||1,a=Math.max(t.length-1,1),o=(e,t)=>[36+e/a*416,10+(1-(t-r)/i)*134],s=t.map((e,t)=>o(t,Number(e.value)||0)).map((e,t)=>`${t===0?`M`:`L`} ${e[0].toFixed(1)} ${e[1].toFixed(1)}`).join(` `),c=[0,1,2,3].map(e=>r+i*e/3),l=e=>{let t=Math.abs(e);return t>=1e3?`${(e/1e3).toFixed(t%1e3==0?0:1)}k`:Number.isInteger(e)?String(e):e.toFixed(1)};return(0,h.jsxs)(`div`,{className:S.lineChart,children:[(0,h.jsxs)(`svg`,{width:`100%`,viewBox:`0 0 460 150`,children:[c.map((e,t)=>{let n=10+(1-(e-r)/i)*134;return(0,h.jsxs)(`g`,{children:[(0,h.jsx)(`line`,{x1:36,x2:452,y1:n,y2:n,className:t===0?S.lineGridAxis:S.lineGrid}),(0,h.jsx)(`text`,{x:30,y:n+3,textAnchor:`end`,className:S.lineTick,children:l(e)})]},t)}),t.map((e,t)=>{let[n,r]=o(t,Number(e.value)||0);return(0,h.jsx)(`circle`,{cx:n,cy:r,r:3,className:S.lineDot,fill:e.color??void 0,children:(0,h.jsx)(`title`,{children:`${e.label}: ${String(e.value)}`})},t)}),(0,h.jsx)(`path`,{d:s,className:S.linePath})]}),(0,h.jsx)(`div`,{className:S.lineLabels,children:t.map((e,t)=>(0,h.jsx)(`span`,{className:S.barLabel,children:e.label},t))})]})}),nt=(0,m.memo)(function({chart:e}){let t=e.data.slice(0,D.maxChartPoints),n=t.map(e=>({...e,v:Math.max(0,Number(e.value)||0)})),r=n.reduce((e,t)=>e+t.v,0)||1,i=r>=1e3?`${Math.round(r/100)/10}k`:Number.isInteger(r)?String(r):r.toFixed(1),a=2*Math.PI*42,o=0;return(0,h.jsxs)(`div`,{className:S.donut,children:[(0,h.jsxs)(`svg`,{width:`120`,height:`120`,viewBox:`0 0 120 120`,children:[(0,h.jsx)(`circle`,{cx:`60`,cy:`60`,r:42,fill:`none`,strokeWidth:`14`,className:S.donutTrack}),n.map((e,n)=>{let i=e.v/r*a,s=(0,h.jsx)(`circle`,{cx:`60`,cy:`60`,r:42,fill:`none`,strokeWidth:`14`,className:S.donutSeg,style:{stroke:Ye(n,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`},strokeDasharray:`${i} ${a-i}`,strokeDashoffset:-o,transform:`rotate(-90 60 60)`,children:(0,h.jsx)(`title`,{children:`${e.label}: ${String(e.value)}`})},n);return o+=i,s}),(0,h.jsx)(`text`,{x:`60`,y:`58`,textAnchor:`middle`,className:S.donutTotal,children:i}),(0,h.jsx)(`text`,{x:`60`,y:`74`,textAnchor:`middle`,className:S.donutTotalLabel,children:`合计`})]}),(0,h.jsx)(`div`,{className:S.donutLegend,children:t.map((e,n)=>(0,h.jsxs)(`span`,{className:S.legendItem,children:[(0,h.jsx)(`span`,{className:S.legendSwatch,style:{background:Ye(n,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}}),e.label,` · `,String(e.value)]},n))})]})});function rt({node:e,onAction:t,answers:n}){let r=e.action,i=e.group,a=i!==void 0,o=e.options.slice(0,D.maxOptions),s=i!==void 0&&n?.answers[i]!==void 0?o.indexOf(n.answers[i]):-1,[c,l]=(0,m.useState)(s>=0?s:e.selected??null),u=(0,m.useId)(),d=a&&n?.locked===!0;return(0,m.useEffect)(()=>{i!==void 0&&(n?.registerMeta(i,{label:e.label??i,options:o,answer:e.answer,explanation:e.explanation}),e.selected!==void 0&&o[e.selected]!==void 0&&n?.answers[i]===void 0&&n?.setAnswer(i,o[e.selected]))},[i,e.label,e.answer,e.explanation,e.options,e.selected]),(0,h.jsxs)(`div`,{className:S.fieldGroup,role:`radiogroup`,"aria-label":e.label,children:[e.label!==void 0&&(0,h.jsx)(`span`,{className:S.fieldLabel,children:e.label}),o.map((e,o)=>(0,h.jsxs)(`label`,{className:S.radio,children:[(0,h.jsx)(`input`,{type:`radio`,name:`genui-radio-${u}`,checked:c===o,disabled:d,onChange:()=>{l(o),a?n?.setAnswer(i,e):r!==void 0&&t!==void 0&&t(r,{type:`radio`,value:e})}}),(0,h.jsx)(`span`,{children:e})]},o))]})}function it(e){if(e.answer!==void 0)return typeof e.answer==`number`?e.options[e.answer]:e.answer}function at({node:e,onAction:t,answers:n}){let r=n?.answers??{},i=n?.fields??{},a=n?.meta??{},o=e.groups,s=Object.fromEntries(Object.entries(i).filter(([e,t])=>t.trim()!==``&&!n?.secretFields.has(e))),c=o===void 0?Math.max(Object.keys(r).length,Object.keys(s).length):o.filter(e=>r[e]!==void 0).length,l=o?.length??c,u=o??Object.keys(r),d=u.some(e=>a[e]?.answer!==void 0),f=n?.locked===!0,p=c>0&&c>=l&&(d||e.action!==void 0&&t!==void 0);if(f){let i=u.filter(e=>r[e]!==void 0&&a[e]?.answer!==void 0),s=i.filter(e=>r[e]===it(a[e])).length;return(0,h.jsxs)(`div`,{className:S.gradeWrap,"data-genui-grade":!0,children:[(0,h.jsxs)(`div`,{className:S.gradeScore,children:[(0,h.jsxs)(`span`,{className:S.gradeScoreValue,children:[s,` / `,i.length]}),(0,h.jsxs)(`span`,{className:S.gradeScoreLabel,children:[`得分`,i.length<u.length?`(${u.length-i.length} 题无答案未计分)`:``]})]}),(0,h.jsx)(`div`,{className:S.gradeList,children:u.map(e=>{let t=r[e],n=a[e];if(t===void 0||n===void 0)return null;let i=it(n);if(i===void 0)return(0,h.jsxs)(`div`,{className:S.gradeItem,children:[(0,h.jsx)(`span`,{className:S.gradeQ,children:n.label}),(0,h.jsxs)(`span`,{className:S.gradeAns,children:[`你的答案:`,t]})]},e);let o=t===i;return(0,h.jsxs)(`div`,{className:`${S.gradeItem} ${o?S.gradeItemOk:S.gradeItemNo}`,children:[(0,h.jsx)(`span`,{className:S.gradeQ,children:n.label}),(0,h.jsx)(`span`,{className:S.gradeTag,children:o?`✓`:`✗`}),(0,h.jsxs)(`span`,{className:S.gradeAns,children:[`你的答案:`,t,!o&&(0,h.jsxs)(`span`,{className:S.gradeRight,children:[` 正确答案:`,i]})]}),n.explanation!==void 0&&(0,h.jsx)(`span`,{className:S.gradeExp,children:n.explanation})]},e)})}),(0,h.jsx)(`button`,{type:`button`,className:`${S.button} ${S.ghost} ${S.submit}`,onClick:()=>{n?.clear(),e.resetAction!==void 0&&t!==void 0&&t(e.resetAction,{type:`submit-reset`,groups:o??Object.keys(r)})},children:`重新作答`})]})}return(0,h.jsxs)(`div`,{className:S.submitRow,children:[(0,h.jsx)(`button`,{type:`button`,className:`${S.button} ${S.primary} ${S.submit}`,disabled:!p,onClick:p?()=>{d?n?.setLocked(!0):e.action!==void 0&&t!==void 0&&t(e.action,{type:`submit`,answers:r,...Object.keys(s).length>0?{fields:s}:{},total:l,answered:c})}:void 0,children:e.label}),l>0&&(0,h.jsxs)(`span`,{className:S.submitHint,"aria-live":`polite`,children:[`已选 `,c,`/`,l]})]})}function ot({node:e,onAction:t}){let[n,r]=(0,m.useState)(e.checked===!0),i=e.action;return(0,h.jsxs)(`label`,{className:S.switchRow,children:[(0,h.jsx)(`span`,{className:S.switchLabel,children:e.label}),(0,h.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":n,className:`${S.switch} ${n?S.switchOn:``}`,onClick:()=>{let e=!n;r(e),i!==void 0&&t!==void 0&&t(i,{type:`switch`,checked:e})},children:(0,h.jsx)(`span`,{className:S.switchKnob})})]})}function st({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=i!==void 0&&n?.fields[i]!==void 0?Number(n.fields[i]):NaN,o=Number.isFinite(a)?a:e.value??e.min??0,[s,c]=(0,m.useState)(o),l=(0,m.useRef)(!1);(0,m.useEffect)(()=>{l.current||(l.current=!0,i!==void 0&&n?.setField(i,String(o)))},[]);let u=e=>{r!==void 0&&t!==void 0&&t(r,{type:`slider`,value:e,...i===void 0?{}:{id:i}})};return(0,h.jsxs)(`label`,{className:S.sliderRow,children:[e.label!==void 0&&(0,h.jsx)(`span`,{className:S.fieldLabel,children:e.label}),(0,h.jsx)(`input`,{type:`range`,className:S.sliderInput,min:e.min,max:e.max,step:e.step??1,value:s,"aria-label":e.label,onChange:e=>{let t=Number(e.currentTarget.value);c(t),i!==void 0&&n?.setField(i,String(t)),u(t)}}),(0,h.jsx)(`span`,{className:S.sliderValue,children:Math.round(s*100)/100})]})}function ct(){let e=(0,m.useRef)(!1),t=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{t.current!==null&&clearTimeout(t.current)},[]),{isComposing:()=>e.current,onCompositionStart:()=>{e.current=!0,t.current!==null&&(clearTimeout(t.current),t.current=null)},onCompositionEnd:()=>{t.current!==null&&clearTimeout(t.current),t.current=setTimeout(()=>{e.current=!1},10)}}}function lt(e){let t=e.nativeEvent;return t.isComposing===!0||t.keyCode===229}function ut({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=e.options.slice(0,D.maxOptions),o=i!==void 0&&n?.fields[i]!==void 0?a.indexOf(n.fields[i]):-1,s=o>=0?a[o]:e.selected!==void 0&&a[e.selected]!==void 0?a[e.selected]:null,[c,l]=(0,m.useState)(s),u=(0,m.useRef)(!1);(0,m.useEffect)(()=>{u.current||(u.current=!0,i!==void 0&&s!==null&&n?.setField(i,s))},[]);let d=e=>{r!==void 0&&t!==void 0&&t(r,{type:`select`,value:e,...i===void 0?{}:{id:i}})};return(0,h.jsxs)(`label`,{className:S.field,children:[e.label!==void 0&&(0,h.jsx)(`span`,{children:e.label}),(0,h.jsxs)(`select`,{className:S.select,value:c??``,onChange:e=>{let t=e.currentTarget.value;l(t),i!==void 0&&n?.setField(i,t),d(t)},children:[c===null&&(0,h.jsx)(`option`,{value:``,hidden:!0,disabled:!0,children:`请选择…`}),a.map((e,t)=>(0,h.jsx)(`option`,{value:e,children:e},t))]})]})}function dt({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=e.inputType===`password`,[o,s]=(0,m.useState)(()=>a?``:e.value??(i===void 0?``:n?.fields[i]??``)),c=(0,m.useRef)(o),l=e=>{r!==void 0&&t!==void 0&&(c.current=o,t(r,{type:`input`,value:o,...i===void 0?{}:{id:i},...e?{submit:!0}:{}}))},u=ct(),d=(0,m.useRef)(!1);return(0,m.useEffect)(()=>{d.current||(d.current=!0,!a&&i!==void 0&&e.value!==void 0&&e.value.trim()!==``&&n?.setField(i,e.value))},[]),(0,m.useEffect)(()=>{a&&i!==void 0&&n?.registerSecretField(i)},[a,i]),(0,h.jsxs)(`label`,{className:S.field,children:[e.label!==void 0&&(0,h.jsx)(`span`,{children:e.label}),(0,h.jsx)(`input`,{className:S.input,type:e.inputType??`text`,placeholder:e.placeholder,value:o,onChange:e=>{let t=e.currentTarget.value;s(t),i!==void 0&&n?.setField(i,t)},onBlur:()=>{o!==c.current&&l(!1)},onCompositionStart:u.onCompositionStart,onCompositionEnd:u.onCompositionEnd,onKeyDown:e=>{e.key===`Enter`&&(u.isComposing()||lt(e)||(e.preventDefault(),l(!0)))}})]})}function ft({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,[a,o]=(0,m.useState)(()=>e.value??(i===void 0?``:n?.fields[i]??``)),s=(0,m.useRef)(a),c=e=>{r!==void 0&&t!==void 0&&(s.current=a,t(r,{type:`textarea`,value:a,...i===void 0?{}:{id:i},...e?{submit:!0}:{}}))},l=ct(),u=(0,m.useRef)(!1);return(0,m.useEffect)(()=>{u.current||(u.current=!0,i!==void 0&&e.value!==void 0&&e.value.trim()!==``&&n?.setField(i,e.value))},[]),(0,h.jsxs)(`label`,{className:S.field,children:[e.label!==void 0&&(0,h.jsx)(`span`,{children:e.label}),(0,h.jsx)(`textarea`,{className:S.textarea,placeholder:e.placeholder,rows:e.rows??4,value:a,onChange:e=>{let t=e.currentTarget.value;o(t),i!==void 0&&n?.setField(i,t)},onBlur:()=>{a!==s.current&&c(!1)},onCompositionStart:l.onCompositionStart,onCompositionEnd:l.onCompositionEnd,onKeyDown:e=>{!(e.metaKey||e.ctrlKey)||e.key!==`Enter`||l.isComposing()||lt(e)||(e.preventDefault(),c(!0))}})]})}let pt={pi:Math.PI,e:Math.E,tau:Math.PI*2},mt={sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,sqrt:Math.sqrt,cbrt:Math.cbrt,exp:Math.exp,log:Math.log10,ln:Math.log,abs:Math.abs,floor:Math.floor,ceil:Math.ceil,round:Math.round,min:Math.min,max:Math.max,pow:(e,t)=>e**+t};var z=class extends Error{pos;constructor(e,t){super(`SafeMath parse error at ${t}: ${e}`),this.pos=t}},ht=class{src;vars;i=0;constructor(e,t){this.src=e,this.vars=t}parse(){let e=this.parseExpr();if(this.skipWs(),this.i<this.src.length)throw new z(`unexpected trailing input`,this.i);return this.evalNode(e)}evalNode(e){return typeof e==`number`?()=>e:e}parseExpr(){let e=this.parseTerm();for(;;){this.skipWs();let t=this.peek();if(t===`+`||t===`-`){this.i++;let n=this.parseTerm(),r=t,i=e;e=r===`+`?e=>this.asNum(i,e)+this.asNum(n,e):e=>this.asNum(i,e)-this.asNum(n,e)}else return e}}parseTerm(){let e=this.parseUnary();for(;;){this.skipWs();let t=this.peek();if(t===`*`||t===`/`||t===`%`){this.i++;let n=this.parseUnary(),r=t,i=e;e=r===`*`?e=>this.asNum(i,e)*this.asNum(n,e):r===`/`?e=>this.asNum(i,e)/this.asNum(n,e):e=>this.asNum(i,e)%this.asNum(n,e)}else return e}}parseUnary(){this.skipWs();let e=this.char();if(e===`-`||e===`+`){this.i++;let t=this.parseUnary();return e===`-`?e=>-this.asNum(t,e):e=>this.asNum(t,e)}return this.parsePower()}parsePower(){let e=this.parseAtom();if(this.skipWs(),this.peek()===`^`){this.i++;let t=this.parsePower(),n=e;return e=>this.asNum(n,e)**+this.asNum(t,e)}return e}parseAtom(){this.skipWs();let e=this.char();if(e===`(`){this.i++;let e=this.parseExpr();if(this.skipWs(),this.peek()!==`)`)throw new z(`expected )`,this.i);return this.i++,e}if(e>=`0`&&e<=`9`||e===`.`)return this.parseNumber();if(this.isIdentStart(e))return this.parseIdent();throw new z(`unexpected character '${e}'`,this.i)}parseNumber(){let e=this.i;for(;this.i<this.src.length&&/[0-9.eE+\-]/.test(this.src[this.i]);)this.i++;let t=this.src.slice(e,this.i),n=Number(t);if(Number.isNaN(n))throw new z(`invalid number '${t}'`,e);return n}parseIdent(){let e=this.i;for(;this.i<this.src.length&&this.isIdentChar(this.src[this.i]);)this.i++;let t=this.src.slice(e,this.i);if(this.skipWs(),this.peek()===`(`){let n=mt[t];if(n===void 0)throw new z(`unknown function '${t}'`,e);this.i++;let r=[];if(this.skipWs(),this.peek()===`)`)this.i++;else for(;;){r.push(this.parseExpr()),this.skipWs();let e=this.peek();if(e===`,`){this.i++;continue}if(e===`)`){this.i++;break}throw new z(`expected , or ) in call`,this.i)}return e=>n(...r.map(t=>this.asNum(t,e)))}if(Object.hasOwn(pt,t))return pt[t];if(t===`x`)return e=>e;if(Object.hasOwn(this.vars,t)){let e=this.vars[t];return()=>e}if(/^[a-z]$/.test(t))return()=>1;throw new z(`unknown identifier '${t}'`,e)}asNum(e,t){return typeof e==`number`?e:e(t)}skipWs(){for(;this.i<this.src.length&&/\s/.test(this.src[this.i]);)this.i++}peek(){return this.src[this.i]}char(){let e=this.peek();if(e===void 0)throw new z(`unexpected end of input`,this.i);return e}isIdentStart(e){return e!==void 0&&/[a-zA-Z_]/.test(e)}isIdentChar(e){return/[a-zA-Z0-9_]/.test(e)}};function gt(e,t={}){try{let n={...t.vars};return delete n.x,new ht(e,n).parse()}catch{return null}}function _t(e,t,n,r=200,i={}){let a=gt(e,{vars:i});if(a===null||!Number.isFinite(t)||!Number.isFinite(n)||n<=t||r<2)return[];let o=[],s=(n-t)/(r-1);for(let e=0;e<r;e++){let n=t+s*e,r=a(n);Number.isFinite(r)&&o.push([n,r])}return o}let vt=`@omdsh-dev/dsh-genui/PlotBlock.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(vt)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@omdsh-dev/dsh-genui`,e.dataset.pluginCss=vt,e.textContent=`._ctrqa_block{--dsl-g-radius-surface:12px;--dsl-g-radius-control:8px;--dsl-g-font-title:13px;--dsl-g-font-meta:12px;--dsl-g-font-data:11px;--dsl-g-gap-md:12px;--dsl-g-gap-sm:8px;--dsl-g-gap-xs:4px;--dsl-g-border:var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,#ffffff1f));--dsl-g-accent:var(--dsw-alias-state-business-primary,#4f8ef7);--dsl-g-accent-soft:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);--dsl-g-tint:8%;--dsl-g-tint-strong:14%;--dsl-g-font-mono:var(--ds-font-family-code,ui-monospace, "SF Mono", monospace);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);gap:var(--dsl-g-gap-sm);flex-direction:column;padding:14px 16px;display:flex}._ctrqa_title{font-size:var(--dsl-g-font-title);letter-spacing:.01em;color:var(--dsw-alias-label-primary);font-weight:600}._ctrqa_gridLine{stroke:var(--dsw-alias-border-l1,#ffffff12);stroke-width:1px}._ctrqa_axis{stroke:var(--dsw-alias-label-tertiary);stroke-width:1px}._ctrqa_tick{fill:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-data);font-family:var(--dsl-g-font-mono)}._ctrqa_line{fill:none;stroke:var(--dsl-g-accent);stroke-width:2px;stroke-linejoin:round;stroke-linecap:round}._ctrqa_area{stroke:none;fill-opacity:.16}._ctrqa_scatterDot{stroke:var(--dsw-alias-bg-base,#17171a);stroke-width:1px}._ctrqa_legend{gap:var(--dsl-g-gap-md);flex-wrap:wrap;display:flex}._ctrqa_legendItem{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);display:inline-flex}._ctrqa_legendSwatch{background:var(--dsl-g-accent);border-radius:2px;width:10px;height:3px}._ctrqa_empty{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-title);gap:var(--dsl-g-gap-xs);flex-direction:column;padding:14px 0;display:flex}._ctrqa_emptyRow{font-family:var(--dsl-g-font-mono)}._ctrqa_surface{cursor:grab;touch-action:none}._ctrqa_surface:active{cursor:grabbing}._ctrqa_sliders{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}._ctrqa_sliderRow{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-meta);display:flex}._ctrqa_sliderName{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;min-width:90px;overflow:hidden}._ctrqa_slider{accent-color:var(--dsl-g-accent);cursor:pointer;flex:1;height:4px}._ctrqa_sliderValue{color:var(--dsw-alias-label-primary);font-family:var(--dsl-g-font-mono);text-align:right;min-width:34px}._ctrqa_animBar{align-items:center;gap:var(--dsl-g-gap-md);display:flex}._ctrqa_playBtn{background:var(--dsl-g-accent-soft);border:1px solid color-mix(in srgb, var(--dsl-g-accent) 30%, transparent);width:fit-content;color:var(--dsl-g-accent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;padding:6px 14px;font-family:inherit;font-weight:600}._ctrqa_playBtn:hover{filter:brightness(1.1)}._ctrqa_animTrack{background:var(--dsw-alias-bg-layer-1);height:5px;box-shadow:inset 0 0 0 1px var(--dsl-g-border);border-radius:999px;flex:1;overflow:hidden}._ctrqa_animFill{background:var(--dsl-g-accent);border-radius:999px;height:100%}._ctrqa_resetBtn{border:1px solid var(--dsl-g-border);width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;padding:6px 14px;font-family:inherit}._ctrqa_resetBtn:hover{border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}._ctrqa_slidersHead{justify-content:space-between;align-items:center;display:flex}._ctrqa_slidersTitle{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}`,document.head.appendChild(e)}var B={animBar:`_ctrqa_animBar`,animFill:`_ctrqa_animFill`,animTrack:`_ctrqa_animTrack`,area:`_ctrqa_area`,axis:`_ctrqa_axis`,block:`_ctrqa_block`,empty:`_ctrqa_empty`,emptyRow:`_ctrqa_emptyRow`,gridLine:`_ctrqa_gridLine`,legend:`_ctrqa_legend`,legendItem:`_ctrqa_legendItem`,legendSwatch:`_ctrqa_legendSwatch`,line:`_ctrqa_line`,playBtn:`_ctrqa_playBtn`,resetBtn:`_ctrqa_resetBtn`,scatterDot:`_ctrqa_scatterDot`,slider:`_ctrqa_slider`,sliderName:`_ctrqa_sliderName`,sliderRow:`_ctrqa_sliderRow`,sliderValue:`_ctrqa_sliderValue`,sliders:`_ctrqa_sliders`,slidersHead:`_ctrqa_slidersHead`,slidersTitle:`_ctrqa_slidersTitle`,surface:`_ctrqa_surface`,tick:`_ctrqa_tick`,title:`_ctrqa_title`};let yt=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-neutral-bluish-400)`,`var(--dsw-static-deepseek-300)`],bt=(e,t,n)=>n??(t>1?yt[e%yt.length]:void 0);function xt(e){let t=1/0,n=-1/0;for(let[,r]of e)r<t&&(t=r),r>n&&(n=r);if(!Number.isFinite(t)||!Number.isFinite(n))return[-1,1];t===n&&(--t,n+=1);let r=(n-t)*.08;return[t-r,n+r]}function St(e,t,n=5){let r=t-e;if(!Number.isFinite(r)||r<=0)return[];let i=10**Math.floor(Math.log10(r/n)),a=r/n/i,o=i*(a>=7.5?10:a>=3.5?5:a>=1.5?2:1),s=[];for(let n=Math.ceil(e/o)*o;n<=t+o*1e-9;n+=o)s.push(Math.round(n*1e9)/1e9);return s}function Ct(e){return Math.abs(e)>=1e5||Math.abs(e)<.001&&e!==0?e.toExponential(1):String(Math.round(e*100)/100)}function wt({points:e,className:t,color:n}){let r=e.length>40?`${e.slice(0,16)}|${e.slice(-16)}`:e;return(0,h.jsx)(`polyline`,{points:e,className:t,style:n===void 0?void 0:{stroke:n}},r)}let Tt=(0,m.memo)(function({series:e,xMin:t=-5,xMax:n=5,yMin:r,yMax:i,title:a}){let[o,s]=(0,m.useState)(()=>{let a={};for(let[t,n]of e.entries())for(let e of n.params??[])e!=null&&(a[`${t}:${e.name}`]=e.value);let[o,s]=xt(e.map((e,r)=>{let i={};for(let t of e.params??[])t!=null&&(i[t.name]=a[`${r}:${t.name}`]??t.value);return _t(e.expr,t,n,240,i)}).flatMap(e=>e));return{xMin:t,xMax:n,yMin:r??o,yMax:i??s}}),c=(0,m.useRef)(null),[l,u]=(0,m.useState)(()=>({})),d=(()=>{for(let[t,n]of e.entries())for(let e of n.params??[])if(e!=null&&e.animateTo!==void 0)return{si:t,param:e};return null})(),[f,p]=(0,m.useState)(!1),[ee,g]=(0,m.useState)(0),_=(0,m.useRef)(null);(0,m.useEffect)(()=>{if(!f||d===null)return;let e=l[`${d.si}:${d.param.name}`]??d.param.value,t=d.param.animateTo,n=d.param.durationMs??4e3,r=performance.now(),i=a=>{let o=Math.min(1,(a-r)/n),s=1-(1-o)**3,c=e+(t-e)*s;u(e=>({...e,[`${d.si}:${d.param.name}`]:c})),g(o),o<1?_.current=requestAnimationFrame(i):d.param.loop===!0?(u(e=>({...e,[`${d.si}:${d.param.name}`]:d.param.value})),g(0),_.current=requestAnimationFrame(()=>p(e=>e))):p(!1)};return _.current=requestAnimationFrame(i),()=>{_.current!==null&&cancelAnimationFrame(_.current)}},[f,d?.si,d?.param.name,d?.param.animateTo]);let v=o.xMin,y=o.xMax,b=o.yMin,x=o.yMax,S=e=>v+(e-34)/436*(y-v),C=e=>34+(e-v)/(y-v)*436,w=e=>14+(1-(e-b)/(x-b))*182,T=e.map((e,t)=>{let n={};for(let r of e.params??[])r!=null&&(n[r.name]=l[`${t}:${r.name}`]??r.value);return{series:e,points:_t(e.expr,v,y,240,n).map(([e,t])=>`${C(e).toFixed(2)},${w(t).toFixed(2)}`).join(` `)}}),te=St(v,y),ne=St(b,x),re=T.some(e=>e.points.length>1),ie=Number.isFinite(v)&&Number.isFinite(y)&&y>v&&Number.isFinite(x)&&Number.isFinite(b)&&x>b,ae=(e,t,n)=>{let r=bt(t,T.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`,i=e.kind??`line`;if(i===`scatter`){let e=n===``?[]:n.split(` `).map(e=>{let[t,n]=e.split(`,`);return[Number(t),Number(n)]});return(0,h.jsx)(`g`,{children:e.map(([e,t],n)=>(0,h.jsx)(`circle`,{cx:e,cy:t,r:2.6,className:B.scatterDot,style:{fill:r}},n))},t)}if(i===`area`){if(n===``)return(0,h.jsx)(wt,{points:``,className:B.line,color:r},t);let e=n.slice(0,n.indexOf(` `)).split(`,`)[0],i=n.slice(n.lastIndexOf(` `)+1).split(`,`)[0],a=w(b),o=`${e},${a.toFixed(2)} ${n} ${i},${a.toFixed(2)}`;return(0,h.jsx)(`polygon`,{points:o,className:B.area,style:{fill:r}},t)}return(0,h.jsx)(wt,{points:n,className:B.line,color:r},t)},oe=e=>{c.current={startX:e.clientX,startY:e.clientY,xMin:v,xMax:y},e.target.setPointerCapture?.(e.pointerId)},se=e=>{let t=c.current;if(t===null)return;let n=t.xMax-t.xMin,r=(t.startX-e.clientX)/436*n;s(e=>({xMin:t.xMin+r,xMax:t.xMax+r,yMin:e.yMin,yMax:e.yMax}))},E=()=>{c.current=null},ce=e=>{let t=y-v,n=t*(e.deltaY>0?1.15:1/1.15),r=e.currentTarget.getBoundingClientRect(),i=S((e.clientX-r.left)/r.width*480),a=i-(i-v)/t*n;s(e=>({xMin:a,xMax:a+n,yMin:e.yMin,yMax:e.yMax}))},D=e.some(e=>(e.params?.length??0)>0);return(0,h.jsxs)(`div`,{className:B.block,"data-genui-plot":!0,children:[a!==void 0&&(0,h.jsx)(`div`,{className:B.title,children:a}),re&&ie?(0,h.jsxs)(`svg`,{width:`100%`,viewBox:`0 0 480 220`,role:`img`,"aria-label":a??`function plot`,className:B.surface,onPointerDown:oe,onPointerMove:se,onPointerUp:E,onPointerLeave:E,onWheel:ce,children:[ne.map(e=>(0,h.jsxs)(`g`,{children:[(0,h.jsx)(`line`,{x1:34,x2:470,y1:w(e),y2:w(e),className:B.gridLine}),(0,h.jsx)(`text`,{x:28,y:w(e)+4,className:B.tick,textAnchor:`end`,children:Ct(e)})]},`y${e}`)),te.map(e=>(0,h.jsxs)(`g`,{children:[(0,h.jsx)(`line`,{x1:C(e),x2:C(e),y1:14,y2:196,className:B.gridLine}),(0,h.jsx)(`text`,{x:C(e),y:210,className:B.tick,textAnchor:`middle`,children:Ct(e)})]},`x${e}`)),(0,h.jsx)(`line`,{x1:34,x2:470,y1:196,y2:196,className:B.axis}),(0,h.jsx)(`line`,{x1:34,x2:34,y1:14,y2:196,className:B.axis}),T.map(({series:e,points:t},n)=>ae(e,n,t))]}):(0,h.jsx)(`div`,{className:B.empty,children:e.map((e,t)=>(0,h.jsxs)(`div`,{className:B.emptyRow,children:[e.expr,` — 无法绘制(表达式无效或范围非法)`]},t))}),D&&(0,h.jsxs)(`div`,{className:B.sliders,children:[(0,h.jsxs)(`div`,{className:B.slidersHead,children:[(0,h.jsx)(`span`,{className:B.slidersTitle,children:`参数调节`}),(0,h.jsx)(`button`,{type:`button`,className:B.resetBtn,onClick:()=>{p(!1);let t={};for(let[n,r]of e.entries())for(let e of r.params??[])e!=null&&(t[`${n}:${e.name}`]=e.value);u(t),g(0)},children:`↺ 重置`})]}),e.map((e,t)=>(e.params??[]).map(n=>{if(n==null)return null;let r=`${t}:${n.name}`,i=l[r]??n.value;return(0,h.jsxs)(`label`,{className:B.sliderRow,children:[(0,h.jsxs)(`span`,{className:B.sliderName,children:[e.label??e.expr,` · `,n.name]}),(0,h.jsx)(`input`,{type:`range`,className:B.slider,min:n.min??0,max:n.max??10,step:n.step??.1,value:i,onChange:e=>{let t=Number(e.currentTarget.value);u(e=>({...e,[r]:t}))}}),(0,h.jsx)(`span`,{className:B.sliderValue,children:Math.round(i*100)/100})]},r)}))]}),d!==null&&(0,h.jsxs)(`div`,{className:B.animBar,children:[(0,h.jsx)(`button`,{type:`button`,className:B.playBtn,onClick:()=>{f?p(!1):(u(e=>({...e,[`${d.si}:${d.param.name}`]:d.param.value})),g(0),p(!0))},children:f?`⏸ 暂停`:`▶ 播放动画`}),f&&(0,h.jsx)(`div`,{className:B.animTrack,children:(0,h.jsx)(`div`,{className:B.animFill,style:{width:`${ee*100}%`}})})]}),(e.length>1||D)&&(0,h.jsx)(`div`,{className:B.legend,children:e.map((t,n)=>(0,h.jsxs)(`span`,{className:B.legendItem,children:[(0,h.jsx)(`span`,{className:B.legendSwatch,style:{background:bt(n,e.length,t.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}}),t.label??t.expr]},n))})]})});function Et(e){let t=window.__DSH_BOOT__?.entries?.find(e=>e.id===Ot)?.rev;return`${kt}/${e}${t===void 0?``:`?rev=${t}`}`}function Dt(e){let t=`${e}.js`,n=At.get(t);if(n!==void 0)return n;let r=new Promise((n,r)=>{let i=document.createElement(`script`);i.src=Et(t),i.async=!0,i.onload=()=>{let i=(window.__GenuiAssets__??{})[e];if(i===void 0){r(Error(`genui asset '${t}' loaded but registered no '${e}' engine`));return}n(i)},i.onerror=()=>{r(Error(`genui asset '${t}' failed to load (host asset route missing?)`))},document.head.appendChild(i)});return At.set(t,r),r}var Ot,kt,At,V=l((()=>{Ot=`@omdsh-dev/dsh-genui`,kt=`/plugins/${Ot}/assets`,At=new Map}));function jt(e){if(Pt.test(e))throw Error(`mermaid output failed the sanitization check; refusing to render`)}function Mt(e){let t=/^([A-Za-z]+)/.exec(e.trim())?.[1]??``;if(t!==`graph`&&t!==`flowchart`)return e;let n=e.replace(/`/g,``).replace(/<br\s*\/?>/gi,` `),r=/(--|==|-\.)(?!>)[ \t]*([^-\n]|-(?!--))*?[ \t]*(-->|==>|\.->)/g,i=[],a=n.replace(r,e=>(i.push(e),`\uE000${i.length-1}\uE001`)),o=/\|([^|\n]*[\[\]][^|\n]*)\|/g,s=[];return a.replace(o,(e,t)=>{let n=t.trim();return n.includes(`"`)?e:(s.push(n),`\uE002${s.length-1}\uE003`)}).replace(/([\[\(])([^\[\]\(\)\{\}"'\n]*)([\]\)])/g,(e,t,n,r)=>{let i=n.trim();return i===``?e:/[\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]/.test(i)||/\s/.test(i)?`${t}"${i}"${r}`:e}).replace(/\uE000(\d+)\uE001/g,(e,t)=>i[Number(t)]??e).replace(/\uE002(\d+)\uE003/g,(e,t)=>{let n=s[Number(t)];return n===void 0?e:`|"${n}"|`})}function Nt(e){let t=e.trim(),n=/^([A-Za-z]+)/.exec(t)?.[1]??``;return n===`graph`||n===`flowchart`||!Ft.test(t)?e:`graph TD\n${t}`}var Pt,Ft,It=l((()=>{Pt=/<script|[\s"']on[a-z]+\s*=|javascript:/i,Ft=/-->(?!>)|==>|-\.->/})),Lt=u({assertSafeSvg:()=>jt,ensureFlowchartKind:()=>Nt,renderMermaid:()=>Rt,repairMermaidSource:()=>Mt});async function Rt(e){return(await Dt(`mermaid`)).renderMermaid(e)}var zt=l((()=>{V(),It()})),Bt=u({mountScene:()=>Vt});async function Vt(e,t){return(await Dt(`three`)).mountScene(e,t)}var Ht=l((()=>{V()}));let Ut={info:S.calloutInfo,success:S.calloutSuccess,warning:S.calloutWarning,error:S.calloutError},Wt=(0,m.memo)(function({node:e}){let t=e.tone??`info`,n=Ut[t]??S.calloutInfo;return(0,h.jsxs)(`div`,{className:`${S.callout} ${n}`,"data-genui-callout":!0,children:[e.title!==void 0&&(0,h.jsx)(`div`,{className:S.calloutTitle,children:e.title}),(0,h.jsx)(`div`,{className:S.calloutBody,children:e.content})]})}),Gt=(0,m.memo)(function({steps:e}){let t=e.steps.slice(0,D.maxSteps),n=e.current??t.length;return(0,h.jsx)(`ol`,{className:S.steps,children:t.map((e,t)=>{let r=t<n,i=t===n;return(0,h.jsxs)(`li`,{className:`${S.step} ${r?S.stepDone:``} ${i?S.stepActive:``}`,children:[(0,h.jsx)(`span`,{className:S.stepMarker,children:r?`✓`:String(t+1)}),(0,h.jsxs)(`span`,{className:S.stepContent,children:[(0,h.jsx)(`span`,{className:S.stepTitle,children:e.title}),e.desc!==void 0&&(0,h.jsx)(`span`,{className:S.stepDesc,children:e.desc})]})]},t)})})}),Kt=(0,m.memo)(function({node:e}){let t=e.pairs.slice(0,D.maxKeyValuePairs);return(0,h.jsx)(`dl`,{className:S.keyvalue,children:t.map((e,t)=>(0,h.jsxs)(`div`,{className:S.kvRow,children:[(0,h.jsx)(`dt`,{className:S.kvKey,children:e.key}),(0,h.jsx)(`dd`,{className:S.kvValue,children:e.value})]},t))})}),qt=(0,m.memo)(function({plot:e}){let t=(0,m.useMemo)(()=>e.series.slice(0,D.maxPlotSeries).map(e=>({expr:e.expr,label:e.label,color:e.color,kind:e.kind,params:e.params})),[e]);return(0,h.jsx)(Tt,{series:t,xMin:e.xMin,xMax:e.xMax,yMin:e.yMin,yMax:e.yMax,title:e.title})}),Jt=(0,m.memo)(function({node:e}){return(0,h.jsx)(p.DiffBlock,{diffs:e.diffs})}),Yt=(0,m.memo)(function({node:e}){let t=e.value;return typeof t!=`object`||!t?(0,h.jsx)(`div`,{className:S.jsonScalar,children:String(t)}):(0,h.jsx)(p.JsonTree,{data:t,copyable:!0})}),Xt=(0,m.memo)(function({node:e}){return(0,h.jsx)(p.CodeBlock,{code:e.code.slice(0,D.maxCode),lang:e.lang})});function Zt({tabs:e,onAction:t,depth:n=0,answers:r}){let[i,a]=(0,m.useState)(0),o=(0,m.useId)(),s=e.tabs.slice(0,D.maxTabs),c=s[i],l=e=>{let t=(e+s.length)%s.length;a(t),document.getElementById(`${o}-tab-${t}`)?.focus()};return(0,h.jsxs)(`div`,{className:S.tabs,children:[(0,h.jsx)(`div`,{className:S.tabBar,role:`tablist`,"aria-orientation":`horizontal`,onKeyDown:e=>{e.key===`ArrowRight`?(e.preventDefault(),l(i+1)):e.key===`ArrowLeft`?(e.preventDefault(),l(i-1)):e.key===`Home`?(e.preventDefault(),l(0)):e.key===`End`&&(e.preventDefault(),l(s.length-1))},children:s.map((e,t)=>(0,h.jsx)(`button`,{id:`${o}-tab-${t}`,type:`button`,role:`tab`,"aria-selected":t===i,"aria-controls":`${o}-panel-${t}`,tabIndex:t===i?0:-1,className:`${S.tab} ${t===i?S.tabActive:``}`,onClick:()=>a(t),children:e.label},t))}),c!==void 0&&(0,h.jsx)(`div`,{className:S.col,role:`tabpanel`,id:`${o}-panel-${i}`,"aria-labelledby":`${o}-tab-${i}`,children:c.items.map((e,i)=>U(e,i,t,n+1,r))})]})}function Qt({node:e,onAction:t,depth:n=0,answers:r}){let[i,a]=(0,m.useState)(0),o=(0,m.useId)(),s=e.items.slice(0,D.maxAccordionItems);return(0,h.jsx)(`div`,{className:S.accordion,children:s.map((e,s)=>(0,h.jsxs)(`div`,{className:S.accItem,children:[(0,h.jsxs)(`button`,{type:`button`,className:S.accHead,id:`${o}-head-${s}`,"aria-expanded":i===s,"aria-controls":`${o}-body-${s}`,onClick:()=>a(i===s?null:s),children:[(0,h.jsx)(`span`,{className:S.accTitle,children:e.title}),(0,h.jsx)(`span`,{className:S.accChevron,children:i===s?`▾`:`▸`})]}),i===s&&(0,h.jsx)(`div`,{className:S.accBody,id:`${o}-body-${s}`,"aria-labelledby":`${o}-head-${s}`,children:e.items.map((e,i)=>U(e,i,t,n+1,r))})]},s))})}let $t=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`button`,{type:`button`,className:`${S.copyChip} ${t?S.copyChipDone:``}`,onClick:()=>{navigator.clipboard?.writeText(e.text).catch(()=>{}),n(!0),setTimeout(()=>n(!1),1500)},children:t?`✓ 已复制`:e.label??`复制`}),(0,h.jsx)(`span`,{className:S.visuallyHidden,role:`status`,children:t?`已复制到剪贴板`:``})]})}),en=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(null),[r,i]=(0,m.useState)(!1),a=e.code.slice(0,D.maxMermaid);return(0,m.useEffect)(()=>{let e=!0;return Promise.resolve().then(()=>(zt(),Lt)).then(async t=>{try{let r=await t.renderMermaid(a);e&&n(r)}catch{e&&i(!0)}}),()=>{e=!1}},[a]),r?(0,h.jsxs)(`div`,{className:S.mermaidFallback,children:[(0,h.jsx)(`pre`,{children:a}),(0,h.jsx)(`div`,{className:S.mermaidErr,children:`图语法有误,已降级显示源码`})]}):t===null?(0,h.jsxs)(`div`,{className:S.mermaidFallback,children:[(0,h.jsx)(`pre`,{children:a}),(0,h.jsx)(`div`,{className:S.mermaidHint,children:`渲染中…`})]}):(0,h.jsx)(`div`,{className:S.mermaid,dangerouslySetInnerHTML:{__html:t},"data-genui-mermaid":!0})}),tn=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(`loading`),r=(0,m.useRef)(null),i=e.meshes.length>D.maxMeshes?{...e,meshes:e.meshes.slice(0,D.maxMeshes)}:e;return(0,m.useEffect)(()=>{let e=!0,t;return Promise.resolve().then(()=>(Ht(),Bt)).then(async a=>{if(!(!e||r.current===null))try{t=await a.mountScene(r.current,i),e&&n(`ready`)}catch{e&&n(`error`)}}),()=>{e=!1,t?.()}},[i]),(0,h.jsxs)(`div`,{className:S.scene3dWrap,"data-genui-scene3d":!0,children:[e.title!==void 0&&(0,h.jsx)(`div`,{className:S.scene3dTitle,children:e.title}),(0,h.jsx)(`div`,{ref:r,className:S.scene3dCanvas}),t===`loading`&&(0,h.jsx)(`div`,{className:S.scene3dHint,children:`加载 3D 场景…`}),t===`error`&&(0,h.jsx)(`div`,{className:S.scene3dHint,children:`3D 渲染失败`})]})}),nn=(0,m.memo)(function({node:e}){let t=e.items.slice(0,D.maxTimelineItems);return(0,h.jsx)(`div`,{className:S.timeline,children:t.map((e,n)=>(0,h.jsxs)(`div`,{className:S.tlItem,children:[(0,h.jsxs)(`div`,{className:S.tlRail,children:[(0,h.jsx)(`span`,{className:S.tlDot}),n<t.length-1&&(0,h.jsx)(`span`,{className:S.tlLine})]}),(0,h.jsxs)(`div`,{className:S.tlBody,children:[(0,h.jsxs)(`div`,{className:S.tlHead,children:[(0,h.jsx)(`span`,{className:S.tlTitle,children:e.title}),e.time!==void 0&&(0,h.jsx)(`span`,{className:S.tlTime,children:e.time})]}),e.desc!==void 0&&(0,h.jsx)(`div`,{className:S.tlDesc,children:e.desc})]})]},n))})}),rn=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(new Set),r=(e,t)=>`${e}-${t}`,i=e=>{n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},a=(e,n,o)=>{if(n>D.maxTreeDepth)return null;let s=e.type===`dir`||e.children!==void 0&&e.children.length>0,c=r(n,o),l=s&&t.has(c);return(0,h.jsxs)(`div`,{className:S.ftRow,style:{paddingLeft:`${n*16}px`},children:[(0,h.jsxs)(`button`,{type:`button`,className:S.ftNameBtn,"aria-expanded":s?!l:void 0,onClick:s?()=>i(c):void 0,children:[(0,h.jsx)(`span`,{className:`${S.ftIcon} ${s?S.ftIconDir:``}`,"aria-hidden":!0,children:s?l?`▸`:`▾`:`·`}),(0,h.jsx)(`span`,{className:`${S.ftName} ${s?S.ftDir:``}`,children:e.name})]}),s&&!l&&(e.children??[]).map((e,t)=>a(e,n+1,t))]},c)};return(0,h.jsx)(`div`,{className:S.fileTree,children:e.items.slice(0,D.maxListItems).map((e,t)=>a(e,0,t))})}),an=(0,m.memo)(function({node:e,onAction:t}){let[n,r]=(0,m.useState)(null),i=e.options.slice(0,D.maxQuizOptions),a=n!==null,o=n===null?void 0:i[n],s=o?.correct===!0,c=e.action;return(0,h.jsxs)(`div`,{className:S.quiz,"data-genui-quiz":!0,children:[(0,h.jsx)(`div`,{className:S.quizQuestion,children:e.question}),(0,h.jsx)(`div`,{className:S.quizOptions,children:i.map((i,o)=>{let s=n===o,l=a?s?i.correct===!0?S.quizOptCorrect:S.quizOptWrong:i.correct===!0?S.quizOptReveal:S.quizOpt:S.quizOpt;return(0,h.jsxs)(`button`,{type:`button`,className:l,disabled:a,onClick:()=>{r(o),c!==void 0&&t!==void 0&&t(c,{type:`quiz`,question:e.question,answer:i.label,correct:i.correct===!0})},children:[(0,h.jsx)(`span`,{className:S.quizMarker,children:a&&(i.correct===!0?`✓`:s?`✗`:``)}),i.label]},o)})}),a&&(0,h.jsxs)(`div`,{className:S.quizResult,"aria-live":`polite`,children:[(0,h.jsxs)(`div`,{className:s?S.quizCorrectMsg:S.quizWrongMsg,children:[s?`✓ 回答正确!`:`✗ 再想想看`,o?.feedback!==void 0&&(0,h.jsx)(`div`,{className:S.quizFeedback,children:o.feedback})]}),e.explanation!==void 0&&(0,h.jsx)(`div`,{className:S.quizExplanation,children:e.explanation}),(0,h.jsx)(`button`,{type:`button`,className:S.quizRetry,onClick:()=>r(null),children:`重新作答`})]})]})}),on=(0,m.memo)(function({node:e}){let t=e.items.slice(0,D.maxBreadcrumbItems);return(0,h.jsx)(`nav`,{className:S.breadcrumb,"aria-label":`breadcrumb`,children:t.map((e,n)=>(0,h.jsxs)(`span`,{className:S.bcItem,children:[(0,h.jsx)(`span`,{className:`${S.bcText} ${n===t.length-1?S.bcCurrent:``}`,children:e}),n<t.length-1&&(0,h.jsx)(`span`,{className:S.bcSep,children:`/`})]},n))})});V();async function sn(e,t,n){return(await Dt(`echarts`)).createChart(e,t,n)}function H(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function cn(){return{accent:H(`--dsw-alias-state-business-primary`,`#4f8ef7`),labelPrimary:H(`--dsw-alias-label-primary`,`#e6e6e6`),labelSecondary:H(`--dsw-alias-label-secondary`,`#a0a0a0`),labelTertiary:H(`--dsw-alias-label-tertiary`,`#6b6b6b`),border:H(`--dsw-alias-border-l1`,`rgba(255,255,255,0.12)`),bgLayer1:H(`--dsw-alias-bg-layer-1`,`#1a1a1e`)}}function ln(e){let t=cn(),n=Je.map(e=>H(e.replace(`var(`,``).replace(`)`,``),t.accent)),r=e.data??[],i=e.series,a=(e={})=>({renderMode:`richText`,backgroundColor:t.bgLayer1,borderColor:t.border,textStyle:{color:t.labelPrimary},...e}),o={color:n,textStyle:{color:t.labelSecondary,fontFamily:`inherit`},backgroundColor:`transparent`,grid:{left:48,right:16,top:24,bottom:32},tooltip:a({trigger:`item`})};switch(e.preset){case`pie`:return{...o,tooltip:a({trigger:`item`,formatter:`{b}: {c} ({d}%)`}),legend:{bottom:0,textStyle:{color:t.labelTertiary}},series:[{type:`pie`,radius:[`40%`,`70%`],avoidLabelOverlap:!0,itemStyle:{borderRadius:6,borderColor:t.bgLayer1,borderWidth:2},label:{color:t.labelSecondary},data:r.map(e=>({name:e.label,value:e.value}))}]};case`scatter`:return{...o,tooltip:a({trigger:`item`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:[{type:`scatter`,symbolSize:10,data:r.map(e=>e.value)}]};case`area`:return{...o,tooltip:a({trigger:`axis`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map((e,t)=>({name:e.label,type:`line`,smooth:!0,areaStyle:{opacity:.15},data:e.data.map(e=>e.value),...un(e.color,t,i)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}};case`line`:return{...o,tooltip:a({trigger:`axis`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map((e,t)=>({name:e.label,type:`line`,smooth:!0,showSymbol:!0,symbolSize:6,data:e.data.map(e=>e.value),...un(e.color,t,i)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}};default:return{...o,tooltip:a({trigger:`axis`,axisPointer:{type:`shadow`}}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map(e=>({name:e.label,type:`bar`,barMaxWidth:40,itemStyle:{borderRadius:[4,4,2,2],...e.color===void 0?{}:{color:e.color}},data:e.data.map(e=>e.value)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}}}}function un(e,t,n){return e===void 0?{}:{itemStyle:{color:e}}}function dn({node:e}){let t=(0,m.useRef)(null),[n,r]=(0,m.useState)(`loading`),i=(0,m.useRef)(null);return(0,m.useEffect)(()=>{let n=!0,a=t.current;return a===null?void 0:(sn(a,e.option??ln(e),{height:e.height??300}).then(e=>{if(!n){e.dispose();return}i.current=e,r(`ready`)}).catch(()=>{n&&r(`error`)}),()=>{n=!1,i.current?.dispose(),i.current=null})},[]),(0,m.useEffect)(()=>{if(n!==`ready`)return;let e=t.current;if(e===null)return;let r=new ResizeObserver(()=>{i.current?.resize()});return r.observe(e),()=>{r.disconnect()}},[n]),(0,m.useEffect)(()=>{if(n!==`ready`||i.current===null)return;let t=e.option??ln(e);i.current.setOption(t,!0)},[e,n]),n===`error`?(0,h.jsxs)(`div`,{className:S.echartFallback,"data-genui-echart":!0,children:[(0,h.jsx)(`div`,{className:S.echartErr,children:`ECharts 渲染失败`}),e.title!==void 0&&(0,h.jsx)(`div`,{className:S.echartHint,children:e.title})]}):(0,h.jsxs)(`div`,{className:S.echartWrap,"data-genui-echart":!0,children:[e.title!==void 0&&(0,h.jsx)(`div`,{className:S.echartTitle,children:e.title}),(0,h.jsx)(`div`,{ref:t,className:S.echartCanvas,style:{height:`${e.height??300}px`},role:`img`,"aria-label":e.title??`ECharts chart`}),n===`loading`&&(0,h.jsx)(`div`,{className:S.echartHint,children:`加载图表…`})]})}let fn=p.getGenuiComponent;function pn(e){return typeof e==`object`&&!!e&&`type`in e}function U(e,t,n,r=0,i){if(r>D.maxDepth)return null;switch(e.type){case`text`:{let n=e.size??`body`;return(0,h.jsx)(`div`,{className:`${S.text} ${S[n]}`+(e.center?` ${S.center}`:``),children:e.content},t)}case`row`:return(0,h.jsxs)(`div`,{className:S.row+(e.wrap?` ${S.wrap}`:``),children:[e.items.map((e,t)=>U(e,t,n,r+1,i)),e.spacer&&(0,h.jsx)(`div`,{className:S.spacer})]},t);case`col`:return(0,h.jsx)(`div`,{className:S.col,style:e.gap===void 0?void 0:{gap:`${e.gap}px`},children:e.items.map((e,t)=>U(e,t,n,r+1,i))},t);case`grid`:return(0,h.jsx)(`div`,{className:S.grid,style:{gridTemplateColumns:`repeat(${Math.max(1,e.cols)}, minmax(0, 1fr))`},children:e.items.map((e,t)=>U(e,t,n,r+1,i))},t);case`card`:return(0,h.jsxs)(`div`,{className:S.card,children:[e.title!==void 0&&(0,h.jsx)(`div`,{className:S.cardTitle,children:e.title}),e.items.map((e,t)=>U(e,t,n,r+1,i))]},t);case`button`:{let r=e.tone??``,i=`${S.button} ${S[r]||``}`+(e.full?` ${S.full}`:``)+(e.small?` ${S.small}`:``),a=e.action,o=a!==void 0&&n!==void 0;return(0,h.jsxs)(Ge,{className:i,disabled:!o,onClick:o?()=>n(a,{type:`button`,label:e.label}):void 0,children:[e.icon!==void 0&&(0,h.jsxs)(`span`,{"aria-hidden":!0,children:[e.icon,` `]}),e.label]},t)}case`input`:return(0,h.jsx)(dt,{node:e,onAction:n,answers:i},t);case`select`:return(0,h.jsx)(ut,{node:e,onAction:n,answers:i},t);case`checkbox`:{let r=e.action;return(0,h.jsxs)(`label`,{className:S.checkbox,children:[(0,h.jsx)(`input`,{type:`checkbox`,defaultChecked:e.checked===!0,onChange:r!==void 0&&n!==void 0?e=>n(r,{type:`checkbox`,checked:e.currentTarget.checked}):void 0}),(0,h.jsx)(`span`,{children:e.label})]},t)}case`link`:{let n=e.href;return n===void 0?(0,h.jsx)(`span`,{className:S.linkText,children:e.label},t):(0,h.jsx)(`a`,{className:S.link,href:n,target:`_blank`,rel:`noopener noreferrer`,children:e.label},t)}case`audio`:return(0,h.jsx)(Ke,{node:e},`${t}:${e.src}`);case`video`:return(0,h.jsx)(qe,{node:e},`${t}:${e.src}`);case`badge`:{let n=e.tone??``;return(0,h.jsxs)(`span`,{className:`${S.badge} ${S[n]||``}`,children:[e.icon!==void 0&&(0,h.jsxs)(`span`,{"aria-hidden":!0,children:[e.icon,` `]}),e.label]},t)}case`stat`:{let n=e.delta!==void 0&&e.delta.startsWith(`-`);return(0,h.jsxs)(`div`,{className:S.stat,children:[(0,h.jsx)(`span`,{className:S.statLabel,children:e.label}),(0,h.jsx)(`span`,{className:S.statValue,children:e.value}),e.delta!==void 0&&(0,h.jsx)(`span`,{className:`${S.statDelta} ${n?S.down:S.up}`,children:e.delta})]},t)}case`progress`:{let n=Math.max(0,Math.min(100,Number(e.value)||0));return(0,h.jsxs)(`div`,{className:S.progress,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n,"aria-label":e.label??e.valueLabel??void 0,children:[(e.label!==void 0||e.valueLabel!==void 0)&&(0,h.jsxs)(`div`,{className:S.progressRow,children:[(0,h.jsx)(`span`,{children:e.label}),e.valueLabel!==void 0&&(0,h.jsx)(`span`,{children:e.valueLabel})]}),(0,h.jsx)(`div`,{className:S.track,children:(0,h.jsx)(`div`,{className:S.fill,style:{width:`${n}%`}})})]},t)}case`divider`:return(0,h.jsx)(`hr`,{className:S.divider},t);case`list`:{let a=e.items.slice(0,D.maxListItems);return(0,h.jsx)(`div`,{className:S.list,children:a.map((e,t)=>(0,h.jsx)(`div`,{className:S.li,children:pn(e)?U(e,t,n,r+1,i):(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:S.liTitle,children:typeof e==`string`?e:e.title}),typeof e!=`string`&&e.desc!==void 0&&(0,h.jsx)(`span`,{className:S.liDesc,children:e.desc})]})},t))},t)}case`table`:return(0,h.jsx)(Qe,{node:e},t);case`chart`:return(0,h.jsx)($e,{chart:e},t);case`tabs`:return(0,h.jsx)(Zt,{tabs:e,onAction:n,depth:r+1,answers:i},t);case`avatar`:return(0,h.jsx)(`div`,{className:S.avatar,style:{background:e.color??We(e.name)},children:e.name.slice(0,1).toUpperCase()},t);case`spacer`:return(0,h.jsx)(`div`,{className:S.spacer},t);case`plot`:return(0,h.jsx)(qt,{plot:e},t);case`callout`:return(0,h.jsx)(Wt,{node:e},t);case`steps`:return(0,h.jsx)(Gt,{steps:e},t);case`keyvalue`:return(0,h.jsx)(Kt,{node:e},t);case`diff`:return(0,h.jsx)(Jt,{node:e},t);case`json`:return(0,h.jsx)(Yt,{node:e},t);case`code`:return(0,h.jsx)(Xt,{node:e},t);case`radio`:return(0,h.jsx)(rt,{node:e,onAction:n,answers:i},`${t}:r${i?.round??0}`);case`submit`:return(0,h.jsx)(at,{node:e,onAction:n,answers:i},t);case`switch`:return(0,h.jsx)(ot,{node:e,onAction:n},t);case`slider`:return(0,h.jsx)(st,{node:e,onAction:n,answers:i},t);case`textarea`:return(0,h.jsx)(ft,{node:e,onAction:n,answers:i},t);case`accordion`:return(0,h.jsx)(Qt,{node:e,onAction:n,depth:r+1,answers:i},t);case`copy`:return(0,h.jsx)($t,{node:e},t);case`mermaid`:return(0,h.jsx)(en,{node:e},t);case`scene3d`:return(0,h.jsx)(tn,{node:e},t);case`timeline`:return(0,h.jsx)(nn,{node:e},t);case`file-tree`:return(0,h.jsx)(rn,{node:e},t);case`breadcrumb`:return(0,h.jsx)(on,{node:e},t);case`quiz`:return(0,h.jsx)(an,{node:e,onAction:n},t);case`echart`:return(0,h.jsx)(dn,{node:e},t);default:{let a=e,o=fn?.(a.type);return o===void 0?null:(0,h.jsx)(o,{node:a,onAction:n,renderChildren:(e,t)=>e.map((e,a)=>U(e,Number(t)+a,n,r+1,i))},t)}}}function mn(e){let t=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{let e=t.current;if(e!==null){for(let t of e.values())clearTimeout(t);e.clear()}},[]),(0,m.useMemo)(()=>{if(e===void 0)return;let n=new Map;return t.current=n,(t,r)=>{let i=n.get(t);i!==void 0&&clearTimeout(i),n.set(t,setTimeout(()=>{n.delete(t),e(t,r)},300))}},[e])}function hn(e,t){return e===t||JSON.stringify(e)===JSON.stringify(t)}let gn=(0,m.memo)(function({spec:e,stateKey:t}){let n=e.gap??16,r=mn(v()),[i]=(0,m.useState)(()=>t===void 0?null:ne(t)),[a,o]=(0,m.useState)(i?.answers??{}),[s,c]=(0,m.useState)(i?.fields??{}),[l,u]=(0,m.useState)({}),[d,f]=(0,m.useState)(i?.locked===!0),[p,ee]=(0,m.useState)(0),[g,_]=(0,m.useState)(new Set),y=(0,m.useCallback)((e,t)=>{o(n=>n[e]===t?n:{...n,[e]:t})},[]),b=(0,m.useCallback)((e,t)=>{c(n=>{if(t.trim()===``){if(!(e in n))return n;let t={...n};return delete t[e],t}return n[e]===t?n:{...n,[e]:t}})},[]),x=(0,m.useCallback)(e=>{_(t=>t.has(e)?t:new Set(t).add(e))},[]),C=(0,m.useCallback)((e,t)=>{u(n=>{let r=n[e];return r!==void 0&&r.label===t.label&&r.answer===t.answer&&r.explanation===t.explanation?n:{...n,[e]:t}})},[]),w=(0,m.useCallback)(()=>{o({}),f(!1),ee(e=>e+1)},[]),T=(0,m.useMemo)(()=>({answers:a,fields:s,secretFields:g,meta:l,locked:d,round:p,setAnswer:y,setField:b,registerSecretField:x,registerMeta:C,clear:w,setLocked:f}),[a,s,g,l,d,p,y,b,x,C,w]);return(0,m.useEffect)(()=>{if(t===void 0)return;let e=setTimeout(()=>{let e=Object.fromEntries(Object.entries(s).filter(([e])=>!g.has(e)));re(t,{answers:a,locked:d,...Object.keys(e).length>0?{fields:e}:{}})},300);return()=>clearTimeout(e)},[t,a,d,s,g]),(0,h.jsxs)(`div`,{className:S.block,"data-genui":!0,children:[e.title!==void 0&&(0,h.jsx)(`div`,{className:S.banner,children:e.title}),(0,h.jsx)(`div`,{className:S.col,style:{gap:`${n}px`},children:e.items.map((e,t)=>(0,h.jsx)(`div`,{className:S.reveal,style:{animationDelay:`${Math.min(t*90,720)}ms`},children:U(e,t,r,0,T)},t))})]})},(e,t)=>e.stateKey===t.stateKey&&hn(e.spec,t.spec));function _n(e){let t=[],n=[],r=e=>{n.length>=32&&n.shift(),n.push(e)},i=!1,a=!1,o=0;for(;o<e.length;o++){let n=e[o];if(i){a?a=!1:n===`\\`?a=!0:n===`"`&&(i=!1);continue}if(n===`"`){i=!0;continue}if(n===`{`||n===`[`){t.push(n);continue}if(n===`}`||n===`]`){if(t.pop()!==(n===`}`?`{`:`[`))break;n===`}`&&t.length<=D.maxDepth&&r({end:o+1,closingSuffix:vn(t)}),t.length===0&&r({end:o+1,closingSuffix:``});continue}}n.sort((e,t)=>t.end-e.end);let s=[];for(let e of n)(s.length===0||s[s.length-1].end!==e.end)&&s.push(e);return{candidates:s.slice(0,32),scannedChars:o}}function vn(e){let t=``;for(let n=e.length-1;n>=0;n--)t+=e[n]===`{`?`}`:`]`;return t}function yn(e){try{let t=JSON.parse(e);return ce(t)?t:E(t)}catch{return null}}function bn(e){let t=e.trim();if(t===``)return null;let n=yn(t);if(n!==null)return n;let{candidates:r}=_n(t);for(let e of r){let n=yn(t.slice(0,e.end)+e.closingSuffix);if(n!==null)return n}return null}let W={maxNodes:200,maxAppends:200},xn=new Map,G=new Set;function Sn(){return{ops:new Map,seen:new Map,overflow:null,local:null,localBarrier:-1,replayBarrier:-1,maxSeenSeq:-1,snapshot:null}}let Cn=`dsh.genui.panel`;function wn(){try{let e=localStorage.getItem(Cn);if(e===null)return{order:[],sessions:{}};let t=JSON.parse(e);return!Array.isArray(t.order)||typeof t.sessions!=`object`||t.sessions===null?{order:[],sessions:{}}:{order:t.order.filter(e=>typeof e==`string`),sessions:t.sessions}}catch{return{order:[],sessions:{}}}}function Tn(e,t){try{let n=wn(),r=n.order.filter(t=>t!==e);r.unshift(e);let i={...n.sessions,[e]:t};for(;r.length>50;){let e=r.pop();e!==void 0&&delete i[e]}localStorage.setItem(Cn,JSON.stringify({order:r,sessions:i}))}catch{}}function En(e){let t=xn.get(e);if(t!==void 0)return t;let n=Sn();try{let t=wn().sessions[e];t!==void 0&&(n={ops:new Map,seen:new Map,overflow:null,local:t.local??null,localBarrier:t.localBarrier??-1,replayBarrier:t.maxSeenSeq??-1,maxSeenSeq:t.maxSeenSeq??-1,snapshot:t.snapshot??null})}catch{}return xn.set(e,n),n}function K(e,t){for(let n=0;n<3;n++){let r=e[n]-t[n];if(r!==0)return r}return 0}function Dn(e,t){if(t!==null&&(t.order[0]<=e.localBarrier||t.order[0]<=e.replayBarrier||e.seen.has(t.sourceId)||e.overflow!==null&&e.overflow.sourceId===t.sourceId||t.mode===`append`&&e.overflow!==null&&K(t.order,e.overflow.order)>0))return null;let n=[...e.ops.values()].filter(t=>t.order[0]>e.localBarrier&&t.order[0]>e.replayBarrier);t!==null&&n.push(t),n.sort((e,t)=>K(e.order,t.order));let r=0;for(let e=0;e<n.length;e++){let t=n[e];t.mode===`replace`&&He(t.spec,W.maxNodes+1)<=W.maxNodes&&(r=e)}let i=e.local,a=null,o=0,s=[],c=e.maxSeenSeq;for(let e=r;e<n.length;e++){let t=n[e];if(t.order[0]>c&&(c=t.order[0]),t.mode===`replace`){if(He(t.spec,W.maxNodes+1)>W.maxNodes){(a===null||K(t.order,a.order)<0)&&(a=t);continue}a=null,i=t.spec,s.length=0,o=0,s.push(t);continue}let r=Ln(i,t.spec);if(o>=W.maxAppends||He(r,W.maxNodes+1)>W.maxNodes){(a===null||K(t.order,a.order)<0)&&(a=t);continue}i=r,o+=1,s.push(t)}return t!==null&&s.length===e.ops.size&&s.every(t=>e.ops.get(t.sourceId)?.mode===t.mode)&&(a===null&&e.overflow===null||a!==null&&e.overflow!==null&&a.sourceId===e.overflow.sourceId)?null:{snapshot:i,kept:s,overflow:a,maxSeenSeq:c}}function On(e,t,n){e.snapshot=t.snapshot,e.overflow=t.overflow,e.maxSeenSeq=t.maxSeenSeq,e.ops=new Map(t.kept.map(e=>[e.sourceId,e]));for(let n of t.kept)e.seen.set(n.sourceId,n.order);t.overflow!==null&&e.seen.set(t.overflow.sourceId,t.overflow.order),Tn(n,{snapshot:e.snapshot,local:e.local,localBarrier:e.localBarrier,maxSeenSeq:e.maxSeenSeq})}function kn(e,t){let n=En(e),r=Dn(n,t);if(r===null)return n.seen.has(t.sourceId)||n.overflow?.sourceId===t.sourceId?`idempotent`:(n.overflow!==null&&t.mode===`append`&&K(t.order,n.overflow.order)>0||An(e,t,n),`blocked`);let i=r.overflow!==null&&r.overflow.sourceId===t.sourceId?`overflow`:`accepted`,a=n.snapshot!==r.snapshot;if(On(n,r,e),a)for(let e of G)e();return i}let q=new Set;function An(e,t,n){let r=`${e}\u0000${t.sourceId}`;q.has(r)||(q.add(r),console.warn(`[genui] 面板操作被重放屏障拒绝(source ${t.sourceId},order[0]=${t.order[0]} ≤ replayBarrier ${n.replayBarrier} / localBarrier ${n.localBarrier})。历史消息重放被拒是预期行为;若是刚发送的新消息,说明消息序号推导异常,请报告。`))}function jn(e,t){let n=En(e),r=n.maxSeenSeq;if(n.local!==t||n.localBarrier!==r){n.local=t,n.localBarrier=r,On(n,Dn(n,null),e);for(let e of G)e()}}let J=new Set;function Mn(e,t){let n=`${e}\u0000${t}`;J.has(n)||(J.add(n),console.warn(`[genui] 面板已到节点/操作上限(${W.maxNodes} 节点、${W.maxAppends} 条追加),本次 append 被拒绝;请让模型发送 replace 更新面板。`))}function Nn(e){let t=xn.delete(e),n=Y.delete(e),r=`${e}\u0000`;for(let e of J)e.startsWith(r)&&J.delete(e);for(let e of q)e.startsWith(r)&&q.delete(e);if(!(!t&&!n)){for(let e of G)e();for(let e of X)e()}}function Pn(e){return En(e).snapshot}function Fn(e){return G.add(e),()=>{G.delete(e)}}function In(e){if(e.items.length!==1)return null;let t=e.items[0];return t?.type!==`tabs`||!Array.isArray(t.tabs)?null:t.tabs}function Ln(e,t){if(e===null||e.items.length===0)return t;let n=e.title??t.title,r={...e,...n===void 0?{}:{title:n}},i=In(e),a=In(t);if(i!==null&&a!==null){let e=new Map(i.map(e=>[e.label,{label:e.label,items:[...e.items]}]));for(let t of a){let n=e.get(t.label);n===void 0?e.set(t.label,{label:t.label,items:[...t.items]}):n.items.push(...t.items)}return{...r,items:[{type:`tabs`,tabs:[...e.values()]}]}}return{...r,items:[...e.items,...t.items]}}let Y=new Map,X=new Set;function Rn(e){Y.set(e,(Y.get(e)??0)+1);for(let e of X)e()}function zn(e){return Y.get(e)??0}function Bn(e){return X.add(e),()=>{X.delete(e)}}function Vn(e){try{return JSON.parse(e),!0}catch{return!1}}function Hn(e){try{return JSON.parse(e),null}catch(e){let t=e instanceof Error?e.message:String(e),n=t.match(/position (\d+)/i);return`${n===null?``:`(字符 ${n[1]} 附近)`}${t.slice(0,140)}`}}function Un(e){try{return JSON.parse(e),null}catch{}let t=``,n=!1,r=!1,i=0;for(let a=0;a<e.length;a++){let o=e[a];if(r){t+=o,r=!1;continue}if(n&&o===`\\`){t+=o,r=!0;continue}if(o===`"`){if(!n){n=!0,t+=o;continue}let r=a+1;for(;r<e.length&&(e[r]===` `||e[r]===` `||e[r]===` +window.__ModuleLoader__.load({id:`@omdsh-dev/dsh-genui`,factory:e=>{var t={exports:{}},n=t.exports;Object.defineProperty(n,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},u=(e,t)=>{let n={};for(var r in e)i(n,r,{get:e[r],enumerable:!0});return t||i(n,Symbol.toStringTag,{value:`Module`}),n},d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e},f=(e,t,n)=>(n=e==null?{}:r(s(e)),d(t||!e||!e.__esModule||!c.call(e,`default`)?i(n,`default`,{value:e,enumerable:!0}):n,e));let p=e("@deepseek-ai/dsh-client-ui-primitives");p=f(p,1);let m=e("react"),h=e("react-dom/client"),g=e("react/jsx-runtime"),_=(0,m.createContext)(void 0),v=p.GenuiActionContext??_;function y(){return(0,m.useContext)(v)}let b={display:`flex`,flexDirection:`column`,gap:`4px`,padding:`8px 12px`,margin:`4px 0`,borderRadius:`8px`,border:`1px solid rgba(127,127,127,0.35)`,background:`rgba(127,127,127,0.08)`,color:`inherit`,fontSize:`12px`,lineHeight:1.5,fontFamily:`inherit`};var x=class extends m.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){console.error(`[dsh-genui] render failed:`,e,t.componentStack??``)}render(){let{error:e}=this.state;return e===null?this.props.children:(0,g.jsxs)(`div`,{style:b,role:`alert`,"data-genui-error":!0,children:[(0,g.jsxs)(`span`,{style:{fontWeight:600},children:[`⚠️ `,this.props.label??`此界面`,`渲染失败(已隔离,不影响其他内容)`]}),(0,g.jsx)(`span`,{style:{opacity:.75,overflowWrap:`anywhere`},children:e.message})]})}};let S=`@omdsh-dev/dsh-genui/GenuiBlock.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(S)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@omdsh-dev/dsh-genui`,e.dataset.pluginCss=S,e.textContent=`.V1MMBW_block{--dsl-g-radius-surface:12px;--dsl-g-radius-control:8px;--dsl-g-radius-pill:999px;--dsl-g-font-display:24px;--dsl-g-font-h1:20px;--dsl-g-font-h2:16px;--dsl-g-font-h3:14px;--dsl-g-font-body:14px;--dsl-g-font-title:13px;--dsl-g-font-meta:12px;--dsl-g-font-data:11px;--dsl-g-gap-lg:16px;--dsl-g-gap-md:12px;--dsl-g-gap-sm:8px;--dsl-g-gap-xs:4px;--dsl-g-border:var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,#ffffff1f));--dsl-g-border-strong:var(--dsw-alias-border-l2,#ffffff1f);--dsl-g-accent:var(--dsw-alias-state-business-primary,#4f8ef7);--dsl-g-accent-soft:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);--dsl-g-hover:color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);--dsl-g-tint:8%;--dsl-g-tint-strong:14%;--dsl-g-font-mono:var(--ds-font-family-code,ui-monospace, "SF Mono", monospace);color:var(--dsw-alias-label-primary);margin:8px 0}.V1MMBW_banner{font-size:var(--dsl-g-font-title);letter-spacing:.01em;color:var(--dsw-alias-label-primary);margin-bottom:var(--dsl-g-gap-lg);border-bottom:1px solid var(--dsl-g-border);padding-bottom:10px;font-weight:600}.V1MMBW_col{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_row{align-items:center;gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_row.V1MMBW_wrap{flex-wrap:wrap}.V1MMBW_grid{gap:var(--dsl-g-gap-md);display:grid}.V1MMBW_spacer{flex:1}.V1MMBW_divider{background:var(--dsw-alias-markdown-hr,var(--dsl-g-border));height:1px;margin:var(--dsl-g-gap-xs) 0;border:none}.V1MMBW_card{background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);padding:var(--dsl-g-gap-lg);gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_cardTitle{font-size:var(--dsl-g-font-meta);letter-spacing:.02em;color:var(--dsw-alias-label-secondary);font-weight:600}.V1MMBW_text{color:var(--dsw-alias-label-primary)}.V1MMBW_text.V1MMBW_h1{font-size:var(--dsl-g-font-h1);letter-spacing:-.02em;font-weight:700;line-height:1.3}.V1MMBW_text.V1MMBW_h2{font-size:var(--dsl-g-font-h2);letter-spacing:-.01em;font-weight:600;line-height:1.35}.V1MMBW_text.V1MMBW_h3{font-size:var(--dsl-g-font-h3);font-weight:600;line-height:1.5}.V1MMBW_text.V1MMBW_body{font-size:var(--dsl-g-font-body);color:var(--dsw-alias-label-primary);line-height:1.6}.V1MMBW_text.V1MMBW_muted{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);line-height:1.5}.V1MMBW_text.V1MMBW_caption{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);letter-spacing:.02em;line-height:1.5}.V1MMBW_text.V1MMBW_center{text-align:center}.V1MMBW_button{border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:var(--dsl-g-radius-control);padding:8px var(--dsl-g-gap-lg);font-size:var(--dsl-g-font-title);cursor:pointer;text-align:center;font-family:inherit;font-weight:600;line-height:1.4;transition:border-color .15s,filter .15s,background .15s,transform .1s}.V1MMBW_button:hover:not(:disabled){border-color:var(--dsl-g-accent);filter:brightness(1.06)}.V1MMBW_button.V1MMBW_primary:hover:not(:disabled){filter:brightness(1.08)}.V1MMBW_button:active:not(:disabled){filter:brightness(.97);transform:translateY(1px)}.V1MMBW_button:disabled{cursor:not-allowed;opacity:.45;filter:none;box-shadow:none;pointer-events:none}.V1MMBW_button.V1MMBW_primary{background:var(--dsl-g-accent);color:#fff;border:none;box-shadow:inset 0 1px #ffffff24}.V1MMBW_button.V1MMBW_danger{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent);color:var(--dsw-alias-state-error-primary,#ffb3b3)}.V1MMBW_button.V1MMBW_success{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent);color:var(--dsw-alias-state-success-secondary,#9fe8c5)}.V1MMBW_button.V1MMBW_ghost{background:0 0}.V1MMBW_button.V1MMBW_full{width:100%}.V1MMBW_button.V1MMBW_small{font-size:var(--dsl-g-font-meta);border-radius:var(--dsl-g-radius-control);padding:4px 12px}.V1MMBW_field{gap:var(--dsl-g-gap-xs);flex-direction:column;display:flex}.V1MMBW_field>span{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_input,.V1MMBW_select{background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);color:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-title);outline:none;width:100%;padding:8px 12px;font-family:inherit}.V1MMBW_input:focus,.V1MMBW_select:focus{border-color:var(--dsl-g-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_input::placeholder{color:var(--dsw-alias-label-caption,#5b6378)}.V1MMBW_checkbox{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;display:flex}.V1MMBW_checkbox input{accent-color:var(--dsl-g-accent);width:15px;height:15px}.V1MMBW_checkbox input:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:4px}.V1MMBW_link{color:var(--dsl-g-accent);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:none;padding:0;font-family:inherit;text-decoration:none}.V1MMBW_link:hover{text-decoration:underline}.V1MMBW_linkText{color:var(--dsl-g-accent);font-size:var(--dsl-g-font-title);font-family:inherit;text-decoration:none}.V1MMBW_media{padding:var(--dsl-g-gap-md);gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;margin:0;display:flex}.V1MMBW_mediaLabel{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_mediaPlayer{width:100%;min-width:0;display:block}.V1MMBW_videoPlayer{object-fit:contain;background:#000;max-height:min(70vh,720px)}.V1MMBW_mediaError{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#f25a5a)}.V1MMBW_badge{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);letter-spacing:.01em;border-radius:var(--dsl-g-radius-pill);background:color-mix(in srgb, var(--dsw-alias-label-tertiary) var(--dsl-g-tint), transparent);width:fit-content;color:var(--dsw-alias-label-secondary);border:1px solid var(--dsl-g-border);padding:1px 10px;font-weight:500;line-height:1.5;display:inline-flex}.V1MMBW_badge.V1MMBW_success{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-success-secondary,#7fe3b4);border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent)}.V1MMBW_badge.V1MMBW_warn{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-warn-secondary,#f7cf7d);border-color:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) 30%, transparent)}.V1MMBW_badge.V1MMBW_danger{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-error-primary,#ff9d9d);border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent)}.V1MMBW_badge.V1MMBW_accent{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);color:var(--dsw-alias-state-business-primary,#9cc3ff);border-color:color-mix(in srgb, var(--dsl-g-accent) 30%, transparent)}.V1MMBW_stat{padding:6px var(--dsl-g-gap-lg);flex-direction:column;gap:2px;display:flex}.V1MMBW_grid>.V1MMBW_stat,.V1MMBW_row>.V1MMBW_stat{border-left:1px solid var(--dsl-g-border)}.V1MMBW_grid>.V1MMBW_stat:first-child,.V1MMBW_row>.V1MMBW_stat:first-child{padding-left:var(--dsl-g-gap-xs);border-left:none}.V1MMBW_statLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);letter-spacing:.02em}.V1MMBW_statValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-display);letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.2}.V1MMBW_statDelta{font-size:var(--dsl-g-font-meta);font-weight:500}.V1MMBW_statDelta.V1MMBW_up{color:var(--dsw-alias-state-success-primary,#22c55e)}.V1MMBW_statDelta.V1MMBW_down{color:var(--dsw-alias-state-error-primary,#f25a5a)}.V1MMBW_progress{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_progressRow{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);justify-content:space-between;display:flex}.V1MMBW_progressRow span:last-child{font-family:var(--dsl-g-font-mono)}.V1MMBW_track{border-radius:var(--dsl-g-radius-pill);background:var(--dsw-alias-bg-layer-1);height:6px;box-shadow:inset 0 0 0 1px var(--dsl-g-border);overflow:hidden}.V1MMBW_fill{border-radius:var(--dsl-g-radius-pill);background:linear-gradient(180deg, color-mix(in srgb, var(--dsl-g-accent) 85%, white), var(--dsl-g-accent));height:100%;transition:width .5s}.V1MMBW_list{flex-direction:column;display:flex}.V1MMBW_li{padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-xs);flex-direction:column;gap:2px;display:flex}.V1MMBW_li+.V1MMBW_li{border-top:1px solid var(--dsl-g-border)}.V1MMBW_li:last-child{border-bottom:none}.V1MMBW_liTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_liDesc{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);line-height:1.5}.V1MMBW_tableWrap{border-radius:var(--dsl-g-radius-control);overscroll-behavior-x:contain;min-width:0;max-width:100%;overflow-x:auto}.V1MMBW_table{border-collapse:collapse;width:100%;font-size:var(--dsl-g-font-title)}.V1MMBW_table th{text-align:left;padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-md);color:var(--dsw-alias-label-tertiary);font-weight:600;font-size:var(--dsl-g-font-meta);border-bottom:1px solid var(--dsl-g-border);white-space:nowrap}.V1MMBW_table td{padding:var(--dsl-g-gap-sm) var(--dsl-g-gap-md);border-bottom:1px solid var(--dsl-g-border);color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;line-height:1.5}.V1MMBW_table tr:last-child td{border-bottom:none}.V1MMBW_table tbody tr{transition:background .12s}.V1MMBW_table tbody tr:hover{background:var(--dsl-g-hover)}.V1MMBW_table th.V1MMBW_thNum,.V1MMBW_table td.V1MMBW_tdNum{text-align:right}.V1MMBW_thSort{color:inherit;font:inherit;font-weight:inherit;cursor:pointer;text-align:left;background:0 0;border:none;margin:0;padding:0;transition:color .12s}.V1MMBW_table th.V1MMBW_thNum .V1MMBW_thSort{text-align:right;width:100%}.V1MMBW_thSort:hover,.V1MMBW_table th[aria-sort]:not([aria-sort=none]) .V1MMBW_thSort{color:var(--dsw-alias-label-primary)}.V1MMBW_thSortMark{color:var(--dsl-g-accent)}.V1MMBW_thSort:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px;border-radius:var(--dsl-g-radius-control)}.V1MMBW_chart{gap:var(--dsl-g-gap-xs);flex-direction:column;display:flex}.V1MMBW_chartPlot{align-items:flex-end;gap:var(--dsl-g-gap-sm);height:132px;display:flex;position:relative}.V1MMBW_baseline{background:var(--dsl-g-border-strong);pointer-events:none;height:1px;position:absolute;bottom:0;left:0;right:0}.V1MMBW_gridline{background:var(--dsw-alias-border-l1,#ffffff0f);pointer-events:none;height:1px;position:absolute;left:0;right:0}.V1MMBW_chartLabels{gap:var(--dsl-g-gap-sm);display:flex}.V1MMBW_chartLabels>span{flex:1;min-width:0}.V1MMBW_barCol{justify-content:flex-end;gap:var(--dsl-g-gap-xs);flex-direction:column;flex:1;min-width:0;height:100%;display:flex}.V1MMBW_barValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);text-align:center;line-height:1.2}.V1MMBW_barFill{background:var(--dsl-g-accent);border-radius:4px 4px 2px 2px;min-height:4px;transition:height .6s,filter .15s}.V1MMBW_barFill:hover{filter:brightness(1.18)}.V1MMBW_barLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);text-align:center;white-space:nowrap;text-overflow:ellipsis;line-height:1.5;overflow:hidden}.V1MMBW_tabs{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_tabBar{gap:var(--dsl-g-gap-xs);border-bottom:1px solid var(--dsl-g-border);display:flex}.V1MMBW_tab{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-1px;padding:6px 12px;font-family:inherit;font-weight:600;line-height:1.5;transition:color .15s,border-bottom-color .15s}.V1MMBW_tab:hover{color:var(--dsw-alias-label-secondary)}.V1MMBW_tabActive{color:var(--dsw-alias-label-primary);border-bottom-color:var(--dsl-g-accent)}.V1MMBW_avatar{width:32px;height:32px;font-size:var(--dsl-g-font-title);color:#fff;border:1px solid #ffffff24;border-radius:50%;flex-shrink:0;place-items:center;font-weight:700;display:grid;box-shadow:inset 0 1px #ffffff29}.V1MMBW_callout{border-radius:var(--dsl-g-radius-control);border:1px solid var(--dsl-g-border);font-size:var(--dsl-g-font-title);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));flex-direction:column;gap:2px;padding:10px 14px;line-height:1.6;display:flex}.V1MMBW_calloutInfo{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent)}.V1MMBW_calloutSuccess{background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent)}.V1MMBW_calloutWarning{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f5b83d) var(--dsl-g-tint), transparent)}.V1MMBW_calloutError{background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent)}.V1MMBW_calloutTitle{font-weight:600;font-size:var(--dsl-g-font-meta);letter-spacing:.02em;color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;display:flex}.V1MMBW_calloutTitle:before{content:"";background:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));border-radius:50%;width:6px;height:6px}.V1MMBW_calloutInfo .V1MMBW_calloutTitle:before{background:var(--dsl-g-accent)}.V1MMBW_calloutSuccess .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_calloutWarning .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-warn-primary,#f5b83d)}.V1MMBW_calloutError .V1MMBW_calloutTitle:before{background:var(--dsw-alias-state-error-primary,#ff6b6b)}.V1MMBW_calloutBody{color:var(--dsw-alias-label-secondary)}.V1MMBW_steps{gap:var(--dsl-g-gap-sm);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.V1MMBW_step{gap:var(--dsl-g-gap-md);align-items:flex-start;display:flex}.V1MMBW_stepMarker{width:24px;height:24px;font-size:var(--dsl-g-font-meta);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsl-g-border);color:var(--dsw-alias-label-tertiary);border-radius:50%;flex-shrink:0;place-items:center;font-weight:700;display:grid}.V1MMBW_stepDone .V1MMBW_stepMarker{background:var(--dsw-alias-state-success-primary,#3ecf8e);color:#fff;border-color:#0000;font-size:13px}.V1MMBW_stepActive .V1MMBW_stepMarker{background:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent);border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}.V1MMBW_stepContent{flex-direction:column;gap:2px;padding-top:3px;display:flex}.V1MMBW_stepTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_stepDesc{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);line-height:1.5}.V1MMBW_keyvalue{flex-direction:column;margin:0;display:flex}.V1MMBW_kvRow{gap:var(--dsl-g-gap-md);font-size:var(--dsl-g-font-title);padding:6px 0;display:flex}.V1MMBW_kvRow+.V1MMBW_kvRow{border-top:1px solid var(--dsl-g-border)}.V1MMBW_kvRow:last-child{border-bottom:none}.V1MMBW_kvKey{width:96px;color:var(--dsw-alias-label-tertiary);flex-shrink:0;font-weight:600}.V1MMBW_kvValue{color:var(--dsw-alias-label-primary);word-break:break-word;margin:0;line-height:1.5}.V1MMBW_jsonScalar{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary)}.V1MMBW_lineChart{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_linePath{fill:none;stroke:var(--dsl-g-accent);stroke-width:2px;stroke-linejoin:round;stroke-linecap:round}.V1MMBW_lineDot{fill:var(--dsl-g-accent);transition:filter .15s}.V1MMBW_lineDot:hover{filter:brightness(1.3)}.V1MMBW_lineGrid{stroke:var(--dsw-alias-border-l1,#ffffff12);stroke-width:1px}.V1MMBW_lineGridAxis{stroke:var(--dsl-g-border-strong);stroke-width:1px}.V1MMBW_lineTick{fill:var(--dsw-alias-label-tertiary);font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data)}.V1MMBW_lineLabels{justify-content:space-between;display:flex}.V1MMBW_groupedBars{gap:var(--dsl-g-gap-xs);align-items:flex-end;width:100%;height:100%;display:flex}.V1MMBW_groupedBar{flex-direction:column;flex:1;justify-content:flex-end;align-items:center;gap:2px;min-width:0;height:100%;display:flex}.V1MMBW_groupValue{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;max-width:100%;line-height:1.2;overflow:hidden}.V1MMBW_groupedFill{background:var(--dsl-g-accent);border-radius:4px 4px 2px 2px;flex:none;width:100%;min-height:3px;transition:filter .15s}.V1MMBW_groupedFill:hover{filter:brightness(1.18)}.V1MMBW_donut{align-items:center;gap:var(--dsl-g-gap-lg);display:flex}.V1MMBW_donutTrack{stroke:var(--dsw-alias-border-l1,#ffffff14)}.V1MMBW_donutSeg{transition:filter .15s}.V1MMBW_donutSeg:hover{filter:brightness(1.18)}.V1MMBW_donutTotal{fill:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-h2);font-weight:700}.V1MMBW_donutTotalLabel{fill:var(--dsw-alias-label-tertiary);font-size:10px}.V1MMBW_donutLegend{gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);flex-direction:column;line-height:1.5;display:flex}.V1MMBW_fieldGroup{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_fieldLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_radio{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;line-height:1.5;display:flex}.V1MMBW_radio input{accent-color:var(--dsl-g-accent)}.V1MMBW_radio input:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:50%}.V1MMBW_submitRow{align-items:center;gap:var(--dsl-g-gap-md);margin-top:2px;display:flex}.V1MMBW_submit{align-self:flex-start}.V1MMBW_submitHint{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_btnSent{margin-left:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-state-success-primary,#3ecf8e);font-weight:600}.V1MMBW_gradeWrap{gap:var(--dsl-g-gap-md);flex-direction:column;display:flex}.V1MMBW_gradeScore{align-items:baseline;gap:var(--dsl-g-gap-sm);display:flex}.V1MMBW_gradeScoreValue{font-size:var(--dsl-g-font-display);color:var(--dsw-alias-label-primary);font-weight:700;line-height:1.2}.V1MMBW_gradeScoreLabel{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}.V1MMBW_gradeList{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_gradeItem{font-size:var(--dsl-g-font-title);padding:var(--dsl-g-gap-sm) 12px;border-radius:var(--dsl-g-radius-control);border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);grid-template-columns:auto auto 1fr;align-items:baseline;gap:6px 10px;line-height:1.5;display:grid}.V1MMBW_gradeItemOk{border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 30%, transparent)}.V1MMBW_gradeItemNo{border-color:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent)}.V1MMBW_gradeQ{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_gradeTag{font-weight:700}.V1MMBW_gradeItemOk .V1MMBW_gradeTag{color:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_gradeItemNo .V1MMBW_gradeTag{color:var(--dsw-alias-state-error-primary,#ff6b6b)}.V1MMBW_gradeAns{color:var(--dsw-alias-label-secondary)}.V1MMBW_gradeRight{color:var(--dsw-alias-state-error-primary,#ffb3b3)}.V1MMBW_gradeExp{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);grid-column:1/-1;line-height:1.5}.V1MMBW_switchRow{justify-content:space-between;align-items:center;gap:var(--dsl-g-gap-md);cursor:pointer;display:flex}.V1MMBW_switchRow:focus-within .V1MMBW_switch{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_switchLabel{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);line-height:1.5}.V1MMBW_switch{border-radius:var(--dsl-g-radius-pill);border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-base,#17171a);width:38px;height:22px;transition:background .2s;position:relative}.V1MMBW_switchOn{background:var(--dsl-g-accent);border-color:#0000}.V1MMBW_switchKnob{background:#fff;border-radius:50%;width:14px;height:14px;transition:left .2s;position:absolute;top:3px;left:3px;box-shadow:0 1px 2px #0000004d}.V1MMBW_switchOn .V1MMBW_switchKnob{left:19px}.V1MMBW_sliderRow{align-items:center;gap:var(--dsl-g-gap-md);width:100%;display:flex}.V1MMBW_sliderInput{min-width:0;accent-color:var(--dsl-g-accent);flex:1}.V1MMBW_sliderInput:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:2px;border-radius:4px}.V1MMBW_sliderValue{text-align:right;min-width:44px;font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-data);color:var(--dsw-alias-label-primary)}.V1MMBW_textarea{background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);width:100%;color:var(--dsw-alias-label-primary);padding:var(--dsl-g-gap-sm) 12px;font-size:var(--dsl-g-font-title);resize:vertical;outline:none;font-family:inherit;line-height:1.5}.V1MMBW_textarea:focus{border-color:var(--dsl-g-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent)}.V1MMBW_accordion{border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex;overflow:hidden}.V1MMBW_accItem{border-bottom:1px solid var(--dsl-g-border)}.V1MMBW_accItem:last-child{border-bottom:none}.V1MMBW_accHead{justify-content:space-between;align-items:center;gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);font-size:var(--dsl-g-font-title);cursor:pointer;border:none;padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;transition:background .15s,color .15s;display:flex}.V1MMBW_accHead:hover{background:color-mix(in srgb, var(--dsw-alias-label-primary) 5%, var(--dsw-alias-bg-layer-1))}.V1MMBW_accHead:active{color:var(--dsl-g-accent)}.V1MMBW_accChevron{color:var(--dsw-alias-label-tertiary);transition:transform .2s}.V1MMBW_accBody{padding:var(--dsl-g-gap-md) 14px;gap:var(--dsl-g-gap-sm);background:var(--dsw-alias-bg-base,#17171a);flex-direction:column;display:flex}.V1MMBW_copyChip{border:1px solid var(--dsl-g-border);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;width:fit-content;padding:6px 14px;font-family:inherit;font-weight:600;transition:all .15s}.V1MMBW_copyChip:hover{border-color:var(--dsl-g-accent)}.V1MMBW_copyChip:active{transform:translateY(1px)}.V1MMBW_copyChipDone{border-color:var(--dsw-alias-state-success-primary,#3ecf8e);color:var(--dsw-alias-state-success-primary,#3ecf8e)}.V1MMBW_mermaid{padding:var(--dsl-g-gap-xs) 0;overflow-x:auto}.V1MMBW_mermaid svg{max-width:100%;height:auto}.V1MMBW_mermaidFallback{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_mermaidFallback pre{padding:var(--dsl-g-gap-sm) 10px;background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-meta);margin:0;overflow-x:auto}.V1MMBW_mermaidErr{color:var(--dsw-alias-state-error-primary,#ff6b6b);font-size:var(--dsl-g-font-meta)}.V1MMBW_mermaidHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_scene3dWrap{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_echartWrap{gap:var(--dsl-g-gap-sm);padding:var(--dsl-g-gap-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_echartTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_echartCanvas{width:100%;min-height:0}.V1MMBW_echartHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_echartFallback{gap:var(--dsl-g-gap-sm);padding:var(--dsl-g-gap-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_echartErr{color:var(--dsw-alias-state-error-primary,#ff6b6b);font-size:var(--dsl-g-font-meta)}.V1MMBW_scene3dTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:700}.V1MMBW_scene3dCanvas{border-radius:var(--dsl-g-radius-surface);background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);height:240px;overflow:hidden}.V1MMBW_scene3dCanvas canvas{display:block}.V1MMBW_scene3dHint{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-meta)}.V1MMBW_timeline{flex-direction:column;display:flex}.V1MMBW_tlItem{gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_tlRail{flex-direction:column;flex-shrink:0;align-items:center;width:12px;display:flex}.V1MMBW_tlDot{background:var(--dsl-g-accent);width:10px;height:10px;box-shadow:0 0 0 3px color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint-strong), transparent);border-radius:50%;flex-shrink:0;margin-top:4px}.V1MMBW_tlLine{background:var(--dsl-g-border);flex:1;width:2px;margin:2px 0}.V1MMBW_tlBody{padding-bottom:var(--dsl-g-gap-lg);flex:1;min-width:0}.V1MMBW_tlHead{align-items:baseline;gap:var(--dsl-g-gap-md);display:flex}.V1MMBW_tlTitle{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.5}.V1MMBW_tlTime{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);white-space:nowrap;margin-left:auto}.V1MMBW_tlDesc{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);margin-top:2px;line-height:1.5}.V1MMBW_fileTree{font-family:var(--dsl-g-font-mono);font-size:var(--dsl-g-font-meta);overscroll-behavior-x:contain;flex-direction:column;min-width:0;max-width:100%;display:flex;overflow-x:auto}.V1MMBW_ftRow{align-items:center;gap:var(--dsl-g-gap-sm);padding:3px var(--dsl-g-gap-xs);border-radius:var(--dsl-g-radius-control);display:flex}.V1MMBW_ftRow:hover{background:var(--dsw-alias-bg-layer-1)}.V1MMBW_ftIcon{text-align:center;width:13px;font-size:10px;font-family:var(--dsl-g-font-mono);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));flex-shrink:0;line-height:1}.V1MMBW_ftIconDir{color:var(--dsl-g-accent);font-size:11px}.V1MMBW_ftName{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.V1MMBW_ftDir{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_ftNameBtn{align-items:center;gap:var(--dsl-g-gap-sm);min-width:0;max-width:100%;font-family:inherit;font-size:var(--dsl-g-font-body);cursor:default;text-align:left;background:0 0;border:none;padding:0;display:inline-flex}button.V1MMBW_ftNameBtn[aria-expanded]{cursor:pointer}.V1MMBW_ftNameBtn:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px;border-radius:var(--dsl-g-radius-control)}.V1MMBW_breadcrumb{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-title);flex-wrap:wrap;display:flex}.V1MMBW_bcItem{align-items:center;gap:var(--dsl-g-gap-xs);display:inline-flex}.V1MMBW_bcText{color:var(--dsw-alias-label-secondary);cursor:pointer}.V1MMBW_bcText:hover{color:var(--dsl-g-accent)}.V1MMBW_bcCurrent{color:var(--dsw-alias-label-primary);cursor:default;font-weight:600}.V1MMBW_bcSep{color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary))}@keyframes V1MMBW_genuiReveal{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes V1MMBW_genuiPopIn{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.V1MMBW_reveal{animation:.45s cubic-bezier(.22,1,.36,1) both V1MMBW_genuiReveal}.V1MMBW_btnSent{animation:.2s both V1MMBW_genuiPopIn}@media (prefers-reduced-motion:reduce){.V1MMBW_reveal,.V1MMBW_btnSent{animation:none}.V1MMBW_fill,.V1MMBW_barFill,.V1MMBW_switch,.V1MMBW_switchKnob{transition:none}}.V1MMBW_tableWrap,.V1MMBW_fileTree,.V1MMBW_mermaid,.V1MMBW_panelBody{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l2,#ffffff38) transparent}.V1MMBW_tableWrap::-webkit-scrollbar,.V1MMBW_fileTree::-webkit-scrollbar,.V1MMBW_mermaid::-webkit-scrollbar,.V1MMBW_panelBody::-webkit-scrollbar{width:8px;height:8px}.V1MMBW_tableWrap::-webkit-scrollbar-thumb,.V1MMBW_fileTree::-webkit-scrollbar-thumb,.V1MMBW_mermaid::-webkit-scrollbar-thumb,.V1MMBW_panelBody::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l2,#ffffff38);border-radius:4px}.V1MMBW_tableWrap::-webkit-scrollbar-track,.V1MMBW_fileTree::-webkit-scrollbar-track,.V1MMBW_mermaid::-webkit-scrollbar-track,.V1MMBW_panelBody::-webkit-scrollbar-track{background:0 0}.V1MMBW_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.V1MMBW_quiz{gap:var(--dsl-g-gap-md);padding:var(--dsl-g-gap-lg);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);flex-direction:column;display:flex}.V1MMBW_quizQuestion{font-size:var(--dsl-g-font-body);color:var(--dsw-alias-label-primary);font-weight:600;line-height:1.6}.V1MMBW_quizOptions{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_quizOpt{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:var(--dsw-alias-bg-base,#17171a);border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-label-secondary);cursor:pointer;padding:10px 14px;font-family:inherit;line-height:1.5;transition:border-color .15s,background .15s;display:flex}.V1MMBW_quizOpt:hover:not(:disabled){border-color:var(--dsl-g-accent);background:var(--dsl-g-accent-soft)}.V1MMBW_quizOpt:focus-visible,.V1MMBW_button:focus-visible,.V1MMBW_tab:focus-visible,.V1MMBW_accHead:focus-visible,.V1MMBW_copyChip:focus-visible,.V1MMBW_link:focus-visible,.V1MMBW_quizRetry:focus-visible,.V1MMBW_resetBtn:focus-visible,.V1MMBW_playBtn:focus-visible,.V1MMBW_bcText:focus-visible{outline:2px solid var(--dsl-g-accent);outline-offset:1px}.V1MMBW_quizOpt:disabled{cursor:default;opacity:.85}.V1MMBW_quizOptCorrect{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 40%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;display:flex}.V1MMBW_quizOptWrong{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) var(--dsl-g-tint), transparent);border:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary,#ff6b6b) 30%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#ff6b6b);padding:10px 14px;font-family:inherit;font-weight:600;line-height:1.5;display:flex}.V1MMBW_quizOptReveal{align-items:center;gap:var(--dsl-g-gap-sm);text-align:left;background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) var(--dsl-g-tint), transparent);border:1px dashed color-mix(in srgb, var(--dsw-alias-state-success-primary,#3ecf8e) 40%, transparent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);padding:10px 14px;font-family:inherit;line-height:1.5;display:flex}.V1MMBW_quizMarker{text-align:center;width:16px;font-weight:700}.V1MMBW_quizResult{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}.V1MMBW_quizCorrectMsg{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-success-primary,#3ecf8e);font-weight:600}.V1MMBW_quizWrongMsg{font-size:var(--dsl-g-font-title);color:var(--dsw-alias-state-error-primary,#ff6b6b);font-weight:600}.V1MMBW_quizFeedback{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);margin-top:3px;font-weight:400;line-height:1.5}.V1MMBW_quizExplanation{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary);padding:var(--dsl-g-gap-sm) 10px;border-top:1px solid var(--dsl-g-border);line-height:1.6}.V1MMBW_quizRetry{border:1px solid var(--dsl-g-border);width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;padding:6px 14px;font-family:inherit}.V1MMBW_quizRetry:hover{border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}.V1MMBW_tool{margin:4px 0}.V1MMBW_toolFallback{align-items:center;gap:var(--dsl-g-gap-md);padding:var(--dsl-g-gap-sm) 12px;border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));font-size:var(--dsl-g-font-title);display:flex}.V1MMBW_toolFallbackTitle{color:var(--dsw-alias-label-primary);font-weight:600}.V1MMBW_toolFallbackMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.V1MMBW_panel{border:1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) 35%, transparent);background:var(--dsw-alias-bg-layer-1,#ffffff0a);border-radius:14px;margin:10px 14px 2px;overflow:hidden}.V1MMBW_panelHeader{align-items:center;display:flex}.V1MMBW_panelToggle{align-items:center;gap:var(--dsl-g-gap-sm);min-width:0;color:inherit;font:inherit;font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;border:0;flex:auto;padding:9px 14px;display:flex}.V1MMBW_panelToggle:hover{background:#ffffff0a}.V1MMBW_panelClose{width:26px;height:26px;color:inherit;cursor:pointer;opacity:.65;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;margin-right:8px;padding:0;font-size:13px;line-height:1;display:flex}.V1MMBW_panelClose:hover{opacity:1;background:#ffffff14}.V1MMBW_panelClose:focus-visible{outline:1px solid var(--dsw-alias-state-business-primary,#4f8ef7);outline-offset:1px;opacity:1}.V1MMBW_panelBadge{padding:0 var(--dsl-g-gap-sm);background:color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) var(--dsl-g-tint-strong), transparent);color:var(--dsw-alias-state-business-primary,#7ba8ff);letter-spacing:.04em;border-radius:6px;flex:none;font-size:11px;font-weight:600;line-height:1.6}.V1MMBW_panelTitle{color:var(--dsw-alias-label-primary,#e6e6e6);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.V1MMBW_panelChevron{color:var(--dsw-alias-label-secondary,#ffffff8c);font-size:var(--dsl-g-font-meta);margin-left:auto}.V1MMBW_panelBody{height:360px;padding:0 16px var(--dsl-g-gap-lg);overflow-y:auto}.V1MMBW_panelResizeHandle{cursor:ns-resize;touch-action:none;background:0 0;border-radius:3px;height:6px;transition:background .15s}.V1MMBW_panelResizeHandle:hover,.V1MMBW_panelResizeHandleActive{background:color-mix(in srgb, var(--dsw-alias-state-business-primary,#4f8ef7) 35%, transparent)}`,document.head.appendChild(e)}var C={accBody:`V1MMBW_accBody`,accChevron:`V1MMBW_accChevron`,accHead:`V1MMBW_accHead`,accItem:`V1MMBW_accItem`,accent:`V1MMBW_accent`,accordion:`V1MMBW_accordion`,avatar:`V1MMBW_avatar`,badge:`V1MMBW_badge`,banner:`V1MMBW_banner`,barCol:`V1MMBW_barCol`,barFill:`V1MMBW_barFill`,barLabel:`V1MMBW_barLabel`,barValue:`V1MMBW_barValue`,baseline:`V1MMBW_baseline`,bcCurrent:`V1MMBW_bcCurrent`,bcItem:`V1MMBW_bcItem`,bcSep:`V1MMBW_bcSep`,bcText:`V1MMBW_bcText`,block:`V1MMBW_block`,body:`V1MMBW_body`,breadcrumb:`V1MMBW_breadcrumb`,btnSent:`V1MMBW_btnSent`,button:`V1MMBW_button`,callout:`V1MMBW_callout`,calloutBody:`V1MMBW_calloutBody`,calloutError:`V1MMBW_calloutError`,calloutInfo:`V1MMBW_calloutInfo`,calloutSuccess:`V1MMBW_calloutSuccess`,calloutTitle:`V1MMBW_calloutTitle`,calloutWarning:`V1MMBW_calloutWarning`,caption:`V1MMBW_caption`,card:`V1MMBW_card`,cardTitle:`V1MMBW_cardTitle`,center:`V1MMBW_center`,chart:`V1MMBW_chart`,chartLabels:`V1MMBW_chartLabels`,chartPlot:`V1MMBW_chartPlot`,checkbox:`V1MMBW_checkbox`,col:`V1MMBW_col`,copyChip:`V1MMBW_copyChip`,copyChipDone:`V1MMBW_copyChipDone`,danger:`V1MMBW_danger`,divider:`V1MMBW_divider`,donut:`V1MMBW_donut`,donutLegend:`V1MMBW_donutLegend`,donutSeg:`V1MMBW_donutSeg`,donutTotal:`V1MMBW_donutTotal`,donutTotalLabel:`V1MMBW_donutTotalLabel`,donutTrack:`V1MMBW_donutTrack`,down:`V1MMBW_down`,echartCanvas:`V1MMBW_echartCanvas`,echartErr:`V1MMBW_echartErr`,echartFallback:`V1MMBW_echartFallback`,echartHint:`V1MMBW_echartHint`,echartTitle:`V1MMBW_echartTitle`,echartWrap:`V1MMBW_echartWrap`,field:`V1MMBW_field`,fieldGroup:`V1MMBW_fieldGroup`,fieldLabel:`V1MMBW_fieldLabel`,fileTree:`V1MMBW_fileTree`,fill:`V1MMBW_fill`,ftDir:`V1MMBW_ftDir`,ftIcon:`V1MMBW_ftIcon`,ftIconDir:`V1MMBW_ftIconDir`,ftName:`V1MMBW_ftName`,ftNameBtn:`V1MMBW_ftNameBtn`,ftRow:`V1MMBW_ftRow`,full:`V1MMBW_full`,genuiPopIn:`V1MMBW_genuiPopIn`,genuiReveal:`V1MMBW_genuiReveal`,ghost:`V1MMBW_ghost`,gradeAns:`V1MMBW_gradeAns`,gradeExp:`V1MMBW_gradeExp`,gradeItem:`V1MMBW_gradeItem`,gradeItemNo:`V1MMBW_gradeItemNo`,gradeItemOk:`V1MMBW_gradeItemOk`,gradeList:`V1MMBW_gradeList`,gradeQ:`V1MMBW_gradeQ`,gradeRight:`V1MMBW_gradeRight`,gradeScore:`V1MMBW_gradeScore`,gradeScoreLabel:`V1MMBW_gradeScoreLabel`,gradeScoreValue:`V1MMBW_gradeScoreValue`,gradeTag:`V1MMBW_gradeTag`,gradeWrap:`V1MMBW_gradeWrap`,grid:`V1MMBW_grid`,gridline:`V1MMBW_gridline`,groupValue:`V1MMBW_groupValue`,groupedBar:`V1MMBW_groupedBar`,groupedBars:`V1MMBW_groupedBars`,groupedFill:`V1MMBW_groupedFill`,h1:`V1MMBW_h1`,h2:`V1MMBW_h2`,h3:`V1MMBW_h3`,input:`V1MMBW_input`,jsonScalar:`V1MMBW_jsonScalar`,keyvalue:`V1MMBW_keyvalue`,kvKey:`V1MMBW_kvKey`,kvRow:`V1MMBW_kvRow`,kvValue:`V1MMBW_kvValue`,li:`V1MMBW_li`,liDesc:`V1MMBW_liDesc`,liTitle:`V1MMBW_liTitle`,lineChart:`V1MMBW_lineChart`,lineDot:`V1MMBW_lineDot`,lineGrid:`V1MMBW_lineGrid`,lineGridAxis:`V1MMBW_lineGridAxis`,lineLabels:`V1MMBW_lineLabels`,linePath:`V1MMBW_linePath`,lineTick:`V1MMBW_lineTick`,link:`V1MMBW_link`,linkText:`V1MMBW_linkText`,list:`V1MMBW_list`,media:`V1MMBW_media`,mediaError:`V1MMBW_mediaError`,mediaLabel:`V1MMBW_mediaLabel`,mediaPlayer:`V1MMBW_mediaPlayer`,mermaid:`V1MMBW_mermaid`,mermaidErr:`V1MMBW_mermaidErr`,mermaidFallback:`V1MMBW_mermaidFallback`,mermaidHint:`V1MMBW_mermaidHint`,muted:`V1MMBW_muted`,panel:`V1MMBW_panel`,panelBadge:`V1MMBW_panelBadge`,panelBody:`V1MMBW_panelBody`,panelChevron:`V1MMBW_panelChevron`,panelClose:`V1MMBW_panelClose`,panelHeader:`V1MMBW_panelHeader`,panelResizeHandle:`V1MMBW_panelResizeHandle`,panelResizeHandleActive:`V1MMBW_panelResizeHandleActive`,panelTitle:`V1MMBW_panelTitle`,panelToggle:`V1MMBW_panelToggle`,playBtn:`V1MMBW_playBtn`,primary:`V1MMBW_primary`,progress:`V1MMBW_progress`,progressRow:`V1MMBW_progressRow`,quiz:`V1MMBW_quiz`,quizCorrectMsg:`V1MMBW_quizCorrectMsg`,quizExplanation:`V1MMBW_quizExplanation`,quizFeedback:`V1MMBW_quizFeedback`,quizMarker:`V1MMBW_quizMarker`,quizOpt:`V1MMBW_quizOpt`,quizOptCorrect:`V1MMBW_quizOptCorrect`,quizOptReveal:`V1MMBW_quizOptReveal`,quizOptWrong:`V1MMBW_quizOptWrong`,quizOptions:`V1MMBW_quizOptions`,quizQuestion:`V1MMBW_quizQuestion`,quizResult:`V1MMBW_quizResult`,quizRetry:`V1MMBW_quizRetry`,quizWrongMsg:`V1MMBW_quizWrongMsg`,radio:`V1MMBW_radio`,resetBtn:`V1MMBW_resetBtn`,reveal:`V1MMBW_reveal`,row:`V1MMBW_row`,scene3dCanvas:`V1MMBW_scene3dCanvas`,scene3dHint:`V1MMBW_scene3dHint`,scene3dTitle:`V1MMBW_scene3dTitle`,scene3dWrap:`V1MMBW_scene3dWrap`,select:`V1MMBW_select`,sliderInput:`V1MMBW_sliderInput`,sliderRow:`V1MMBW_sliderRow`,sliderValue:`V1MMBW_sliderValue`,small:`V1MMBW_small`,spacer:`V1MMBW_spacer`,stat:`V1MMBW_stat`,statDelta:`V1MMBW_statDelta`,statLabel:`V1MMBW_statLabel`,statValue:`V1MMBW_statValue`,step:`V1MMBW_step`,stepActive:`V1MMBW_stepActive`,stepContent:`V1MMBW_stepContent`,stepDesc:`V1MMBW_stepDesc`,stepDone:`V1MMBW_stepDone`,stepMarker:`V1MMBW_stepMarker`,stepTitle:`V1MMBW_stepTitle`,steps:`V1MMBW_steps`,submit:`V1MMBW_submit`,submitHint:`V1MMBW_submitHint`,submitRow:`V1MMBW_submitRow`,success:`V1MMBW_success`,switch:`V1MMBW_switch`,switchKnob:`V1MMBW_switchKnob`,switchLabel:`V1MMBW_switchLabel`,switchOn:`V1MMBW_switchOn`,switchRow:`V1MMBW_switchRow`,tab:`V1MMBW_tab`,tabActive:`V1MMBW_tabActive`,tabBar:`V1MMBW_tabBar`,table:`V1MMBW_table`,tableWrap:`V1MMBW_tableWrap`,tabs:`V1MMBW_tabs`,tdNum:`V1MMBW_tdNum`,text:`V1MMBW_text`,textarea:`V1MMBW_textarea`,thNum:`V1MMBW_thNum`,thSort:`V1MMBW_thSort`,thSortMark:`V1MMBW_thSortMark`,timeline:`V1MMBW_timeline`,tlBody:`V1MMBW_tlBody`,tlDesc:`V1MMBW_tlDesc`,tlDot:`V1MMBW_tlDot`,tlHead:`V1MMBW_tlHead`,tlItem:`V1MMBW_tlItem`,tlLine:`V1MMBW_tlLine`,tlRail:`V1MMBW_tlRail`,tlTime:`V1MMBW_tlTime`,tlTitle:`V1MMBW_tlTitle`,tool:`V1MMBW_tool`,toolFallback:`V1MMBW_toolFallback`,toolFallbackMeta:`V1MMBW_toolFallbackMeta`,toolFallbackTitle:`V1MMBW_toolFallbackTitle`,track:`V1MMBW_track`,up:`V1MMBW_up`,videoPlayer:`V1MMBW_videoPlayer`,visuallyHidden:`V1MMBW_visuallyHidden`,warn:`V1MMBW_warn`,wrap:`V1MMBW_wrap`};let w=`dsh.genui.interaction`;function T(){return{order:[],blocks:{}}}function E(){try{let e=localStorage.getItem(w);if(e===null)return T();let t=JSON.parse(e);return!Array.isArray(t.order)||typeof t.blocks!=`object`||t.blocks===null?T():{order:t.order.filter(e=>typeof e==`string`),blocks:t.blocks}}catch{return T()}}function ee(e){try{localStorage.setItem(w,JSON.stringify(e))}catch{}}function te(e){return e===``?null:E().blocks[e]??null}function ne(e,t){if(e===``)return;let n=E(),r=n.order.filter(t=>t!==e);r.unshift(e);let i={...n.blocks,[e]:t};for(;r.length>200;){let e=r.pop();e!==void 0&&delete i[e]}ee({order:r,blocks:i})}function re(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)>>>0;return t.toString(36)}function ie(e,t,n){return`f:${e}:${String(t)}:${re(n)}`}function ae(e,t){return`p:${e}:${re(t)}`}function oe(e,t){return`t:${e}:${t}`}function D(e){if(typeof e!=`object`||!e)return null;let t=e;if(typeof t.type!=`string`||t.type===``)return null;let n={type:`col`,items:[e]};return t.panel===!0&&(n.panel=!0),t.append===!0&&(n.append=!0),n}function se(e){if(typeof e!=`object`||!e)return!1;let t=e;return!(!Array.isArray(t.items)||t.title!==void 0&&typeof t.title!=`string`||t.gap!==void 0&&typeof t.gap!=`number`)}let O={maxDepth:8,maxNodes:200,maxString:2e3,maxCode:12e3,maxMermaid:8e3,maxGridCols:12,maxTabs:12,maxAccordionItems:24,maxListItems:50,maxOptions:50,maxTableRows:50,maxTableCols:12,maxChartPoints:60,maxPlotSeries:8,maxPlotParams:6,maxMeshes:5,maxQuizOptions:8,maxSteps:24,maxTimelineItems:24,maxBreadcrumbItems:12,maxKeyValuePairs:24,maxTreeDepth:6,maxDiagramNodes:9,maxDiagramEdges:12,maxDiagramZones:3,maxDiagramFocal:2,maxDiagramLabel:14,maxEChartOptionDepth:10,maxEChartArrayLen:500,maxEChartOptionNodes:2e3};function ce(e,t){return typeof e==`string`&&t.includes(e)}function k(e,t){return typeof e==`string`?e.slice(0,t):void 0}let le=/^(?:#[\da-fA-F]{3,8}|rgba?\([^)]{0,64}\)|hsla?\([^)]{0,64}\)|var\(--dsw-[\w-]+(?:,\s*#[0-9a-fA-F]{3,8})?\))$/;function A(e){if(typeof e!=`string`)return;let t=e.trim();return t.length<=64&&le.test(t)?t:void 0}function ue(e){if(typeof e!=`string`)return;let t=e.trim();if(!(t.length>2048))return/^https?:\/\//i.test(t)||/^mailto:[^@\s]+@[^@\s]+$/i.test(t)?t:void 0}function de(e){if(typeof e!=`string`)return;let t=e.trim();if(!(t===``||t.length>2048)&&(/^https?:\/\//i.test(t)||!(/^[a-z][a-z0-9+.-]*:/i.test(t)||/^[/\\]{2}/.test(t))))return t}function j(e,t,n){return typeof e==`number`&&Number.isFinite(e)?Math.min(n,Math.max(t,e)):void 0}function M(e,t,n){return typeof e==`number`&&Number.isFinite(e)?Math.min(n,Math.max(t,Math.trunc(e))):void 0}function N(e,t){return ce(e,t)?e:void 0}function P(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function F(e,t){return t===void 0?{}:{[e]:t}}let fe=[`h1`,`h2`,`h3`,`body`,`muted`,`caption`],pe=[`primary`,`danger`,`success`,`ghost`],me=[`success`,`warn`,`danger`,`accent`],he=[`text`,`email`,`password`],ge=[`info`,`success`,`warning`,`error`],_e=[`bars`,`line`,`donut`],ve=[`line`,`area`,`scatter`],ye=[`16:9`,`4:3`,`1:1`,`9:16`],be=[`box`,`sphere`,`cone`,`cylinder`,`torus`],xe=[`file`,`dir`],Se=`architecture.it-state.flowchart.sequence.state.er.timeline.swimlane.quadrant.radar.loop.nested.tree.org-chart.layers.venn.pyramid.bar.line.gantt.scatter.high-level.process.medallion.data-flow.dp-integration.dp-security-matrix`.split(`.`),Ce=[`focal`,`backend`,`store`,`external`,`input`,`optional`,`security`],we=[`light`,`dark`,`editorial`],Te=[`solid`,`dashed`,`accent`,`link`],Ee=[`auto`,`orthogonal`,`straight`],De=[`bar`,`line`,`area`,`pie`,`scatter`];function I(e,t,n){if(!Array.isArray(e))return[];let r=[];for(let i of e){if(t.remaining<=0)break;--t.remaining;let e=Oe(i,t,n);e!==null&&r.push(e)}return r}function Oe(e,t,n){if(n>O.maxDepth)return null;let r=P(e);if(r===void 0)return null;let i=r.type;if(typeof i!=`string`)return null;switch(i){case`text`:{let e=k(r.content,O.maxString)??k(r.text,O.maxString);return e===void 0?null:{type:`text`,content:e,...F(`size`,N(r.size,fe)),...F(`center`,r.center===!0||void 0)}}case`row`:return{type:`row`,items:I(r.items,t,n+1),...F(`wrap`,r.wrap===!0||void 0),...F(`spacer`,r.spacer===!0||void 0)};case`col`:return{type:`col`,items:I(r.items,t,n+1),...F(`gap`,j(r.gap,0,96))};case`grid`:return{type:`grid`,cols:M(r.cols,1,O.maxGridCols)??1,items:I(r.items,t,n+1)};case`card`:return{type:`card`,items:I(r.items,t,n+1),...F(`title`,k(r.title,O.maxString))};case`button`:{let e=k(r.label,O.maxString);return e===void 0?null:{type:`button`,label:e,...F(`tone`,N(r.tone,pe)),...F(`full`,r.full===!0||void 0),...F(`small`,r.small===!0||void 0),...F(`icon`,k(r.icon,64)),...F(`action`,k(r.action,200))}}case`input`:return{type:`input`,...F(`label`,k(r.label,O.maxString)),...F(`placeholder`,k(r.placeholder,O.maxString)),...F(`value`,k(r.value,O.maxString)),...F(`inputType`,N(r.inputType,he)),...F(`action`,k(r.action,200)),...F(`id`,k(r.id,200))};case`select`:{let e=L(r.options,O.maxOptions,O.maxString);return e===void 0?null:{type:`select`,options:e,...F(`label`,k(r.label,O.maxString)),...F(`action`,k(r.action,200)),...F(`selected`,M(r.selected,0,e.length-1)),...F(`id`,k(r.id,200))}}case`checkbox`:{let e=k(r.label,O.maxString);return e===void 0?null:{type:`checkbox`,label:e,...F(`checked`,r.checked===!0||void 0),...F(`action`,k(r.action,200))}}case`link`:{let e=k(r.label,O.maxString);return e===void 0?null:{type:`link`,label:e,...F(`href`,ue(r.href))}}case`audio`:{let e=de(r.src);return e===void 0?null:{type:`audio`,src:e,...F(`alt`,k(r.alt,O.maxString)),...F(`loop`,r.loop===!0||void 0)}}case`video`:{let e=de(r.src);return e===void 0?null:{type:`video`,src:e,...F(`alt`,k(r.alt,O.maxString)),...F(`poster`,de(r.poster)),...F(`loop`,r.loop===!0||void 0),...F(`muted`,r.muted===!0||void 0),...F(`aspectRatio`,N(r.aspectRatio,ye))}}case`badge`:{let e=k(r.label,O.maxString)??k(r.text,O.maxString)??k(r.value,O.maxString);return e===void 0?null:{type:`badge`,label:e,...F(`tone`,N(r.tone,me)),...F(`icon`,k(r.icon,64))}}case`stat`:{let e=k(r.label,O.maxString),t=k(r.value,128);return e===void 0||t===void 0?null:{type:`stat`,label:e,value:t,...F(`delta`,k(r.delta,64))}}case`progress`:{let e=j(r.value,0,100);return e===void 0?null:{type:`progress`,value:e,...F(`label`,k(r.label,O.maxString)),...F(`valueLabel`,k(r.valueLabel,64))}}case`divider`:return{type:`divider`};case`spacer`:return{type:`spacer`};case`avatar`:{let e=k(r.name,64);return e===void 0?null:{type:`avatar`,name:e,...F(`color`,A(r.color))}}case`list`:{let e=ke(r.items,O.maxListItems,t,n+1);return e===void 0?null:{type:`list`,items:e}}case`table`:{let e=L(r.columns,O.maxTableCols,128),t=Ae(r.rows,O.maxTableRows,O.maxTableCols);return e===void 0||t===void 0?null:{type:`table`,columns:e,rows:t}}case`chart`:{let e=je(r.data,O.maxChartPoints),t=Array.isArray(r.series)?Me(r.series,O.maxPlotSeries,O.maxChartPoints):void 0;return e===void 0&&t===void 0?null:{type:`chart`,data:e??[],...F(`kind`,N(r.kind,_e)),...F(`series`,t)}}case`tabs`:{let e=Ne(r.tabs,t,n);return e===void 0?null:{type:`tabs`,tabs:e}}case`plot`:{let e=Pe(r.series,O.maxPlotSeries);return e===void 0?null:{type:`plot`,series:e,...F(`xMin`,j(r.xMin,-1e6,1e6)),...F(`xMax`,j(r.xMax,-1e6,1e6)),...F(`yMin`,j(r.yMin,-1e9,1e9)),...F(`yMax`,j(r.yMax,-1e9,1e9)),...F(`title`,k(r.title,O.maxString))}}case`callout`:{let e=k(r.content,O.maxString);return e===void 0?null:{type:`callout`,content:e,...F(`tone`,N(r.tone,ge)),...F(`title`,k(r.title,O.maxString))}}case`steps`:{let e=Fe(r.steps);return e===void 0?null:{type:`steps`,steps:e,...F(`current`,M(r.current,0,e.length))}}case`keyvalue`:{let e=Ie(r.pairs,O.maxKeyValuePairs);return e===void 0?null:{type:`keyvalue`,pairs:e}}case`diff`:{let e=Le(r.diffs);return e===void 0?null:{type:`diff`,diffs:e}}case`json`:return`value`in r?{type:`json`,value:r.value}:null;case`code`:{let e=k(r.code,O.maxCode);return e===void 0?null:{type:`code`,code:e,...F(`lang`,k(r.lang,64))}}case`radio`:{let e=L(r.options,O.maxOptions,O.maxString);return e===void 0?null:{type:`radio`,options:e,...F(`label`,k(r.label,O.maxString)),...F(`selected`,M(r.selected,0,e.length-1)),...F(`action`,k(r.action,200)),...F(`group`,k(r.group,200)),...F(`answer`,typeof r.answer==`number`&&Number.isFinite(r.answer)&&r.answer>=0&&r.answer<e.length?Math.trunc(r.answer):typeof r.answer==`string`?r.answer.slice(0,512):void 0),...F(`explanation`,k(r.explanation,O.maxString))}}case`submit`:{let e=k(r.label,O.maxString),t=k(r.action,200);return e===void 0?null:{type:`submit`,label:e,...F(`action`,t),...F(`resetAction`,k(r.resetAction,200)),...F(`groups`,L(r.groups,O.maxOptions,200))}}case`switch`:{let e=k(r.label,O.maxString);return e===void 0?null:{type:`switch`,label:e,...F(`checked`,r.checked===!0||void 0),...F(`action`,k(r.action,200))}}case`slider`:{let e=j(r.min,-1e9,1e9)??0,t=j(r.max,-1e9,1e9)??100,n=Math.min(e,t),i=Math.max(e,t),a=j(r.step,1e-9,Math.max(i-n,1e-9)),o=j(r.value,n,i)??n;return{type:`slider`,min:n,max:i,...F(`step`,a),value:o,...F(`label`,k(r.label,O.maxString)),...F(`action`,k(r.action,200)),...F(`id`,k(r.id,200))}}case`textarea`:return{type:`textarea`,...F(`label`,k(r.label,O.maxString)),...F(`placeholder`,k(r.placeholder,O.maxString)),...F(`rows`,M(r.rows,1,30)),...F(`value`,k(r.value,O.maxString)),...F(`action`,k(r.action,200)),...F(`id`,k(r.id,200))};case`accordion`:{let e=Re(r.items,t,n);return e===void 0?null:{type:`accordion`,items:e}}case`copy`:{let e=k(r.text,O.maxCode);return e===void 0?null:{type:`copy`,text:e,...F(`label`,k(r.label,128))}}case`mermaid`:{let e=k(r.code,O.maxMermaid);return e===void 0?null:{type:`mermaid`,code:e}}case`scene3d`:{let e=ze(r.meshes);return e===void 0?null:{type:`scene3d`,meshes:e,...F(`title`,k(r.title,O.maxString)),...F(`ambient`,j(r.ambient,0,2)),...F(`background`,A(r.background))}}case`diagram`:return Ge(r);case`timeline`:{let e=Ke(r.items,O.maxTimelineItems);return e===void 0?null:{type:`timeline`,items:e}}case`file-tree`:{let e=qe(r.items,O.maxListItems);return e===void 0?null:{type:`file-tree`,items:e}}case`breadcrumb`:{let e=L(r.items,O.maxBreadcrumbItems,O.maxString);return e===void 0?null:{type:`breadcrumb`,items:e}}case`quiz`:{let e=k(r.question,O.maxString),t=Ye(r.options);return e===void 0||t===void 0?null:{type:`quiz`,question:e,options:t,...F(`explanation`,k(r.explanation,O.maxString)),...F(`id`,k(r.id,200)),...F(`action`,k(r.action,200))}}case`echart`:{let e=r.data===void 0?void 0:je(r.data,O.maxChartPoints),t=r.series!==void 0&&Array.isArray(r.series)?Me(r.series,O.maxPlotSeries,O.maxChartPoints):void 0,n=r.option===void 0?void 0:Ze(r.option,0,{count:O.maxEChartOptionNodes}),i=n===void 0||typeof n!=`object`||!n||Array.isArray(n)?void 0:n;return i===void 0&&e===void 0&&t===void 0?null:{type:`echart`,...F(`title`,k(r.title,O.maxString)),...F(`height`,M(r.height,100,800)),...F(`preset`,N(r.preset,De)),...F(`data`,e),...F(`series`,t),...F(`option`,i)}}default:return e}}function L(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;if(typeof i==`string`)r.push(i.slice(0,n));else if(typeof i==`object`&&i){let e=i,t=typeof e.label==`string`?e.label:typeof e.value==`string`?e.value:typeof e.title==`string`?e.title:JSON.stringify(i);r.push(t.slice(0,n))}}return r}function ke(e,t,n,r){if(!Array.isArray(e))return;let i=[];for(let a of e){if(i.length>=t)break;if(typeof a==`string`){i.push(a.slice(0,O.maxString));continue}let e=P(a),o=e===void 0?void 0:k(e.title,O.maxString);if(o!==void 0){i.push({title:o,...F(`desc`,e===void 0?void 0:k(e.desc,O.maxString))});continue}if(e!==void 0&&typeof e.type==`string`){if(n.remaining<=0)break;--n.remaining;let t=Oe(e,n,r);t!==null&&i.push(t)}}return i}function Ae(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;if(!Array.isArray(i))continue;let e=[];for(let t of i){if(e.length>=n)break;typeof t==`string`?e.push(t.slice(0,256)):typeof t==`number`&&Number.isFinite(t)&&e.push(t)}e.length>0&&r.push(e)}return r}function je(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=P(r),i=e===void 0?void 0:k(e.label,128),a=e===void 0?void 0:j(e.value,-0xe8d4a51000,0xe8d4a51000);i!==void 0&&a!==void 0&&n.push({label:i,value:a,...F(`color`,e===void 0?void 0:A(e.color))})}return n}function Me(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;let e=P(i),a=e===void 0?void 0:k(e.label,128),o=e===void 0?void 0:je(e.data,n);a!==void 0&&o!==void 0&&r.push({label:a,data:o,...F(`color`,e===void 0?void 0:A(e.color))})}return r}function Ne(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=O.maxTabs)break;let e=P(i),a=e===void 0?void 0:k(e.label,128);a!==void 0&&e!==void 0&&r.push({label:a,items:I(e.items,t,n+1)})}return r}function Pe(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=P(r),i=e===void 0?void 0:k(e.expr,512);if(i===void 0||e===void 0)continue;let a=[];if(Array.isArray(e.params))for(let t of e.params){if(a.length>=O.maxPlotParams)break;let e=P(t),n=e===void 0?void 0:k(e.name,64),r=e===void 0?void 0:j(e.value,-1e9,1e9);n!==void 0&&r!==void 0&&a.push({name:n,value:r,...F(`min`,e===void 0?void 0:j(e.min,-1e9,1e9)),...F(`max`,e===void 0?void 0:j(e.max,-1e9,1e9)),...F(`step`,e===void 0?void 0:j(e.step,1e-9,1e9)),...F(`animateTo`,e===void 0?void 0:j(e.animateTo,-1e9,1e9)),...F(`durationMs`,e===void 0?void 0:j(e.durationMs,1,12e4)),...F(`loop`,e===void 0?void 0:e.loop===!0||void 0)})}n.push({expr:i,...F(`label`,k(e.label,128)),...F(`color`,A(e.color)),...F(`kind`,N(e.kind,ve)),...F(`params`,a.length>0?a:void 0)})}return n}function Fe(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=O.maxSteps)break;let e=P(n),r=e===void 0?void 0:k(e.title,256);r!==void 0&&t.push({title:r,...F(`desc`,e===void 0?void 0:k(e.desc,O.maxString))})}return t}function Ie(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=P(r),i=e===void 0?void 0:k(e.key,256),a=e===void 0?void 0:k(e.value,O.maxString);i!==void 0&&a!==void 0&&n.push({key:i,value:a})}return n}function Le(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=24)break;let e=P(n),r=e===void 0?void 0:k(e.path,1024),i=e===void 0?void 0:k(e.newText,2e4);if(r===void 0||i===void 0)continue;let a=e===void 0?void 0:e.oldText;t.push({path:r,newText:i,oldText:a===null||typeof a!=`string`?null:a.slice(0,2e4)})}return t}function Re(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=O.maxAccordionItems)break;let e=P(i),a=e===void 0?void 0:k(e.title,256);a!==void 0&&e!==void 0&&r.push({title:a,items:I(e.items,t,n+1)})}return r}function ze(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=O.maxMeshes)break;let e=P(n),r=e===void 0?void 0:N(e.shape,be);if(r===void 0)continue;let i=e===void 0?void 0:j(e.scale,-1e6,1e6)??Be(e.scale),a=e===void 0?void 0:j(e.size,-1e6,1e6)??Be(e.size);t.push({shape:r,...F(`color`,e===void 0?void 0:A(e.color)),...F(`position`,e===void 0?void 0:Be(e.position)),...F(`rotation`,e===void 0?void 0:Be(e.rotation)),...F(`scale`,i),...F(`size`,a)})}return t}function Be(e){if(!Array.isArray(e)||e.length!==3)return;let[t,n,r]=e;if(!(typeof t!=`number`||!Number.isFinite(t)||typeof n!=`number`||!Number.isFinite(n)||typeof r!=`number`||!Number.isFinite(r)))return[Math.min(1e6,Math.max(-1e6,t)),Math.min(1e6,Math.max(-1e6,n)),Math.min(1e6,Math.max(-1e6,r))]}function R(e,t,n){return Math.min(n,Math.max(t,Math.round(e/4)*4))}function Ve(e){if(!Array.isArray(e))return;let t=[],n=new Set;for(let r of e){if(t.length>=O.maxDiagramNodes)break;let e=P(r);if(e===void 0)continue;let i=k(e.id,128),a=k(e.label,O.maxString);if(i===void 0||a===void 0||n.has(i))continue;n.add(i);let o=N(e.type,Ce),s=e.x===void 0?void 0:R(j(e.x,-1e6,1e6)??0,0,1e6),c=e.y===void 0?void 0:R(j(e.y,-1e6,1e6)??0,0,1e6),l=e.w===void 0?void 0:R(j(e.w,-1e6,1e6)??96,40,2e3),u=e.h===void 0?void 0:R(j(e.h,-1e6,1e6)??48,24,1200);t.push({id:i,label:a,...F(`sub`,k(e.sub,256)),...F(`type`,o),...F(`x`,s),...F(`y`,c),...F(`w`,l),...F(`h`,u),...F(`tag`,k(e.tag,32))})}return t}function He(e){if(e===void 0)return[];if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=O.maxDiagramEdges)break;let e=P(n);if(e===void 0)continue;let r=k(e.from,128),i=k(e.to,128);r!==void 0&&i!==void 0&&t.push({from:r,to:i,...F(`label`,k(e.label,O.maxDiagramLabel)),...F(`kind`,N(e.kind,Te)),...F(`route`,N(e.route,Ee))})}return t}function Ue(e){let t=P(e);if(t===void 0)return;let n={};for(let e of[`paper`,`paper-2`,`ink`,`muted`,`soft`,`rule`,`accent`,`accent-tint`,`link`]){let r=A(t[e]);r!==void 0&&(n[e]=r)}return Object.keys(n).length===0?void 0:n}function We(e){if(e===void 0)return[];if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=O.maxDiagramZones)break;let e=P(n);if(e===void 0)continue;let r=k(e.label,64);r!==void 0&&t.push({label:r,...F(`x`,e.x===void 0?void 0:R(j(e.x,-1e6,1e6)??0,0,1e6)),...F(`y`,e.y===void 0?void 0:R(j(e.y,-1e6,1e6)??0,0,1e6)),...F(`w`,e.w===void 0?void 0:R(j(e.w,-1e6,1e6)??100,40,2e3)),...F(`h`,e.h===void 0?void 0:R(j(e.h,-1e6,1e6)??100,40,1200))})}return t}function Ge(e){let t=P(e);if(t===void 0)return null;let n=N(t.kind,Se);if(n===void 0)return null;let r=Ve(t.nodes);if(r===void 0)return null;let i=He(t.edges);if(i===void 0)return null;let a=We(t.zones);return a===void 0?null:{type:`diagram`,kind:n,nodes:r,edges:i,zones:a,...F(`variant`,N(t.variant,we)),...F(`title`,k(t.title,256)),...F(`theme`,Ue(t.theme))}}function Ke(e,t){if(!Array.isArray(e))return;let n=[];for(let r of e){if(n.length>=t)break;let e=P(r),i=e===void 0?void 0:k(e.title,256);i!==void 0&&n.push({title:i,...F(`desc`,e===void 0?void 0:k(e.desc,O.maxString)),...F(`time`,e===void 0?void 0:k(e.time,128))})}return n}function qe(e,t){return Je(e,t,O.maxTreeDepth)}function Je(e,t,n){if(!Array.isArray(e))return;let r=[];for(let i of e){if(r.length>=t)break;let e=P(i),a=e===void 0?void 0:k(e.name,256);if(a===void 0)continue;let o=e!==void 0&&n>0&&Array.isArray(e.children)?Je(e.children,t,n-1):void 0;r.push({name:a,...F(`type`,e===void 0?void 0:N(e.type,xe)),...F(`children`,o)})}return r}function Ye(e){if(!Array.isArray(e))return;let t=[];for(let n of e){if(t.length>=O.maxQuizOptions)break;let e=P(n),r=e===void 0?void 0:k(e.label,512);r!==void 0&&t.push({label:r,...F(`correct`,e===void 0?void 0:e.correct===!0||void 0),...F(`feedback`,e===void 0?void 0:k(e.feedback,O.maxString))})}return t}let Xe=/<(?:script|img|svg|iframe|video|audio|object|embed|source)\b|on[a-z]+\s*=|javascript:/i;function Ze(e,t,n){if(n.count<=0||(--n.count,t>O.maxEChartOptionDepth))return;if(typeof e==`string`){let t=e.slice(0,O.maxString);return t.toLowerCase().includes(`url(`)||Xe.test(t)?void 0:t}if(typeof e==`number`&&Number.isFinite(e)||typeof e==`boolean`)return e;if(e===null)return null;if(Array.isArray(e)){let r=Math.min(e.length,O.maxEChartArrayLen),i=[];for(let a=0;a<r;a++){let r=Ze(e[a],t+1,n);r!==void 0&&i.push(r)}return i.length>0?i:void 0}let r=P(e);if(r===void 0)return;let i={};for(let[e,a]of Object.entries(r)){let r=Ze(a,t+1,n);r!==void 0&&(e===`tooltip`&&typeof r==`object`&&r&&!Array.isArray(r)&&(r.renderMode=`richText`),i[e]=r)}return Object.keys(i).length>0?i:void 0}function z(e){let t=P(e);if(t===void 0)return null;if(!Array.isArray(t.items)){let t=D(e);return t===null?null:z(t)}let n={remaining:O.maxNodes};return{...F(`title`,k(t.title,O.maxString)),...F(`gap`,j(t.gap,0,96)),...F(`panel`,t.panel===!0||void 0),...F(`append`,t.append===!0||void 0),items:I(t.items,n,0)}}function Qe(e,t=1/0){let n=0,r=e=>{if(Array.isArray(e))for(let i of e){if(n>=t)return;n+=1;let e=P(i);if(e!==void 0){if(e.type===`tabs`&&Array.isArray(e.tabs))for(let i of e.tabs){if(n>=t)return;let e=P(i);e!==void 0&&r(e.items)}else if(e.type===`accordion`&&Array.isArray(e.items))for(let i of e.items){if(n>=t)return;let e=P(i);e!==void 0&&r(e.items)}else if(e.type===`file-tree`&&Array.isArray(e.items))r(e.items);else if(e.type===`list`&&Array.isArray(e.items))for(let i of e.items){if(n>=t)return;let e=P(i);e!==void 0&&typeof e.type==`string`&&r([e])}}}},i=P(e);return r(i===void 0?[]:i.items),n}let $e=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-deepseek-300)`,`var(--dsw-static-neutral-bluish-400)`];function et(e){let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)>>>0;return $e[t%$e.length]}function tt({className:e,disabled:t,onClick:n,children:r}){let[i,a]=(0,m.useState)(!1),o=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{o.current!==null&&clearTimeout(o.current)},[]),(0,g.jsxs)(g.Fragment,{children:[(0,g.jsxs)(`button`,{type:`button`,className:e,disabled:t,onClick:n===void 0?void 0:()=>{n(),o.current!==null&&clearTimeout(o.current),a(!0),o.current=setTimeout(()=>a(!1),1400)},children:[r,i&&(0,g.jsx)(`span`,{className:C.btnSent,"aria-hidden":!0,children:`✓ 已触发`})]}),(0,g.jsx)(`span`,{className:C.visuallyHidden,role:`status`,children:i?`已触发`:``})]})}let nt=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,g.jsxs)(`figure`,{className:C.media,children:[e.alt!==void 0&&(0,g.jsx)(`figcaption`,{className:C.mediaLabel,children:e.alt}),t?(0,g.jsx)(`div`,{className:C.mediaError,role:`alert`,children:`音频无法播放`}):(0,g.jsx)(`audio`,{className:C.mediaPlayer,src:e.src,"aria-label":e.alt??`音频`,controls:!0,preload:`metadata`,loop:e.loop===!0,onError:()=>n(!0)})]})}),rt=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,g.jsxs)(`figure`,{className:C.media,children:[e.alt!==void 0&&(0,g.jsx)(`figcaption`,{className:C.mediaLabel,children:e.alt}),t?(0,g.jsx)(`div`,{className:C.mediaError,role:`alert`,children:`视频无法播放`}):(0,g.jsx)(`video`,{className:`${C.mediaPlayer} ${C.videoPlayer}`,src:e.src,poster:e.poster,"aria-label":e.alt??`视频`,controls:!0,preload:`metadata`,playsInline:!0,loop:e.loop===!0,muted:e.muted===!0,style:e.aspectRatio===void 0?void 0:{aspectRatio:e.aspectRatio.replace(`:`,` / `)},onError:()=>n(!0)})]})}),it=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-neutral-bluish-400)`,`var(--dsw-static-deepseek-300)`],at=(e,t,n)=>n??(t>1?it[e%it.length]:void 0);function ot(e){if(typeof e==`number`)return Number.isFinite(e)?e:NaN;if(typeof e!=`string`)return NaN;let t=e.trim();if(t===``)return NaN;t=t.replace(/^[¥$€£]/,``),t.endsWith(`%`)&&(t=t.slice(0,-1));let n=1;if(t.endsWith(`万`))n=1e4,t=t.slice(0,-1);else if(t.endsWith(`亿`))n=1e8,t=t.slice(0,-1);else if(/[kmb]$/i.test(t)){let e=t.slice(-1).toLowerCase();n=e===`k`?1e3:e===`m`?1e6:1e9,t=t.slice(0,-1)}t=t.replace(/[,,\s]/g,``);let r=Number(t);return Number.isFinite(r)?r*n:NaN}function st(e,t){return Array.from({length:t},(t,n)=>{let r=!1;for(let t of e){let e=t[n];if(e!=null&&e!==``){if(!Number.isFinite(ot(e)))return!1;r=!0}}return r})}let ct=(0,m.memo)(function({node:e}){let t=e.columns.slice(0,O.maxTableCols),n=e.rows.slice(0,O.maxTableRows),[r,i]=(0,m.useState)(null),a=r===null?n:[...n].sort((e,t)=>{let n=ot(e[r.col]),i=ot(t[r.col]);if(Number.isFinite(n)&&Number.isFinite(i)&&n!==i)return(n-i)*r.dir;if(Number.isFinite(n)!==Number.isFinite(i))return Number.isFinite(n)?-r.dir:r.dir;let a=String(e[r.col]??``),o=String(t[r.col]??``);return(a<o?-1:+(a>o))*r.dir}),o=e=>{i(t=>t!==null&&t.col===e?t.dir===1?{col:e,dir:-1}:null:{col:e,dir:1})},s=st(n,t.length);return(0,g.jsx)(`div`,{className:C.tableWrap,children:(0,g.jsxs)(`table`,{className:C.table,children:[(0,g.jsx)(`thead`,{children:(0,g.jsx)(`tr`,{children:t.map((e,t)=>(0,g.jsx)(`th`,{className:s[t]?C.thNum:void 0,"aria-sort":r!==null&&r.col===t?r.dir===1?`ascending`:`descending`:`none`,children:(0,g.jsxs)(`button`,{type:`button`,className:C.thSort,onClick:()=>o(t),children:[e,r!==null&&r.col===t&&(0,g.jsx)(`span`,{className:C.thSortMark,"aria-hidden":!0,children:r.dir===1?` ▲`:` ▼`})]})},t))})}),(0,g.jsx)(`tbody`,{children:a.map((e,n)=>(0,g.jsx)(`tr`,{children:e.slice(0,t.length).map((e,t)=>(0,g.jsx)(`td`,{className:s[t]?C.tdNum:void 0,children:String(e)},t))},n))})]})})}),lt=(0,m.memo)(function({chart:e}){let t=e.kind??`bars`;return t===`donut`?(0,g.jsx)(ft,{chart:e}):t===`line`?(0,g.jsx)(dt,{chart:e}):(0,g.jsx)(ut,{chart:e})}),ut=(0,m.memo)(function({chart:e}){let t=e.series===void 0?void 0:e.series.slice(0,O.maxPlotSeries);if(t!==void 0&&t.length>0){let e=t[0].data.map(e=>e.label),n=Math.max(...t.flatMap(e=>e.data.map(e=>Number(e.value)||0)),1);return(0,g.jsxs)(`div`,{className:C.chart,children:[(0,g.jsxs)(`div`,{className:C.chartPlot,children:[[0,25,50,75].map(e=>(0,g.jsx)(`span`,{className:e===0?C.baseline:C.gridline,style:{bottom:`${e}%`}},e)),e.map((e,r)=>(0,g.jsx)(`div`,{className:C.barCol,children:(0,g.jsx)(`div`,{className:C.groupedBars,children:t.map((e,i)=>{let a=e.data[r],o=a===void 0?0:Number(a.value)||0,s=a===void 0?0:Math.min(Math.round(Math.max(0,o)/n*100),82);return(0,g.jsxs)(`div`,{className:C.groupedBar,title:a===void 0?e.label:`${e.label}: ${String(a.value)}`,children:[(0,g.jsx)(`span`,{className:C.groupValue,children:a===void 0?``:String(a.value)}),(0,g.jsx)(`div`,{className:C.groupedFill,style:{height:`${s}%`,background:at(i,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}})]},i)})})},r))]}),(0,g.jsx)(`div`,{className:C.chartLabels,children:e.map(e=>(0,g.jsx)(`span`,{className:C.barLabel,children:e},e))})]})}let n=e.data.slice(0,O.maxChartPoints),r=Math.max(...n.map(e=>Number(e.value)||0),1);return(0,g.jsxs)(`div`,{className:C.chart,children:[(0,g.jsxs)(`div`,{className:C.chartPlot,children:[[0,25,50,75].map(e=>(0,g.jsx)(`span`,{className:e===0?C.baseline:C.gridline,style:{bottom:`${e}%`}},e)),n.map((e,t)=>{let n=Number(e.value)||0,i=Math.min(Math.round(Math.max(0,n)/r*100),85);return(0,g.jsxs)(`div`,{className:C.barCol,title:`${e.label}: ${String(e.value)}`,children:[(0,g.jsx)(`span`,{className:C.barValue,children:String(e.value)}),(0,g.jsx)(`div`,{className:C.barFill,style:{height:`${i}%`,...e.color===void 0?{}:{background:e.color}}})]},t)})]}),(0,g.jsx)(`div`,{className:C.chartLabels,children:n.map(e=>(0,g.jsx)(`span`,{className:C.barLabel,children:e.label},e.label))})]})}),dt=(0,m.memo)(function({chart:e}){let t=e.data.slice(0,O.maxChartPoints),n=Math.max(...t.map(e=>Number(e.value)||0),1),r=Math.min(...t.map(e=>Number(e.value)||0),0),i=n-r||1,a=Math.max(t.length-1,1),o=(e,t)=>[36+e/a*416,10+(1-(t-r)/i)*134],s=t.map((e,t)=>o(t,Number(e.value)||0)).map((e,t)=>`${t===0?`M`:`L`} ${e[0].toFixed(1)} ${e[1].toFixed(1)}`).join(` `),c=[0,1,2,3].map(e=>r+i*e/3),l=e=>{let t=Math.abs(e);return t>=1e3?`${(e/1e3).toFixed(t%1e3==0?0:1)}k`:Number.isInteger(e)?String(e):e.toFixed(1)};return(0,g.jsxs)(`div`,{className:C.lineChart,children:[(0,g.jsxs)(`svg`,{width:`100%`,viewBox:`0 0 460 150`,children:[c.map((e,t)=>{let n=10+(1-(e-r)/i)*134;return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`line`,{x1:36,x2:452,y1:n,y2:n,className:t===0?C.lineGridAxis:C.lineGrid}),(0,g.jsx)(`text`,{x:30,y:n+3,textAnchor:`end`,className:C.lineTick,children:l(e)})]},t)}),t.map((e,t)=>{let[n,r]=o(t,Number(e.value)||0);return(0,g.jsx)(`circle`,{cx:n,cy:r,r:3,className:C.lineDot,fill:e.color??void 0,children:(0,g.jsx)(`title`,{children:`${e.label}: ${String(e.value)}`})},t)}),(0,g.jsx)(`path`,{d:s,className:C.linePath})]}),(0,g.jsx)(`div`,{className:C.lineLabels,children:t.map((e,t)=>(0,g.jsx)(`span`,{className:C.barLabel,children:e.label},t))})]})}),ft=(0,m.memo)(function({chart:e}){let t=e.data.slice(0,O.maxChartPoints),n=t.map(e=>({...e,v:Math.max(0,Number(e.value)||0)})),r=n.reduce((e,t)=>e+t.v,0)||1,i=r>=1e3?`${Math.round(r/100)/10}k`:Number.isInteger(r)?String(r):r.toFixed(1),a=2*Math.PI*42,o=0;return(0,g.jsxs)(`div`,{className:C.donut,children:[(0,g.jsxs)(`svg`,{width:`120`,height:`120`,viewBox:`0 0 120 120`,children:[(0,g.jsx)(`circle`,{cx:`60`,cy:`60`,r:42,fill:`none`,strokeWidth:`14`,className:C.donutTrack}),n.map((e,n)=>{let i=e.v/r*a,s=(0,g.jsx)(`circle`,{cx:`60`,cy:`60`,r:42,fill:`none`,strokeWidth:`14`,className:C.donutSeg,style:{stroke:at(n,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`},strokeDasharray:`${i} ${a-i}`,strokeDashoffset:-o,transform:`rotate(-90 60 60)`,children:(0,g.jsx)(`title`,{children:`${e.label}: ${String(e.value)}`})},n);return o+=i,s}),(0,g.jsx)(`text`,{x:`60`,y:`58`,textAnchor:`middle`,className:C.donutTotal,children:i}),(0,g.jsx)(`text`,{x:`60`,y:`74`,textAnchor:`middle`,className:C.donutTotalLabel,children:`合计`})]}),(0,g.jsx)(`div`,{className:C.donutLegend,children:t.map((e,n)=>(0,g.jsxs)(`span`,{className:C.legendItem,children:[(0,g.jsx)(`span`,{className:C.legendSwatch,style:{background:at(n,t.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}}),e.label,` · `,String(e.value)]},n))})]})});function pt({node:e,onAction:t,answers:n}){let r=e.action,i=e.group,a=i!==void 0,o=e.options.slice(0,O.maxOptions),s=i!==void 0&&n?.answers[i]!==void 0?o.indexOf(n.answers[i]):-1,[c,l]=(0,m.useState)(s>=0?s:e.selected??null),u=(0,m.useId)(),d=a&&n?.locked===!0;return(0,m.useEffect)(()=>{i!==void 0&&(n?.registerMeta(i,{label:e.label??i,options:o,answer:e.answer,explanation:e.explanation}),e.selected!==void 0&&o[e.selected]!==void 0&&n?.answers[i]===void 0&&n?.setAnswer(i,o[e.selected]))},[i,e.label,e.answer,e.explanation,e.options,e.selected]),(0,g.jsxs)(`div`,{className:C.fieldGroup,role:`radiogroup`,"aria-label":e.label,children:[e.label!==void 0&&(0,g.jsx)(`span`,{className:C.fieldLabel,children:e.label}),o.map((e,o)=>(0,g.jsxs)(`label`,{className:C.radio,children:[(0,g.jsx)(`input`,{type:`radio`,name:`genui-radio-${u}`,checked:c===o,disabled:d,onChange:()=>{l(o),a?n?.setAnswer(i,e):r!==void 0&&t!==void 0&&t(r,{type:`radio`,value:e})}}),(0,g.jsx)(`span`,{children:e})]},o))]})}function mt(e){if(e.answer!==void 0)return typeof e.answer==`number`?e.options[e.answer]:e.answer}function ht({node:e,onAction:t,answers:n}){let r=n?.answers??{},i=n?.fields??{},a=n?.meta??{},o=e.groups,s=Object.fromEntries(Object.entries(i).filter(([e,t])=>t.trim()!==``&&!n?.secretFields.has(e))),c=o===void 0?Math.max(Object.keys(r).length,Object.keys(s).length):o.filter(e=>r[e]!==void 0).length,l=o?.length??c,u=o??Object.keys(r),d=u.some(e=>a[e]?.answer!==void 0),f=n?.locked===!0,p=c>0&&c>=l&&(d||e.action!==void 0&&t!==void 0);if(f){let i=u.filter(e=>r[e]!==void 0&&a[e]?.answer!==void 0),s=i.filter(e=>r[e]===mt(a[e])).length;return(0,g.jsxs)(`div`,{className:C.gradeWrap,"data-genui-grade":!0,children:[(0,g.jsxs)(`div`,{className:C.gradeScore,children:[(0,g.jsxs)(`span`,{className:C.gradeScoreValue,children:[s,` / `,i.length]}),(0,g.jsxs)(`span`,{className:C.gradeScoreLabel,children:[`得分`,i.length<u.length?`(${u.length-i.length} 题无答案未计分)`:``]})]}),(0,g.jsx)(`div`,{className:C.gradeList,children:u.map(e=>{let t=r[e],n=a[e];if(t===void 0||n===void 0)return null;let i=mt(n);if(i===void 0)return(0,g.jsxs)(`div`,{className:C.gradeItem,children:[(0,g.jsx)(`span`,{className:C.gradeQ,children:n.label}),(0,g.jsxs)(`span`,{className:C.gradeAns,children:[`你的答案:`,t]})]},e);let o=t===i;return(0,g.jsxs)(`div`,{className:`${C.gradeItem} ${o?C.gradeItemOk:C.gradeItemNo}`,children:[(0,g.jsx)(`span`,{className:C.gradeQ,children:n.label}),(0,g.jsx)(`span`,{className:C.gradeTag,children:o?`✓`:`✗`}),(0,g.jsxs)(`span`,{className:C.gradeAns,children:[`你的答案:`,t,!o&&(0,g.jsxs)(`span`,{className:C.gradeRight,children:[` 正确答案:`,i]})]}),n.explanation!==void 0&&(0,g.jsx)(`span`,{className:C.gradeExp,children:n.explanation})]},e)})}),(0,g.jsx)(`button`,{type:`button`,className:`${C.button} ${C.ghost} ${C.submit}`,onClick:()=>{n?.clear(),e.resetAction!==void 0&&t!==void 0&&t(e.resetAction,{type:`submit-reset`,groups:o??Object.keys(r)})},children:`重新作答`})]})}return(0,g.jsxs)(`div`,{className:C.submitRow,children:[(0,g.jsx)(`button`,{type:`button`,className:`${C.button} ${C.primary} ${C.submit}`,disabled:!p,onClick:p?()=>{d?n?.setLocked(!0):e.action!==void 0&&t!==void 0&&t(e.action,{type:`submit`,answers:r,...Object.keys(s).length>0?{fields:s}:{},total:l,answered:c})}:void 0,children:e.label}),l>0&&(0,g.jsxs)(`span`,{className:C.submitHint,"aria-live":`polite`,children:[`已选 `,c,`/`,l]})]})}function gt({node:e,onAction:t}){let[n,r]=(0,m.useState)(e.checked===!0),i=e.action;return(0,g.jsxs)(`label`,{className:C.switchRow,children:[(0,g.jsx)(`span`,{className:C.switchLabel,children:e.label}),(0,g.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":n,className:`${C.switch} ${n?C.switchOn:``}`,onClick:()=>{let e=!n;r(e),i!==void 0&&t!==void 0&&t(i,{type:`switch`,checked:e})},children:(0,g.jsx)(`span`,{className:C.switchKnob})})]})}function _t({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=i!==void 0&&n?.fields[i]!==void 0?Number(n.fields[i]):NaN,o=Number.isFinite(a)?a:e.value??e.min??0,[s,c]=(0,m.useState)(o),l=(0,m.useRef)(!1);(0,m.useEffect)(()=>{l.current||(l.current=!0,i!==void 0&&n?.setField(i,String(o)))},[]);let u=e=>{r!==void 0&&t!==void 0&&t(r,{type:`slider`,value:e,...i===void 0?{}:{id:i}})};return(0,g.jsxs)(`label`,{className:C.sliderRow,children:[e.label!==void 0&&(0,g.jsx)(`span`,{className:C.fieldLabel,children:e.label}),(0,g.jsx)(`input`,{type:`range`,className:C.sliderInput,min:e.min,max:e.max,step:e.step??1,value:s,"aria-label":e.label,onChange:e=>{let t=Number(e.currentTarget.value);c(t),i!==void 0&&n?.setField(i,String(t)),u(t)}}),(0,g.jsx)(`span`,{className:C.sliderValue,children:Math.round(s*100)/100})]})}function vt(){let e=(0,m.useRef)(!1),t=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{t.current!==null&&clearTimeout(t.current)},[]),{isComposing:()=>e.current,onCompositionStart:()=>{e.current=!0,t.current!==null&&(clearTimeout(t.current),t.current=null)},onCompositionEnd:()=>{t.current!==null&&clearTimeout(t.current),t.current=setTimeout(()=>{e.current=!1},10)}}}function yt(e){let t=e.nativeEvent;return t.isComposing===!0||t.keyCode===229}function bt({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=e.options.slice(0,O.maxOptions),o=i!==void 0&&n?.fields[i]!==void 0?a.indexOf(n.fields[i]):-1,s=o>=0?a[o]:e.selected!==void 0&&a[e.selected]!==void 0?a[e.selected]:null,[c,l]=(0,m.useState)(s),u=(0,m.useRef)(!1);(0,m.useEffect)(()=>{u.current||(u.current=!0,i!==void 0&&s!==null&&n?.setField(i,s))},[]);let d=e=>{r!==void 0&&t!==void 0&&t(r,{type:`select`,value:e,...i===void 0?{}:{id:i}})};return(0,g.jsxs)(`label`,{className:C.field,children:[e.label!==void 0&&(0,g.jsx)(`span`,{children:e.label}),(0,g.jsxs)(`select`,{className:C.select,value:c??``,onChange:e=>{let t=e.currentTarget.value;l(t),i!==void 0&&n?.setField(i,t),d(t)},children:[c===null&&(0,g.jsx)(`option`,{value:``,hidden:!0,disabled:!0,children:`请选择…`}),a.map((e,t)=>(0,g.jsx)(`option`,{value:e,children:e},t))]})]})}function xt({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,a=e.inputType===`password`,[o,s]=(0,m.useState)(()=>a?``:e.value??(i===void 0?``:n?.fields[i]??``)),c=(0,m.useRef)(o),l=e=>{r!==void 0&&t!==void 0&&(c.current=o,t(r,{type:`input`,value:o,...i===void 0?{}:{id:i},...e?{submit:!0}:{}}))},u=vt(),d=(0,m.useRef)(!1);return(0,m.useEffect)(()=>{d.current||(d.current=!0,!a&&i!==void 0&&e.value!==void 0&&e.value.trim()!==``&&n?.setField(i,e.value))},[]),(0,m.useEffect)(()=>{a&&i!==void 0&&n?.registerSecretField(i)},[a,i]),(0,g.jsxs)(`label`,{className:C.field,children:[e.label!==void 0&&(0,g.jsx)(`span`,{children:e.label}),(0,g.jsx)(`input`,{className:C.input,type:e.inputType??`text`,placeholder:e.placeholder,value:o,onChange:e=>{let t=e.currentTarget.value;s(t),i!==void 0&&n?.setField(i,t)},onBlur:()=>{o!==c.current&&l(!1)},onCompositionStart:u.onCompositionStart,onCompositionEnd:u.onCompositionEnd,onKeyDown:e=>{e.key===`Enter`&&(u.isComposing()||yt(e)||(e.preventDefault(),l(!0)))}})]})}function St({node:e,onAction:t,answers:n}){let r=e.action,i=e.id,[a,o]=(0,m.useState)(()=>e.value??(i===void 0?``:n?.fields[i]??``)),s=(0,m.useRef)(a),c=e=>{r!==void 0&&t!==void 0&&(s.current=a,t(r,{type:`textarea`,value:a,...i===void 0?{}:{id:i},...e?{submit:!0}:{}}))},l=vt(),u=(0,m.useRef)(!1);return(0,m.useEffect)(()=>{u.current||(u.current=!0,i!==void 0&&e.value!==void 0&&e.value.trim()!==``&&n?.setField(i,e.value))},[]),(0,g.jsxs)(`label`,{className:C.field,children:[e.label!==void 0&&(0,g.jsx)(`span`,{children:e.label}),(0,g.jsx)(`textarea`,{className:C.textarea,placeholder:e.placeholder,rows:e.rows??4,value:a,onChange:e=>{let t=e.currentTarget.value;o(t),i!==void 0&&n?.setField(i,t)},onBlur:()=>{a!==s.current&&c(!1)},onCompositionStart:l.onCompositionStart,onCompositionEnd:l.onCompositionEnd,onKeyDown:e=>{!(e.metaKey||e.ctrlKey)||e.key!==`Enter`||l.isComposing()||yt(e)||(e.preventDefault(),c(!0))}})]})}let Ct={pi:Math.PI,e:Math.E,tau:Math.PI*2},wt={sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,sqrt:Math.sqrt,cbrt:Math.cbrt,exp:Math.exp,log:Math.log10,ln:Math.log,abs:Math.abs,floor:Math.floor,ceil:Math.ceil,round:Math.round,min:Math.min,max:Math.max,pow:(e,t)=>e**+t};var B=class extends Error{pos;constructor(e,t){super(`SafeMath parse error at ${t}: ${e}`),this.pos=t}},Tt=class{src;vars;i=0;constructor(e,t){this.src=e,this.vars=t}parse(){let e=this.parseExpr();if(this.skipWs(),this.i<this.src.length)throw new B(`unexpected trailing input`,this.i);return this.evalNode(e)}evalNode(e){return typeof e==`number`?()=>e:e}parseExpr(){let e=this.parseTerm();for(;;){this.skipWs();let t=this.peek();if(t===`+`||t===`-`){this.i++;let n=this.parseTerm(),r=t,i=e;e=r===`+`?e=>this.asNum(i,e)+this.asNum(n,e):e=>this.asNum(i,e)-this.asNum(n,e)}else return e}}parseTerm(){let e=this.parseUnary();for(;;){this.skipWs();let t=this.peek();if(t===`*`||t===`/`||t===`%`){this.i++;let n=this.parseUnary(),r=t,i=e;e=r===`*`?e=>this.asNum(i,e)*this.asNum(n,e):r===`/`?e=>this.asNum(i,e)/this.asNum(n,e):e=>this.asNum(i,e)%this.asNum(n,e)}else return e}}parseUnary(){this.skipWs();let e=this.char();if(e===`-`||e===`+`){this.i++;let t=this.parseUnary();return e===`-`?e=>-this.asNum(t,e):e=>this.asNum(t,e)}return this.parsePower()}parsePower(){let e=this.parseAtom();if(this.skipWs(),this.peek()===`^`){this.i++;let t=this.parsePower(),n=e;return e=>this.asNum(n,e)**+this.asNum(t,e)}return e}parseAtom(){this.skipWs();let e=this.char();if(e===`(`){this.i++;let e=this.parseExpr();if(this.skipWs(),this.peek()!==`)`)throw new B(`expected )`,this.i);return this.i++,e}if(e>=`0`&&e<=`9`||e===`.`)return this.parseNumber();if(this.isIdentStart(e))return this.parseIdent();throw new B(`unexpected character '${e}'`,this.i)}parseNumber(){let e=this.i;for(;this.i<this.src.length&&/[0-9.eE+\-]/.test(this.src[this.i]);)this.i++;let t=this.src.slice(e,this.i),n=Number(t);if(Number.isNaN(n))throw new B(`invalid number '${t}'`,e);return n}parseIdent(){let e=this.i;for(;this.i<this.src.length&&this.isIdentChar(this.src[this.i]);)this.i++;let t=this.src.slice(e,this.i);if(this.skipWs(),this.peek()===`(`){let n=wt[t];if(n===void 0)throw new B(`unknown function '${t}'`,e);this.i++;let r=[];if(this.skipWs(),this.peek()===`)`)this.i++;else for(;;){r.push(this.parseExpr()),this.skipWs();let e=this.peek();if(e===`,`){this.i++;continue}if(e===`)`){this.i++;break}throw new B(`expected , or ) in call`,this.i)}return e=>n(...r.map(t=>this.asNum(t,e)))}if(Object.hasOwn(Ct,t))return Ct[t];if(t===`x`)return e=>e;if(Object.hasOwn(this.vars,t)){let e=this.vars[t];return()=>e}if(/^[a-z]$/.test(t))return()=>1;throw new B(`unknown identifier '${t}'`,e)}asNum(e,t){return typeof e==`number`?e:e(t)}skipWs(){for(;this.i<this.src.length&&/\s/.test(this.src[this.i]);)this.i++}peek(){return this.src[this.i]}char(){let e=this.peek();if(e===void 0)throw new B(`unexpected end of input`,this.i);return e}isIdentStart(e){return e!==void 0&&/[a-zA-Z_]/.test(e)}isIdentChar(e){return/[a-zA-Z0-9_]/.test(e)}};function Et(e,t={}){try{let n={...t.vars};return delete n.x,new Tt(e,n).parse()}catch{return null}}function Dt(e,t,n,r=200,i={}){let a=Et(e,{vars:i});if(a===null||!Number.isFinite(t)||!Number.isFinite(n)||n<=t||r<2)return[];let o=[],s=(n-t)/(r-1);for(let e=0;e<r;e++){let n=t+s*e,r=a(n);Number.isFinite(r)&&o.push([n,r])}return o}let Ot=`@omdsh-dev/dsh-genui/PlotBlock.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(Ot)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@omdsh-dev/dsh-genui`,e.dataset.pluginCss=Ot,e.textContent=`._ctrqa_block{--dsl-g-radius-surface:12px;--dsl-g-radius-control:8px;--dsl-g-font-title:13px;--dsl-g-font-meta:12px;--dsl-g-font-data:11px;--dsl-g-gap-md:12px;--dsl-g-gap-sm:8px;--dsl-g-gap-xs:4px;--dsl-g-border:var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,#ffffff1f));--dsl-g-accent:var(--dsw-alias-state-business-primary,#4f8ef7);--dsl-g-accent-soft:color-mix(in srgb, var(--dsl-g-accent) var(--dsl-g-tint), transparent);--dsl-g-tint:8%;--dsl-g-tint-strong:14%;--dsl-g-font-mono:var(--ds-font-family-code,ui-monospace, "SF Mono", monospace);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-markdown-code-block));border:1px solid var(--dsl-g-border);border-radius:var(--dsl-g-radius-surface);gap:var(--dsl-g-gap-sm);flex-direction:column;padding:14px 16px;display:flex}._ctrqa_title{font-size:var(--dsl-g-font-title);letter-spacing:.01em;color:var(--dsw-alias-label-primary);font-weight:600}._ctrqa_gridLine{stroke:var(--dsw-alias-border-l1,#ffffff12);stroke-width:1px}._ctrqa_axis{stroke:var(--dsw-alias-label-tertiary);stroke-width:1px}._ctrqa_tick{fill:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-data);font-family:var(--dsl-g-font-mono)}._ctrqa_line{fill:none;stroke:var(--dsl-g-accent);stroke-width:2px;stroke-linejoin:round;stroke-linecap:round}._ctrqa_area{stroke:none;fill-opacity:.16}._ctrqa_scatterDot{stroke:var(--dsw-alias-bg-base,#17171a);stroke-width:1px}._ctrqa_legend{gap:var(--dsl-g-gap-md);flex-wrap:wrap;display:flex}._ctrqa_legendItem{align-items:center;gap:var(--dsl-g-gap-xs);font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-secondary);display:inline-flex}._ctrqa_legendSwatch{background:var(--dsl-g-accent);border-radius:2px;width:10px;height:3px}._ctrqa_empty{color:var(--dsw-alias-label-tertiary);font-size:var(--dsl-g-font-title);gap:var(--dsl-g-gap-xs);flex-direction:column;padding:14px 0;display:flex}._ctrqa_emptyRow{font-family:var(--dsl-g-font-mono)}._ctrqa_surface{cursor:grab;touch-action:none}._ctrqa_surface:active{cursor:grabbing}._ctrqa_sliders{gap:var(--dsl-g-gap-sm);flex-direction:column;display:flex}._ctrqa_sliderRow{align-items:center;gap:var(--dsl-g-gap-sm);font-size:var(--dsl-g-font-meta);display:flex}._ctrqa_sliderName{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;min-width:90px;overflow:hidden}._ctrqa_slider{accent-color:var(--dsl-g-accent);cursor:pointer;flex:1;height:4px}._ctrqa_sliderValue{color:var(--dsw-alias-label-primary);font-family:var(--dsl-g-font-mono);text-align:right;min-width:34px}._ctrqa_animBar{align-items:center;gap:var(--dsl-g-gap-md);display:flex}._ctrqa_playBtn{background:var(--dsl-g-accent-soft);border:1px solid color-mix(in srgb, var(--dsl-g-accent) 30%, transparent);width:fit-content;color:var(--dsl-g-accent);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;padding:6px 14px;font-family:inherit;font-weight:600}._ctrqa_playBtn:hover{filter:brightness(1.1)}._ctrqa_animTrack{background:var(--dsw-alias-bg-layer-1);height:5px;box-shadow:inset 0 0 0 1px var(--dsl-g-border);border-radius:999px;flex:1;overflow:hidden}._ctrqa_animFill{background:var(--dsl-g-accent);border-radius:999px;height:100%}._ctrqa_resetBtn{border:1px solid var(--dsl-g-border);width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:var(--dsl-g-radius-control);font-size:var(--dsl-g-font-title);cursor:pointer;background:0 0;padding:6px 14px;font-family:inherit}._ctrqa_resetBtn:hover{border-color:var(--dsl-g-accent);color:var(--dsl-g-accent)}._ctrqa_slidersHead{justify-content:space-between;align-items:center;display:flex}._ctrqa_slidersTitle{font-size:var(--dsl-g-font-meta);color:var(--dsw-alias-label-tertiary)}`,document.head.appendChild(e)}var V={animBar:`_ctrqa_animBar`,animFill:`_ctrqa_animFill`,animTrack:`_ctrqa_animTrack`,area:`_ctrqa_area`,axis:`_ctrqa_axis`,block:`_ctrqa_block`,empty:`_ctrqa_empty`,emptyRow:`_ctrqa_emptyRow`,gridLine:`_ctrqa_gridLine`,legend:`_ctrqa_legend`,legendItem:`_ctrqa_legendItem`,legendSwatch:`_ctrqa_legendSwatch`,line:`_ctrqa_line`,playBtn:`_ctrqa_playBtn`,resetBtn:`_ctrqa_resetBtn`,scatterDot:`_ctrqa_scatterDot`,slider:`_ctrqa_slider`,sliderName:`_ctrqa_sliderName`,sliderRow:`_ctrqa_sliderRow`,sliderValue:`_ctrqa_sliderValue`,sliders:`_ctrqa_sliders`,slidersHead:`_ctrqa_slidersHead`,slidersTitle:`_ctrqa_slidersTitle`,surface:`_ctrqa_surface`,tick:`_ctrqa_tick`,title:`_ctrqa_title`};let kt=[`var(--dsw-static-deepseek-400)`,`var(--dsw-static-green-400)`,`var(--dsw-static-amber-400)`,`var(--dsw-static-red-400)`,`var(--dsw-static-blue-450)`,`var(--dsw-static-deepseek-450)`,`var(--dsw-static-neutral-bluish-400)`,`var(--dsw-static-deepseek-300)`],At=(e,t,n)=>n??(t>1?kt[e%kt.length]:void 0);function jt(e){let t=1/0,n=-1/0;for(let[,r]of e)r<t&&(t=r),r>n&&(n=r);if(!Number.isFinite(t)||!Number.isFinite(n))return[-1,1];t===n&&(--t,n+=1);let r=(n-t)*.08;return[t-r,n+r]}function Mt(e,t,n=5){let r=t-e;if(!Number.isFinite(r)||r<=0)return[];let i=10**Math.floor(Math.log10(r/n)),a=r/n/i,o=i*(a>=7.5?10:a>=3.5?5:a>=1.5?2:1),s=[];for(let n=Math.ceil(e/o)*o;n<=t+o*1e-9;n+=o)s.push(Math.round(n*1e9)/1e9);return s}function Nt(e){return Math.abs(e)>=1e5||Math.abs(e)<.001&&e!==0?e.toExponential(1):String(Math.round(e*100)/100)}function Pt({points:e,className:t,color:n}){let r=e.length>40?`${e.slice(0,16)}|${e.slice(-16)}`:e;return(0,g.jsx)(`polyline`,{points:e,className:t,style:n===void 0?void 0:{stroke:n}},r)}let Ft=(0,m.memo)(function({series:e,xMin:t=-5,xMax:n=5,yMin:r,yMax:i,title:a}){let[o,s]=(0,m.useState)(()=>{let a={};for(let[t,n]of e.entries())for(let e of n.params??[])e!=null&&(a[`${t}:${e.name}`]=e.value);let[o,s]=jt(e.map((e,r)=>{let i={};for(let t of e.params??[])t!=null&&(i[t.name]=a[`${r}:${t.name}`]??t.value);return Dt(e.expr,t,n,240,i)}).flatMap(e=>e));return{xMin:t,xMax:n,yMin:r??o,yMax:i??s}}),c=(0,m.useRef)(null),[l,u]=(0,m.useState)(()=>({})),d=(()=>{for(let[t,n]of e.entries())for(let e of n.params??[])if(e!=null&&e.animateTo!==void 0)return{si:t,param:e};return null})(),[f,p]=(0,m.useState)(!1),[h,_]=(0,m.useState)(0),v=(0,m.useRef)(null);(0,m.useEffect)(()=>{if(!f||d===null)return;let e=l[`${d.si}:${d.param.name}`]??d.param.value,t=d.param.animateTo,n=d.param.durationMs??4e3,r=performance.now(),i=a=>{let o=Math.min(1,(a-r)/n),s=1-(1-o)**3,c=e+(t-e)*s;u(e=>({...e,[`${d.si}:${d.param.name}`]:c})),_(o),o<1?v.current=requestAnimationFrame(i):d.param.loop===!0?(u(e=>({...e,[`${d.si}:${d.param.name}`]:d.param.value})),_(0),v.current=requestAnimationFrame(()=>p(e=>e))):p(!1)};return v.current=requestAnimationFrame(i),()=>{v.current!==null&&cancelAnimationFrame(v.current)}},[f,d?.si,d?.param.name,d?.param.animateTo]);let y=o.xMin,b=o.xMax,x=o.yMin,S=o.yMax,C=e=>y+(e-34)/436*(b-y),w=e=>34+(e-y)/(b-y)*436,T=e=>14+(1-(e-x)/(S-x))*182,E=e.map((e,t)=>{let n={};for(let r of e.params??[])r!=null&&(n[r.name]=l[`${t}:${r.name}`]??r.value);return{series:e,points:Dt(e.expr,y,b,240,n).map(([e,t])=>`${w(e).toFixed(2)},${T(t).toFixed(2)}`).join(` `)}}),ee=Mt(y,b),te=Mt(x,S),ne=E.some(e=>e.points.length>1),re=Number.isFinite(y)&&Number.isFinite(b)&&b>y&&Number.isFinite(S)&&Number.isFinite(x)&&S>x,ie=(e,t,n)=>{let r=At(t,E.length,e.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`,i=e.kind??`line`;if(i===`scatter`){let e=n===``?[]:n.split(` `).map(e=>{let[t,n]=e.split(`,`);return[Number(t),Number(n)]});return(0,g.jsx)(`g`,{children:e.map(([e,t],n)=>(0,g.jsx)(`circle`,{cx:e,cy:t,r:2.6,className:V.scatterDot,style:{fill:r}},n))},t)}if(i===`area`){if(n===``)return(0,g.jsx)(Pt,{points:``,className:V.line,color:r},t);let e=n.slice(0,n.indexOf(` `)).split(`,`)[0],i=n.slice(n.lastIndexOf(` `)+1).split(`,`)[0],a=T(x),o=`${e},${a.toFixed(2)} ${n} ${i},${a.toFixed(2)}`;return(0,g.jsx)(`polygon`,{points:o,className:V.area,style:{fill:r}},t)}return(0,g.jsx)(Pt,{points:n,className:V.line,color:r},t)},ae=e=>{c.current={startX:e.clientX,startY:e.clientY,xMin:y,xMax:b},e.target.setPointerCapture?.(e.pointerId)},oe=e=>{let t=c.current;if(t===null)return;let n=t.xMax-t.xMin,r=(t.startX-e.clientX)/436*n;s(e=>({xMin:t.xMin+r,xMax:t.xMax+r,yMin:e.yMin,yMax:e.yMax}))},D=()=>{c.current=null},se=e=>{let t=b-y,n=t*(e.deltaY>0?1.15:1/1.15),r=e.currentTarget.getBoundingClientRect(),i=C((e.clientX-r.left)/r.width*480),a=i-(i-y)/t*n;s(e=>({xMin:a,xMax:a+n,yMin:e.yMin,yMax:e.yMax}))},O=e.some(e=>(e.params?.length??0)>0);return(0,g.jsxs)(`div`,{className:V.block,"data-genui-plot":!0,children:[a!==void 0&&(0,g.jsx)(`div`,{className:V.title,children:a}),ne&&re?(0,g.jsxs)(`svg`,{width:`100%`,viewBox:`0 0 480 220`,role:`img`,"aria-label":a??`function plot`,className:V.surface,onPointerDown:ae,onPointerMove:oe,onPointerUp:D,onPointerLeave:D,onWheel:se,children:[te.map(e=>(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`line`,{x1:34,x2:470,y1:T(e),y2:T(e),className:V.gridLine}),(0,g.jsx)(`text`,{x:28,y:T(e)+4,className:V.tick,textAnchor:`end`,children:Nt(e)})]},`y${e}`)),ee.map(e=>(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`line`,{x1:w(e),x2:w(e),y1:14,y2:196,className:V.gridLine}),(0,g.jsx)(`text`,{x:w(e),y:210,className:V.tick,textAnchor:`middle`,children:Nt(e)})]},`x${e}`)),(0,g.jsx)(`line`,{x1:34,x2:470,y1:196,y2:196,className:V.axis}),(0,g.jsx)(`line`,{x1:34,x2:34,y1:14,y2:196,className:V.axis}),E.map(({series:e,points:t},n)=>ie(e,n,t))]}):(0,g.jsx)(`div`,{className:V.empty,children:e.map((e,t)=>(0,g.jsxs)(`div`,{className:V.emptyRow,children:[e.expr,` — 无法绘制(表达式无效或范围非法)`]},t))}),O&&(0,g.jsxs)(`div`,{className:V.sliders,children:[(0,g.jsxs)(`div`,{className:V.slidersHead,children:[(0,g.jsx)(`span`,{className:V.slidersTitle,children:`参数调节`}),(0,g.jsx)(`button`,{type:`button`,className:V.resetBtn,onClick:()=>{p(!1);let t={};for(let[n,r]of e.entries())for(let e of r.params??[])e!=null&&(t[`${n}:${e.name}`]=e.value);u(t),_(0)},children:`↺ 重置`})]}),e.map((e,t)=>(e.params??[]).map(n=>{if(n==null)return null;let r=`${t}:${n.name}`,i=l[r]??n.value;return(0,g.jsxs)(`label`,{className:V.sliderRow,children:[(0,g.jsxs)(`span`,{className:V.sliderName,children:[e.label??e.expr,` · `,n.name]}),(0,g.jsx)(`input`,{type:`range`,className:V.slider,min:n.min??0,max:n.max??10,step:n.step??.1,value:i,onChange:e=>{let t=Number(e.currentTarget.value);u(e=>({...e,[r]:t}))}}),(0,g.jsx)(`span`,{className:V.sliderValue,children:Math.round(i*100)/100})]},r)}))]}),d!==null&&(0,g.jsxs)(`div`,{className:V.animBar,children:[(0,g.jsx)(`button`,{type:`button`,className:V.playBtn,onClick:()=>{f?p(!1):(u(e=>({...e,[`${d.si}:${d.param.name}`]:d.param.value})),_(0),p(!0))},children:f?`⏸ 暂停`:`▶ 播放动画`}),f&&(0,g.jsx)(`div`,{className:V.animTrack,children:(0,g.jsx)(`div`,{className:V.animFill,style:{width:`${h*100}%`}})})]}),(e.length>1||O)&&(0,g.jsx)(`div`,{className:V.legend,children:e.map((t,n)=>(0,g.jsxs)(`span`,{className:V.legendItem,children:[(0,g.jsx)(`span`,{className:V.legendSwatch,style:{background:At(n,e.length,t.color)??`var(--dsw-alias-state-business-primary, #4f8ef7)`}}),t.label??t.expr]},n))})]})});function It(e){let t=window.__DSH_BOOT__?.entries?.find(e=>e.id===Rt)?.rev;return`${zt}/${e}${t===void 0?``:`?rev=${t}`}`}function Lt(e){let t=`${e}.js`,n=Bt.get(t);if(n!==void 0)return n;let r=new Promise((n,r)=>{let i=document.createElement(`script`);i.src=It(t),i.async=!0,i.onload=()=>{let i=(window.__GenuiAssets__??{})[e];if(i===void 0){r(Error(`genui asset '${t}' loaded but registered no '${e}' engine`));return}n(i)},i.onerror=()=>{r(Error(`genui asset '${t}' failed to load (host asset route missing?)`))},document.head.appendChild(i)});return Bt.set(t,r),r}var Rt,zt,Bt,H=l((()=>{Rt=`@omdsh-dev/dsh-genui`,zt=`/plugins/${Rt}/assets`,Bt=new Map}));function Vt(e){if(Wt.test(e))throw Error(`mermaid output failed the sanitization check; refusing to render`)}function Ht(e){let t=/^([A-Za-z]+)/.exec(e.trim())?.[1]??``;if(t!==`graph`&&t!==`flowchart`)return e;let n=e.replace(/`/g,``).replace(/<br\s*\/?>/gi,` `),r=/(--|==|-\.)(?!>)[ \t]*([^-\n]|-(?!--))*?[ \t]*(-->|==>|\.->)/g,i=[],a=n.replace(r,e=>(i.push(e),`\uE000${i.length-1}\uE001`)),o=/\|([^|\n]*[\[\]][^|\n]*)\|/g,s=[];return a.replace(o,(e,t)=>{let n=t.trim();return n.includes(`"`)?e:(s.push(n),`\uE002${s.length-1}\uE003`)}).replace(/([\[\(])([^\[\]\(\)\{\}"'\n]*)([\]\)])/g,(e,t,n,r)=>{let i=n.trim();return i===``?e:/[\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]/.test(i)||/\s/.test(i)?`${t}"${i}"${r}`:e}).replace(/\uE000(\d+)\uE001/g,(e,t)=>i[Number(t)]??e).replace(/\uE002(\d+)\uE003/g,(e,t)=>{let n=s[Number(t)];return n===void 0?e:`|"${n}"|`})}function Ut(e){let t=e.trim(),n=/^([A-Za-z]+)/.exec(t)?.[1]??``;return n===`graph`||n===`flowchart`||!Gt.test(t)?e:`graph TD\n${t}`}var Wt,Gt,Kt=l((()=>{Wt=/<script|[\s"']on[a-z]+\s*=|javascript:/i,Gt=/-->(?!>)|==>|-\.->/})),qt=u({assertSafeSvg:()=>Vt,ensureFlowchartKind:()=>Ut,renderMermaid:()=>Jt,repairMermaidSource:()=>Ht});async function Jt(e){return(await Lt(`mermaid`)).renderMermaid(e)}var Yt=l((()=>{H(),Kt()})),Xt=u({mountScene:()=>Zt});async function Zt(e,t){return(await Lt(`three`)).mountScene(e,t)}var Qt=l((()=>{H()}));let $t={info:C.calloutInfo,success:C.calloutSuccess,warning:C.calloutWarning,error:C.calloutError},en=(0,m.memo)(function({node:e}){let t=e.tone??`info`,n=$t[t]??C.calloutInfo;return(0,g.jsxs)(`div`,{className:`${C.callout} ${n}`,"data-genui-callout":!0,children:[e.title!==void 0&&(0,g.jsx)(`div`,{className:C.calloutTitle,children:e.title}),(0,g.jsx)(`div`,{className:C.calloutBody,children:e.content})]})}),tn=(0,m.memo)(function({steps:e}){let t=e.steps.slice(0,O.maxSteps),n=e.current??t.length;return(0,g.jsx)(`ol`,{className:C.steps,children:t.map((e,t)=>{let r=t<n,i=t===n;return(0,g.jsxs)(`li`,{className:`${C.step} ${r?C.stepDone:``} ${i?C.stepActive:``}`,children:[(0,g.jsx)(`span`,{className:C.stepMarker,children:r?`✓`:String(t+1)}),(0,g.jsxs)(`span`,{className:C.stepContent,children:[(0,g.jsx)(`span`,{className:C.stepTitle,children:e.title}),e.desc!==void 0&&(0,g.jsx)(`span`,{className:C.stepDesc,children:e.desc})]})]},t)})})}),nn=(0,m.memo)(function({node:e}){let t=e.pairs.slice(0,O.maxKeyValuePairs);return(0,g.jsx)(`dl`,{className:C.keyvalue,children:t.map((e,t)=>(0,g.jsxs)(`div`,{className:C.kvRow,children:[(0,g.jsx)(`dt`,{className:C.kvKey,children:e.key}),(0,g.jsx)(`dd`,{className:C.kvValue,children:e.value})]},t))})}),rn=(0,m.memo)(function({plot:e}){let t=(0,m.useMemo)(()=>e.series.slice(0,O.maxPlotSeries).map(e=>({expr:e.expr,label:e.label,color:e.color,kind:e.kind,params:e.params})),[e]);return(0,g.jsx)(Ft,{series:t,xMin:e.xMin,xMax:e.xMax,yMin:e.yMin,yMax:e.yMax,title:e.title})}),an=(0,m.memo)(function({node:e}){return(0,g.jsx)(p.DiffBlock,{diffs:e.diffs})}),on=(0,m.memo)(function({node:e}){let t=e.value;return typeof t!=`object`||!t?(0,g.jsx)(`div`,{className:C.jsonScalar,children:String(t)}):(0,g.jsx)(p.JsonTree,{data:t,copyable:!0})}),sn=(0,m.memo)(function({node:e}){return(0,g.jsx)(p.CodeBlock,{code:e.code.slice(0,O.maxCode),lang:e.lang})});function cn({tabs:e,onAction:t,depth:n=0,answers:r}){let[i,a]=(0,m.useState)(0),o=(0,m.useId)(),s=e.tabs.slice(0,O.maxTabs),c=s[i],l=e=>{let t=(e+s.length)%s.length;a(t),document.getElementById(`${o}-tab-${t}`)?.focus()};return(0,g.jsxs)(`div`,{className:C.tabs,children:[(0,g.jsx)(`div`,{className:C.tabBar,role:`tablist`,"aria-orientation":`horizontal`,onKeyDown:e=>{e.key===`ArrowRight`?(e.preventDefault(),l(i+1)):e.key===`ArrowLeft`?(e.preventDefault(),l(i-1)):e.key===`Home`?(e.preventDefault(),l(0)):e.key===`End`&&(e.preventDefault(),l(s.length-1))},children:s.map((e,t)=>(0,g.jsx)(`button`,{id:`${o}-tab-${t}`,type:`button`,role:`tab`,"aria-selected":t===i,"aria-controls":`${o}-panel-${t}`,tabIndex:t===i?0:-1,className:`${C.tab} ${t===i?C.tabActive:``}`,onClick:()=>a(t),children:e.label},t))}),c!==void 0&&(0,g.jsx)(`div`,{className:C.col,role:`tabpanel`,id:`${o}-panel-${i}`,"aria-labelledby":`${o}-tab-${i}`,children:c.items.map((e,i)=>K(e,i,t,n+1,r))})]})}function ln({node:e,onAction:t,depth:n=0,answers:r}){let[i,a]=(0,m.useState)(0),o=(0,m.useId)(),s=e.items.slice(0,O.maxAccordionItems);return(0,g.jsx)(`div`,{className:C.accordion,children:s.map((e,s)=>(0,g.jsxs)(`div`,{className:C.accItem,children:[(0,g.jsxs)(`button`,{type:`button`,className:C.accHead,id:`${o}-head-${s}`,"aria-expanded":i===s,"aria-controls":`${o}-body-${s}`,onClick:()=>a(i===s?null:s),children:[(0,g.jsx)(`span`,{className:C.accTitle,children:e.title}),(0,g.jsx)(`span`,{className:C.accChevron,children:i===s?`▾`:`▸`})]}),i===s&&(0,g.jsx)(`div`,{className:C.accBody,id:`${o}-body-${s}`,"aria-labelledby":`${o}-head-${s}`,children:e.items.map((e,i)=>K(e,i,t,n+1,r))})]},s))})}let un=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(!1);return(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`button`,{type:`button`,className:`${C.copyChip} ${t?C.copyChipDone:``}`,onClick:()=>{navigator.clipboard?.writeText(e.text).catch(()=>{}),n(!0),setTimeout(()=>n(!1),1500)},children:t?`✓ 已复制`:e.label??`复制`}),(0,g.jsx)(`span`,{className:C.visuallyHidden,role:`status`,children:t?`已复制到剪贴板`:``})]})}),dn=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(null),[r,i]=(0,m.useState)(!1),a=e.code.slice(0,O.maxMermaid);return(0,m.useEffect)(()=>{let e=!0;return Promise.resolve().then(()=>(Yt(),qt)).then(async t=>{try{let r=await t.renderMermaid(a);e&&n(r)}catch{e&&i(!0)}}),()=>{e=!1}},[a]),r?(0,g.jsxs)(`div`,{className:C.mermaidFallback,children:[(0,g.jsx)(`pre`,{children:a}),(0,g.jsx)(`div`,{className:C.mermaidErr,children:`图语法有误,已降级显示源码`})]}):t===null?(0,g.jsxs)(`div`,{className:C.mermaidFallback,children:[(0,g.jsx)(`pre`,{children:a}),(0,g.jsx)(`div`,{className:C.mermaidHint,children:`渲染中…`})]}):(0,g.jsx)(`div`,{className:C.mermaid,dangerouslySetInnerHTML:{__html:t},"data-genui-mermaid":!0})}),fn=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(`loading`),r=(0,m.useRef)(null),i=e.meshes.length>O.maxMeshes?{...e,meshes:e.meshes.slice(0,O.maxMeshes)}:e;return(0,m.useEffect)(()=>{let e=!0,t;return Promise.resolve().then(()=>(Qt(),Xt)).then(async a=>{if(!(!e||r.current===null))try{t=await a.mountScene(r.current,i),e&&n(`ready`)}catch{e&&n(`error`)}}),()=>{e=!1,t?.()}},[i]),(0,g.jsxs)(`div`,{className:C.scene3dWrap,"data-genui-scene3d":!0,children:[e.title!==void 0&&(0,g.jsx)(`div`,{className:C.scene3dTitle,children:e.title}),(0,g.jsx)(`div`,{ref:r,className:C.scene3dCanvas}),t===`loading`&&(0,g.jsx)(`div`,{className:C.scene3dHint,children:`加载 3D 场景…`}),t===`error`&&(0,g.jsx)(`div`,{className:C.scene3dHint,children:`3D 渲染失败`})]})}),pn=(0,m.memo)(function({node:e}){let t=e.items.slice(0,O.maxTimelineItems);return(0,g.jsx)(`div`,{className:C.timeline,children:t.map((e,n)=>(0,g.jsxs)(`div`,{className:C.tlItem,children:[(0,g.jsxs)(`div`,{className:C.tlRail,children:[(0,g.jsx)(`span`,{className:C.tlDot}),n<t.length-1&&(0,g.jsx)(`span`,{className:C.tlLine})]}),(0,g.jsxs)(`div`,{className:C.tlBody,children:[(0,g.jsxs)(`div`,{className:C.tlHead,children:[(0,g.jsx)(`span`,{className:C.tlTitle,children:e.title}),e.time!==void 0&&(0,g.jsx)(`span`,{className:C.tlTime,children:e.time})]}),e.desc!==void 0&&(0,g.jsx)(`div`,{className:C.tlDesc,children:e.desc})]})]},n))})}),mn=(0,m.memo)(function({node:e}){let[t,n]=(0,m.useState)(new Set),r=(e,t)=>`${e}-${t}`,i=e=>{n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},a=(e,n,o)=>{if(n>O.maxTreeDepth)return null;let s=e.type===`dir`||e.children!==void 0&&e.children.length>0,c=r(n,o),l=s&&t.has(c);return(0,g.jsxs)(`div`,{className:C.ftRow,style:{paddingLeft:`${n*16}px`},children:[(0,g.jsxs)(`button`,{type:`button`,className:C.ftNameBtn,"aria-expanded":s?!l:void 0,onClick:s?()=>i(c):void 0,children:[(0,g.jsx)(`span`,{className:`${C.ftIcon} ${s?C.ftIconDir:``}`,"aria-hidden":!0,children:s?l?`▸`:`▾`:`·`}),(0,g.jsx)(`span`,{className:`${C.ftName} ${s?C.ftDir:``}`,children:e.name})]}),s&&!l&&(e.children??[]).map((e,t)=>a(e,n+1,t))]},c)};return(0,g.jsx)(`div`,{className:C.fileTree,children:e.items.slice(0,O.maxListItems).map((e,t)=>a(e,0,t))})}),hn=(0,m.memo)(function({node:e,onAction:t}){let[n,r]=(0,m.useState)(null),i=e.options.slice(0,O.maxQuizOptions),a=n!==null,o=n===null?void 0:i[n],s=o?.correct===!0,c=e.action;return(0,g.jsxs)(`div`,{className:C.quiz,"data-genui-quiz":!0,children:[(0,g.jsx)(`div`,{className:C.quizQuestion,children:e.question}),(0,g.jsx)(`div`,{className:C.quizOptions,children:i.map((i,o)=>{let s=n===o,l=a?s?i.correct===!0?C.quizOptCorrect:C.quizOptWrong:i.correct===!0?C.quizOptReveal:C.quizOpt:C.quizOpt;return(0,g.jsxs)(`button`,{type:`button`,className:l,disabled:a,onClick:()=>{r(o),c!==void 0&&t!==void 0&&t(c,{type:`quiz`,question:e.question,answer:i.label,correct:i.correct===!0})},children:[(0,g.jsx)(`span`,{className:C.quizMarker,children:a&&(i.correct===!0?`✓`:s?`✗`:``)}),i.label]},o)})}),a&&(0,g.jsxs)(`div`,{className:C.quizResult,"aria-live":`polite`,children:[(0,g.jsxs)(`div`,{className:s?C.quizCorrectMsg:C.quizWrongMsg,children:[s?`✓ 回答正确!`:`✗ 再想想看`,o?.feedback!==void 0&&(0,g.jsx)(`div`,{className:C.quizFeedback,children:o.feedback})]}),e.explanation!==void 0&&(0,g.jsx)(`div`,{className:C.quizExplanation,children:e.explanation}),(0,g.jsx)(`button`,{type:`button`,className:C.quizRetry,onClick:()=>r(null),children:`重新作答`})]})]})}),gn=(0,m.memo)(function({node:e}){let t=e.items.slice(0,O.maxBreadcrumbItems);return(0,g.jsx)(`nav`,{className:C.breadcrumb,"aria-label":`breadcrumb`,children:t.map((e,n)=>(0,g.jsxs)(`span`,{className:C.bcItem,children:[(0,g.jsx)(`span`,{className:`${C.bcText} ${n===t.length-1?C.bcCurrent:``}`,children:e}),n<t.length-1&&(0,g.jsx)(`span`,{className:C.bcSep,children:`/`})]},n))})}),_n=[`architecture`,`it-state`,`high-level`,`process`,`medallion`,`data-flow`,`dp-integration`];function vn(e){return _n.includes(e)}function yn(e,t){let n=e%t,r=Math.floor(e/t);return{x:40+n*160,y:40+r*96,w:128,h:64}}function bn(e){return e.map((e,t)=>({node:e,box:{x:40,y:40+t*96,w:128,h:64}}))}function xn(e){return e.map((e,t)=>({node:e,box:{x:40+t*160,y:40,w:128,h:64}}))}function Sn(e,t=3){return e.map((e,n)=>{let r=Math.floor(n/t);return{node:e,box:{x:40+n%t*160,y:40+r*96,w:128,h:64}}})}function Cn(e,t){let n=new Map(e.map(e=>[e.id,e])),r=new Map,i=[];for(let a of e){let e=t(a.id);if(e===void 0||!n.has(e))i.push(a.id);else{let t=r.get(e)??[];t.push(a.id),r.set(e,t)}}let a=new Map,o=new Map,s=(e,t)=>{let n=o.get(e)??0,i=r.get(e)??[],c=t;if(i.length===0)return a.set(e,{x:t,y:40+n*112,w:128,h:64}),t+128;for(let e of i)c=s(e,c);let l=a.get(i[0]),u=a.get(i[i.length-1]),d=(l.x+u.x+u.w)/2-64;return a.set(e,{x:Math.max(t,d),y:40+n*112,w:128,h:64}),c},c=40;for(let e of i)c=s(e,c)+32;return e.map(e=>({node:e,box:a.get(e.id)??{x:40,y:40,w:128,h:64}}))}function wn(e,t){let n=e.nodes,r=e.edges??[],i;i=vn(e.kind)?n.map((e,t)=>({node:e,box:{x:e.x??40+t%3*160,y:e.y??40+Math.floor(t/3)*96,w:e.w??128,h:e.h??64}})):e.kind===`tree`||e.kind===`org-chart`||e.kind===`nested`?Cn(n,t??(()=>void 0)):e.kind===`layers`||e.kind===`pyramid`||e.kind===`gantt`?Sn(n):e.kind===`flowchart`||e.kind===`process`||e.kind===`sequence`?bn(n):e.kind===`timeline`||e.kind===`line`||e.kind===`scatter`||e.kind===`bar`?xn(n):n.map((e,t)=>({node:e,box:yn(t,3)}));let a=0,o=0;for(let e of i)a=Math.max(a,e.box.x+e.box.w),o=Math.max(o,e.box.y+e.box.h);a=Math.max(320,Math.ceil((a+40)/4)*4),o=Math.max(200,Math.ceil((o+40)/4)*4);let s=r.map(e=>({edge:e,fromId:e.from,toId:e.to}));return{nodes:i,edges:s,width:a,height:o}}function Tn(e){return{x:e.x+e.w/2,y:e.y+e.h/2}}function En(e,t,n){if(n===`left`)return{x:e.x,y:e.y+e.h/2,port:`left`};if(n===`right`)return{x:e.x+e.w,y:e.y+e.h/2,port:`right`};if(n===`top`)return{x:e.x+e.w/2,y:e.y,port:`top`};if(n===`bottom`)return{x:e.x+e.w/2,y:e.y+e.h,port:`bottom`};let r=Tn(e),i=Tn(t),a=i.x-r.x,o=i.y-r.y;return Math.abs(a)>=Math.abs(o)?a>=0?{x:e.x+e.w,y:e.y+e.h/2,port:`right`}:{x:e.x,y:e.y+e.h/2,port:`left`}:o>=0?{x:e.x+e.w/2,y:e.y+e.h,port:`bottom`}:{x:e.x+e.w/2,y:e.y,port:`top`}}function Dn(e,t){if(e.x===t.x||e.y===t.y)return`M ${e.x} ${e.y} L ${t.x} ${t.y}`;let n=e.port===`left`||e.port===`right`,r=t.port===`left`||t.port===`right`;if(n&&r){let n=(e.x+t.x)/2,r=e.port===`right`?1:-1;return`M ${e.x} ${e.y} H ${n-r*8} Q ${n} ${e.y} ${n} ${e.y+8} V ${t.y-8} Q ${n} ${t.y} ${n+8} ${t.y} H ${t.x}`}if(!n&&!r){let n=(e.y+t.y)/2,r=e.port===`bottom`?1:-1;return`M ${e.x} ${e.y} V ${n-r*8} Q ${e.x} ${n} ${e.x+8} ${n} H ${t.x-8} Q ${t.x} ${n} ${t.x} ${n+8} V ${t.y}`}if(n){let n=e.port===`right`?1:-1;return`M ${e.x} ${e.y} H ${e.x+n*8*2} Q ${e.x+n*8*2} ${e.y} ${e.x+n*8*2} ${t.y} V ${t.y} H ${t.x}`}let i=e.port===`bottom`?1:-1;return`M ${e.x} ${e.y} V ${e.y+i*8*2} Q ${e.x} ${e.y+i*8*2} ${t.x} ${e.y+i*8*2} H ${t.x} V ${t.y}`}function On(e,t,n){let r=En(e,t,n?.fromPort),i=En(t,e,n?.toPort);return{d:Dn(r,i),a:r,b:i}}function kn(e,t){let n=(e.x+t.x)/2,r=(e.y+t.y)/2,i=Math.abs(e.x-t.x)<Math.abs(e.y-t.y);return i?{cx:n+(t.x>=e.x?1:-1)*16,cy:r,maskY:r-6,vertical:i}:{cx:n,cy:r,maskY:r-20,vertical:i}}let An={paper:`#f5f5f5`,paper2:`#ececec`,ink:`#2d3142`,muted:`#4f5d75`,soft:`#7a8399`,rule:`rgba(45,49,66,0.12)`,accent:`#eb6c36`,accentTint:`rgba(235,108,54,0.08)`,link:`#2e5aa8`},jn={paper:`#2d3142`,paper2:`#393e53`,ink:`#f5f5f5`,muted:`#bfc0c0`,soft:`#8e98ac`,rule:`rgba(245,245,245,0.12)`,accent:`#f08a59`,accentTint:`rgba(240,138,89,0.10)`,link:`#6a95d8`};function Mn(e,t){let n=e===`dark`?jn:An;return t===void 0?n:{paper:t.paper??n.paper,paper2:t[`paper-2`]??n.paper2,ink:t.ink??n.ink,muted:t.muted??n.muted,soft:t.soft??n.soft,rule:t.rule??n.rule,accent:t.accent??n.accent,accentTint:t[`accent-tint`]??n.accentTint,link:t.link??n.link}}function Nn(e,t){switch(e){case`focal`:return{fill:t.accentTint,stroke:t.accent};case`store`:return{fill:U(t.ink,.05),stroke:t.muted};case`external`:return{fill:U(t.ink,.03),stroke:U(t.ink,.3)};case`input`:return{fill:U(t.muted,.1),stroke:t.soft};case`optional`:return{fill:U(t.ink,.02),stroke:U(t.ink,.2),dashed:!0};case`security`:return{fill:U(t.accent,.05),stroke:U(t.accent,.5),dashed:!0};default:return{fill:`#ffffff`,stroke:t.ink}}}function Pn(e,t){switch(e){case`accent`:return t.accent;case`link`:return t.link;default:return t.muted}}function U(e,t){if(e.startsWith(`#`)){let n=e.slice(1),r=n.length===3?n.split(``).map(e=>e+e).join(``):n;return`rgba(${parseInt(r.slice(0,2),16)},${parseInt(r.slice(2,4),16)},${parseInt(r.slice(4,6),16)},${t})`}return e.replace(/rgba?\(([^)]*)\)/,(n,r)=>{let i=r.split(`,`).map(e=>e.trim());return i.length===3?`rgba(${i.join(`,`)},${t})`:i.length===4?`rgba(${i[0]},${i[1]},${i[2]},${t})`:e})}let Fn=`'Geist', -apple-system, 'Segoe UI', sans-serif`,W=`'Geist Mono', ui-monospace, 'SF Mono', monospace`;function In(e){let t=new Map;for(let n of e)t.has(n.to)||t.set(n.to,n.from);return e=>t.get(e)}function Ln(e,t,n,r,i,a,o){let s=Nn(r,o),c=e.x+e.w/2,l=e.y+(e.h-64)/2+28,u=e.y+(e.h-64)/2+44,d=Math.min(44,Math.max(24,(i??``).length*7+8));return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`rect`,{x:e.x,y:e.y,width:e.w,height:e.h,rx:6,fill:o.paper}),(0,g.jsx)(`rect`,{x:e.x,y:e.y,width:e.w,height:e.h,rx:6,fill:s.fill,stroke:s.stroke,strokeWidth:1,strokeDasharray:s.dashed===!0?`5,4`:void 0}),i!==void 0&&(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`rect`,{x:e.x+8,y:e.y+6,width:d,height:12,rx:2,fill:`transparent`,stroke:U(s.stroke,.4),strokeWidth:.8}),(0,g.jsx)(`text`,{x:e.x+8+d/2,y:e.y+15,fill:U(s.stroke,.8),fontSize:7,fontFamily:W,textAnchor:`middle`,letterSpacing:.8,children:i})]}),(0,g.jsx)(`text`,{x:e.x+e.w-6,y:e.y+e.h-6,fill:U(s.stroke,.12),fontSize:24,fontWeight:600,fontFamily:W,textAnchor:`end`,children:String(a).padStart(2,`0`)}),(0,g.jsx)(`text`,{x:c,y:l,fill:o.ink,fontSize:12,fontWeight:600,fontFamily:Fn,textAnchor:`middle`,children:t}),n!==void 0&&(0,g.jsx)(`text`,{x:c,y:u,fill:o.soft,fontSize:9,fontFamily:W,textAnchor:`middle`,children:n})]})}function Rn(e,t,n,r){let i=On(e.from,e.to),a=Pn(e.kind,n),o=e.kind===`dashed`,s=e.kind===`accent`?1.4:1.2,c=kn(i.a,i.b);return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`path`,{d:i.d,fill:`none`,stroke:a,strokeWidth:s,strokeDasharray:o?`5,4`:void 0,markerEnd:`url(#${r})`}),e.label!==void 0&&(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`rect`,{x:c.cx-(e.label.length*5+8)/2,y:c.maskY,width:e.label.length*5+8,height:12,rx:2,fill:n.paper}),(0,g.jsx)(`text`,{x:c.cx,y:c.maskY+9,fill:n.soft,fontSize:8,fontFamily:W,textAnchor:`middle`,letterSpacing:.5,children:e.label})]})]},t)}function zn(e,t){return(0,g.jsxs)(`defs`,{children:[(0,g.jsx)(`marker`,{id:`${e}-arrow`,markerWidth:8,markerHeight:6,refX:7,refY:3,orient:`auto`,children:(0,g.jsx)(`polygon`,{points:`0 0, 8 3, 0 6`,fill:t.muted})}),(0,g.jsx)(`marker`,{id:`${e}-arrow-accent`,markerWidth:8,markerHeight:6,refX:7,refY:3,orient:`auto`,children:(0,g.jsx)(`polygon`,{points:`0 0, 8 3, 0 6`,fill:t.accent})}),(0,g.jsx)(`marker`,{id:`${e}-arrow-link`,markerWidth:8,markerHeight:6,refX:7,refY:3,orient:`auto`,children:(0,g.jsx)(`polygon`,{points:`0 0, 8 3, 0 6`,fill:t.link})})]})}function Bn(e,t){return(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`defs`,{children:(0,g.jsx)(`pattern`,{id:`${e}-dots`,width:22,height:22,patternUnits:`userSpaceOnUse`,children:(0,g.jsx)(`circle`,{cx:1,cy:1,r:.9,fill:U(t.ink,.1)})})}),(0,g.jsx)(`rect`,{width:`100%`,height:`100%`,fill:t.paper}),(0,g.jsx)(`rect`,{width:`100%`,height:`100%`,fill:`url(#${e}-dots)`,opacity:.55})]})}function Vn(e,t){let n=e.label.length*7+12,r=e.x+e.w/2;return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`rect`,{x:e.x,y:e.y,width:e.w,height:e.h,rx:8,fill:U(t.ink,.02),stroke:U(t.ink,.1),strokeWidth:.8}),(0,g.jsx)(`rect`,{x:r-n/2,y:e.y+4,width:n,height:12,rx:2,fill:t.paper}),(0,g.jsx)(`text`,{x:r,y:e.y+13,fill:U(t.ink,.4),fontSize:7,fontFamily:W,textAnchor:`middle`,letterSpacing:1.2,children:e.label})]})}function Hn(e){return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`line`,{x1:40,y1:0,x2:1e3,y2:0,stroke:U(e.ink,.1),strokeWidth:.8}),(0,g.jsx)(`text`,{x:40,y:16,fill:e.soft,fontSize:8,fontFamily:W,letterSpacing:1.6,children:`LEGEND`}),[{label:`Focal`,type:`focal`},{label:`Backend`,type:`backend`},{label:`Store`,type:`store`},{label:`External`,type:`external`},{label:`Optional`,type:`optional`},{label:`Security`,type:`security`}].map((t,n)=>{let r=Nn(t.type,e),i=40+n*170;return(0,g.jsxs)(`g`,{children:[(0,g.jsx)(`rect`,{x:i,y:32,width:14,height:10,rx:2,fill:r.fill,stroke:r.stroke,strokeWidth:1,strokeDasharray:r.dashed===!0?`3,2`:void 0}),(0,g.jsx)(`text`,{x:i+20,y:41,fill:e.soft,fontSize:8.5,fontFamily:Fn,children:t.label})]},t.label)})]})}function Un(e,t){return e===`accent`?`${t}-arrow-accent`:e===`link`?`${t}-arrow-link`:`${t}-arrow`}let Wn=0;function Gn(){return Wn+=1,`genui-diagram-${Wn}`}function Kn({node:e}){let t=(0,m.useMemo)(Gn,[]),n=(0,m.useMemo)(()=>Mn(e.variant,e.theme),[e.variant,e.theme]),r=(0,m.useMemo)(()=>wn(e,In(e.edges??[])),[e]),i=(0,m.useMemo)(()=>new Map(r.nodes.map(e=>[e.node.id,e.box])),[r]),a=`${t}-title`,o=`${t}-caption`,s=`${t}-desc`,c=r.nodes.slice(0,O.maxDiagramNodes),l=r.edges.slice(0,O.maxDiagramEdges),u=(e.zones??[]).slice(0,O.maxDiagramZones),d=0,f=O.maxDiagramFocal,p=r.height,h=p+56+24;return(0,g.jsxs)(`figure`,{className:`genui-diagram`,"data-genui-diagram":!0,children:[e.title!==void 0&&(0,g.jsx)(`figcaption`,{id:o,style:{fontFamily:`Instrument Serif, 'Times New Roman', serif`,fontSize:20,marginBottom:8,color:n.ink},children:e.title}),(0,g.jsxs)(`svg`,{role:`img`,"aria-labelledby":a,"aria-describedby":s,viewBox:`0 0 ${r.width} ${h}`,style:{maxWidth:`100%`,height:`auto`,background:n.paper},children:[(0,g.jsx)(`title`,{id:a,children:e.title??e.kind}),(0,g.jsx)(`desc`,{id:s,children:`${e.kind} diagram with ${c.length} nodes and ${l.length} connectors`}),zn(t,n),Bn(t,n),(0,g.jsx)(`g`,{children:u.map((e,t)=>(0,g.jsx)(`g`,{children:Vn({label:e.label,x:e.x??0,y:e.y??0,w:e.w??100,h:e.h??100},n)},`zone-${t}`))}),(0,g.jsx)(`g`,{children:l.map((e,r)=>{let a=i.get(e.fromId),o=i.get(e.toId);return a===void 0||o===void 0?null:Rn({from:a,to:o,label:e.edge.label,kind:e.edge.kind},r,n,Un(e.edge.kind,t))})}),(0,g.jsx)(`g`,{children:c.map((e,t)=>{let r=e.node.type===`focal`&&d>=f?void 0:e.node.type;return e.node.type===`focal`&&(d+=1),(0,g.jsx)(`g`,{children:Ln(e.box,e.node.label,e.node.sub,r,e.node.tag,t+1,n)},e.node.id)})}),(0,g.jsx)(`g`,{transform:`translate(0, ${p+8})`,children:Hn(n)})]})]})}H();async function qn(e,t,n){return(await Lt(`echarts`)).createChart(e,t,n)}function G(e,t){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Jn(){return{accent:G(`--dsw-alias-state-business-primary`,`#4f8ef7`),labelPrimary:G(`--dsw-alias-label-primary`,`#e6e6e6`),labelSecondary:G(`--dsw-alias-label-secondary`,`#a0a0a0`),labelTertiary:G(`--dsw-alias-label-tertiary`,`#6b6b6b`),border:G(`--dsw-alias-border-l1`,`rgba(255,255,255,0.12)`),bgLayer1:G(`--dsw-alias-bg-layer-1`,`#1a1a1e`)}}function Yn(e){let t=Jn(),n=it.map(e=>G(e.replace(`var(`,``).replace(`)`,``),t.accent)),r=e.data??[],i=e.series,a=(e={})=>({renderMode:`richText`,backgroundColor:t.bgLayer1,borderColor:t.border,textStyle:{color:t.labelPrimary},...e}),o={color:n,textStyle:{color:t.labelSecondary,fontFamily:`inherit`},backgroundColor:`transparent`,grid:{left:48,right:16,top:24,bottom:32},tooltip:a({trigger:`item`})};switch(e.preset){case`pie`:return{...o,tooltip:a({trigger:`item`,formatter:`{b}: {c} ({d}%)`}),legend:{bottom:0,textStyle:{color:t.labelTertiary}},series:[{type:`pie`,radius:[`40%`,`70%`],avoidLabelOverlap:!0,itemStyle:{borderRadius:6,borderColor:t.bgLayer1,borderWidth:2},label:{color:t.labelSecondary},data:r.map(e=>({name:e.label,value:e.value}))}]};case`scatter`:return{...o,tooltip:a({trigger:`item`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:[{type:`scatter`,symbolSize:10,data:r.map(e=>e.value)}]};case`area`:return{...o,tooltip:a({trigger:`axis`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map((e,t)=>({name:e.label,type:`line`,smooth:!0,areaStyle:{opacity:.15},data:e.data.map(e=>e.value),...Xn(e.color,t,i)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}};case`line`:return{...o,tooltip:a({trigger:`axis`}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map((e,t)=>({name:e.label,type:`line`,smooth:!0,showSymbol:!0,symbolSize:6,data:e.data.map(e=>e.value),...Xn(e.color,t,i)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}};default:return{...o,tooltip:a({trigger:`axis`,axisPointer:{type:`shadow`}}),xAxis:{type:`category`,data:r.map(e=>e.label),axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary}},yAxis:{type:`value`,axisLine:{lineStyle:{color:t.border}},axisLabel:{color:t.labelTertiary},splitLine:{lineStyle:{color:t.border,opacity:.5}}},series:(i??[{label:``,data:r}]).map(e=>({name:e.label,type:`bar`,barMaxWidth:40,itemStyle:{borderRadius:[4,4,2,2],...e.color===void 0?{}:{color:e.color}},data:e.data.map(e=>e.value)})),legend:i===void 0?void 0:{bottom:0,textStyle:{color:t.labelTertiary}}}}}function Xn(e,t,n){return e===void 0?{}:{itemStyle:{color:e}}}function Zn({node:e}){let t=(0,m.useRef)(null),[n,r]=(0,m.useState)(`loading`),i=(0,m.useRef)(null);return(0,m.useEffect)(()=>{let n=!0,a=t.current;return a===null?void 0:(qn(a,e.option??Yn(e),{height:e.height??300}).then(e=>{if(!n){e.dispose();return}i.current=e,r(`ready`)}).catch(()=>{n&&r(`error`)}),()=>{n=!1,i.current?.dispose(),i.current=null})},[]),(0,m.useEffect)(()=>{if(n!==`ready`)return;let e=t.current;if(e===null)return;let r=new ResizeObserver(()=>{i.current?.resize()});return r.observe(e),()=>{r.disconnect()}},[n]),(0,m.useEffect)(()=>{if(n!==`ready`||i.current===null)return;let t=e.option??Yn(e);i.current.setOption(t,!0)},[e,n]),n===`error`?(0,g.jsxs)(`div`,{className:C.echartFallback,"data-genui-echart":!0,children:[(0,g.jsx)(`div`,{className:C.echartErr,children:`ECharts 渲染失败`}),e.title!==void 0&&(0,g.jsx)(`div`,{className:C.echartHint,children:e.title})]}):(0,g.jsxs)(`div`,{className:C.echartWrap,"data-genui-echart":!0,children:[e.title!==void 0&&(0,g.jsx)(`div`,{className:C.echartTitle,children:e.title}),(0,g.jsx)(`div`,{ref:t,className:C.echartCanvas,style:{height:`${e.height??300}px`},role:`img`,"aria-label":e.title??`ECharts chart`}),n===`loading`&&(0,g.jsx)(`div`,{className:C.echartHint,children:`加载图表…`})]})}let Qn=p.getGenuiComponent;function $n(e){return typeof e==`object`&&!!e&&`type`in e}function K(e,t,n,r=0,i){if(r>O.maxDepth)return null;switch(e.type){case`text`:{let n=e.size??`body`;return(0,g.jsx)(`div`,{className:`${C.text} ${C[n]}`+(e.center?` ${C.center}`:``),children:e.content},t)}case`row`:return(0,g.jsxs)(`div`,{className:C.row+(e.wrap?` ${C.wrap}`:``),children:[e.items.map((e,t)=>K(e,t,n,r+1,i)),e.spacer&&(0,g.jsx)(`div`,{className:C.spacer})]},t);case`col`:return(0,g.jsx)(`div`,{className:C.col,style:e.gap===void 0?void 0:{gap:`${e.gap}px`},children:e.items.map((e,t)=>K(e,t,n,r+1,i))},t);case`grid`:return(0,g.jsx)(`div`,{className:C.grid,style:{gridTemplateColumns:`repeat(${Math.max(1,e.cols)}, minmax(0, 1fr))`},children:e.items.map((e,t)=>K(e,t,n,r+1,i))},t);case`card`:return(0,g.jsxs)(`div`,{className:C.card,children:[e.title!==void 0&&(0,g.jsx)(`div`,{className:C.cardTitle,children:e.title}),e.items.map((e,t)=>K(e,t,n,r+1,i))]},t);case`button`:{let r=e.tone??``,i=`${C.button} ${C[r]||``}`+(e.full?` ${C.full}`:``)+(e.small?` ${C.small}`:``),a=e.action,o=a!==void 0&&n!==void 0;return(0,g.jsxs)(tt,{className:i,disabled:!o,onClick:o?()=>n(a,{type:`button`,label:e.label}):void 0,children:[e.icon!==void 0&&(0,g.jsxs)(`span`,{"aria-hidden":!0,children:[e.icon,` `]}),e.label]},t)}case`input`:return(0,g.jsx)(xt,{node:e,onAction:n,answers:i},t);case`select`:return(0,g.jsx)(bt,{node:e,onAction:n,answers:i},t);case`checkbox`:{let r=e.action;return(0,g.jsxs)(`label`,{className:C.checkbox,children:[(0,g.jsx)(`input`,{type:`checkbox`,defaultChecked:e.checked===!0,onChange:r!==void 0&&n!==void 0?e=>n(r,{type:`checkbox`,checked:e.currentTarget.checked}):void 0}),(0,g.jsx)(`span`,{children:e.label})]},t)}case`link`:{let n=e.href;return n===void 0?(0,g.jsx)(`span`,{className:C.linkText,children:e.label},t):(0,g.jsx)(`a`,{className:C.link,href:n,target:`_blank`,rel:`noopener noreferrer`,children:e.label},t)}case`audio`:return(0,g.jsx)(nt,{node:e},`${t}:${e.src}`);case`video`:return(0,g.jsx)(rt,{node:e},`${t}:${e.src}`);case`badge`:{let n=e.tone??``;return(0,g.jsxs)(`span`,{className:`${C.badge} ${C[n]||``}`,children:[e.icon!==void 0&&(0,g.jsxs)(`span`,{"aria-hidden":!0,children:[e.icon,` `]}),e.label]},t)}case`stat`:{let n=e.delta!==void 0&&e.delta.startsWith(`-`);return(0,g.jsxs)(`div`,{className:C.stat,children:[(0,g.jsx)(`span`,{className:C.statLabel,children:e.label}),(0,g.jsx)(`span`,{className:C.statValue,children:e.value}),e.delta!==void 0&&(0,g.jsx)(`span`,{className:`${C.statDelta} ${n?C.down:C.up}`,children:e.delta})]},t)}case`progress`:{let n=Math.max(0,Math.min(100,Number(e.value)||0));return(0,g.jsxs)(`div`,{className:C.progress,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n,"aria-label":e.label??e.valueLabel??void 0,children:[(e.label!==void 0||e.valueLabel!==void 0)&&(0,g.jsxs)(`div`,{className:C.progressRow,children:[(0,g.jsx)(`span`,{children:e.label}),e.valueLabel!==void 0&&(0,g.jsx)(`span`,{children:e.valueLabel})]}),(0,g.jsx)(`div`,{className:C.track,children:(0,g.jsx)(`div`,{className:C.fill,style:{width:`${n}%`}})})]},t)}case`divider`:return(0,g.jsx)(`hr`,{className:C.divider},t);case`list`:{let a=e.items.slice(0,O.maxListItems);return(0,g.jsx)(`div`,{className:C.list,children:a.map((e,t)=>(0,g.jsx)(`div`,{className:C.li,children:$n(e)?K(e,t,n,r+1,i):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:C.liTitle,children:typeof e==`string`?e:e.title}),typeof e!=`string`&&e.desc!==void 0&&(0,g.jsx)(`span`,{className:C.liDesc,children:e.desc})]})},t))},t)}case`table`:return(0,g.jsx)(ct,{node:e},t);case`chart`:return(0,g.jsx)(lt,{chart:e},t);case`tabs`:return(0,g.jsx)(cn,{tabs:e,onAction:n,depth:r+1,answers:i},t);case`avatar`:return(0,g.jsx)(`div`,{className:C.avatar,style:{background:e.color??et(e.name)},children:e.name.slice(0,1).toUpperCase()},t);case`spacer`:return(0,g.jsx)(`div`,{className:C.spacer},t);case`plot`:return(0,g.jsx)(rn,{plot:e},t);case`callout`:return(0,g.jsx)(en,{node:e},t);case`steps`:return(0,g.jsx)(tn,{steps:e},t);case`keyvalue`:return(0,g.jsx)(nn,{node:e},t);case`diff`:return(0,g.jsx)(an,{node:e},t);case`json`:return(0,g.jsx)(on,{node:e},t);case`code`:return(0,g.jsx)(sn,{node:e},t);case`radio`:return(0,g.jsx)(pt,{node:e,onAction:n,answers:i},`${t}:r${i?.round??0}`);case`submit`:return(0,g.jsx)(ht,{node:e,onAction:n,answers:i},t);case`switch`:return(0,g.jsx)(gt,{node:e,onAction:n},t);case`slider`:return(0,g.jsx)(_t,{node:e,onAction:n,answers:i},t);case`textarea`:return(0,g.jsx)(St,{node:e,onAction:n,answers:i},t);case`accordion`:return(0,g.jsx)(ln,{node:e,onAction:n,depth:r+1,answers:i},t);case`copy`:return(0,g.jsx)(un,{node:e},t);case`mermaid`:return(0,g.jsx)(dn,{node:e},t);case`scene3d`:return(0,g.jsx)(fn,{node:e},t);case`timeline`:return(0,g.jsx)(pn,{node:e},t);case`file-tree`:return(0,g.jsx)(mn,{node:e},t);case`breadcrumb`:return(0,g.jsx)(gn,{node:e},t);case`quiz`:return(0,g.jsx)(hn,{node:e,onAction:n},t);case`diagram`:return(0,g.jsx)(Kn,{node:e},t);case`echart`:return(0,g.jsx)(Zn,{node:e},t);default:{let a=e,o=Qn?.(a.type);return o===void 0?null:(0,g.jsx)(o,{node:a,onAction:n,renderChildren:(e,t)=>e.map((e,a)=>K(e,Number(t)+a,n,r+1,i))},t)}}}function er(e){let t=(0,m.useRef)(null);return(0,m.useEffect)(()=>()=>{let e=t.current;if(e!==null){for(let t of e.values())clearTimeout(t);e.clear()}},[]),(0,m.useMemo)(()=>{if(e===void 0)return;let n=new Map;return t.current=n,(t,r)=>{let i=n.get(t);i!==void 0&&clearTimeout(i),n.set(t,setTimeout(()=>{n.delete(t),e(t,r)},300))}},[e])}function tr(e,t){return e===t||JSON.stringify(e)===JSON.stringify(t)}let nr=(0,m.memo)(function({spec:e,stateKey:t}){let n=e.gap??16,r=er(y()),[i]=(0,m.useState)(()=>t===void 0?null:te(t)),[a,o]=(0,m.useState)(i?.answers??{}),[s,c]=(0,m.useState)(i?.fields??{}),[l,u]=(0,m.useState)({}),[d,f]=(0,m.useState)(i?.locked===!0),[p,h]=(0,m.useState)(0),[_,v]=(0,m.useState)(new Set),b=(0,m.useCallback)((e,t)=>{o(n=>n[e]===t?n:{...n,[e]:t})},[]),x=(0,m.useCallback)((e,t)=>{c(n=>{if(t.trim()===``){if(!(e in n))return n;let t={...n};return delete t[e],t}return n[e]===t?n:{...n,[e]:t}})},[]),S=(0,m.useCallback)(e=>{v(t=>t.has(e)?t:new Set(t).add(e))},[]),w=(0,m.useCallback)((e,t)=>{u(n=>{let r=n[e];return r!==void 0&&r.label===t.label&&r.answer===t.answer&&r.explanation===t.explanation?n:{...n,[e]:t}})},[]),T=(0,m.useCallback)(()=>{o({}),f(!1),h(e=>e+1)},[]),E=(0,m.useMemo)(()=>({answers:a,fields:s,secretFields:_,meta:l,locked:d,round:p,setAnswer:b,setField:x,registerSecretField:S,registerMeta:w,clear:T,setLocked:f}),[a,s,_,l,d,p,b,x,S,w,T]);return(0,m.useEffect)(()=>{if(t===void 0)return;let e=setTimeout(()=>{let e=Object.fromEntries(Object.entries(s).filter(([e])=>!_.has(e)));ne(t,{answers:a,locked:d,...Object.keys(e).length>0?{fields:e}:{}})},300);return()=>clearTimeout(e)},[t,a,d,s,_]),(0,g.jsxs)(`div`,{className:C.block,"data-genui":!0,children:[e.title!==void 0&&(0,g.jsx)(`div`,{className:C.banner,children:e.title}),(0,g.jsx)(`div`,{className:C.col,style:{gap:`${n}px`},children:e.items.map((e,t)=>(0,g.jsx)(`div`,{className:C.reveal,style:{animationDelay:`${Math.min(t*90,720)}ms`},children:K(e,t,r,0,E)},t))})]})},(e,t)=>e.stateKey===t.stateKey&&tr(e.spec,t.spec));function rr(e){let t=[],n=[],r=e=>{n.length>=32&&n.shift(),n.push(e)},i=!1,a=!1,o=0;for(;o<e.length;o++){let n=e[o];if(i){a?a=!1:n===`\\`?a=!0:n===`"`&&(i=!1);continue}if(n===`"`){i=!0;continue}if(n===`{`||n===`[`){t.push(n);continue}if(n===`}`||n===`]`){if(t.pop()!==(n===`}`?`{`:`[`))break;n===`}`&&t.length<=O.maxDepth&&r({end:o+1,closingSuffix:ir(t)}),t.length===0&&r({end:o+1,closingSuffix:``});continue}}n.sort((e,t)=>t.end-e.end);let s=[];for(let e of n)(s.length===0||s[s.length-1].end!==e.end)&&s.push(e);return{candidates:s.slice(0,32),scannedChars:o}}function ir(e){let t=``;for(let n=e.length-1;n>=0;n--)t+=e[n]===`{`?`}`:`]`;return t}function ar(e){try{let t=JSON.parse(e);return se(t)?t:D(t)}catch{return null}}function or(e){let t=e.trim();if(t===``)return null;let n=ar(t);if(n!==null)return n;let{candidates:r}=rr(t);for(let e of r){let n=ar(t.slice(0,e.end)+e.closingSuffix);if(n!==null)return n}return null}let q={maxNodes:200,maxAppends:200},sr=new Map,J=new Set;function cr(){return{ops:new Map,seen:new Map,overflow:null,local:null,localBarrier:-1,replayBarrier:-1,maxSeenSeq:-1,snapshot:null}}let lr=`dsh.genui.panel`;function ur(){try{let e=localStorage.getItem(lr);if(e===null)return{order:[],sessions:{}};let t=JSON.parse(e);return!Array.isArray(t.order)||typeof t.sessions!=`object`||t.sessions===null?{order:[],sessions:{}}:{order:t.order.filter(e=>typeof e==`string`),sessions:t.sessions}}catch{return{order:[],sessions:{}}}}function dr(e,t){try{let n=ur(),r=n.order.filter(t=>t!==e);r.unshift(e);let i={...n.sessions,[e]:t};for(;r.length>50;){let e=r.pop();e!==void 0&&delete i[e]}localStorage.setItem(lr,JSON.stringify({order:r,sessions:i}))}catch{}}function fr(e){let t=sr.get(e);if(t!==void 0)return t;let n=cr();try{let t=ur().sessions[e];t!==void 0&&(n={ops:new Map,seen:new Map,overflow:null,local:t.local??null,localBarrier:t.localBarrier??-1,replayBarrier:t.maxSeenSeq??-1,maxSeenSeq:t.maxSeenSeq??-1,snapshot:t.snapshot??null})}catch{}return sr.set(e,n),n}function Y(e,t){for(let n=0;n<3;n++){let r=e[n]-t[n];if(r!==0)return r}return 0}function pr(e,t){if(t!==null&&(t.order[0]<=e.localBarrier||t.order[0]<=e.replayBarrier||e.seen.has(t.sourceId)||e.overflow!==null&&e.overflow.sourceId===t.sourceId||t.mode===`append`&&e.overflow!==null&&Y(t.order,e.overflow.order)>0))return null;let n=[...e.ops.values()].filter(t=>t.order[0]>e.localBarrier&&t.order[0]>e.replayBarrier);t!==null&&n.push(t),n.sort((e,t)=>Y(e.order,t.order));let r=0;for(let e=0;e<n.length;e++){let t=n[e];t.mode===`replace`&&Qe(t.spec,q.maxNodes+1)<=q.maxNodes&&(r=e)}let i=e.local,a=null,o=0,s=[],c=e.maxSeenSeq;for(let e=r;e<n.length;e++){let t=n[e];if(t.order[0]>c&&(c=t.order[0]),t.mode===`replace`){if(Qe(t.spec,q.maxNodes+1)>q.maxNodes){(a===null||Y(t.order,a.order)<0)&&(a=t);continue}a=null,i=t.spec,s.length=0,o=0,s.push(t);continue}let r=Cr(i,t.spec);if(o>=q.maxAppends||Qe(r,q.maxNodes+1)>q.maxNodes){(a===null||Y(t.order,a.order)<0)&&(a=t);continue}i=r,o+=1,s.push(t)}return t!==null&&s.length===e.ops.size&&s.every(t=>e.ops.get(t.sourceId)?.mode===t.mode)&&(a===null&&e.overflow===null||a!==null&&e.overflow!==null&&a.sourceId===e.overflow.sourceId)?null:{snapshot:i,kept:s,overflow:a,maxSeenSeq:c}}function mr(e,t,n){e.snapshot=t.snapshot,e.overflow=t.overflow,e.maxSeenSeq=t.maxSeenSeq,e.ops=new Map(t.kept.map(e=>[e.sourceId,e]));for(let n of t.kept)e.seen.set(n.sourceId,n.order);t.overflow!==null&&e.seen.set(t.overflow.sourceId,t.overflow.order),dr(n,{snapshot:e.snapshot,local:e.local,localBarrier:e.localBarrier,maxSeenSeq:e.maxSeenSeq})}function hr(e,t){let n=fr(e),r=pr(n,t);if(r===null)return n.seen.has(t.sourceId)||n.overflow?.sourceId===t.sourceId?`idempotent`:(n.overflow!==null&&t.mode===`append`&&Y(t.order,n.overflow.order)>0||gr(e,t,n),`blocked`);let i=r.overflow!==null&&r.overflow.sourceId===t.sourceId?`overflow`:`accepted`,a=n.snapshot!==r.snapshot;if(mr(n,r,e),a)for(let e of J)e();return i}let X=new Set;function gr(e,t,n){let r=`${e}\u0000${t.sourceId}`;X.has(r)||(X.add(r),console.warn(`[genui] 面板操作被重放屏障拒绝(source ${t.sourceId},order[0]=${t.order[0]} ≤ replayBarrier ${n.replayBarrier} / localBarrier ${n.localBarrier})。历史消息重放被拒是预期行为;若是刚发送的新消息,说明消息序号推导异常,请报告。`))}function _r(e,t){let n=fr(e),r=n.maxSeenSeq;if(n.local!==t||n.localBarrier!==r){n.local=t,n.localBarrier=r,mr(n,pr(n,null),e);for(let e of J)e()}}let Z=new Set;function vr(e,t){let n=`${e}\u0000${t}`;Z.has(n)||(Z.add(n),console.warn(`[genui] 面板已到节点/操作上限(${q.maxNodes} 节点、${q.maxAppends} 条追加),本次 append 被拒绝;请让模型发送 replace 更新面板。`))}function yr(e){let t=sr.delete(e),n=Q.delete(e),r=`${e}\u0000`;for(let e of Z)e.startsWith(r)&&Z.delete(e);for(let e of X)e.startsWith(r)&&X.delete(e);if(!(!t&&!n)){for(let e of J)e();for(let e of wr)e()}}function br(e){return fr(e).snapshot}function xr(e){return J.add(e),()=>{J.delete(e)}}function Sr(e){if(e.items.length!==1)return null;let t=e.items[0];return t?.type!==`tabs`||!Array.isArray(t.tabs)?null:t.tabs}function Cr(e,t){if(e===null||e.items.length===0)return t;let n=e.title??t.title,r={...e,...n===void 0?{}:{title:n}},i=Sr(e),a=Sr(t);if(i!==null&&a!==null){let e=new Map(i.map(e=>[e.label,{label:e.label,items:[...e.items]}]));for(let t of a){let n=e.get(t.label);n===void 0?e.set(t.label,{label:t.label,items:[...t.items]}):n.items.push(...t.items)}return{...r,items:[{type:`tabs`,tabs:[...e.values()]}]}}return{...r,items:[...e.items,...t.items]}}let Q=new Map,wr=new Set;function Tr(e){Q.set(e,(Q.get(e)??0)+1);for(let e of wr)e()}function Er(e){return Q.get(e)??0}function Dr(e){return wr.add(e),()=>{wr.delete(e)}}function Or(e){try{return JSON.parse(e),!0}catch{return!1}}function kr(e){try{return JSON.parse(e),null}catch(e){let t=e instanceof Error?e.message:String(e),n=t.match(/position (\d+)/i);return`${n===null?``:`(字符 ${n[1]} 附近)`}${t.slice(0,140)}`}}function Ar(e){try{return JSON.parse(e),null}catch{}let t=``,n=!1,r=!1,i=0;for(let a=0;a<e.length;a++){let o=e[a];if(r){t+=o,r=!1;continue}if(n&&o===`\\`){t+=o,r=!0;continue}if(o===`"`){if(!n){n=!0,t+=o;continue}let r=a+1;for(;r<e.length&&(e[r]===` `||e[r]===` `||e[r]===` `||e[r]===`\r`);)r++;let s=r<e.length?e[r]:``;s===`,`||s===`]`||s===`}`||s===`:`||s===``?(n=!1,t+=o):(t+=`\\"`,i++);continue}if(o===`,`){let t=a+1;for(;t<e.length&&(e[t]===` `||e[t]===` `||e[t]===` -`||e[t]===`\r`);)t++;let n=t<e.length?e[t]:``;if(n===`}`||n===`]`||n===``){i++;continue}}t+=o}if(i===0)return null;try{return JSON.parse(t),{text:t,repairs:i}}catch{return null}}function Wn(e){try{return JSON.parse(e),null}catch{}let t=``,n=[],r=!1,i=!1,a=0;for(let o=0;o<e.length;o++){let s=e[o];if(i){t+=s,i=!1;continue}if(r){if(s===`\\`){t+=s,i=!0;continue}if(s!==`"`){t+=s;continue}let n=o+1;for(;n<e.length&&(e[n]===` `||e[n]===` `||e[n]===` +`||e[t]===`\r`);)t++;let n=t<e.length?e[t]:``;if(n===`}`||n===`]`||n===``){i++;continue}}t+=o}if(i===0)return null;try{return JSON.parse(t),{text:t,repairs:i}}catch{return null}}function jr(e){try{return JSON.parse(e),null}catch{}let t=``,n=[],r=!1,i=!1,a=0;for(let o=0;o<e.length;o++){let s=e[o];if(i){t+=s,i=!1;continue}if(r){if(s===`\\`){t+=s,i=!0;continue}if(s!==`"`){t+=s;continue}let n=o+1;for(;n<e.length&&(e[n]===` `||e[n]===` `||e[n]===` `||e[n]===`\r`);)n++;let c=n<e.length?e[n]:``;c===`,`||c===`]`||c===`}`||c===`:`||c===``?(r=!1,t+=s):(t+=`\\"`,a++);continue}if(s===`"`){r=!0,t+=s;continue}if(s===`{`){n.push(`}`),t+=s;continue}if(s===`[`){n.push(`]`),t+=s;continue}if(s===`}`||s===`]`){n[n.length-1]===s?(n.pop(),t+=s):a++;continue}if(s===`,`){let t=o+1;for(;t<e.length&&(e[t]===` `||e[t]===` `||e[t]===` -`||e[t]===`\r`);)t++;let n=t<e.length?e[t]:``;if(n===`}`||n===`]`||n===``){a++;continue}}t+=s}for(r&&(t+=`"`,a++);n.length>0;)t+=n.pop(),a++;if(a===0)return null;try{return JSON.parse(t),{text:t,repairs:a}}catch{return null}}let Gn={margin:`0 0 6px`,padding:`6px 10px`,borderRadius:6,background:`rgba(239, 68, 68, 0.14)`,border:`1px solid rgba(239, 68, 68, 0.4)`,color:`#f87171`,fontSize:12,lineHeight:1.55,whiteSpace:`pre-wrap`};function Kn({raw:e,fenceKey:t}){let n=(0,m.useRef)(null),[r,i]=(0,m.useState)(!1);(0,m.useLayoutEffect)(()=>{let e=n.current;e!==null&&e.closest(`[data-streaming]`)===null&&i(!0)});let a=r&&e.trim()!==``?Hn(e):null;return(0,h.jsxs)(`div`,{ref:n,children:[a!==null&&(0,h.jsxs)(`div`,{style:Gn,role:`alert`,children:[`⚠️ dsh-ui fence JSON 解析失败`,a,` —— 围栏保持为代码块;请让模型检查并修复 JSON 后重发。`]}),(0,h.jsx)(p.CodeBlock,{code:`${e}\n`,lang:`dsh-ui`},t)]})}function qn({sessionId:e,sourceId:t,order:n,spec:r}){return(0,m.useEffect)(()=>{kn(e,{sourceId:t,order:n,mode:r.append===!0?`append`:`replace`,spec:r})===`overflow`&&Mn(e,t)},[e,t,n,r]),null}function Jn(e,t){let n=bn(e),r=n===null?null:R(n);if(r===null){let n=Un(e);if(n!==null){let e=bn(n.text);r=e===null?null:R(e)}if(r===null&&t?.source!==void 0){let t=Wn(e);if(t!==null){let e=bn(t.text);r=e===null?null:R(e)}}}return r}function Yn(e,t,n){let r=t?.sessionId;return(0,h.jsx)(b,{label:`该界面`,children:(0,h.jsx)(gn,{spec:n,stateKey:r===void 0?void 0:ae(r,t?.source?.id??String(e),JSON.stringify(n))})},t?.source?.id??e)}function Xn(e,t,n){let r=Jn(e,n);return r===null?null:r.panel===!0?n!==void 0&&n.sessionId!==void 0&&n.source!==void 0?r.append===!0&&!Vn(e)?(0,h.jsx)(m.Fragment,{},t):(0,h.jsx)(qn,{sessionId:n.sessionId,sourceId:n.source.id,order:n.source.order,spec:r},t):(0,h.jsx)(m.Fragment,{},t):Yn(t,n,r)}function Zn(e,t,n){let r=Jn(e,n);return r===null?(0,h.jsx)(Kn,{fenceKey:t,raw:e},t):r.panel===!0?n!==void 0&&n.sessionId!==void 0&&n.source!==void 0?r.append===!0&&!Vn(e)?null:(0,h.jsx)(qn,{sessionId:n.sessionId,sourceId:n.source.id,order:n.source.order,spec:r},t):null:Yn(t,n,r)}let Z=`.md-code-block, .code-block, .code-block-small`,Q=`data-genui-rendered`,Qn=`[data-streaming]`,$n=`genui-dom-fence`;function er(e){let t=e.querySelectorAll(`pre`);if(t.length>1)return!1;let n=t[0]??null;for(let t of e.querySelectorAll(`p, ul, ol, dl, table, h1, h2, h3, h4, h5, h6, blockquote, hr, img, figure`))if(!(n!==null&&n.contains(t)))return!1;return!0}function tr(e){return(0,m.isValidElement)(e)&&e.type===m.Fragment}function nr(e){return e.nodeType===Node.TEXT_NODE}function $(e){let t=e.querySelector(`pre`);for(let n of e.querySelectorAll(`*`)){if(n.childElementCount!==0||n.textContent!==`dsh-ui`||t!==null&&t.contains(n))continue;let r=n.closest(Z);if(r===null||r===e)return`dsh-ui`}return null}function rr(e){let t=e.querySelector(`pre`);for(let n of e.querySelectorAll(`*`))if(n.childElementCount===0&&!(t!==null&&t.contains(n)))return n.textContent??``;return``}function ir(e){let t=e.querySelector(`pre`);if(t===null)return``;let n=``;for(let e of t.childNodes)nr(e),n+=e.textContent??``;return n}function ar(e){return e.closest(Qn)===null}function or(e,t=document){let n=e.parentElement;for(let e=0;n!==null&&n!==t&&e<4;e+=1,n=n.parentElement)if($(n)===`dsh-ui`)return er(n)?n:null;return null}function sr(e,t=document){let n=e.parentElement;for(let e=0;n!==null&&n!==t&&e<4;e+=1,n=n.parentElement)if($(n)===`dsh-ui`&&!er(n))return n;return null}function cr(e=document){let t=new Set,n=[];for(let r of e.querySelectorAll(Z))(r.parentElement===null||r.parentElement.closest(Z)===null)&&(t.has(r)||er(r)&&(n.push(r),t.add(r)));for(let r of e.querySelectorAll(`pre`)){if(r.closest(Z)!==null)continue;let i=or(r,e);if(i===null){sr(r,e)!==null&&!ur&&(ur=!0,console.warn(`[dsh-genui] 跳过带 dsh-ui 标签但疑似消息容器的节点(含段落或多个代码体)——防止 DOM 通道隐藏整条消息(issue #19)`));continue}t.has(i)||(lr||(lr=!0,console.warn(`[dsh-genui] 围栏表面类名未被已知选择器命中(宿主 DOM 漂移),已按 label+pre 结构识别 dsh-ui 围栏`)),n.push(i),t.add(i))}return n}let lr=!1,ur=!1,dr=ee.createRoot,fr=`[data-chat-flow-key], [data-chat-flow-kind]`;function pr(e){return e.closest(`[data-chat-anchor-key]`)??e.closest(fr)??e}function mr(e,t){let n=e===t?document:e,r=0;for(let e of cr(n))if(e.closest(Qn)===null&&$(e)!==null&&(r+=1,e===t))return r;return r+1}function hr(e){let t=e.getAttribute(`data-chat-anchor-key`)??``,n=/assistant-step(\d+):(\d+)$/.exec(t);if(n!==null){let e=Number(n[1]),t=Number(n[2]);if(Number.isFinite(e)&&Number.isFinite(t))return e*1e3+t}let r=document.querySelectorAll(`[data-chat-anchor-key], ${fr}`);for(let t=0;t<r.length;t+=1)if(r[t]===e)return t;return 0}function gr(e,t){if(typeof document>`u`)return()=>{};lr=!1,ur=!1;let n=new Map,r=()=>{try{return e.sessions.list.getSnapshot().current}catch{return}};function i(e,t,n){n&&e.getAttribute(`data-chat-anchor-key`)===null&&s(t,`no [data-chat-anchor-key] ancestor for a dsh-ui fence (host render path without row anchor — e.g. Safari); using fallback identity dom:unknown:N`);let i=mr(e,t),a=`dom:${e.getAttribute(`data-chat-anchor-key`)??`unknown`}:${i}`,o=r();return{key:a,context:{...o===void 0?{}:{sessionId:o},...n?{source:{id:a,order:[hr(e),0,i]}}:{}}}}function a(e){let t=n.get(e);t!==void 0&&(n.delete(e),t.root.unmount(),t.container.remove(),e.style.display=``,e.removeAttribute(Q))}let o=new WeakSet;function s(e,t){o.has(e)||(o.add(e),console.warn(`[dsh-genui] ${t}`))}function c(e){if(e.hasAttribute(Q))return;let a=pr(e),o=ar(e);if(o&&$(e)===null)return;let c=ir(e);if(c.trim()===``){o&&s(e,`settled dsh-ui fence has an empty body; keeping the code block`);return}let{key:l,context:u}=i(a,e,o),d=Xn(c,l,u);if(d===null){o&&s(e,`settled dsh-ui fence body does not parse; keeping the code block`);return}let f=document.createElement(`div`);f.className=$n,e.after(f);let p;try{p=dr(f)}catch(t){f.remove(),s(e,`failed to create a React root for a dsh-ui fence (${t instanceof Error?t.message:String(t)}); keeping the stock code block visible`);return}try{p.render((0,h.jsx)(_.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:d}))}catch(t){try{p.unmount()}catch{}f.remove(),s(e,`failed to mount a dsh-ui fence (${t instanceof Error?t.message:String(t)}); keeping the stock code block visible`);return}e.style.display=`none`,e.setAttribute(Q,``),n.set(e,{root:p,container:f,block:e,lastRaw:c,lastSettled:o,lastNode:d})}function l(){for(let e of Array.from(n.values())){let t=e.block;if(!t.isConnected){e.container.isConnected&&a(t);continue}if((e.container.parentElement!==t.parentElement||e.container.previousElementSibling!==t)&&t.after(e.container),!e.container.isConnected){t.style.display=``,t.removeAttribute(Q),n.delete(t);try{e.root.unmount()}catch{}e.container.remove(),s(t,`dsh-ui replacement container could not be re-attached after a host re-render; restoring the stock code block`);continue}t.style.display!==`none`&&(t.style.display=`none`),t.hasAttribute(Q)||t.setAttribute(Q,``)}}function u(){for(let[e,o]of n){if(!e.isConnected){a(e);continue}let c=ir(e),l=ar(e);if(l&&!o.lastSettled){let t=rr(e);if(t!==``&&t!==`dsh-ui`){a(e);continue}}let u=!tr(o.lastNode)&&o.container.childElementCount===0;if(o.lastRaw!==c||o.lastSettled!==l||u){let{key:d,context:f}=i(pr(e),e,l),p=Xn(c,d,f);if(p===null){a(e);continue}if(u){try{o.root.unmount()}catch{}let i=document.createElement(`div`);i.className=$n,o.container.remove(),e.after(i);try{let e=dr(i);e.render((0,h.jsx)(_.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:p})),o.root=e,o.container=i}catch(t){i.remove(),e.style.display=``,e.removeAttribute(Q),n.delete(e),s(e,`failed to rebuild a wiped dsh-ui mount (${t instanceof Error?t.message:String(t)}); restoring the stock code block`);continue}}else try{o.root.render((0,h.jsx)(_.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:p}))}catch(t){a(e),s(e,`failed to re-render a dsh-ui fence (${t instanceof Error?t.message:String(t)}); restoring the stock code block`);continue}o.lastRaw=c,o.lastSettled=l,o.lastNode=p}}l();for(let e of cr())c(e)}let d=!1,f=()=>{d||(d=!0,requestAnimationFrame(()=>{d=!1,u()}))},p=new MutationObserver(()=>{l(),f()});p.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`data-streaming`],characterData:!0});let m=window.setInterval(u,1e3);return u(),()=>{p.disconnect(),window.clearInterval(m);for(let e of Array.from(n.keys()))a(e)}}let _r={title:`GenUI 面板`,items:[{type:`text`,size:`h3`,content:`GenUI 生成式界面`},{type:`text`,size:`muted`,content:`面板会原地更新:对话里说「更新面板」,或再次执行 /panel 刷新。`},{type:`grid`,cols:4,items:[{type:`stat`,label:`组件`,value:`38`},{type:`stat`,label:`单个`,value:`12`},{type:`stat`,label:`组合`,value:`8`},{type:`stat`,label:`高级`,value:`18`}]},{type:`list`,items:[{title:`单个 ×12`,desc:`text button input select checkbox link badge stat progress divider avatar spacer`},{title:`组合 ×8`,desc:`row col grid card list table chart tabs`},{title:`数据 ×7`,desc:`plot callout steps keyvalue diff json code`},{title:`交互 ×5`,desc:`radio switch textarea accordion copy`},{title:`高级 ×5`,desc:`mermaid scene3d timeline file-tree breadcrumb`},{title:`教学 ×1`,desc:`quiz`}]},{type:`callout`,tone:`info`,title:`更新方式`,content:`对话说「更新面板」→ 模型输出 panel:true 围栏;/panel clear 清空面板。`}]};function vr(e,t){let n=t.trim().toLowerCase();if(n===`clear`||n===`off`||n===`close`){jn(e,null);return}jn(e,_r),Rn(e)}function yr(e,t){return{token:`/panel`,hint:`开启 GenUI 面板;/panel <指令> 让模型定制;/panel clear 清空`,submit:async(n,r)=>{let i=n.trim();return i===``?vr(e,``):/^(clear|off|close)$/i.test(i)?vr(e,i):(vr(e,``),t(e,i)),{kind:`success`}}}}function br(e){return{trigger:`/`,name:`genui`,order:60,candidates:async(e,t)=>[{name:`panel`,description:`开启 GenUI 面板(/panel clear 清空;/panel <指令> 定制内容)`,hint:`/panel`}],onPick(t){return{claim:yr(t.session.sessionId,e)}},matchEnter:async(t,n,r)=>{if(/^\/panel(?:\s|$)/.test(n.trim()))return{claim:yr(t.sessionId,e)}}}}function xr({sessionId:e,sendGenuiAction:t}){let n=(0,m.useSyncExternalStore)(Fn,()=>Pn(e)),r=(0,m.useSyncExternalStore)(Bn,()=>zn(e)),[i,a]=(0,m.useState)(!0),[o,s]=(0,m.useState)(null),[c,l]=(0,m.useState)(!1),u=(0,m.useRef)(null),d=(0,m.useRef)(null);(0,m.useEffect)(()=>{r>0&&a(!1)},[r]),(0,m.useEffect)(()=>()=>{Nn(e)},[e]),(0,m.useEffect)(()=>{if(c)return()=>{u.current=null}},[c]);let f=(0,m.useCallback)(e=>{e.preventDefault();let t=e.currentTarget,n=o??360;u.current={y:e.clientY,height:n},l(!0);try{t.setPointerCapture(e.pointerId)}catch{}let r=e=>{let t=u.current;if(t===null)return;let n=Math.min(600,Math.max(120,t.height+(t.y-e.clientY)));s(n)},i=()=>{u.current=null,l(!1),t.removeEventListener(`pointermove`,r),t.removeEventListener(`pointerup`,i),t.removeEventListener(`pointercancel`,i)};t.addEventListener(`pointermove`,r),t.addEventListener(`pointerup`,i),t.addEventListener(`pointercancel`,i)},[o]);return n===null||n.items.length===0?null:(0,h.jsxs)(`div`,{className:S.panel,"data-genui-panel":!0,children:[!i&&(0,h.jsx)(`div`,{role:`separator`,"aria-orientation":`horizontal`,"aria-label":`调整面板高度`,className:`${S.panelResizeHandle}${c?` ${S.panelResizeHandleActive}`:``}`,onPointerDown:f}),(0,h.jsxs)(`div`,{className:S.panelHeader,children:[(0,h.jsxs)(`button`,{type:`button`,className:S.panelToggle,"aria-expanded":!i,onClick:()=>a(e=>!e),children:[(0,h.jsx)(`span`,{className:S.panelBadge,children:`面板`}),(0,h.jsx)(`span`,{className:S.panelTitle,children:n.title??`GenUI 面板`}),(0,h.jsx)(`span`,{className:S.panelChevron,"aria-hidden":!0,children:i?`▸`:`▾`})]}),(0,h.jsx)(`button`,{type:`button`,className:S.panelClose,"aria-label":`关闭面板`,title:`关闭面板`,onClick:()=>jn(e,null),children:(0,h.jsx)(`span`,{"aria-hidden":!0,children:`✕`})})]}),!i&&(0,h.jsx)(`div`,{ref:d,className:S.panelBody,"data-genui-panel-body":!0,style:o===null?void 0:{height:o},children:(0,h.jsx)(_.Provider,{value:t,children:(0,h.jsx)(b,{label:`面板`,children:(0,h.jsx)(gn,{spec:n,stateKey:oe(e,JSON.stringify(n))})})})})]})}function Sr({toolName:e,block:t,sessionId:n}){let r=`meta`in t?t.meta:void 0,i=(0,m.useMemo)(()=>r===void 0?null:R(r),[r]);return(0,m.useEffect)(()=>{i!==null&&i.items.length>0&&kn(n,{sourceId:JSON.stringify([`render_ui`,t.callId]),order:[`seq`in t&&typeof t.seq==`number`?t.seq:0,-1,0],mode:`replace`,spec:i})},[n,i,t]),i===null||i.items.length===0?(0,h.jsxs)(`div`,{className:S.toolFallback,"data-genui-tool":!0,children:[(0,h.jsx)(`span`,{className:S.toolFallbackTitle,children:e}),(0,h.jsx)(`span`,{className:S.toolFallbackMeta,children:t.callId})]}):(0,h.jsx)(`div`,{className:S.tool,"data-genui-tool":!0,children:(0,h.jsx)(b,{label:`工具卡片`,children:(0,h.jsx)(gn,{spec:i,stateKey:se(n,t.callId)})})})}V();function Cr(){if(!(typeof document>`u`))for(let e of[`mermaid.js`,`three.js`]){if(document.head.querySelector(`link[rel="prefetch"][href="${Et(e)}"]`)!==null)continue;let t=document.createElement(`link`);t.rel=`prefetch`,t.as=`script`,t.href=Et(e),document.head.appendChild(t)}}function wr(e,t){let n=e.sessions.scope(t)?.get(`conversation`);return{sessionId:t,sendGenuiAction:(e,r)=>{if(n===void 0)return;let i=Object.keys(r).length===0?``:` 组件数据: ${JSON.stringify(r)}`;n.send(`[genui-action] ${e}。用户刚刚在面板中触发了动作 "${e}",请根据组件数据执行相应操作,只输出一个 panel:true 的 dsh-ui 围栏来更新面板,回复文本至多一行 10 字以内的确认(如"已刷新"),不要解释、不要普通围栏。${i}`).catch(n=>{console.warn(`[genui] 面板动作 "${e}" 发送失败(session ${t}):`,n instanceof Error?n.message:String(n))})}}}function Tr(e,t,n){let r=e.sessions.scope(t)?.get(`conversation`);r!==void 0&&r.send(`用户执行了 /panel 并请求:${n}。请只输出一个 panel:true 的 dsh-ui 围栏来更新会话面板,内容按请求定制;回复文本至多一行 10 字以内的确认(如"已更新"),不要解释、不要普通围栏。`).catch(e=>{console.warn(`[genui] /panel 指令发送失败(session ${t}):`,e instanceof Error?e.message:String(e))})}function Er(e,t,n,r){let i=e.sessions.scope(t)?.get(`conversation`);if(i===void 0)return;let a=Object.keys(r).length===0?``:` 组件数据: ${JSON.stringify(r)}`;i.send(`[genui-action] ${n}。用户刚刚在界面中触发了动作 "${n}",请根据组件数据执行相应操作,并用 dsh-ui 输出更新后的界面。${a}`).catch(()=>{})}function Dr(e){let t=p.registerFenceRenderer;console.info(`[genui] client active; fence-channel=${typeof t==`function`?`registry`:`dom`}`);let n=typeof t==`function`?[t(`dsh-ui`,Zn)]:[gr(e,(t,n,r)=>Er(e,t,n,r))];return Cr(),n.push(e.slots.inject(`tool.call.toolview`,()=>e.slots.register({name:`tool.call.toolview`,key:`render_ui`},Sr))),n.push(e.slots.inject(`conversation.input.dock`,()=>e.slots.register({name:`conversation.input.dock`,id:`genui-panel`,order:50,inject:t=>wr(e,t)},xr))),e.inject([`inputTriggers`],t=>{let n=t.get(`inputTriggers`);n!==void 0&&t.effect(()=>n.registerSource(br((t,n)=>Tr(e,t,n))),`genui: /panel`)}),()=>{for(let e of n)e()}}return n.apply=Dr,n.inject=[`slots`,`sessions`],n.prefetchGenuiAssets=Cr,n.renderGenuiFence=Zn,t.exports}}); \ No newline at end of file +`||e[t]===`\r`);)t++;let n=t<e.length?e[t]:``;if(n===`}`||n===`]`||n===``){a++;continue}}t+=s}for(r&&(t+=`"`,a++);n.length>0;)t+=n.pop(),a++;if(a===0)return null;try{return JSON.parse(t),{text:t,repairs:a}}catch{return null}}let Mr={margin:`0 0 6px`,padding:`6px 10px`,borderRadius:6,background:`rgba(239, 68, 68, 0.14)`,border:`1px solid rgba(239, 68, 68, 0.4)`,color:`#f87171`,fontSize:12,lineHeight:1.55,whiteSpace:`pre-wrap`};function Nr({raw:e,fenceKey:t}){let n=(0,m.useRef)(null),[r,i]=(0,m.useState)(!1);(0,m.useLayoutEffect)(()=>{let e=n.current;e!==null&&e.closest(`[data-streaming]`)===null&&i(!0)});let a=r&&e.trim()!==``?kr(e):null;return(0,g.jsxs)(`div`,{ref:n,children:[a!==null&&(0,g.jsxs)(`div`,{style:Mr,role:`alert`,children:[`⚠️ dsh-ui fence JSON 解析失败`,a,` —— 围栏保持为代码块;请让模型检查并修复 JSON 后重发。`]}),(0,g.jsx)(p.CodeBlock,{code:`${e}\n`,lang:`dsh-ui`},t)]})}function Pr({sessionId:e,sourceId:t,order:n,spec:r}){return(0,m.useEffect)(()=>{hr(e,{sourceId:t,order:n,mode:r.append===!0?`append`:`replace`,spec:r})===`overflow`&&vr(e,t)},[e,t,n,r]),null}function Fr(e,t){let n=or(e),r=n===null?null:z(n);if(r===null){let n=Ar(e);if(n!==null){let e=or(n.text);r=e===null?null:z(e)}if(r===null&&t?.source!==void 0){let t=jr(e);if(t!==null){let e=or(t.text);r=e===null?null:z(e)}}}return r}function Ir(e,t,n){let r=t?.sessionId;return(0,g.jsx)(x,{label:`该界面`,children:(0,g.jsx)(nr,{spec:n,stateKey:r===void 0?void 0:ie(r,t?.source?.id??String(e),JSON.stringify(n))})},t?.source?.id??e)}function Lr(e,t,n){let r=Fr(e,n);return r===null?null:r.panel===!0?n!==void 0&&n.sessionId!==void 0&&n.source!==void 0?r.append===!0&&!Or(e)?(0,g.jsx)(m.Fragment,{},t):(0,g.jsx)(Pr,{sessionId:n.sessionId,sourceId:n.source.id,order:n.source.order,spec:r},t):(0,g.jsx)(m.Fragment,{},t):Ir(t,n,r)}function Rr(e,t,n){let r=Fr(e,n);return r===null?(0,g.jsx)(Nr,{fenceKey:t,raw:e},t):r.panel===!0?n!==void 0&&n.sessionId!==void 0&&n.source!==void 0?r.append===!0&&!Or(e)?null:(0,g.jsx)(Pr,{sessionId:n.sessionId,sourceId:n.source.id,order:n.source.order,spec:r},t):null:Ir(t,n,r)}let zr=`.md-code-block, .code-block, .code-block-small`,$=`data-genui-rendered`,Br=`[data-streaming]`,Vr=`genui-dom-fence`;function Hr(e){let t=e.querySelectorAll(`pre`);if(t.length>1)return!1;let n=t[0]??null;for(let t of e.querySelectorAll(`p, ul, ol, dl, table, h1, h2, h3, h4, h5, h6, blockquote, hr, img, figure`))if(!(n!==null&&n.contains(t)))return!1;return!0}function Ur(e){return(0,m.isValidElement)(e)&&e.type===m.Fragment}function Wr(e){return e.nodeType===Node.TEXT_NODE}function Gr(e){let t=e.querySelector(`pre`);for(let n of e.querySelectorAll(`*`)){if(n.childElementCount!==0||n.textContent!==`dsh-ui`||t!==null&&t.contains(n))continue;let r=n.closest(zr);if(r===null||r===e)return`dsh-ui`}return null}function Kr(e){let t=e.querySelector(`pre`);for(let n of e.querySelectorAll(`*`))if(n.childElementCount===0&&!(t!==null&&t.contains(n)))return n.textContent??``;return``}function qr(e){let t=e.querySelector(`pre`);if(t===null)return``;let n=``;for(let e of t.childNodes)Wr(e),n+=e.textContent??``;return n}function Jr(e){return e.closest(Br)===null}function Yr(e,t=document){let n=e.parentElement;for(let e=0;n!==null&&n!==t&&e<4;e+=1,n=n.parentElement)if(Gr(n)===`dsh-ui`)return Hr(n)?n:null;return null}function Xr(e,t=document){let n=e.parentElement;for(let e=0;n!==null&&n!==t&&e<4;e+=1,n=n.parentElement)if(Gr(n)===`dsh-ui`&&!Hr(n))return n;return null}function Zr(e=document){let t=new Set,n=[];for(let r of e.querySelectorAll(zr))(r.parentElement===null||r.parentElement.closest(zr)===null)&&(t.has(r)||Hr(r)&&(n.push(r),t.add(r)));for(let r of e.querySelectorAll(`pre`)){if(r.closest(zr)!==null)continue;let i=Yr(r,e);if(i===null){Xr(r,e)!==null&&!$r&&($r=!0,console.warn(`[dsh-genui] 跳过带 dsh-ui 标签但疑似消息容器的节点(含段落或多个代码体)——防止 DOM 通道隐藏整条消息(issue #19)`));continue}t.has(i)||(Qr||(Qr=!0,console.warn(`[dsh-genui] 围栏表面类名未被已知选择器命中(宿主 DOM 漂移),已按 label+pre 结构识别 dsh-ui 围栏`)),n.push(i),t.add(i))}return n}let Qr=!1,$r=!1,ei=h.createRoot,ti=`[data-chat-flow-key], [data-chat-flow-kind]`;function ni(e){return e.closest(`[data-chat-anchor-key]`)??e.closest(ti)??e}function ri(e,t){let n=e===t?document:e,r=0;for(let e of Zr(n))if(e.closest(Br)===null&&Gr(e)!==null&&(r+=1,e===t))return r;return r+1}function ii(e){let t=e.getAttribute(`data-chat-anchor-key`)??``,n=/assistant-step(\d+):(\d+)$/.exec(t);if(n!==null){let e=Number(n[1]),t=Number(n[2]);if(Number.isFinite(e)&&Number.isFinite(t))return e*1e3+t}let r=document.querySelectorAll(`[data-chat-anchor-key], ${ti}`);for(let t=0;t<r.length;t+=1)if(r[t]===e)return t;return 0}function ai(e,t){if(typeof document>`u`)return()=>{};Qr=!1,$r=!1;let n=new Map,r=()=>{try{return e.sessions.list.getSnapshot().current}catch{return}};function i(e,t,n){n&&e.getAttribute(`data-chat-anchor-key`)===null&&s(t,`no [data-chat-anchor-key] ancestor for a dsh-ui fence (host render path without row anchor — e.g. Safari); using fallback identity dom:unknown:N`);let i=ri(e,t),a=`dom:${e.getAttribute(`data-chat-anchor-key`)??`unknown`}:${i}`,o=r();return{key:a,context:{...o===void 0?{}:{sessionId:o},...n?{source:{id:a,order:[ii(e),0,i]}}:{}}}}function a(e){let t=n.get(e);t!==void 0&&(n.delete(e),t.root.unmount(),t.container.remove(),e.style.display=``,e.removeAttribute($))}let o=new WeakSet;function s(e,t){o.has(e)||(o.add(e),console.warn(`[dsh-genui] ${t}`))}function c(e){if(e.hasAttribute($))return;let a=ni(e),o=Jr(e);if(o&&Gr(e)===null)return;let c=qr(e);if(c.trim()===``){o&&s(e,`settled dsh-ui fence has an empty body; keeping the code block`);return}let{key:l,context:u}=i(a,e,o),d=Lr(c,l,u);if(d===null){o&&s(e,`settled dsh-ui fence body does not parse; keeping the code block`);return}let f=document.createElement(`div`);f.className=Vr,e.after(f);let p;try{p=ei(f)}catch(t){f.remove(),s(e,`failed to create a React root for a dsh-ui fence (${t instanceof Error?t.message:String(t)}); keeping the stock code block visible`);return}try{p.render((0,g.jsx)(v.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:d}))}catch(t){try{p.unmount()}catch{}f.remove(),s(e,`failed to mount a dsh-ui fence (${t instanceof Error?t.message:String(t)}); keeping the stock code block visible`);return}e.style.display=`none`,e.setAttribute($,``),n.set(e,{root:p,container:f,block:e,lastRaw:c,lastSettled:o,lastNode:d})}function l(){for(let e of Array.from(n.values())){let t=e.block;if(!t.isConnected){e.container.isConnected&&a(t);continue}if((e.container.parentElement!==t.parentElement||e.container.previousElementSibling!==t)&&t.after(e.container),!e.container.isConnected){t.style.display=``,t.removeAttribute($),n.delete(t);try{e.root.unmount()}catch{}e.container.remove(),s(t,`dsh-ui replacement container could not be re-attached after a host re-render; restoring the stock code block`);continue}t.style.display!==`none`&&(t.style.display=`none`),t.hasAttribute($)||t.setAttribute($,``)}}function u(){for(let[e,o]of n){if(!e.isConnected){a(e);continue}let c=qr(e),l=Jr(e);if(l&&!o.lastSettled){let t=Kr(e);if(t!==``&&t!==`dsh-ui`){a(e);continue}}let u=!Ur(o.lastNode)&&o.container.childElementCount===0;if(o.lastRaw!==c||o.lastSettled!==l||u){let{key:d,context:f}=i(ni(e),e,l),p=Lr(c,d,f);if(p===null){a(e);continue}if(u){try{o.root.unmount()}catch{}let i=document.createElement(`div`);i.className=Vr,o.container.remove(),e.after(i);try{let e=ei(i);e.render((0,g.jsx)(v.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:p})),o.root=e,o.container=i}catch(t){i.remove(),e.style.display=``,e.removeAttribute($),n.delete(e),s(e,`failed to rebuild a wiped dsh-ui mount (${t instanceof Error?t.message:String(t)}); restoring the stock code block`);continue}}else try{o.root.render((0,g.jsx)(v.Provider,{value:(e,n)=>{let i=r();i!==void 0&&t(i,e,n)},children:p}))}catch(t){a(e),s(e,`failed to re-render a dsh-ui fence (${t instanceof Error?t.message:String(t)}); restoring the stock code block`);continue}o.lastRaw=c,o.lastSettled=l,o.lastNode=p}}l();for(let e of Zr())c(e)}let d=!1,f=()=>{d||(d=!0,requestAnimationFrame(()=>{d=!1,u()}))},p=new MutationObserver(()=>{l(),f()});p.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`data-streaming`],characterData:!0});let m=window.setInterval(u,1e3);return u(),()=>{p.disconnect(),window.clearInterval(m);for(let e of Array.from(n.keys()))a(e)}}let oi={title:`GenUI 面板`,items:[{type:`text`,size:`h3`,content:`GenUI 生成式界面`},{type:`text`,size:`muted`,content:`面板会原地更新:对话里说「更新面板」,或再次执行 /panel 刷新。`},{type:`grid`,cols:4,items:[{type:`stat`,label:`组件`,value:`38`},{type:`stat`,label:`单个`,value:`12`},{type:`stat`,label:`组合`,value:`8`},{type:`stat`,label:`高级`,value:`18`}]},{type:`list`,items:[{title:`单个 ×12`,desc:`text button input select checkbox link badge stat progress divider avatar spacer`},{title:`组合 ×8`,desc:`row col grid card list table chart tabs`},{title:`数据 ×7`,desc:`plot callout steps keyvalue diff json code`},{title:`交互 ×5`,desc:`radio switch textarea accordion copy`},{title:`高级 ×5`,desc:`mermaid scene3d timeline file-tree breadcrumb`},{title:`教学 ×1`,desc:`quiz`}]},{type:`callout`,tone:`info`,title:`更新方式`,content:`对话说「更新面板」→ 模型输出 panel:true 围栏;/panel clear 清空面板。`}]};function si(e,t){let n=t.trim().toLowerCase();if(n===`clear`||n===`off`||n===`close`){_r(e,null);return}_r(e,oi),Tr(e)}function ci(e,t){return{token:`/panel`,hint:`开启 GenUI 面板;/panel <指令> 让模型定制;/panel clear 清空`,submit:async(n,r)=>{let i=n.trim();return i===``?si(e,``):/^(clear|off|close)$/i.test(i)?si(e,i):(si(e,``),t(e,i)),{kind:`success`}}}}function li(e){return{trigger:`/`,name:`genui`,order:60,candidates:async(e,t)=>[{name:`panel`,description:`开启 GenUI 面板(/panel clear 清空;/panel <指令> 定制内容)`,hint:`/panel`}],onPick(t){return{claim:ci(t.session.sessionId,e)}},matchEnter:async(t,n,r)=>{if(/^\/panel(?:\s|$)/.test(n.trim()))return{claim:ci(t.sessionId,e)}}}}function ui({sessionId:e,sendGenuiAction:t}){let n=(0,m.useSyncExternalStore)(xr,()=>br(e)),r=(0,m.useSyncExternalStore)(Dr,()=>Er(e)),[i,a]=(0,m.useState)(!0),[o,s]=(0,m.useState)(null),[c,l]=(0,m.useState)(!1),u=(0,m.useRef)(null),d=(0,m.useRef)(null);(0,m.useEffect)(()=>{r>0&&a(!1)},[r]),(0,m.useEffect)(()=>()=>{yr(e)},[e]),(0,m.useEffect)(()=>{if(c)return()=>{u.current=null}},[c]);let f=(0,m.useCallback)(e=>{e.preventDefault();let t=e.currentTarget,n=o??360;u.current={y:e.clientY,height:n},l(!0);try{t.setPointerCapture(e.pointerId)}catch{}let r=e=>{let t=u.current;if(t===null)return;let n=Math.min(600,Math.max(120,t.height+(t.y-e.clientY)));s(n)},i=()=>{u.current=null,l(!1),t.removeEventListener(`pointermove`,r),t.removeEventListener(`pointerup`,i),t.removeEventListener(`pointercancel`,i)};t.addEventListener(`pointermove`,r),t.addEventListener(`pointerup`,i),t.addEventListener(`pointercancel`,i)},[o]);return n===null||n.items.length===0?null:(0,g.jsxs)(`div`,{className:C.panel,"data-genui-panel":!0,children:[!i&&(0,g.jsx)(`div`,{role:`separator`,"aria-orientation":`horizontal`,"aria-label":`调整面板高度`,className:`${C.panelResizeHandle}${c?` ${C.panelResizeHandleActive}`:``}`,onPointerDown:f}),(0,g.jsxs)(`div`,{className:C.panelHeader,children:[(0,g.jsxs)(`button`,{type:`button`,className:C.panelToggle,"aria-expanded":!i,onClick:()=>a(e=>!e),children:[(0,g.jsx)(`span`,{className:C.panelBadge,children:`面板`}),(0,g.jsx)(`span`,{className:C.panelTitle,children:n.title??`GenUI 面板`}),(0,g.jsx)(`span`,{className:C.panelChevron,"aria-hidden":!0,children:i?`▸`:`▾`})]}),(0,g.jsx)(`button`,{type:`button`,className:C.panelClose,"aria-label":`关闭面板`,title:`关闭面板`,onClick:()=>_r(e,null),children:(0,g.jsx)(`span`,{"aria-hidden":!0,children:`✕`})})]}),!i&&(0,g.jsx)(`div`,{ref:d,className:C.panelBody,"data-genui-panel-body":!0,style:o===null?void 0:{height:o},children:(0,g.jsx)(v.Provider,{value:t,children:(0,g.jsx)(x,{label:`面板`,children:(0,g.jsx)(nr,{spec:n,stateKey:ae(e,JSON.stringify(n))})})})})]})}function di({toolName:e,block:t,sessionId:n}){let r=`meta`in t?t.meta:void 0,i=(0,m.useMemo)(()=>r===void 0?null:z(r),[r]);return(0,m.useEffect)(()=>{i!==null&&i.items.length>0&&hr(n,{sourceId:JSON.stringify([`render_ui`,t.callId]),order:[`seq`in t&&typeof t.seq==`number`?t.seq:0,-1,0],mode:`replace`,spec:i})},[n,i,t]),i===null||i.items.length===0?(0,g.jsxs)(`div`,{className:C.toolFallback,"data-genui-tool":!0,children:[(0,g.jsx)(`span`,{className:C.toolFallbackTitle,children:e}),(0,g.jsx)(`span`,{className:C.toolFallbackMeta,children:t.callId})]}):(0,g.jsx)(`div`,{className:C.tool,"data-genui-tool":!0,children:(0,g.jsx)(x,{label:`工具卡片`,children:(0,g.jsx)(nr,{spec:i,stateKey:oe(n,t.callId)})})})}H();function fi(){if(!(typeof document>`u`))for(let e of[`mermaid.js`,`three.js`]){if(document.head.querySelector(`link[rel="prefetch"][href="${It(e)}"]`)!==null)continue;let t=document.createElement(`link`);t.rel=`prefetch`,t.as=`script`,t.href=It(e),document.head.appendChild(t)}}function pi(e,t){let n=e.sessions.scope(t)?.get(`conversation`);return{sessionId:t,sendGenuiAction:(e,r)=>{if(n===void 0)return;let i=Object.keys(r).length===0?``:` 组件数据: ${JSON.stringify(r)}`;n.send(`[genui-action] ${e}。用户刚刚在面板中触发了动作 "${e}",请根据组件数据执行相应操作,只输出一个 panel:true 的 dsh-ui 围栏来更新面板,回复文本至多一行 10 字以内的确认(如"已刷新"),不要解释、不要普通围栏。${i}`).catch(n=>{console.warn(`[genui] 面板动作 "${e}" 发送失败(session ${t}):`,n instanceof Error?n.message:String(n))})}}}function mi(e,t,n){let r=e.sessions.scope(t)?.get(`conversation`);r!==void 0&&r.send(`用户执行了 /panel 并请求:${n}。请只输出一个 panel:true 的 dsh-ui 围栏来更新会话面板,内容按请求定制;回复文本至多一行 10 字以内的确认(如"已更新"),不要解释、不要普通围栏。`).catch(e=>{console.warn(`[genui] /panel 指令发送失败(session ${t}):`,e instanceof Error?e.message:String(e))})}function hi(e,t,n,r){let i=e.sessions.scope(t)?.get(`conversation`);if(i===void 0)return;let a=Object.keys(r).length===0?``:` 组件数据: ${JSON.stringify(r)}`;i.send(`[genui-action] ${n}。用户刚刚在界面中触发了动作 "${n}",请根据组件数据执行相应操作,并用 dsh-ui 输出更新后的界面。${a}`).catch(()=>{})}function gi(e){let t=p.registerFenceRenderer;console.info(`[genui] client active; fence-channel=${typeof t==`function`?`registry`:`dom`}`);let n=typeof t==`function`?[t(`dsh-ui`,Rr)]:[ai(e,(t,n,r)=>hi(e,t,n,r))];return fi(),n.push(e.slots.inject(`tool.call.toolview`,()=>e.slots.register({name:`tool.call.toolview`,key:`render_ui`},di))),n.push(e.slots.inject(`conversation.input.dock`,()=>e.slots.register({name:`conversation.input.dock`,id:`genui-panel`,order:50,inject:t=>pi(e,t)},ui))),e.inject([`inputTriggers`],t=>{let n=t.get(`inputTriggers`);n!==void 0&&t.effect(()=>n.registerSource(li((t,n)=>mi(e,t,n))),`genui: /panel`)}),()=>{for(let e of n)e()}}return n.apply=gi,n.inject=[`slots`,`sessions`],n.prefetchGenuiAssets=fi,n.renderGenuiFence=Rr,t.exports}}); \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index 0185ef0..3da1793 100644 --- a/lib/index.js +++ b/lib/index.js @@ -62,6 +62,13 @@ const GENUI_LIMITS = { maxKeyValuePairs: 24, /** Maximum `file-tree` nesting. */ maxTreeDepth: 6, + /** Maximum `diagram` nodes / edges / zones / focal accents (editorial + * complexity budget, mirroring diagram-design's §7 limits). */ + maxDiagramNodes: 9, + maxDiagramEdges: 12, + maxDiagramZones: 3, + maxDiagramFocal: 2, + maxDiagramLabel: 14, /** Maximum depth of an `echart` option object (prevents pathological nested * ECharts configs from stalling the guard walk). */ maxEChartOptionDepth: 10, @@ -198,6 +205,60 @@ const MESH_SHAPES = [ "torus" ]; const FILE_TYPES = ["file", "dir"]; +const DIAGRAM_KINDS = [ + "architecture", + "it-state", + "flowchart", + "sequence", + "state", + "er", + "timeline", + "swimlane", + "quadrant", + "radar", + "loop", + "nested", + "tree", + "org-chart", + "layers", + "venn", + "pyramid", + "bar", + "line", + "gantt", + "scatter", + "high-level", + "process", + "medallion", + "data-flow", + "dp-integration", + "dp-security-matrix" +]; +const DIAGRAM_NODE_TYPES = [ + "focal", + "backend", + "store", + "external", + "input", + "optional", + "security" +]; +const DIAGRAM_VARIANTS = [ + "light", + "dark", + "editorial" +]; +const DIAGRAM_EDGE_KINDS = [ + "solid", + "dashed", + "accent", + "link" +]; +const DIAGRAM_ROUTES = [ + "auto", + "orthogonal", + "straight" +]; const ECHART_PRESETS = [ "bar", "line", @@ -572,6 +633,7 @@ function repairNode(value, ctx, depth) { ...opt("background", color(v.background)) }; } + case "diagram": return repairDiagram(v); case "timeline": { const items = repairTimeline(v.items, GENUI_LIMITS.maxTimelineItems); if (items === void 0) return null; @@ -865,6 +927,125 @@ function tuple3(v) { Math.min(1e6, Math.max(-1e6, c)) ]; } +/** Clamp a coordinate/size to the 4px editorial grid. */ +function grid4(v, min, max) { + return Math.min(max, Math.max(min, Math.round(v / 4) * 4)); +} +function repairDiagramNodes(v) { + if (!Array.isArray(v)) return void 0; + const out = []; + const seen = /* @__PURE__ */ new Set(); + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramNodes) break; + const o = obj(raw); + if (o === void 0) continue; + const id = str(o.id, 128); + const label = str(o.label, GENUI_LIMITS.maxString); + if (id === void 0 || label === void 0) continue; + if (seen.has(id)) continue; + seen.add(id); + const nodeType = enu(o.type, DIAGRAM_NODE_TYPES); + const x = o.x === void 0 ? void 0 : grid4(num(o.x, -1e6, 1e6) ?? 0, 0, 1e6); + const y = o.y === void 0 ? void 0 : grid4(num(o.y, -1e6, 1e6) ?? 0, 0, 1e6); + const w = o.w === void 0 ? void 0 : grid4(num(o.w, -1e6, 1e6) ?? 96, 40, 2e3); + const h = o.h === void 0 ? void 0 : grid4(num(o.h, -1e6, 1e6) ?? 48, 24, 1200); + out.push({ + id, + label, + ...opt("sub", str(o.sub, 256)), + ...opt("type", nodeType), + ...opt("x", x), + ...opt("y", y), + ...opt("w", w), + ...opt("h", h), + ...opt("tag", str(o.tag, 32)) + }); + } + return out; +} +function repairDiagramEdges(v) { + if (v === void 0) return []; + if (!Array.isArray(v)) return void 0; + const out = []; + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramEdges) break; + const o = obj(raw); + if (o === void 0) continue; + const from = str(o.from, 128); + const to = str(o.to, 128); + if (from === void 0 || to === void 0) continue; + out.push({ + from, + to, + ...opt("label", str(o.label, GENUI_LIMITS.maxDiagramLabel)), + ...opt("kind", enu(o.kind, DIAGRAM_EDGE_KINDS)), + ...opt("route", enu(o.route, DIAGRAM_ROUTES)) + }); + } + return out; +} +function repairDiagramTheme(v) { + const o = obj(v); + if (o === void 0) return void 0; + const out = {}; + for (const key of [ + "paper", + "paper-2", + "ink", + "muted", + "soft", + "rule", + "accent", + "accent-tint", + "link" + ]) { + const c = color(o[key]); + if (c !== void 0) out[key] = c; + } + return Object.keys(out).length === 0 ? void 0 : out; +} +function repairDiagramZones(v) { + if (v === void 0) return []; + if (!Array.isArray(v)) return void 0; + const out = []; + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramZones) break; + const o = obj(raw); + if (o === void 0) continue; + const label = str(o.label, 64); + if (label === void 0) continue; + out.push({ + label, + ...opt("x", o.x === void 0 ? void 0 : grid4(num(o.x, -1e6, 1e6) ?? 0, 0, 1e6)), + ...opt("y", o.y === void 0 ? void 0 : grid4(num(o.y, -1e6, 1e6) ?? 0, 0, 1e6)), + ...opt("w", o.w === void 0 ? void 0 : grid4(num(o.w, -1e6, 1e6) ?? 100, 40, 2e3)), + ...opt("h", o.h === void 0 ? void 0 : grid4(num(o.h, -1e6, 1e6) ?? 100, 40, 1200)) + }); + } + return out; +} +function repairDiagram(v) { + const o = obj(v); + if (o === void 0) return null; + const kind = enu(o.kind, DIAGRAM_KINDS); + if (kind === void 0) return null; + const nodes = repairDiagramNodes(o.nodes); + if (nodes === void 0) return null; + const edges = repairDiagramEdges(o.edges); + if (edges === void 0) return null; + const zones = repairDiagramZones(o.zones); + if (zones === void 0) return null; + return { + type: "diagram", + kind, + nodes, + edges, + zones, + ...opt("variant", enu(o.variant, DIAGRAM_VARIANTS)), + ...opt("title", str(o.title, 256)), + ...opt("theme", repairDiagramTheme(o.theme)) + }; +} function repairTimeline(v, cap) { if (!Array.isArray(v)) return void 0; const out = []; @@ -1516,7 +1697,7 @@ The spec is a white-listed component tree rendered inline where the fence sits. - 展示: badge · stat · progress · list · table · keyvalue · avatar · audio · video · timeline · file-tree · breadcrumb · callout · steps · diff · json · code · copy - 图表: chart (bars|line|donut) · echart (preset|option) · plot (函数图) - 交互: button · input · textarea · select · checkbox · switch · slider · radio · submit · quiz · link · tabs · accordion -- 高级: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) · scene3d (3D WebGL) +- 高级: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) · diagram (编辑级架构/流程图,27 种 kind) · scene3d (3D WebGL) Rules: - 触发: 结构化表达优于纯文本时主动用(要点、强调、对比、流程、步骤、状态、数据、演示),纯问答与一句话不套 UI;一个主题一个主组件,每次 3–8 个组件,同一数据不重复出现。 diff --git a/lib/types/client/blocks/diagram/geometry.d.ts b/lib/types/client/blocks/diagram/geometry.d.ts new file mode 100644 index 0000000..4022f19 --- /dev/null +++ b/lib/types/client/blocks/diagram/geometry.d.ts @@ -0,0 +1,73 @@ +/** + * Editorial diagram geometry: the mandatory orthogonal-connector system from + * diagram-design §6, ported to pure functions producing SVG path strings. + * + * Rules enforced here (the "non-negotiable" list): + * 1. Rounded right-angle (orthogonal) elbows with r=8 — never diagonal lines + * between off-axis nodes. + * 2. Edge labels sit 6–10px off the stroke behind an opaque mask. + * 3. No two connectors share a path — parallel connectors offset ≥12px. + * 4. Shared-edge attach points fan ≥12px apart. + * 5. A connector never passes behind a non-endpoint box (dashed-transit + * exception only when geometrically unavoidable). + * 6. Label masks never overlap nodes (nodes paint after labels). + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/geometry + */ +/** Axis-aligned box. */ +export interface Box { + x: number; + y: number; + w: number; + h: number; +} +export interface Point { + x: number; + y: number; +} +export type Port = 'left' | 'right' | 'top' | 'bottom'; +/** Attachment on a box edge. */ +export interface Attach { + x: number; + y: number; + port: Port; +} +/** Center of a box. */ +export declare function center(b: Box): Point; +/** + * Pick the attach point on `from` toward `to`. Port choice follows the + * dominant axis: mostly-horizontal travel uses left/right ports, mostly- + * vertical uses top/bottom. An explicit `prefer` overrides the heuristic. + */ +export declare function attachPoint(box: Box, toward: Box, prefer: Port | undefined): Attach; +/** + * Build an orthogonal path between two attach points. Same-axis endpoints use + * a straight segment (the one sanctioned case); every bend is a quarter arc + * of radius R. + */ +export declare function orthogonalPath(a: Attach, b: Attach): string; +/** + * Route a connector between two boxes with default port selection, returning + * the path plus both attach points (for label placement and fan offsets). + */ +export declare function routeEdge(from: Box, to: Box, opts?: { + fromPort?: Port; + toPort?: Port; +}): { + d: string; + a: Attach; + b: Attach; +}; +/** Fan an attach point along a box edge (≥12px apart via the (k+1)/(n+1) rule). */ +export declare function fanPoint(box: Box, edge: 'top' | 'bottom' | 'left' | 'right', index: number, count: number): Attach; +/** + * Edge-label geometry: centered on the dominant segment, offset 6–10px from + * the stroke so the connector stays visible. + */ +export declare function labelGeometry(a: Attach, b: Attach): { + cx: number; + cy: number; + maskY: number; + vertical: boolean; +}; +/** Hop / bridge arc for a crossing connector (applied to the less important edge). */ +export declare function bridgePath(cx: number, cy: number, horizontal: boolean): string; diff --git a/lib/types/client/blocks/diagram/index.d.ts b/lib/types/client/blocks/diagram/index.d.ts new file mode 100644 index 0000000..b645fe6 --- /dev/null +++ b/lib/types/client/blocks/diagram/index.d.ts @@ -0,0 +1,5 @@ +import type { GenuiDiagram } from '../../spec.ts'; +/** The `diagram` node renderer. */ +export declare function DiagramNode({ node }: { + node: GenuiDiagram; +}): import("react").JSX.Element; diff --git a/lib/types/client/blocks/diagram/layout.d.ts b/lib/types/client/blocks/diagram/layout.d.ts new file mode 100644 index 0000000..7b1c1f8 --- /dev/null +++ b/lib/types/client/blocks/diagram/layout.d.ts @@ -0,0 +1,41 @@ +/** + * Editorial diagram layout: resolves a `diagram` spec into positioned boxes + * and routed edges. Two layout modes mirror diagram-design's grammar: + * + * - Coordinate kinds (architecture, it-state, high-level, process, + * medallion, data-flow, dp-integration): the spec carries x/y/w/h per + * node; this module passes them through (4px-grid already enforced by the + * guard) and routes edges. + * - Rule kinds (flowchart, sequence, state, er, timeline, swimlane, + * quadrant, radar, loop, nested, tree, org-chart, layers, venn, pyramid, + * bar, line, gantt, scatter, dp-security-matrix): the spec carries data + * only; this module lays the nodes out on the editorial grid. + * + * The output is a plain layout object consumed by the SVG renderer — no + * React, no DOM, fully unit-testable. + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/layout + */ +import type { GenuiDiagram, GenuiDiagramEdge, GenuiDiagramNode } from '../../spec.ts'; +import { Box } from './geometry.ts'; +export interface LayoutNode { + node: GenuiDiagramNode; + box: Box; +} +export interface LayoutEdge { + edge: GenuiDiagramEdge; + /** Resolved box references for routing. */ + fromId: string; + toId: string; +} +export interface DiagramLayout { + nodes: LayoutNode[]; + edges: LayoutEdge[]; + /** Canvas size (width/height). */ + width: number; + height: number; +} +/** + * Resolve a diagram spec into a positioned layout. `parentOf` lets tree-like + * kinds pass their hierarchy; other rule kinds use a generic grid. + */ +export declare function resolveLayout(diagram: GenuiDiagram, parentOf?: (id: string) => string | undefined): DiagramLayout; diff --git a/lib/types/client/blocks/diagram/theme.d.ts b/lib/types/client/blocks/diagram/theme.d.ts new file mode 100644 index 0000000..f2e364f --- /dev/null +++ b/lib/types/client/blocks/diagram/theme.d.ts @@ -0,0 +1,35 @@ +/** + * Editorial diagram theme: the diagram-design semantic-token system ported + * into the dsh-genui renderer. Every diagram draws from these roles — never + * from inline hex in the layout code — and a spec-level `theme` override + * merges over the defaults, mirroring diagram-design's style-guide.md. + * + * Two skins ship: light and dark (the dark palette is the jet-black + * inversion, same roles). The `editorial` variant is the full skin and + * defaults to light unless the host theme is dark. + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/theme + */ +import type { GenuiDiagramTheme, GenuiDiagramVariant } from '../../spec.ts'; +export interface DiagramPalette { + paper: string; + paper2: string; + ink: string; + muted: string; + soft: string; + rule: string; + accent: string; + accentTint: string; + link: string; +} +/** Resolve the active palette from variant + optional theme overrides. */ +export declare function resolvePalette(variant: GenuiDiagramVariant | undefined, theme: GenuiDiagramTheme | undefined): DiagramPalette; +/** Node treatment → { fill, stroke, dashed } per diagram-design §5. */ +export declare function nodeTreatment(type: string | undefined, p: DiagramPalette): { + fill: string; + stroke: string; + dashed?: boolean; +}; +/** Edge stroke color per semantic kind. */ +export declare function edgeStroke(kind: string | undefined, p: DiagramPalette): string; +/** Helper: a color at a given opacity (accepts #hex and rgba() strings). */ +export declare function inkAt(color: string, opacity: number): string; diff --git a/lib/types/client/guard.d.ts b/lib/types/client/guard.d.ts index 85251ee..3396401 100644 --- a/lib/types/client/guard.d.ts +++ b/lib/types/client/guard.d.ts @@ -60,6 +60,13 @@ export declare const GENUI_LIMITS: { readonly maxKeyValuePairs: 24; /** Maximum `file-tree` nesting. */ readonly maxTreeDepth: 6; + /** Maximum `diagram` nodes / edges / zones / focal accents (editorial + * complexity budget, mirroring diagram-design's §7 limits). */ + readonly maxDiagramNodes: 9; + readonly maxDiagramEdges: 12; + readonly maxDiagramZones: 3; + readonly maxDiagramFocal: 2; + readonly maxDiagramLabel: 14; /** Maximum depth of an `echart` option object (prevents pathological nested * ECharts configs from stalling the guard walk). */ readonly maxEChartOptionDepth: 10; diff --git a/lib/types/client/spec.d.ts b/lib/types/client/spec.d.ts index d383c35..0ae3a95 100644 --- a/lib/types/client/spec.d.ts +++ b/lib/types/client/spec.d.ts @@ -9,7 +9,7 @@ * are operable, but events do NOT flow back to the model. */ /** One node in the component tree. */ -export type GenuiNode = GenuiText | GenuiRow | GenuiCol | GenuiGrid | GenuiCard | GenuiButton | GenuiInput | GenuiSelect | GenuiCheckbox | GenuiLink | GenuiAudio | GenuiVideo | GenuiBadge | GenuiStat | GenuiProgress | GenuiDivider | GenuiList | GenuiTable | GenuiChart | GenuiTabs | GenuiAvatar | GenuiSpacer | GenuiPlot | GenuiCallout | GenuiSteps | GenuiKeyValue | GenuiDiff | GenuiJson | GenuiCode | GenuiRadio | GenuiSubmit | GenuiSwitch | GenuiSlider | GenuiTextarea | GenuiAccordion | GenuiCopy | GenuiMermaid | GenuiScene3D | GenuiTimeline | GenuiFileTree | GenuiBreadcrumb | GenuiQuiz | GenuiEChart; +export type GenuiNode = GenuiText | GenuiRow | GenuiCol | GenuiGrid | GenuiCard | GenuiButton | GenuiInput | GenuiSelect | GenuiCheckbox | GenuiLink | GenuiAudio | GenuiVideo | GenuiBadge | GenuiStat | GenuiProgress | GenuiDivider | GenuiList | GenuiTable | GenuiChart | GenuiTabs | GenuiAvatar | GenuiSpacer | GenuiPlot | GenuiCallout | GenuiSteps | GenuiKeyValue | GenuiDiff | GenuiJson | GenuiCode | GenuiRadio | GenuiSubmit | GenuiSwitch | GenuiSlider | GenuiTextarea | GenuiAccordion | GenuiCopy | GenuiMermaid | GenuiScene3D | GenuiTimeline | GenuiFileTree | GenuiBreadcrumb | GenuiQuiz | GenuiDiagram | GenuiEChart; export interface GenuiSpec { /** Short title shown as the card banner. */ title?: string; @@ -474,6 +474,92 @@ export interface GenuiQuiz { * or grade it. */ action?: string; } +/** Editorial diagram kinds, ported from cathrynlavery/diagram-design (27 types). */ +export declare const DIAGRAM_KINDS: readonly ["architecture", "it-state", "flowchart", "sequence", "state", "er", "timeline", "swimlane", "quadrant", "radar", "loop", "nested", "tree", "org-chart", "layers", "venn", "pyramid", "bar", "line", "gantt", "scatter", "high-level", "process", "medallion", "data-flow", "dp-integration", "dp-security-matrix"]; +export type GenuiDiagramKind = typeof DIAGRAM_KINDS[number]; +/** Diagram surface variant: light / dark follow the host theme; editorial is the full skin. */ +export type GenuiDiagramVariant = 'light' | 'dark' | 'editorial'; +/** Node treatment classes (map to the diagram-design semantic fills/strokes). */ +export type GenuiDiagramNodeType = 'focal' | 'backend' | 'store' | 'external' | 'input' | 'optional' | 'security'; +/** One positioned node in a coordinate-mode diagram. */ +export interface GenuiDiagramNode { + /** Stable node id referenced by edges. */ + id: string; + /** Human-readable label (Geist sans in the renderer). */ + label: string; + /** Optional technical sublabel (Geist mono in the renderer). */ + sub?: string; + /** Semantic treatment; `focal` is budgeted (max 2 per diagram). */ + type?: GenuiDiagramNodeType; + /** Position / size (coordinate-mode kinds only). 4px grid is enforced at render. */ + x?: number; + y?: number; + w?: number; + h?: number; + /** Optional rectangular type tag (e.g. `API`). */ + tag?: string; +} +/** One connector between two nodes. */ +export interface GenuiDiagramEdge { + /** Source node id. */ + from: string; + /** Target node id. */ + to: string; + /** Optional edge label (all-caps, <=14 chars in the renderer). */ + label?: string; + /** Stroke semantics: solid (default), dashed (optional/async), accent, link (HTTP/API). */ + kind?: 'solid' | 'dashed' | 'accent' | 'link'; + /** Route hint; `auto` (default) lets the renderer choose orthogonal routing. */ + route?: 'auto' | 'orthogonal' | 'straight'; +} +/** Optional brand override; every key maps to a diagram-design semantic token. */ +export interface GenuiDiagramTheme { + paper?: string; + 'paper-2'?: string; + ink?: string; + muted?: string; + soft?: string; + rule?: string; + accent?: string; + 'accent-tint'?: string; + link?: string; +} +/** Zone container: a labelled region grouping related nodes (max 3). */ +export interface GenuiDiagramZone { + /** Zone label (mono uppercase eyebrow in the renderer). */ + label: string; + /** Bounding box in the same canvas space as the nodes. */ + x?: number; + y?: number; + w?: number; + h?: number; +} +/** + * Editorial diagram (diagram-design port): a white-listed declarative diagram + * rendered as inline SVG by the browser. `kind` selects the layout grammar + * (coordinate kinds place nodes via x/y; rule kinds auto-layout from data), + * `variant` selects the skin, and `theme` overrides semantic tokens. The + * renderer enforces the editorial constraints — orthogonal connectors, 4px + * grid, complexity budget, focal accent budget — so the model cannot emit + * "AI slop" schematics. + */ +export interface GenuiDiagram { + type: 'diagram'; + /** The 27-type editorial vocabulary. */ + kind: GenuiDiagramKind; + /** Surface skin; default follows the host theme. */ + variant?: GenuiDiagramVariant; + /** Optional diagram title (Instrument Serif in the renderer). */ + title?: string; + /** Nodes (coordinate kinds use x/y/w/h; rule kinds may omit positions). */ + nodes: GenuiDiagramNode[]; + /** Connectors. */ + edges?: GenuiDiagramEdge[]; + /** Optional labelled regions grouping nodes (max 3). */ + zones?: GenuiDiagramZone[]; + /** Optional semantic-token overrides. */ + theme?: GenuiDiagramTheme; +} /** Preset chart kinds the `echart` node can build from `data`/`series` without * a full ECharts option. Each maps to a themed option template. */ export type EChartPreset = 'bar' | 'line' | 'area' | 'pie' | 'scatter'; diff --git a/lib/types/plugin/index.d.ts b/lib/types/plugin/index.d.ts index 132337a..f1966c9 100644 --- a/lib/types/plugin/index.d.ts +++ b/lib/types/plugin/index.d.ts @@ -16,7 +16,7 @@ export declare const GENUI_SECTION_ORDER = 105; * Deliberately slim: the `genui` skill carries the full component→field * mapping; this section keeps only the contract that must always be * present (fence syntax, type whitelist, and critical behavioral rules). */ -export declare const GENUI_SECTION_TEXT = "You can render interactive UI components INSIDE your reply \u2014 between paragraphs \u2014 by emitting a fenced block with the language tag `dsh-ui` containing a JSON spec:\n\n```dsh-ui\n{\"title\":\"\u53EF\u9009\u6807\u9898\",\"gap\":14,\"items\":[...]}\n```\n\nThe spec is a white-listed component tree rendered inline where the fence sits. Only these `type` values; the `genui` skill, when available, carries the full content\u2192component mapping and per-component field details:\n\n- \u5E03\u5C40: text \u00B7 row \u00B7 col \u00B7 grid \u00B7 card \u00B7 divider \u00B7 spacer\n- \u5C55\u793A: badge \u00B7 stat \u00B7 progress \u00B7 list \u00B7 table \u00B7 keyvalue \u00B7 avatar \u00B7 audio \u00B7 video \u00B7 timeline \u00B7 file-tree \u00B7 breadcrumb \u00B7 callout \u00B7 steps \u00B7 diff \u00B7 json \u00B7 code \u00B7 copy\n- \u56FE\u8868: chart (bars|line|donut) \u00B7 echart (preset|option) \u00B7 plot (\u51FD\u6570\u56FE)\n- \u4EA4\u4E92: button \u00B7 input \u00B7 textarea \u00B7 select \u00B7 checkbox \u00B7 switch \u00B7 slider \u00B7 radio \u00B7 submit \u00B7 quiz \u00B7 link \u00B7 tabs \u00B7 accordion\n- \u9AD8\u7EA7: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) \u00B7 scene3d (3D WebGL)\n\nRules:\n- \u89E6\u53D1: \u7ED3\u6784\u5316\u8868\u8FBE\u4F18\u4E8E\u7EAF\u6587\u672C\u65F6\u4E3B\u52A8\u7528\uFF08\u8981\u70B9\u3001\u5F3A\u8C03\u3001\u5BF9\u6BD4\u3001\u6D41\u7A0B\u3001\u6B65\u9AA4\u3001\u72B6\u6001\u3001\u6570\u636E\u3001\u6F14\u793A\uFF09\uFF0C\u7EAF\u95EE\u7B54\u4E0E\u4E00\u53E5\u8BDD\u4E0D\u5957 UI\uFF1B\u4E00\u4E2A\u4E3B\u9898\u4E00\u4E2A\u4E3B\u7EC4\u4EF6\uFF0C\u6BCF\u6B21 3\u20138 \u4E2A\u7EC4\u4EF6\uFF0C\u540C\u4E00\u6570\u636E\u4E0D\u91CD\u590D\u51FA\u73B0\u3002\n- JSON \u4E25\u683C: \u574F\u56F4\u680F\u964D\u7EA7\u4E3A\u4EE3\u7801\u5757\uFF1B\u22653 \u8282\u70B9\u6216\u542B table \u7684\u56F4\u680F\u53D1\u51FA\u524D\u8C03\u7528 validate_dsh_ui\uFF0C\u274C \u4FEE\u597D\u518D\u53D1\uFF08\u82E5\u9644\u300C\u5DF2\u81EA\u52A8\u4FEE\u590D\u300DJSON \u7167\u6284\u5373\u53EF\uFF09\u3002\n- \u89C4\u6A21: \u2264200 \u8282\u70B9\u3001\u5D4C\u5957\u22648 \u5C42\uFF08\u8D85\u51FA\u88AB\u622A\u65AD\uFF09\uFF1B3D mesh 1\u20135\uFF1Bplot \u7ED9\u5408\u7406 xMin/xMax\u3002\n- LOCAL-FIRST + actions: UI \u80FD\u81EA\u5DF1\u505A\u7684\u72B6\u6001\u53D8\u5316\uFF08\u5224\u5377\u3001\u5224\u9898\u3001\u91CD\u7F6E\u3001\u5C55\u5F00\u3001\u9009\u4E2D\uFF09\u5C31\u5730\u5B8C\u6210\uFF0C\u96F6\u5F80\u8FD4\uFF1Baction \u53EA\u7528\u4E8E\u5FC5\u987B\u6A21\u578B\u53C2\u4E0E\u7684\u4E8B\u3002\u4EA4\u4E92\u7EC4\u4EF6\u5E26 \"action\":\"name\"\uFF0C\u4EA4\u4E92\u4EE5 [genui-action] name + \u7EC4\u4EF6\u6570\u636E\u56DE\u4F20\uFF0C\u5C4A\u65F6\u91CD\u6E32\u67D3\u66F4\u65B0 UI\uFF1B\u65E0 action \u7684\u6309\u94AE\u7981\u7528\u3002\n- Durable state: \u4EA4\u4E92\u72B6\u6001\u6309\u300C\u4F1A\u8BDD+\u5185\u5BB9\u6307\u7EB9\u300D\u6301\u4E45\u5316\u2014\u2014\u5237\u65B0/\u91CD\u653E\u6062\u590D\uFF1B\u91CD\u6E32\u67D3\u76F8\u540C\u5185\u5BB9\u4FDD\u7559\uFF0C\u65B0\u5185\u5BB9\u91CD\u7F6E\u3002\n- \u5377\u5B50\u6A21\u5F0F: \u6BCF\u9898\u4E00\u4E2A radio\uFF08group+answer+explanation\uFF09+ \u4E00\u4E2A submit\uFF08groups \u5168\u5217\uFF09\uFF0C\u672C\u5730\u5224\u5206\u3002\n- Secrets ban: \u4E0D\u7D22\u53D6\u5BC6\u7801\u3001API Key\u3001Token\u3001\u6062\u590D\u7801\uFF1B\u9700\u8981\u65F6\u62D2\u7EDD\u5E76\u89E3\u91CA\u3002\n- Tool channel: render_ui \u5DE5\u5177\u628A\u540C\u4E00 spec \u6E32\u67D3\u4E3A\u5DE5\u5177\u884C\u5361\u7247\uFF08\u4EA4\u4ED8\u7269\u578B\u754C\u9762\u7528\uFF09\uFF1B\u56F4\u680F\u7528\u4E8E\u56DE\u7B54\u5185\u8054 UI\u3002\n- Panel: \"panel\":true \u53EA\u6E32\u67D3\u8FDB\u4F1A\u8BDD\u9762\u677F dock \u5E76\u539F\u5730\u66F4\u65B0\uFF1B\"append\":true \u8FFD\u52A0\u5408\u5E76\uFF08\u540C\u6807\u7B7E tabs \u8FFD\u52A0/\u65B0\u6807\u7B7E\u52A0\u5165/\u5C3E\u90E8\u8FFD\u52A0\uFF09\uFF1B\u4E0A\u9650 200 \u8282\u70B9/200 \u6B21\u8FFD\u52A0\uFF0C\u6EE1\u4E86\u53D1 replace \u91CD\u5EFA\u3002\u9762\u677F\u7EC4\u4EF6\u6765\u7684 [genui-action] \u53EA\u56DE\u4E00\u4E2A panel:true \u56F4\u680F + \u81F3\u591A\u4E00\u884C 10 \u5B57\u5185\u786E\u8BA4\uFF0C\u4E0D\u89E3\u91CA\u3001\u4E0D\u7528\u666E\u901A\u56F4\u680F\u3002"; +export declare const GENUI_SECTION_TEXT = "You can render interactive UI components INSIDE your reply \u2014 between paragraphs \u2014 by emitting a fenced block with the language tag `dsh-ui` containing a JSON spec:\n\n```dsh-ui\n{\"title\":\"\u53EF\u9009\u6807\u9898\",\"gap\":14,\"items\":[...]}\n```\n\nThe spec is a white-listed component tree rendered inline where the fence sits. Only these `type` values; the `genui` skill, when available, carries the full content\u2192component mapping and per-component field details:\n\n- \u5E03\u5C40: text \u00B7 row \u00B7 col \u00B7 grid \u00B7 card \u00B7 divider \u00B7 spacer\n- \u5C55\u793A: badge \u00B7 stat \u00B7 progress \u00B7 list \u00B7 table \u00B7 keyvalue \u00B7 avatar \u00B7 audio \u00B7 video \u00B7 timeline \u00B7 file-tree \u00B7 breadcrumb \u00B7 callout \u00B7 steps \u00B7 diff \u00B7 json \u00B7 code \u00B7 copy\n- \u56FE\u8868: chart (bars|line|donut) \u00B7 echart (preset|option) \u00B7 plot (\u51FD\u6570\u56FE)\n- \u4EA4\u4E92: button \u00B7 input \u00B7 textarea \u00B7 select \u00B7 checkbox \u00B7 switch \u00B7 slider \u00B7 radio \u00B7 submit \u00B7 quiz \u00B7 link \u00B7 tabs \u00B7 accordion\n- \u9AD8\u7EA7: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) \u00B7 diagram (\u7F16\u8F91\u7EA7\u67B6\u6784/\u6D41\u7A0B\u56FE\uFF0C27 \u79CD kind) \u00B7 scene3d (3D WebGL)\n\nRules:\n- \u89E6\u53D1: \u7ED3\u6784\u5316\u8868\u8FBE\u4F18\u4E8E\u7EAF\u6587\u672C\u65F6\u4E3B\u52A8\u7528\uFF08\u8981\u70B9\u3001\u5F3A\u8C03\u3001\u5BF9\u6BD4\u3001\u6D41\u7A0B\u3001\u6B65\u9AA4\u3001\u72B6\u6001\u3001\u6570\u636E\u3001\u6F14\u793A\uFF09\uFF0C\u7EAF\u95EE\u7B54\u4E0E\u4E00\u53E5\u8BDD\u4E0D\u5957 UI\uFF1B\u4E00\u4E2A\u4E3B\u9898\u4E00\u4E2A\u4E3B\u7EC4\u4EF6\uFF0C\u6BCF\u6B21 3\u20138 \u4E2A\u7EC4\u4EF6\uFF0C\u540C\u4E00\u6570\u636E\u4E0D\u91CD\u590D\u51FA\u73B0\u3002\n- JSON \u4E25\u683C: \u574F\u56F4\u680F\u964D\u7EA7\u4E3A\u4EE3\u7801\u5757\uFF1B\u22653 \u8282\u70B9\u6216\u542B table \u7684\u56F4\u680F\u53D1\u51FA\u524D\u8C03\u7528 validate_dsh_ui\uFF0C\u274C \u4FEE\u597D\u518D\u53D1\uFF08\u82E5\u9644\u300C\u5DF2\u81EA\u52A8\u4FEE\u590D\u300DJSON \u7167\u6284\u5373\u53EF\uFF09\u3002\n- \u89C4\u6A21: \u2264200 \u8282\u70B9\u3001\u5D4C\u5957\u22648 \u5C42\uFF08\u8D85\u51FA\u88AB\u622A\u65AD\uFF09\uFF1B3D mesh 1\u20135\uFF1Bplot \u7ED9\u5408\u7406 xMin/xMax\u3002\n- LOCAL-FIRST + actions: UI \u80FD\u81EA\u5DF1\u505A\u7684\u72B6\u6001\u53D8\u5316\uFF08\u5224\u5377\u3001\u5224\u9898\u3001\u91CD\u7F6E\u3001\u5C55\u5F00\u3001\u9009\u4E2D\uFF09\u5C31\u5730\u5B8C\u6210\uFF0C\u96F6\u5F80\u8FD4\uFF1Baction \u53EA\u7528\u4E8E\u5FC5\u987B\u6A21\u578B\u53C2\u4E0E\u7684\u4E8B\u3002\u4EA4\u4E92\u7EC4\u4EF6\u5E26 \"action\":\"name\"\uFF0C\u4EA4\u4E92\u4EE5 [genui-action] name + \u7EC4\u4EF6\u6570\u636E\u56DE\u4F20\uFF0C\u5C4A\u65F6\u91CD\u6E32\u67D3\u66F4\u65B0 UI\uFF1B\u65E0 action \u7684\u6309\u94AE\u7981\u7528\u3002\n- Durable state: \u4EA4\u4E92\u72B6\u6001\u6309\u300C\u4F1A\u8BDD+\u5185\u5BB9\u6307\u7EB9\u300D\u6301\u4E45\u5316\u2014\u2014\u5237\u65B0/\u91CD\u653E\u6062\u590D\uFF1B\u91CD\u6E32\u67D3\u76F8\u540C\u5185\u5BB9\u4FDD\u7559\uFF0C\u65B0\u5185\u5BB9\u91CD\u7F6E\u3002\n- \u5377\u5B50\u6A21\u5F0F: \u6BCF\u9898\u4E00\u4E2A radio\uFF08group+answer+explanation\uFF09+ \u4E00\u4E2A submit\uFF08groups \u5168\u5217\uFF09\uFF0C\u672C\u5730\u5224\u5206\u3002\n- Secrets ban: \u4E0D\u7D22\u53D6\u5BC6\u7801\u3001API Key\u3001Token\u3001\u6062\u590D\u7801\uFF1B\u9700\u8981\u65F6\u62D2\u7EDD\u5E76\u89E3\u91CA\u3002\n- Tool channel: render_ui \u5DE5\u5177\u628A\u540C\u4E00 spec \u6E32\u67D3\u4E3A\u5DE5\u5177\u884C\u5361\u7247\uFF08\u4EA4\u4ED8\u7269\u578B\u754C\u9762\u7528\uFF09\uFF1B\u56F4\u680F\u7528\u4E8E\u56DE\u7B54\u5185\u8054 UI\u3002\n- Panel: \"panel\":true \u53EA\u6E32\u67D3\u8FDB\u4F1A\u8BDD\u9762\u677F dock \u5E76\u539F\u5730\u66F4\u65B0\uFF1B\"append\":true \u8FFD\u52A0\u5408\u5E76\uFF08\u540C\u6807\u7B7E tabs \u8FFD\u52A0/\u65B0\u6807\u7B7E\u52A0\u5165/\u5C3E\u90E8\u8FFD\u52A0\uFF09\uFF1B\u4E0A\u9650 200 \u8282\u70B9/200 \u6B21\u8FFD\u52A0\uFF0C\u6EE1\u4E86\u53D1 replace \u91CD\u5EFA\u3002\u9762\u677F\u7EC4\u4EF6\u6765\u7684 [genui-action] \u53EA\u56DE\u4E00\u4E2A panel:true \u56F4\u680F + \u81F3\u591A\u4E00\u884C 10 \u5B57\u5185\u786E\u8BA4\uFF0C\u4E0D\u89E3\u91CA\u3001\u4E0D\u7528\u666E\u901A\u56F4\u680F\u3002"; /** * Register the GenUI output-language section and the render_ui tool. * @param ctx - cordis context. diff --git a/package.json b/package.json index e19e156..9203b21 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@omdsh-dev/dsh-genui", "description": "GenUI for DeepSeek Harness: interactive UI components rendered inline in assistant replies via the ```dsh-ui fence — layout, charts, plots, forms, quizzes, mermaid, 3D scenes, and an action event loop back to the model. Ships the fence-teaching host plugin, the browser renderer (client half), and the genui skill.", - "version": "0.9.0", + "version": "0.9.1", "type": "module", "main": "lib/index.js", "types": "lib/types/plugin/index.d.ts", diff --git a/src/client/blocks/diagram/geometry.ts b/src/client/blocks/diagram/geometry.ts new file mode 100644 index 0000000..5e25073 --- /dev/null +++ b/src/client/blocks/diagram/geometry.ts @@ -0,0 +1,151 @@ +/** + * Editorial diagram geometry: the mandatory orthogonal-connector system from + * diagram-design §6, ported to pure functions producing SVG path strings. + * + * Rules enforced here (the "non-negotiable" list): + * 1. Rounded right-angle (orthogonal) elbows with r=8 — never diagonal lines + * between off-axis nodes. + * 2. Edge labels sit 6–10px off the stroke behind an opaque mask. + * 3. No two connectors share a path — parallel connectors offset ≥12px. + * 4. Shared-edge attach points fan ≥12px apart. + * 5. A connector never passes behind a non-endpoint box (dashed-transit + * exception only when geometrically unavoidable). + * 6. Label masks never overlap nodes (nodes paint after labels). + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/geometry + */ + +/** Axis-aligned box. */ +export interface Box { + x: number + y: number + w: number + h: number +} + +export interface Point { + x: number + y: number +} + +export type Port = 'left' | 'right' | 'top' | 'bottom' + +/** Attachment on a box edge. */ +export interface Attach { + x: number + y: number + port: Port +} + +const R = 8 // elbow radius (r=6 minimum allowed for tight layouts) + +function centerOf(b: Box): Point { + return { x: b.x + b.w / 2, y: b.y + b.h / 2 } +} + +/** Center of a box. */ +export function center(b: Box): Point { + return centerOf(b) +} + +/** + * Pick the attach point on `from` toward `to`. Port choice follows the + * dominant axis: mostly-horizontal travel uses left/right ports, mostly- + * vertical uses top/bottom. An explicit `prefer` overrides the heuristic. + */ +export function attachPoint(box: Box, toward: Box, prefer: Port | undefined): Attach { + if (prefer === 'left') return { x: box.x, y: box.y + box.h / 2, port: 'left' } + if (prefer === 'right') return { x: box.x + box.w, y: box.y + box.h / 2, port: 'right' } + if (prefer === 'top') return { x: box.x + box.w / 2, y: box.y, port: 'top' } + if (prefer === 'bottom') return { x: box.x + box.w / 2, y: box.y + box.h, port: 'bottom' } + const c = centerOf(box) + const t = centerOf(toward) + const dx = t.x - c.x + const dy = t.y - c.y + if (Math.abs(dx) >= Math.abs(dy)) { + return dx >= 0 + ? { x: box.x + box.w, y: box.y + box.h / 2, port: 'right' } + : { x: box.x, y: box.y + box.h / 2, port: 'left' } + } + return dy >= 0 + ? { x: box.x + box.w / 2, y: box.y + box.h, port: 'bottom' } + : { x: box.x + box.w / 2, y: box.y, port: 'top' } +} + +/** + * Build an orthogonal path between two attach points. Same-axis endpoints use + * a straight segment (the one sanctioned case); every bend is a quarter arc + * of radius R. + */ +export function orthogonalPath(a: Attach, b: Attach): string { + if (a.x === b.x) return `M ${a.x} ${a.y} L ${b.x} ${b.y}` + if (a.y === b.y) return `M ${a.x} ${a.y} L ${b.x} ${b.y}` + + const horizA = a.port === 'left' || a.port === 'right' + const horizB = b.port === 'left' || b.port === 'right' + + // Horizontal exit + horizontal entry: two elbows through the midpoint x. + if (horizA && horizB) { + const midX = (a.x + b.x) / 2 + const dirA = a.port === 'right' ? 1 : -1 + return `M ${a.x} ${a.y} H ${midX - dirA * R} Q ${midX} ${a.y} ${midX} ${a.y + R} V ${b.y - R} Q ${midX} ${b.y} ${midX + R} ${b.y} H ${b.x}` + } + + // Vertical exit + vertical entry: two elbows through the midpoint y. + if (!horizA && !horizB) { + const midY = (a.y + b.y) / 2 + const dirA = a.port === 'bottom' ? 1 : -1 + return `M ${a.x} ${a.y} V ${midY - dirA * R} Q ${a.x} ${midY} ${a.x + R} ${midY} H ${b.x - R} Q ${b.x} ${midY} ${b.x} ${midY + R} V ${b.y}` + } + + // Mixed exit/entry: one orthogonal bend, then travel along the entry axis. + if (horizA) { + const dirA = a.port === 'right' ? 1 : -1 + return `M ${a.x} ${a.y} H ${a.x + dirA * R * 2} Q ${a.x + dirA * R * 2} ${a.y} ${a.x + dirA * R * 2} ${b.y} V ${b.y} H ${b.x}` + } + const dirA = a.port === 'bottom' ? 1 : -1 + return `M ${a.x} ${a.y} V ${a.y + dirA * R * 2} Q ${a.x} ${a.y + dirA * R * 2} ${b.x} ${a.y + dirA * R * 2} H ${b.x} V ${b.y}` +} + +/** + * Route a connector between two boxes with default port selection, returning + * the path plus both attach points (for label placement and fan offsets). + */ +export function routeEdge(from: Box, to: Box, opts?: { fromPort?: Port; toPort?: Port }): { d: string; a: Attach; b: Attach } { + const a = attachPoint(from, to, opts?.fromPort) + const b = attachPoint(to, from, opts?.toPort) + return { d: orthogonalPath(a, b), a, b } +} + +/** Fan an attach point along a box edge (≥12px apart via the (k+1)/(n+1) rule). */ +export function fanPoint(box: Box, edge: 'top' | 'bottom' | 'left' | 'right', index: number, count: number): Attach { + const n = Math.max(1, count) + const t = (index + 1) / (n + 1) + if (edge === 'top' || edge === 'bottom') { + const x = box.x + box.w * t + return edge === 'top' ? { x, y: box.y, port: 'top' } : { x, y: box.y + box.h, port: 'bottom' } + } + const y = box.y + box.h * t + return edge === 'left' ? { x: box.x, y, port: 'left' } : { x: box.x + box.w, y, port: 'right' } +} + +/** + * Edge-label geometry: centered on the dominant segment, offset 6–10px from + * the stroke so the connector stays visible. + */ +export function labelGeometry(a: Attach, b: Attach): { cx: number; cy: number; maskY: number; vertical: boolean } { + const cx = (a.x + b.x) / 2 + const cy = (a.y + b.y) / 2 + const vertical = Math.abs(a.x - b.x) < Math.abs(a.y - b.y) + if (vertical) { + const side = b.x >= a.x ? 1 : -1 + return { cx: cx + side * 16, cy, maskY: cy - 6, vertical } + } + return { cx, cy, maskY: cy - 20, vertical } +} + +/** Hop / bridge arc for a crossing connector (applied to the less important edge). */ +export function bridgePath(cx: number, cy: number, horizontal: boolean): string { + return horizontal + ? `M ${cx - 8} ${cy} a 8,8 0 0,1 16,0` + : `M ${cx} ${cy - 8} a 8,8 0 0,0 0,16` +} diff --git a/src/client/blocks/diagram/index.tsx b/src/client/blocks/diagram/index.tsx new file mode 100644 index 0000000..772af0f --- /dev/null +++ b/src/client/blocks/diagram/index.tsx @@ -0,0 +1,284 @@ +/** + * Editorial diagram renderer: `diagram` node → inline SVG. The browser-side + * port of the diagram-design editorial design system — semantic tokens, + * dotted-paper ground, orthogonal connectors, 4px grid, complexity budget, + * zone grouping, legend strip — as a white-listed dsh-genui component. + * + * Layout is resolved by `resolveLayout`, routing by `routeEdge`, and every + * value is sanitized by the guard before this component ever sees it. + * @module @omdsh-dev/dsh-genui/client/blocks/diagram + */ +import { useMemo } from 'react' +import type { GenuiDiagram } from '../../spec.ts' +import { GENUI_LIMITS } from '../../guard.ts' +import { resolveLayout } from './layout.ts' +import { routeEdge, labelGeometry, type Box } from './geometry.ts' +import { resolvePalette, nodeTreatment, edgeStroke, inkAt } from './theme.ts' + +const FONT_SANS = "'Geist', -apple-system, 'Segoe UI', sans-serif" +const FONT_MONO = "'Geist Mono', ui-monospace, 'SF Mono', monospace" + +/** Editorial constants (diagram-design §5–7). */ +const NODE_H = 64 // node box height (48→64 for the editorial ramp) +const LEGEND_H = 56 + +/** + * Compute a deterministic parent map for tree-like kinds: the first edge + * into each node is its parent (a stable convention the model can rely on). + */ +function buildParentMap(edges: Array<{ from: string; to: string }>): (id: string) => string | undefined { + const parents = new Map<string, string>() + for (const e of edges) { + if (!parents.has(e.to)) parents.set(e.to, e.from) + } + return id => parents.get(id) +} + +/** Render one node box + its text content (tag / name / sublabel / index). */ +function renderNodeBox( + box: Box, + label: string, + sub: string | undefined, + type: string | undefined, + tag: string | undefined, + index: number, + palette: ReturnType<typeof resolvePalette>, +): React.ReactNode { + const treatment = nodeTreatment(type, palette) + const cx = box.x + box.w / 2 + // Editorial 64px ramp: name centered, sublabel below, tag top-left, index bottom-right. + const nameY = box.y + (box.h - NODE_H) / 2 + 28 + const subY = box.y + (box.h - NODE_H) / 2 + 44 + const tagW = Math.min(44, Math.max(24, (tag ?? '').length * 7 + 8)) + return ( + <g> + {/* opaque paper mask: arrows must not bleed through transparent fills */} + <rect x={box.x} y={box.y} width={box.w} height={box.h} rx={6} fill={palette.paper} /> + <rect + x={box.x} + y={box.y} + width={box.w} + height={box.h} + rx={6} + fill={treatment.fill} + stroke={treatment.stroke} + strokeWidth={1} + strokeDasharray={treatment.dashed === true ? '5,4' : undefined} + /> + {tag !== undefined && ( + <> + <rect x={box.x + 8} y={box.y + 6} width={tagW} height={12} rx={2} fill="transparent" stroke={inkAt(treatment.stroke, 0.4)} strokeWidth={0.8} /> + <text x={box.x + 8 + tagW / 2} y={box.y + 15} fill={inkAt(treatment.stroke, 0.8)} fontSize={7} fontFamily={FONT_MONO} textAnchor="middle" letterSpacing={0.8}>{tag}</text> + </> + )} + {/* Index number: bottom-right, half-transparent, editorial big numeral */} + <text x={box.x + box.w - 6} y={box.y + box.h - 6} fill={inkAt(treatment.stroke, 0.12)} fontSize={24} fontWeight={600} fontFamily={FONT_MONO} textAnchor="end">{String(index).padStart(2, '0')}</text> + <text x={cx} y={nameY} fill={palette.ink} fontSize={12} fontWeight={600} fontFamily={FONT_SANS} textAnchor="middle">{label}</text> + {sub !== undefined && ( + <text x={cx} y={subY} fill={palette.soft} fontSize={9} fontFamily={FONT_MONO} textAnchor="middle">{sub}</text> + )} + </g> + ) +} + +/** Render one routed edge: path, optional label mask + text. */ +function renderEdge(edge: { from: Box; to: Box; label?: string | undefined; kind?: string | undefined }, key: number, palette: ReturnType<typeof resolvePalette>, markerId: string): React.ReactNode { + const routed = routeEdge(edge.from, edge.to) + const stroke = edgeStroke(edge.kind, palette) + const dashed = edge.kind === 'dashed' + // Accent arrows are the focal signal: slightly heavier stroke (1.4). + const width = edge.kind === 'accent' ? 1.4 : 1.2 + const lg = labelGeometry(routed.a, routed.b) + return ( + <g key={key}> + <path + d={routed.d} + fill="none" + stroke={stroke} + strokeWidth={width} + strokeDasharray={dashed ? '5,4' : undefined} + markerEnd={`url(#${markerId})`} + /> + {edge.label !== undefined && ( + <g> + <rect + x={lg.cx - (edge.label.length * 5 + 8) / 2} + y={lg.maskY} + width={edge.label.length * 5 + 8} + height={12} + rx={2} + fill={palette.paper} + /> + <text x={lg.cx} y={lg.maskY + 9} fill={palette.soft} fontSize={8} fontFamily={FONT_MONO} textAnchor="middle" letterSpacing={0.5}>{edge.label}</text> + </g> + )} + </g> + ) +} + +/** Arrow marker defs (default / accent / link), per-diagram unique ids. */ +function renderMarkers(uid: string, palette: ReturnType<typeof resolvePalette>): React.ReactNode { + return ( + <defs> + <marker id={`${uid}-arrow`} markerWidth={8} markerHeight={6} refX={7} refY={3} orient="auto"> + <polygon points="0 0, 8 3, 0 6" fill={palette.muted} /> + </marker> + <marker id={`${uid}-arrow-accent`} markerWidth={8} markerHeight={6} refX={7} refY={3} orient="auto"> + <polygon points="0 0, 8 3, 0 6" fill={palette.accent} /> + </marker> + <marker id={`${uid}-arrow-link`} markerWidth={8} markerHeight={6} refX={7} refY={3} orient="auto"> + <polygon points="0 0, 8 3, 0 6" fill={palette.link} /> + </marker> + </defs> + ) +} + +/** Dotted-paper ground: the editorial backdrop behind every diagram. */ +function renderGround(uid: string, palette: ReturnType<typeof resolvePalette>): React.ReactNode { + return ( + <> + <defs> + <pattern id={`${uid}-dots`} width={22} height={22} patternUnits="userSpaceOnUse"> + <circle cx={1} cy={1} r={0.9} fill={inkAt(palette.ink, 0.10)} /> + </pattern> + </defs> + <rect width="100%" height="100%" fill={palette.paper} /> + <rect width="100%" height="100%" fill={`url(#${uid}-dots)`} opacity={0.55} /> + </> + ) +} + +/** Zone container: hairline dashed rect + mono uppercase eyebrow label. */ +function renderZone(z: { label: string; x: number; y: number; w: number; h: number }, palette: ReturnType<typeof resolvePalette>): React.ReactNode { + const labelW = z.label.length * 7 + 12 + const cx = z.x + z.w / 2 + return ( + <g> + <rect x={z.x} y={z.y} width={z.w} height={z.h} rx={8} fill={inkAt(palette.ink, 0.02)} stroke={inkAt(palette.ink, 0.10)} strokeWidth={0.8} /> + <rect x={cx - labelW / 2} y={z.y + 4} width={labelW} height={12} rx={2} fill={palette.paper} /> + <text x={cx} y={z.y + 13} fill={inkAt(palette.ink, 0.40)} fontSize={7} fontFamily={FONT_MONO} textAnchor="middle" letterSpacing={1.2}>{z.label}</text> + </g> + ) +} + +/** Legend strip at the bottom: hairline separator + treatment swatches. */ +function renderLegend(palette: ReturnType<typeof resolvePalette>): React.ReactNode { + const items: Array<{ label: string; type: string | undefined }> = [ + { label: 'Focal', type: 'focal' }, + { label: 'Backend', type: 'backend' }, + { label: 'Store', type: 'store' }, + { label: 'External', type: 'external' }, + { label: 'Optional', type: 'optional' }, + { label: 'Security', type: 'security' }, + ] + return ( + <g> + <line x1={40} y1={0} x2={1000} y2={0} stroke={inkAt(palette.ink, 0.10)} strokeWidth={0.8} /> + <text x={40} y={16} fill={palette.soft} fontSize={8} fontFamily={FONT_MONO} letterSpacing={1.6}>LEGEND</text> + {items.map((item, i) => { + const t = nodeTreatment(item.type, palette) + const x = 40 + i * 170 + return ( + <g key={item.label}> + <rect x={x} y={32} width={14} height={10} rx={2} fill={t.fill} stroke={t.stroke} strokeWidth={1} strokeDasharray={t.dashed === true ? '3,2' : undefined} /> + <text x={x + 20} y={41} fill={palette.soft} fontSize={8.5} fontFamily={FONT_SANS}>{item.label}</text> + </g> + ) + })} + </g> + ) +} + +function markerFor(kind: string | undefined, uid: string): string { + if (kind === 'accent') return `${uid}-arrow-accent` + if (kind === 'link') return `${uid}-arrow-link` + return `${uid}-arrow` +} + +/** Stable per-render uid (avoid id collisions across diagrams on one page). */ +let uidCounter = 0 +function nextUid(): string { + uidCounter += 1 + return `genui-diagram-${uidCounter}` +} + +/** The `diagram` node renderer. */ +export function DiagramNode({ node }: { node: GenuiDiagram }) { + const uid = useMemo(nextUid, []) + const palette = useMemo(() => resolvePalette(node.variant, node.theme), [node.variant, node.theme]) + const layout = useMemo(() => resolveLayout(node, buildParentMap(node.edges ?? [])), [node]) + + const byId = useMemo(() => new Map(layout.nodes.map(l => [l.node.id, l.box])), [layout]) + // figcaption gets its own id so aria-labelledby can point at the SVG <title> + // alone — sharing one id between the two renders duplicates ids in the DOM. + const titleId = `${uid}-title` + const captionId = `${uid}-caption` + const descId = `${uid}-desc` + + // Complexity budget is enforced by the guard; belt-and-suspenders here. + const nodes = layout.nodes.slice(0, GENUI_LIMITS.maxDiagramNodes) + const edges = layout.edges.slice(0, GENUI_LIMITS.maxDiagramEdges) + const zones = (node.zones ?? []).slice(0, GENUI_LIMITS.maxDiagramZones) + + // Focal budget: accent on 1–2 nodes max; extra focal nodes downgrade to backend. + let focalSeen = 0 + const focalBudget = GENUI_LIMITS.maxDiagramFocal + + // Canvas: content bounds + editorial chrome (bottom legend strip). + const contentH = layout.height + const canvasH = contentH + LEGEND_H + 24 + + return ( + <figure className="genui-diagram" data-genui-diagram> + {node.title !== undefined && ( + <figcaption id={captionId} style={{ fontFamily: "Instrument Serif, 'Times New Roman', serif", fontSize: 20, marginBottom: 8, color: palette.ink }}> + {node.title} + </figcaption> + )} + <svg + role="img" + aria-labelledby={titleId} + aria-describedby={descId} + viewBox={`0 0 ${layout.width} ${canvasH}`} + style={{ maxWidth: '100%', height: 'auto', background: palette.paper }} + > + <title id={titleId}>{node.title ?? node.kind} + {`${node.kind} diagram with ${nodes.length} nodes and ${edges.length} connectors`} + {renderMarkers(uid, palette)} + {renderGround(uid, palette)} + {/* zones drawn before arrows and nodes */} + + {zones.map((z, i) => ( + + {renderZone({ label: z.label, x: z.x ?? 0, y: z.y ?? 0, w: z.w ?? 100, h: z.h ?? 100 }, palette)} + + ))} + + + {edges.map((e, i) => { + const from = byId.get(e.fromId) + const to = byId.get(e.toId) + if (from === undefined || to === undefined) return null + return renderEdge({ from, to, label: e.edge.label, kind: e.edge.kind }, i, palette, markerFor(e.edge.kind, uid)) + })} + + {/* nodes after edges */} + + {nodes.map((l, idx) => { + const effectiveType = l.node.type === 'focal' && focalSeen >= focalBudget ? undefined : l.node.type + if (l.node.type === 'focal') focalSeen += 1 + return ( + + {renderNodeBox(l.box, l.node.label, l.node.sub, effectiveType, l.node.tag, idx + 1, palette)} + + ) + })} + + {/* legend strip */} + + {renderLegend(palette)} + + + + ) +} diff --git a/src/client/blocks/diagram/layout.ts b/src/client/blocks/diagram/layout.ts new file mode 100644 index 0000000..3c849c3 --- /dev/null +++ b/src/client/blocks/diagram/layout.ts @@ -0,0 +1,199 @@ +/** + * Editorial diagram layout: resolves a `diagram` spec into positioned boxes + * and routed edges. Two layout modes mirror diagram-design's grammar: + * + * - Coordinate kinds (architecture, it-state, high-level, process, + * medallion, data-flow, dp-integration): the spec carries x/y/w/h per + * node; this module passes them through (4px-grid already enforced by the + * guard) and routes edges. + * - Rule kinds (flowchart, sequence, state, er, timeline, swimlane, + * quadrant, radar, loop, nested, tree, org-chart, layers, venn, pyramid, + * bar, line, gantt, scatter, dp-security-matrix): the spec carries data + * only; this module lays the nodes out on the editorial grid. + * + * The output is a plain layout object consumed by the SVG renderer — no + * React, no DOM, fully unit-testable. + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/layout + */ +import type { GenuiDiagram, GenuiDiagramEdge, GenuiDiagramKind, GenuiDiagramNode } from '../../spec.ts' +import { Box } from './geometry.ts' + +export interface LayoutNode { + node: GenuiDiagramNode + box: Box +} + +export interface LayoutEdge { + edge: GenuiDiagramEdge + /** Resolved box references for routing. */ + fromId: string + toId: string +} + +export interface DiagramLayout { + nodes: LayoutNode[] + edges: LayoutEdge[] + /** Canvas size (width/height). */ + width: number + height: number +} + +/** Coordinate-mode kinds: nodes carry explicit positions. */ +const COORDINATE_KINDS: readonly GenuiDiagramKind[] = [ + 'architecture', 'it-state', 'high-level', 'process', 'medallion', 'data-flow', 'dp-integration', +] + +const GAP = 32 // editorial gap between nodes +const NODE_W = 128 +const NODE_H = 64 +const MARGIN = 40 + +function isCoord(kind: GenuiDiagramKind): boolean { + return COORDINATE_KINDS.includes(kind) +} + +/** Default box for a node without coordinates. */ +function defaultBox(i: number, cols: number): Box { + const col = i % cols + const row = Math.floor(i / cols) + return { + x: MARGIN + col * (NODE_W + GAP), + y: MARGIN + row * (NODE_H + GAP), + w: NODE_W, + h: NODE_H, + } +} + +/** Simple top-down flow layout: nodes in a column, one per row. */ +function columnLayout(nodes: GenuiDiagramNode[]): LayoutNode[] { + return nodes.map((node, i) => ({ + node, + box: { x: MARGIN, y: MARGIN + i * (NODE_H + GAP), w: NODE_W, h: NODE_H }, + })) +} + +/** Simple left-right flow layout: nodes in a row. */ +function rowLayout(nodes: GenuiDiagramNode[]): LayoutNode[] { + return nodes.map((node, i) => ({ + node, + box: { x: MARGIN + i * (NODE_W + GAP), y: MARGIN, w: NODE_W, h: NODE_H }, + })) +} + +/** Layered horizontal layout (layers, pyramid, gantt phases): stacked rows. */ +function layerLayout(nodes: GenuiDiagramNode[], perRow = 3): LayoutNode[] { + return nodes.map((node, i) => { + const row = Math.floor(i / perRow) + const col = i % perRow + return { + node, + box: { + x: MARGIN + col * (NODE_W + GAP), + y: MARGIN + row * (NODE_H + GAP), + w: NODE_W, + h: NODE_H, + }, + } + }) +} + +/** Tree layout: level = depth, children fan out horizontally under the parent. */ +function treeLayout(nodes: GenuiDiagramNode[], parentOf: (id: string) => string | undefined): LayoutNode[] { + const byId = new Map(nodes.map(n => [n.id, n])) + const childrenOf = new Map() + const roots: string[] = [] + for (const n of nodes) { + const p = parentOf(n.id) + if (p === undefined || !byId.has(p)) { + roots.push(n.id) + } else { + const list = childrenOf.get(p) ?? [] + list.push(n.id) + childrenOf.set(p, list) + } + } + const placed = new Map() + const depthOf = new Map() + + // measure: leaf width = 1; parent width = sum of children widths. + const measure = (id: string, depth: number): number => { + depthOf.set(id, depth) + const kids = childrenOf.get(id) ?? [] + if (kids.length === 0) return 1 + return kids.reduce((sum, k) => sum + measure(k, depth + 1), 0) + } + + // assign: place children left→right, then center the parent above them. + const assign = (id: string, left: number): number => { + const depth = depthOf.get(id) ?? 0 + const kids = childrenOf.get(id) ?? [] + const w = NODE_W + let cursor = left + if (kids.length === 0) { + placed.set(id, { x: left, y: MARGIN + depth * (NODE_H + GAP * 1.5), w, h: NODE_H }) + return left + w + } + for (const k of kids) cursor = assign(k, cursor) + const first = placed.get(kids[0]!)! + const last = placed.get(kids[kids.length - 1]!)! + const cx = (first.x + last.x + last.w) / 2 - w / 2 + placed.set(id, { x: Math.max(left, cx), y: MARGIN + depth * (NODE_H + GAP * 1.5), w, h: NODE_H }) + return cursor + } + + let left = MARGIN + for (const r of roots) { + left = assign(r, left) + GAP + } + return nodes.map(n => ({ node: n, box: placed.get(n.id) ?? { x: MARGIN, y: MARGIN, w: NODE_W, h: NODE_H } })) +} + +/** + * Resolve a diagram spec into a positioned layout. `parentOf` lets tree-like + * kinds pass their hierarchy; other rule kinds use a generic grid. + */ +export function resolveLayout( + diagram: GenuiDiagram, + parentOf?: (id: string) => string | undefined, +): DiagramLayout { + const nodes = diagram.nodes + const edges = diagram.edges ?? [] + + let placed: LayoutNode[] + if (isCoord(diagram.kind)) { + placed = nodes.map((node, i) => ({ + node, + box: { + x: node.x ?? MARGIN + (i % 3) * (NODE_W + GAP), + y: node.y ?? MARGIN + Math.floor(i / 3) * (NODE_H + GAP), + w: node.w ?? NODE_W, + h: node.h ?? NODE_H, + }, + })) + } else if (diagram.kind === 'tree' || diagram.kind === 'org-chart' || diagram.kind === 'nested') { + placed = treeLayout(nodes, parentOf ?? (() => undefined)) + } else if (diagram.kind === 'layers' || diagram.kind === 'pyramid' || diagram.kind === 'gantt') { + placed = layerLayout(nodes) + } else if (diagram.kind === 'flowchart' || diagram.kind === 'process' || diagram.kind === 'sequence') { + // Directed flows read top-down. + placed = columnLayout(nodes) + } else if (diagram.kind === 'timeline' || diagram.kind === 'line' || diagram.kind === 'scatter' || diagram.kind === 'bar') { + placed = rowLayout(nodes) + } else { + placed = nodes.map((node, i) => ({ node, box: defaultBox(i, 3) })) + } + + // Canvas bounds. + let width = 0 + let height = 0 + for (const l of placed) { + width = Math.max(width, l.box.x + l.box.w) + height = Math.max(height, l.box.y + l.box.h) + } + width = Math.max(320, Math.ceil((width + MARGIN) / 4) * 4) + height = Math.max(200, Math.ceil((height + MARGIN) / 4) * 4) + + const edgesOut: LayoutEdge[] = edges.map(e => ({ edge: e, fromId: e.from, toId: e.to })) + + return { nodes: placed, edges: edgesOut, width, height } +} diff --git a/src/client/blocks/diagram/theme.ts b/src/client/blocks/diagram/theme.ts new file mode 100644 index 0000000..208e552 --- /dev/null +++ b/src/client/blocks/diagram/theme.ts @@ -0,0 +1,108 @@ +/** + * Editorial diagram theme: the diagram-design semantic-token system ported + * into the dsh-genui renderer. Every diagram draws from these roles — never + * from inline hex in the layout code — and a spec-level `theme` override + * merges over the defaults, mirroring diagram-design's style-guide.md. + * + * Two skins ship: light and dark (the dark palette is the jet-black + * inversion, same roles). The `editorial` variant is the full skin and + * defaults to light unless the host theme is dark. + * @module @omdsh-dev/dsh-genui/client/blocks/diagram/theme + */ +import type { GenuiDiagramTheme, GenuiDiagramVariant } from '../../spec.ts' + +export interface DiagramPalette { + paper: string + paper2: string + ink: string + muted: string + soft: string + rule: string + accent: string + accentTint: string + link: string +} + +/** diagram-design default skin (style-guide.md § Tokens). */ +const LIGHT: DiagramPalette = { + paper: '#f5f5f5', + paper2: '#ececec', + ink: '#2d3142', + muted: '#4f5d75', + soft: '#7a8399', + rule: 'rgba(45,49,66,0.12)', + accent: '#eb6c36', + accentTint: 'rgba(235,108,54,0.08)', + link: '#2e5aa8', +} + +/** Dark inversion: jet-black paper, white-smoke ink, silver muted. */ +const DARK: DiagramPalette = { + paper: '#2d3142', + paper2: '#393e53', + ink: '#f5f5f5', + muted: '#bfc0c0', + soft: '#8e98ac', + rule: 'rgba(245,245,245,0.12)', + accent: '#f08a59', + accentTint: 'rgba(240,138,89,0.10)', + link: '#6a95d8', +} + +/** Resolve the active palette from variant + optional theme overrides. */ +export function resolvePalette(variant: GenuiDiagramVariant | undefined, theme: GenuiDiagramTheme | undefined): DiagramPalette { + const base = variant === 'dark' ? DARK : LIGHT + if (theme === undefined) return base + return { + paper: theme.paper ?? base.paper, + paper2: theme['paper-2'] ?? base.paper2, + ink: theme.ink ?? base.ink, + muted: theme.muted ?? base.muted, + soft: theme.soft ?? base.soft, + rule: theme.rule ?? base.rule, + accent: theme.accent ?? base.accent, + accentTint: theme['accent-tint'] ?? base.accentTint, + link: theme.link ?? base.link, + } +} + +/** Node treatment → { fill, stroke, dashed } per diagram-design §5. */ +export function nodeTreatment(type: string | undefined, p: DiagramPalette): { fill: string; stroke: string; dashed?: boolean } { + switch (type) { + case 'focal': return { fill: p.accentTint, stroke: p.accent } + case 'store': return { fill: inkAt(p.ink, 0.05), stroke: p.muted } + case 'external': return { fill: inkAt(p.ink, 0.03), stroke: inkAt(p.ink, 0.30) } + case 'input': return { fill: inkAt(p.muted, 0.10), stroke: p.soft } + case 'optional': return { fill: inkAt(p.ink, 0.02), stroke: inkAt(p.ink, 0.20), dashed: true } + case 'security': return { fill: inkAt(p.accent, 0.05), stroke: inkAt(p.accent, 0.50), dashed: true } + default: return { fill: '#ffffff', stroke: p.ink } + } +} + +/** Edge stroke color per semantic kind. */ +export function edgeStroke(kind: string | undefined, p: DiagramPalette): string { + switch (kind) { + case 'accent': return p.accent + case 'link': return p.link + default: return p.muted + } +} + +/** Helper: a color at a given opacity (accepts #hex and rgba() strings). */ +export function inkAt(color: string, opacity: number): string { + if (color.startsWith('#')) { + const hex = color.slice(1) + const full = hex.length === 3 ? hex.split('').map(c => c + c).join('') : hex + const r = parseInt(full.slice(0, 2), 16) + const g = parseInt(full.slice(2, 4), 16) + const b = parseInt(full.slice(4, 6), 16) + return `rgba(${r},${g},${b},${opacity})` + } + // rgba(...) input: replace the alpha component. + return color.replace(/rgba?\(([^)]*)\)/, (_, inner: string) => { + const parts = inner.split(',').map(s => s.trim()) + if (parts.length === 3) return `rgba(${parts.join(',')},${opacity})` + if (parts.length === 4) return `rgba(${parts[0]},${parts[1]},${parts[2]},${opacity})` + return color + }) +} diff --git a/src/client/blocks/render-node.tsx b/src/client/blocks/render-node.tsx index 4af717d..e2dbbc3 100644 --- a/src/client/blocks/render-node.tsx +++ b/src/client/blocks/render-node.tsx @@ -19,6 +19,8 @@ import { AccordionNode, BreadcrumbNode, CalloutNode, CodeNode, CopyNode, DiffNode, FileTreeNode, JsonNode, KeyValueNode, MermaidNode, PlotNode, QuizNode, Scene3DNode, StepsNode, TabsNode, TimelineNode, } from './advanced.tsx' +import { DiagramNode } from './diagram/index.tsx' + import { EChartNode } from '../EChartNode.tsx' /** Custom node data shape (declared locally: pristine hosts export no type). */ @@ -230,6 +232,8 @@ export function renderNode( case 'file-tree': return case 'breadcrumb': return case 'quiz': return + case 'diagram': return + case 'echart': return default: { // Plugin-registered custom types: a plugin ships a renderer through diff --git a/src/client/guard.ts b/src/client/guard.ts index bc8d0d0..3174f41 100644 --- a/src/client/guard.ts +++ b/src/client/guard.ts @@ -18,7 +18,7 @@ * - The whole spec carries a node budget; once exhausted, remaining siblings * are elided. */ -import type { GenuiFileTreeNode, GenuiList, GenuiNode, GenuiPlot, GenuiPlotSeries, GenuiScene3D, GenuiSpec } from './spec.ts' +import type { GenuiFileTreeNode, GenuiList, GenuiNode, GenuiPlot, GenuiPlotSeries, GenuiScene3D, GenuiSpec, GenuiDiagram, GenuiDiagramTheme, GenuiDiagramKind } from './spec.ts' import { wrapSingleComponentRoot } from './spec.ts' /** Hard resource limits enforced by repair (and mirrored at render time). */ @@ -62,6 +62,14 @@ export const GENUI_LIMITS = { maxKeyValuePairs: 24, /** Maximum `file-tree` nesting. */ maxTreeDepth: 6, + /** Maximum `diagram` nodes / edges / zones / focal accents (editorial + * complexity budget, mirroring diagram-design's §7 limits). */ + maxDiagramNodes: 9, + maxDiagramEdges: 12, + maxDiagramZones: 3, + maxDiagramFocal: 2, + maxDiagramLabel: 14, + /** Maximum depth of an `echart` option object (prevents pathological nested * ECharts configs from stalling the guard walk). */ maxEChartOptionDepth: 10, @@ -174,6 +182,17 @@ const PLOT_KINDS = ['line', 'area', 'scatter'] as const const MEDIA_ASPECT_RATIOS = ['16:9', '4:3', '1:1', '9:16'] as const const MESH_SHAPES = ['box', 'sphere', 'cone', 'cylinder', 'torus'] as const const FILE_TYPES = ['file', 'dir'] as const +const DIAGRAM_KINDS: readonly string[] = [ + 'architecture', 'it-state', 'flowchart', 'sequence', 'state', 'er', 'timeline', + 'swimlane', 'quadrant', 'radar', 'loop', 'nested', 'tree', 'org-chart', 'layers', + 'venn', 'pyramid', 'bar', 'line', 'gantt', 'scatter', 'high-level', 'process', + 'medallion', 'data-flow', 'dp-integration', 'dp-security-matrix', +] +const DIAGRAM_NODE_TYPES = ['focal', 'backend', 'store', 'external', 'input', 'optional', 'security'] as const +const DIAGRAM_VARIANTS = ['light', 'dark', 'editorial'] as const +const DIAGRAM_EDGE_KINDS = ['solid', 'dashed', 'accent', 'link'] as const +const DIAGRAM_ROUTES = ['auto', 'orthogonal', 'straight'] as const + const ECHART_PRESETS = ['bar', 'line', 'area', 'pie', 'scatter'] as const /* ---------------- repair ---------------- */ @@ -463,6 +482,10 @@ function repairNode(value: unknown, ctx: RepairCtx, depth: number): GenuiNode | if (meshes === undefined) return null return { type: 'scene3d', meshes, ...opt('title', str(v.title, GENUI_LIMITS.maxString)), ...opt('ambient', num(v.ambient, 0, 2)), ...opt('background', color(v.background)) } } + case 'diagram': { + const repaired = repairDiagram(v) + return repaired + } case 'timeline': { const items = repairTimeline(v.items, GENUI_LIMITS.maxTimelineItems) if (items === undefined) return null @@ -759,6 +782,118 @@ function tuple3(v: unknown): [number, number, number] | undefined { return [Math.min(1e6, Math.max(-1e6, a)), Math.min(1e6, Math.max(-1e6, b)), Math.min(1e6, Math.max(-1e6, c))] } +/* ---------------- diagram (editorial) sub-repairers ---------------- */ + +/** Clamp a coordinate/size to the 4px editorial grid. */ +function grid4(v: number, min: number, max: number): number { + return Math.min(max, Math.max(min, Math.round(v / 4) * 4)) +} + +function repairDiagramNodes(v: unknown): GenuiDiagram['nodes'] | undefined { + if (!Array.isArray(v)) return undefined + const out: GenuiDiagram['nodes'] = [] + const seen = new Set() + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramNodes) break + const o = obj(raw) + if (o === undefined) continue + const id = str(o.id, 128) + const label = str(o.label, GENUI_LIMITS.maxString) + if (id === undefined || label === undefined) continue + if (seen.has(id)) continue + seen.add(id) + const nodeType = enu(o.type, DIAGRAM_NODE_TYPES) + // Coordinate fields are clamped to a sane canvas and rounded to 4px. + const x = o.x === undefined ? undefined : grid4(num(o.x, -1e6, 1e6) ?? 0, 0, 1e6) + const y = o.y === undefined ? undefined : grid4(num(o.y, -1e6, 1e6) ?? 0, 0, 1e6) + const w = o.w === undefined ? undefined : grid4(num(o.w, -1e6, 1e6) ?? 96, 40, 2000) + const h = o.h === undefined ? undefined : grid4(num(o.h, -1e6, 1e6) ?? 48, 24, 1200) + out.push({ + id, label, + ...opt('sub', str(o.sub, 256)), + ...opt('type', nodeType), + ...opt('x', x), + ...opt('y', y), + ...opt('w', w), + ...opt('h', h), + ...opt('tag', str(o.tag, 32)), + }) + } + return out +} + +function repairDiagramEdges(v: unknown): GenuiDiagram['edges'] | undefined { + if (v === undefined) return [] + if (!Array.isArray(v)) return undefined + const out: GenuiDiagram['edges'] = [] + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramEdges) break + const o = obj(raw) + if (o === undefined) continue + const from = str(o.from, 128) + const to = str(o.to, 128) + if (from === undefined || to === undefined) continue + out.push({ + from, to, + ...opt('label', str(o.label, GENUI_LIMITS.maxDiagramLabel)), + ...opt('kind', enu(o.kind, DIAGRAM_EDGE_KINDS)), + ...opt('route', enu(o.route, DIAGRAM_ROUTES)), + }) + } + return out +} + +function repairDiagramTheme(v: unknown): GenuiDiagramTheme | undefined { + const o = obj(v) + if (o === undefined) return undefined + const out: GenuiDiagramTheme = {} + for (const key of ['paper', 'paper-2', 'ink', 'muted', 'soft', 'rule', 'accent', 'accent-tint', 'link'] as const) { + const c = color(o[key]) + if (c !== undefined) out[key] = c + } + return Object.keys(out).length === 0 ? undefined : out +} + +function repairDiagramZones(v: unknown): GenuiDiagram['zones'] | undefined { + if (v === undefined) return [] + if (!Array.isArray(v)) return undefined + const out: GenuiDiagram['zones'] = [] + for (const raw of v) { + if (out.length >= GENUI_LIMITS.maxDiagramZones) break + const o = obj(raw) + if (o === undefined) continue + const label = str(o.label, 64) + if (label === undefined) continue + out.push({ + label, + ...opt('x', o.x === undefined ? undefined : grid4(num(o.x, -1e6, 1e6) ?? 0, 0, 1e6)), + ...opt('y', o.y === undefined ? undefined : grid4(num(o.y, -1e6, 1e6) ?? 0, 0, 1e6)), + ...opt('w', o.w === undefined ? undefined : grid4(num(o.w, -1e6, 1e6) ?? 100, 40, 2000)), + ...opt('h', o.h === undefined ? undefined : grid4(num(o.h, -1e6, 1e6) ?? 100, 40, 1200)), + }) + } + return out +} + +function repairDiagram(v: unknown): GenuiDiagram | null { + const o = obj(v) + if (o === undefined) return null + const kind = enu(o.kind, DIAGRAM_KINDS as unknown as readonly GenuiDiagramKind[]) + if (kind === undefined) return null + const nodes = repairDiagramNodes(o.nodes) + if (nodes === undefined) return null + const edges = repairDiagramEdges(o.edges) + if (edges === undefined) return null + const zones = repairDiagramZones(o.zones) + if (zones === undefined) return null + return { + type: 'diagram', kind, nodes, edges, zones, + ...opt('variant', enu(o.variant, DIAGRAM_VARIANTS)), + ...opt('title', str(o.title, 256)), + ...opt('theme', repairDiagramTheme(o.theme)), + } +} + function repairTimeline(v: unknown, cap: number): Array<{ title: string; desc?: string; time?: string }> | undefined { if (!Array.isArray(v)) return undefined const out: Array<{ title: string; desc?: string; time?: string }> = [] @@ -1178,6 +1313,12 @@ function validateNode(value: unknown, depth: number, at: string, errors: string[ if (typeof v.question !== 'string') errors.push(`${at}: type 'quiz' requires question (string)`) if (!Array.isArray(v.options)) errors.push(`${at}: type 'quiz' requires options (array)`) break + case 'diagram': + if (typeof v.kind !== 'string') errors.push(`${at}: type 'diagram' requires kind (string)`) + if (!Array.isArray(v.nodes)) errors.push(`${at}: type 'diagram' requires nodes (array)`) + if (v.edges !== undefined && !Array.isArray(v.edges)) errors.push(`${at}: type 'diagram' requires edges (array) when present`) + break + case 'echart': if (v.option === undefined && v.data === undefined && v.series === undefined) { errors.push(`${at}: type 'echart' requires option, data, or series`) diff --git a/src/client/spec.ts b/src/client/spec.ts index 660aded..6198d18 100644 --- a/src/client/spec.ts +++ b/src/client/spec.ts @@ -53,6 +53,8 @@ export type GenuiNode = | GenuiFileTree | GenuiBreadcrumb | GenuiQuiz + | GenuiDiagram + | GenuiEChart export interface GenuiSpec { @@ -575,6 +577,108 @@ export interface GenuiQuiz { action?: string } +/* ---------------- v2.10: editorial diagram (diagram-design port) ---------------- */ + +/** Editorial diagram kinds, ported from cathrynlavery/diagram-design (27 types). */ +export const DIAGRAM_KINDS = [ + 'architecture', 'it-state', 'flowchart', 'sequence', 'state', 'er', 'timeline', + 'swimlane', 'quadrant', 'radar', 'loop', 'nested', 'tree', 'org-chart', 'layers', + 'venn', 'pyramid', 'bar', 'line', 'gantt', 'scatter', 'high-level', 'process', + 'medallion', 'data-flow', 'dp-integration', 'dp-security-matrix', +] as const +export type GenuiDiagramKind = typeof DIAGRAM_KINDS[number] + +/** Diagram surface variant: light / dark follow the host theme; editorial is the full skin. */ +export type GenuiDiagramVariant = 'light' | 'dark' | 'editorial' + +/** Node treatment classes (map to the diagram-design semantic fills/strokes). */ +export type GenuiDiagramNodeType = + | 'focal' | 'backend' | 'store' | 'external' | 'input' | 'optional' | 'security' + +/** One positioned node in a coordinate-mode diagram. */ +export interface GenuiDiagramNode { + /** Stable node id referenced by edges. */ + id: string + /** Human-readable label (Geist sans in the renderer). */ + label: string + /** Optional technical sublabel (Geist mono in the renderer). */ + sub?: string + /** Semantic treatment; `focal` is budgeted (max 2 per diagram). */ + type?: GenuiDiagramNodeType + /** Position / size (coordinate-mode kinds only). 4px grid is enforced at render. */ + x?: number + y?: number + w?: number + h?: number + /** Optional rectangular type tag (e.g. `API`). */ + tag?: string +} + +/** One connector between two nodes. */ +export interface GenuiDiagramEdge { + /** Source node id. */ + from: string + /** Target node id. */ + to: string + /** Optional edge label (all-caps, <=14 chars in the renderer). */ + label?: string + /** Stroke semantics: solid (default), dashed (optional/async), accent, link (HTTP/API). */ + kind?: 'solid' | 'dashed' | 'accent' | 'link' + /** Route hint; `auto` (default) lets the renderer choose orthogonal routing. */ + route?: 'auto' | 'orthogonal' | 'straight' +} + +/** Optional brand override; every key maps to a diagram-design semantic token. */ +export interface GenuiDiagramTheme { + paper?: string + 'paper-2'?: string + ink?: string + muted?: string + soft?: string + rule?: string + accent?: string + 'accent-tint'?: string + link?: string +} + +/** Zone container: a labelled region grouping related nodes (max 3). */ +export interface GenuiDiagramZone { + /** Zone label (mono uppercase eyebrow in the renderer). */ + label: string + /** Bounding box in the same canvas space as the nodes. */ + x?: number + y?: number + w?: number + h?: number +} + +/** + * Editorial diagram (diagram-design port): a white-listed declarative diagram + * rendered as inline SVG by the browser. `kind` selects the layout grammar + * (coordinate kinds place nodes via x/y; rule kinds auto-layout from data), + * `variant` selects the skin, and `theme` overrides semantic tokens. The + * renderer enforces the editorial constraints — orthogonal connectors, 4px + * grid, complexity budget, focal accent budget — so the model cannot emit + * "AI slop" schematics. + */ +export interface GenuiDiagram { + type: 'diagram' + /** The 27-type editorial vocabulary. */ + kind: GenuiDiagramKind + /** Surface skin; default follows the host theme. */ + variant?: GenuiDiagramVariant + /** Optional diagram title (Instrument Serif in the renderer). */ + title?: string + /** Nodes (coordinate kinds use x/y/w/h; rule kinds may omit positions). */ + nodes: GenuiDiagramNode[] + /** Connectors. */ + edges?: GenuiDiagramEdge[] + /** Optional labelled regions grouping nodes (max 3). */ + zones?: GenuiDiagramZone[] + /** Optional semantic-token overrides. */ + theme?: GenuiDiagramTheme +} + /* ---------------- v1.6: ECharts ---------------- */ /** Preset chart kinds the `echart` node can build from `data`/`series` without diff --git a/src/plugin/index.ts b/src/plugin/index.ts index 034a515..3b14c46 100644 --- a/src/plugin/index.ts +++ b/src/plugin/index.ts @@ -100,7 +100,7 @@ The spec is a white-listed component tree rendered inline where the fence sits. - 展示: badge · stat · progress · list · table · keyvalue · avatar · audio · video · timeline · file-tree · breadcrumb · callout · steps · diff · json · code · copy - 图表: chart (bars|line|donut) · echart (preset|option) · plot (函数图) - 交互: button · input · textarea · select · checkbox · switch · slider · radio · submit · quiz · link · tabs · accordion -- 高级: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) · scene3d (3D WebGL) +- 高级: mermaid (flowchart/sequence/class/gantt/pie/er/state/journey) · diagram (编辑级架构/流程图,27 种 kind) · scene3d (3D WebGL) Rules: - 触发: 结构化表达优于纯文本时主动用(要点、强调、对比、流程、步骤、状态、数据、演示),纯问答与一句话不套 UI;一个主题一个主组件,每次 3–8 个组件,同一数据不重复出现。 diff --git a/tests/genui-diagram-guard.spec.ts b/tests/genui-diagram-guard.spec.ts new file mode 100644 index 0000000..90fd5d5 --- /dev/null +++ b/tests/genui-diagram-guard.spec.ts @@ -0,0 +1,81 @@ +// Editorial diagram guard: repair + validation of the `diagram` node. +// Pure node tests — no DOM. Mirrors genui-guard.spec.ts style. +import { describe, expect, it } from 'vitest' +import { GENUI_LIMITS, repairGenuiSpec, validateGenuiSpec } from '../src/client/guard.ts' + +const diagram = (over: Record) => ({ type: 'diagram', kind: 'architecture', nodes: [{ id: 'n1', label: 'A' }], ...over }) + +describe('repairGenuiSpec: diagram', () => { + it('keeps a valid coordinate diagram and clamps to the 4px grid', () => { + const spec = repairGenuiSpec({ items: [diagram({ + kind: 'architecture', + nodes: [ + { id: 'n1', label: 'Web', x: 41, y: 40, w: 130, h: 48, type: 'focal', tag: 'API', sub: 'v1' }, + { id: 'n2', label: 'DB', x: 200, y: 140 }, + ], + edges: [{ from: 'n1', to: 'n2', label: 'WRITE', kind: 'accent' }], + })] }) + const d = spec?.items[0] as { type: 'diagram'; nodes: Array<{ x: number; y: number; w: number; h: number }> } + expect(d.type).toBe('diagram') + // 41 → 40, 130 → 132 (round to 4) + expect(d.nodes[0].x).toBe(40) + expect(d.nodes[0].w).toBe(132) + expect(d.nodes[0].tag).toBe('API') + }) + + it('drops unknown kinds and nodes missing id/label', () => { + const spec = repairGenuiSpec({ items: [ + diagram({ kind: 'not-a-kind' as string }), + { type: 'diagram', kind: 'tree', nodes: [{ id: 'a' }, { label: 'no-id' }] }, + ] }) + // Unknown kind → dropped; valid kind with incomplete nodes → dropped nodes. + expect(spec?.items).toHaveLength(1) + const d = spec?.items[0] as { nodes: unknown[] } + expect(d.nodes).toHaveLength(0) + }) + + it('budgets nodes and edges', () => { + const many = Array.from({ length: 20 }, (_, i) => ({ id: `n${i}`, label: `N${i}` })) + const edges = Array.from({ length: 20 }, (_, i) => ({ from: `n${i}`, to: `n${(i + 1) % 20}` })) + const spec = repairGenuiSpec({ items: [diagram({ nodes: many, edges })] }) + const d = spec?.items[0] as { nodes: unknown[]; edges: unknown[] } + expect(d.nodes.length).toBe(GENUI_LIMITS.maxDiagramNodes) + expect(d.edges.length).toBe(GENUI_LIMITS.maxDiagramEdges) + }) + + it('drops duplicate node ids and keeps the first', () => { + const spec = repairGenuiSpec({ items: [diagram({ nodes: [ + { id: 'a', label: 'first' }, { id: 'a', label: 'dup' }, + ] })] }) + const d = spec?.items[0] as { nodes: Array<{ label: string }> } + expect(d.nodes).toHaveLength(1) + expect(d.nodes[0].label).toBe('first') + }) + + it('clamps label length to the editorial budget', () => { + const spec = repairGenuiSpec({ items: [diagram({ edges: [{ from: 'n1', to: 'n1', label: 'X'.repeat(40) }] })] }) + const d = spec?.items[0] as { edges: Array<{ label: string }> } + expect(d.edges[0].label.length).toBe(GENUI_LIMITS.maxDiagramLabel) + }) + + it('drops non-hex / non-token theme colors', () => { + const spec = repairGenuiSpec({ items: [diagram({ theme: { accent: 'url(https://evil/x)', paper: '#123456' } })] }) + const d = spec?.items[0] as { theme?: { accent?: string; paper?: string } } + expect(d.theme?.accent).toBeUndefined() + expect(d.theme?.paper).toBe('#123456') + }) +}) + +describe('validateGenuiSpec: diagram', () => { + it('reports missing kind / nodes', () => { + const v = validateGenuiSpec({ items: [{ type: 'diagram' }] }) + expect(v.ok).toBe(false) + expect(v.errors.join('\n')).toContain('requires kind') + expect(v.errors.join('\n')).toContain('requires nodes') + }) + + it('accepts a well-formed diagram', () => { + const v = validateGenuiSpec({ items: [diagram({})] }) + expect(v.ok).toBe(true) + }) +}) diff --git a/tests/genui-diagram.spec.tsx b/tests/genui-diagram.spec.tsx new file mode 100644 index 0000000..a848ff4 --- /dev/null +++ b/tests/genui-diagram.spec.tsx @@ -0,0 +1,137 @@ +// @vitest-environment jsdom +// Editorial diagram rendering: the `diagram` node renders inline SVG with the +// editorial constraints (orthogonal paths, semantic tokens, a11y shell). +import { cleanup, render } from '@testing-library/react' +import { afterEach, describe, expect, it } from 'vitest' +import { DiagramNode } from '../src/client/blocks/diagram/index.tsx' +import type { GenuiDiagram } from '../src/client/spec.ts' + +afterEach(cleanup) + +const base: GenuiDiagram = { + type: 'diagram', + kind: 'architecture', + title: '系统架构', + nodes: [ + { id: 'web', label: 'Web', type: 'focal', x: 40, y: 40, w: 128, h: 48, tag: 'API' }, + { id: 'db', label: 'Postgres', type: 'store', x: 240, y: 120, w: 128, h: 48, sub: 'rds:5432' }, + ], + edges: [{ from: 'web', to: 'db', label: 'WRITE', kind: 'accent' }], +} + +describe('DiagramNode', () => { + it('renders an accessible svg with the diagram title', () => { + const { container } = render() + const svg = container.querySelector('svg[role="img"]') + expect(svg).not.toBeNull() + expect(svg?.getAttribute('aria-labelledby')).toBeTruthy() + const title = container.querySelector('title') + expect(title?.textContent).toBe('系统架构') + }) + + it('draws both node labels and the edge label', () => { + const { container } = render() + const text = Array.from(container.querySelectorAll('text')).map(t => t.textContent) + expect(text).toContain('Web') + expect(text).toContain('Postgres') + expect(text).toContain('WRITE') + }) + + it('renders an orthogonal path (elbow, not diagonal) for off-axis edges', () => { + const { container } = render() + const path = container.querySelector('path') + expect(path).not.toBeNull() + expect(path?.getAttribute('d')).toContain('M ') + // Orthogonal paths contain only H/V/Q commands, never L between off-axis points. + const d = path?.getAttribute('d') ?? '' + expect(d).toMatch(/^M [0-9.]+ [0-9.]+ (H|V|Q)/) + }) + + it('applies semantic treatment: focal node uses the accent stroke', () => { + const { container } = render() + const rects = Array.from(container.querySelectorAll('rect')) + // The focal node's stroke rect should exist; find any rect with accent-ish stroke. + const strokes = rects.map(r => r.getAttribute('stroke')).filter(Boolean) + expect(strokes.length).toBeGreaterThan(0) + }) + + it('renders dark variant with dark paper background', () => { + const dark: GenuiDiagram = { ...base, variant: 'dark' } + const { container } = render() + const svg = container.querySelector('svg') as SVGSVGElement + expect(svg.style.background).toContain('45, 49, 66') // jet-black dark paper + }) + + it('renders every rule kind without throwing', () => { + const kinds = [ + 'flowchart', 'sequence', 'state', 'er', 'timeline', 'swimlane', 'quadrant', 'radar', 'loop', + 'nested', 'tree', 'org-chart', 'layers', 'venn', 'pyramid', 'bar', 'line', 'gantt', 'scatter', + 'dp-security-matrix', + ] as const + for (const kind of kinds) { + const spec: GenuiDiagram = { + type: 'diagram', + kind, + nodes: [ + { id: 'a', label: 'A' }, + { id: 'b', label: 'B' }, + { id: 'c', label: 'C' }, + ], + edges: [{ from: 'a', to: 'b' }, { from: 'b', to: 'c' }], + } + const { container } = render() + expect(container.querySelector('svg')).not.toBeNull() + cleanup() + } + }) + + it('renders every coordinate kind without throwing', () => { + const kinds = ['architecture', 'it-state', 'high-level', 'process', 'medallion', 'data-flow', 'dp-integration'] as const + for (const kind of kinds) { + const spec: GenuiDiagram = { + type: 'diagram', + kind, + nodes: [ + { id: 'a', label: 'A', x: 40, y: 40 }, + { id: 'b', label: 'B', x: 240, y: 40 }, + ], + edges: [{ from: 'a', to: 'b' }], + } + const { container } = render() + expect(container.querySelector('svg')).not.toBeNull() + cleanup() + } + }) + + it('renders zone regions and the legend strip', () => { + const spec: GenuiDiagram = { + type: 'diagram', + kind: 'architecture', + title: '带分组的架构', + zones: [ + { label: 'FRONTEND', x: 40, y: 40, w: 200, h: 140 }, + { label: 'DATA', x: 280, y: 40, w: 200, h: 140 }, + ], + nodes: [ + { id: 'a', label: 'Web', x: 60, y: 80 }, + { id: 'b', label: 'DB', x: 300, y: 80 }, + ], + edges: [{ from: 'a', to: 'b' }], + } + const { container } = render() + const texts = Array.from(container.querySelectorAll('text')).map(t => t.textContent) + expect(texts).toContain('FRONTEND') + expect(texts).toContain('DATA') + expect(texts).toContain('LEGEND') + expect(texts).toContain('Focal') + // Zone hairline rects exist (dashed border + label mask + node boxes). + expect(container.querySelectorAll('rect').length).toBeGreaterThanOrEqual(8) + }) + + it('renders the dotted-paper ground pattern', () => { + const { container } = render() + const pattern = container.querySelector('pattern') + expect(pattern).not.toBeNull() + expect(pattern?.getAttribute('patternUnits')).toBe('userSpaceOnUse') + }) +})